Eine schnellere Alternative für {PatternSequence [1, PatternSequence [2, 3 ..] ..] ..}

Sep 23 2020

Ich muss ein Muster verbessern oder einen Ansatz wechseln.

Es wird am besten durch ein Beispiel beschrieben

Für eine Hierarchie / Reihenfolge, die durch eine Liste gegeben ist, z.

order = {1, 2, 3} 

und eine Liste:

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
  }

Ich muss überprüfen, ob listeine Sequenz übereinstimmt, die definiert ist durch order:

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

Dieses Muster skaliert sehr schlecht, schon wird man die Bewertung nicht beenden.

Die Funktion sollte nur listals Argument dienen, die Ordnungskonstante berücksichtigen. Das Muster muss nicht automatisch erstellt werden.

Antworten

10 LeonidShifrin Sep 23 2020 at 22:53

Folgendes scheint für mich zu funktionieren, es sei denn, mir fehlt etwas:

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
    ]
 ]

(Das Teil Replace[match[{rest}][#], False :> Return[False, Map]]&ist optional und kann grundsätzlich durch just ersetzt werden match[{rest}]).

Beispiel:

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

Diese Lösung versucht, die Liste in eine Liste eines einzelnen Elementtyps zu reduzieren. Wenn dies erfolgreich ist, folgt die Liste dem vorgeschriebenen Muster.

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

{0.0019598, True}

Dies ist eine Einstellung zur Zustandsmaschine, die Daniel in einem Kommentar empfohlen hat:

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}