# Replace successively repeating sub-sequences by fewer of them

Imagine I have a complicated sequence {....,a1,a2,a3,...,x1,x2,x1,x2,x1,x2,x1,x2,....,z1,z2,z3,...}

I want to replace the repeating pattern x1,x2,x1,x2,x1,x2,x1,x2 (which could be anything more than two - here it is four repetitions) by just x1,x2 or separately by x1,x2,x1,x2.

I tried SequenceReplace but was not successful.

SequenceReplace[{Repeated[PatternSequence[x1, x2], {2, Infinity}],
e_} -> Union[{ x1, x2 }, e ]]@{x1, x2, x1, x2, x1, x2, x3, x4}


did not work..

• Does SequenceReplace[{x1, x2, x1, x2, x1, x2, x3, x4}, {PatternSequence[x1, x2] .. } -> Splice[{x1, x2}]] suit your needs? May 10, 2020 at 18:06
• This shows many syntax errors May 10, 2020 at 18:08
• It works on 12.1 in the Cloud; this is a little harder to do in earlier versions. May 10, 2020 at 18:10
• I have 12.0. Are you sure this is literal? PatternSequence[x1, x2] .. May 10, 2020 at 18:13
• Does this work without any problems in every version: somelist//.{h___,x1,x2,x1,x2,t___}->{h,x1,x2,t}
– Bill
May 10, 2020 at 18:25

## 2 Answers

ClearAll[seqReplace, removeRepeats]

seqReplace = SequenceReplace[{Repeated[p : PatternSequence[_, ___], {2, ∞}]} :> p];

removeRepeats = FixedPoint[seqReplace, #] &


Examples:

lst1 = {x1, x2, x1, x2, x1, x2, a, b, b, b, x3, x2, x1, x3, x2, x1, x1, x1, x1};

removeRepeats @ lst1

 {x1, x2, a, b, x3, x2, x1}

lst2 = {x1, x1, x2, x1, x2, x2, x2, x1, x2, a, b, b, x3, x2, x1, x3, x2, x1, x1, x1, x1};

removeRepeats @ lst2

 {x1, x2, a, b, x3, x2, x1}


Consider the following using ReplaceRepeated:

pattremove =
ReplaceRepeated[{start___, x1_, x2_, x1_, x2_, end___} :> {start, x1, x2, end}];

pattremove@{a1, a2, a3, x1, x2, x1, x2, x1, x2, x1, x2, x1, x2, z1, z2}
(* Out: {a1, a2, a3, x1, x2, z1, z2} *)

pattremove@{1, 2, 3, 4, 3, 4, 5, 6, 5, 6, 7}
(* Out: {1, 2, 3, 4, 5, 6, 7} *)

pattremove@{1, 2, 3, 4, 3, 4, 5, 6, 5, 6, 5, 6, 5, 6, 7}
(* Out: {1, 2, 3, 4, 5, 6, 7} *)