# Subdivide a sequence

Yesterday I couldn't solve a problem which seemed to be rather simple. I tried RepleaceRepeated, SequenceReplace and similar functions.

1. Example data

list = {5, 1, 4, 3, 1, 4, 9, 4, 3, 1, 2, 0, 0, 1, 4, 4, 0, 0, 0};


2. Expected result

 {{5}, {1, 4, 3, 1}, {4, 9, 4}, {3}, {1, 2, 0, 0, 1}, {4}, {4}, {0, 0, 0}};


3. Rules

1. Go to the first element, 5, and look ahead until the end of the list to see if it is repeated. If not, bracket it. We call this single case.
2. Go to the next element, 1, and look ahead until you find the first closing 1. Bracket the opening and closing 1 and all elements between. We call this repetition case.
3. Repetition case
4. Single case
5. Repetition case with inclusion of another repetition case (3, 4, 3). Included repetition cases are not bracketed.
6. Two equal numbers form two single cases.
7. Three or more equal numbers form one repetition case.

4. Another example:

{5, 1, 4, 3, 1, 4, 9, 4, 3, 1, 2, 0, 0, 1, 4, 4, 0, 5, 0, 0}


would result in

{{5, 1, 4, 3, 1, 4, 9, 4, 3, 1, 2, 0, 0, 1, 4, 4, 0, 5}, {0}, {0}};

• How does this occur in the first example: {1, 2, 3, 4, 3, 1}? Also since there are two 4s at the end of the list, it can't be called a single case. Should this result {4,4} instead - just as the three zeros result in {0,0,0} at the end?
– Syed
Commented Oct 26, 2023 at 8:24
• {1, 2, 3, 4, 3, 1} would become {{1, 2, 3, 4, 3, 1}} - Two equal numbers following each other should be treated as two singles like shown under Expected result.
– eldo
Commented Oct 26, 2023 at 8:33

Clear["Global*"];
list = {5, 1, 4, 3, 1, 4, 9, 4, 3, 1, 2, 0, 0, 1, 4, 4, 0, 0, 0};
blist = {5, 1, 4, 3, 1, 4, 9, 4, 3, 1, 2, 0, 0, 1, 4, 4, 0, 5, 0, 0};
f[list_List] := SequenceReplace[list, {
f : {Repeated[a_, {3, ∞}]} :> ConstantArray[a, Length@f]
, g : {Repeated[a_, {2}]} :> Sequence[{a}, {a}]
, h : {a_, Except[a_] ..., a_} :> Sequence @@ {h}
}
] // Replace[#, a_Integer -> {a}, 1] &


Usage:

f /@ {list, blist} // Column


Result:

• +1, very nice, now I see that I copied a wrong expected result to my question. Corrected just now.
– eldo
Commented Oct 26, 2023 at 9:20
• Thanks, you can also correct the picture to match under Rules, item 3 in the post.
– Syed
Commented Oct 26, 2023 at 9:22

Just an extended comment (don't accept this answer). In the answers from Syed and vindobona, the case handling adjacent pairs can be eliminated. In Syed's case, there is already a default case that treats all remaining elements as singletons. In vindobona's case, the default must be added, but it's simpler.

fSyedNew[list_List] :=
SequenceReplace[
list,
{f : {Repeated[a_, {3, \[Infinity]}]} :> ConstantArray[a, Length@f],
h : {a_, Except[a_] .., a_} :> Sequence @@ {h}}] // Replace[#, a_Integer -> {a}, 1] &

(* Note that ... was changed to .. in the h rule. *)

fvindobonaNew[list_List] :=
SequenceSplit[
list,
{p : {a_ ..} /; Length@p > 2 :> p,
p : {a_, Except[a_] .., a_} :> p,
p : {_} :> p}]

h = ReplaceAll[{a_, a_} :> Sequence[{a}, {a}]] @*
SequenceReplace[p : {a_, Except[a_] ..., a_} :> Flatten @ p] @*
Split;

h @ list

{{5}, {1, 4, 3, 1}, {4, 9, 4}, {3}, {1, 2, 0, 0, 1}, {4}, {4}, {0, 0, 0}}


Using SequenceSplit:

lists = {{5,1,4,3,1,4,9,4,3,1,2,0,0,1,4,4,0,0,0},
{5,1,4,3,1,4,9,4,3,1,2,0,0,1,4,4,0,5,0,0}};

f[list_List] := SequenceSplit[list,
{   p : {a_ ..} /; Length@p > 2 :> Table[a, Length@p]
, p : {a_, a_} :> Splice@{{a}, {a}}
, p : {a_, Except[a_] .., a_} :> p
}]

Echo@*f /@ lists;

(* Output *)
{{5},{1,4,3,1},{4,9,4},{3},{1,2,0,0,1},{4},{4},{0,0,0}}
{{5,1,4,3,1,4,9,4,3,1,2,0,0,1,4,4,0,5},{0},{0}}
`