Eine schnellere Alternative für {PatternSequence [1, PatternSequence [2, 3 ..] ..] ..}
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
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} *)
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}