Haciendo una alternativa más rápida para {PatternSequence [1, PatternSequence [2, 3 ..] ..] ..}
Necesito mejorar un patrón o cambiar de enfoque.
Se describe mejor con un ejemplo
Para una jerarquía / orden dado por una lista, por ejemplo:
order = {1, 2, 3}
y una lista:
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
}
Necesito verificar que listcoincida con una secuencia definida por order:
MatchQ[list, {PatternSequence[1, PatternSequence[2, 3 ..] ..] ..}]
Este patrón escala muy mal, ya que no se termina de evaluar.
La función solo debe tomar listcomo argumento, considerar el orden constante. El patrón no necesita construirse automáticamente.
Respuestas
Lo siguiente parece funcionar para mí, a menos que me falte algo:
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
]
]
(La pieza Replace[match[{rest}][#], False :> Return[False, Map]]&es opcional y, en principio, puede sustituirse por solo match[{rest}]).
Ejemplo:
match[{1, 2, 3}][list] // AbsoluteTiming
match[{1, 2, 3}][Append[list, 1]] // AbsoluteTiming
(* {0.00038, True} *)
(* {0.000383, False} *)
Esta solución intenta reducir la lista a una lista de un solo tipo de elementos; si tiene éxito, la lista sigue el patrón prescrito.
MatchQ[
SequenceReplace[
SequenceReplace[list, {2, 3 ..} :> x],
{1, x ..} :> y
],
{y ..}
] // AbsoluteTiming
{0.0019598, True}
Esta es una versión de la máquina de estado que Daniel recomendó en un comentario:
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}