Fazendo uma alternativa mais rápida para {PatternSequence [1, PatternSequence [2, 3 ..] ..] ..}
Preciso melhorar um padrão ou mudar uma abordagem.
É melhor descrito por um exemplo
Para uma hierarquia / ordem fornecida por uma lista, por exemplo:
order = {1, 2, 3}
e uma 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
}
Preciso verificar se listcorresponde a uma sequência definida por order:
MatchQ[list, {PatternSequence[1, PatternSequence[2, 3 ..] ..] ..}]
Este padrão escala muito mal, já que não se vai terminar de avaliar.
A função deve ter apenas listcomo argumento, considere a constante de ordem. O padrão não precisa ser construído automaticamente.
Respostas
O seguinte parece funcionar para mim, a menos que esteja faltando alguma coisa:
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
]
]
(A peça Replace[match[{rest}][#], False :> Return[False, Map]]&é opcional e pode, em princípio, ser substituída por apenas match[{rest}]).
Exemplo:
match[{1, 2, 3}][list] // AbsoluteTiming
match[{1, 2, 3}][Append[list, 1]] // AbsoluteTiming
(* {0.00038, True} *)
(* {0.000383, False} *)
Esta solução tenta reduzir a lista a uma lista de um único tipo de elementos; se tiver êxito, a lista segue o padrão prescrito.
MatchQ[
SequenceReplace[
SequenceReplace[list, {2, 3 ..} :> x],
{1, x ..} :> y
],
{y ..}
] // AbsoluteTiming
{0.0019598, True}
Esta é uma visão da máquina de estado que Daniel recomendou em um comentário:
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}