Membuat alternatif yang lebih cepat untuk {PatternSequence [1, PatternSequence [2, 3 ..] ..] ..}

Sep 23 2020

Saya perlu memperbaiki pola atau mengganti pendekatan.

Ini paling baik dijelaskan dengan sebuah contoh

Untuk hierarki / urutan yang diberikan oleh daftar misalnya:

order = {1, 2, 3} 

dan daftar:

list = {
  1, 2, 3, 2, 3, 3, 2, 3, 3, 2, 3, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3,
   3, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3
  }

Saya perlu memverifikasi bahwa listcocok dengan urutan yang ditentukan oleh order:

MatchQ[list, {PatternSequence[1, PatternSequence[2, 3 ..] ..] ..}]

Pola ini berskala sangat buruk, karena pola itu tidak akan menyelesaikan evaluasi.

Fungsi ini hanya mengambil listargumen, pertimbangkan konstanta urutan. Pola tidak perlu dibuat secara otomatis.

Jawaban

10 LeonidShifrin Sep 23 2020 at 22:53

Hal berikut tampaknya berhasil untuk saya, kecuali saya melewatkan sesuatu:

ClearAll[match]
match[{}][{}] := True;
match[{fst_, rest___}][l_List] :=
  And @@ Map[
    Replace[
      match[{rest}][#], 
      False :> Return[False, Map]
    ]&,
    Replace[
      ReplaceList[
        l, 
        {
          {___, fst, middle : Except[fst] ..., fst, ___} :> {middle}, 
          {___, fst, r : Except[fst] ...} :> {r}
        }
      ],
      {} -> False
    ]
 ]

(Bagian Replace[match[{rest}][#], False :> Return[False, Map]]&ini opsional dan pada prinsipnya dapat diganti dengan hanya match[{rest}]).

Contoh:

match[{1, 2, 3}][list] // AbsoluteTiming
match[{1, 2, 3}][Append[list, 1]] // AbsoluteTiming

(* {0.00038, True} *)

(* {0.000383, False} *)
10 C.E. Sep 24 2020 at 02:44

Solusi ini mencoba untuk mengurangi daftar menjadi daftar satu jenis elemen, jika berhasil maka daftar mengikuti pola yang ditentukan.

MatchQ[
  SequenceReplace[
   SequenceReplace[list, {2, 3 ..} :> x],
   {1, x ..} :> y
   ],
  {y ..}
  ] // AbsoluteTiming

{0.0019598, True}

Ini adalah contoh mesin negara yang direkomendasikan Daniel dalam komentar:

f[1, 2] = 2;
f[2, 3] = 3;
f[3, 2] = 2;
f[3, 1] = 1;
f[3, 3] = 3;
f[_, _] := Throw[False]

And[
  First[list] == 1 && Last[list] == 3,
  Catch[Fold[f, list]; True]
] // AbsoluteTiming

{0.0000455, True}