6
$\begingroup$

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

enter image description here

  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}};
$\endgroup$
2
  • $\begingroup$ 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? $\endgroup$
    – Syed
    Commented Oct 26, 2023 at 8:24
  • $\begingroup$ {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. $\endgroup$
    – eldo
    Commented Oct 26, 2023 at 8:33

4 Answers 4

6
$\begingroup$
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:

enter image description here

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

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}]
$\endgroup$
6
$\begingroup$
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}}
$\endgroup$
5
$\begingroup$

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}}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.