18
\$\begingroup\$

Challenge description

Given a list / array of items, display all groups of consecutive repeating items.

Input / output description

Your input is a list / array of items (you can assume all of them are of the same type). You don't need to support every type your language has, but is has to support at least one (preferably int, but types like boolean, although not very interesting, are also fine). Sample outputs:

[4, 4, 2, 2, 9, 9] -> [[4, 4], [2, 2], [9, 9]]
[1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4] -> [[1, 1, 1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]
[1, 1, 1, 3, 3, 1, 1, 2, 2, 2, 1, 1, 3] -> [[1, 1, 1], [3, 3], [1, 1], [2, 2, 2], [1, 1], [3]]
[9, 7, 8, 6, 5] -> [[9], [7], [8], [6], [5]]
[5, 5, 5] -> [[5, 5, 5]]
['A', 'B', 'B', 'B', 'C', 'D', 'X', 'Y', 'Y', 'Z'] -> [['A'], ['B', 'B', 'B'], ['C'], ['D'], ['X'], ['Y', 'Y'], ['Z']]
[True, True, True, False, False, True, False, False, True, True, True] -> [[True, True, True], [False, False], [True], [False, False], [True, True, True]]
[0] -> [[0]]

As for empty lists, output is undefined - it can be nothing, an empty list, or an exception - whatever suits your golfing purposes the best. You don't have to create a separate list of lists either, so this is a perfectly valid output as well:

[1, 1, 1, 2, 2, 3, 3, 3, 4, 9] ->

1 1 1
2 2
3 3 3
4
9

The important thing is to keep the groups separated in some way. This is so the shortest code in bytes wins

\$\endgroup\$
12
  • \$\begingroup\$ Maybe we output a list that has some special separator value? \$\endgroup\$
    – xnor
    Commented Jul 4, 2016 at 9:57
  • \$\begingroup\$ @xnor: Can you provide an example? An array of ints separated by, for instance, 0s would be a bad idea since there can be 0s in the input... \$\endgroup\$
    – shooqie
    Commented Jul 4, 2016 at 10:10
  • \$\begingroup\$ For example, [4, 4, '', 2, 2, '', 9, 9] or [4, 4, [], 2, 2, [], 9, 9]. \$\endgroup\$
    – xnor
    Commented Jul 4, 2016 at 10:11
  • \$\begingroup\$ Actually, what types do we have to support. Can the elements themselves to be lists? I imagine some languages have built-in types that can't be printed or have weird equality-checking. \$\endgroup\$
    – xnor
    Commented Jul 4, 2016 at 10:11
  • \$\begingroup\$ @xnor: Yeah, that's what my concern was - if your input has lists inside it, then using empty list as a separator might be confusing. That's why I included "you can assume all the items are of the same type", so that can use a different type as a separator. \$\endgroup\$
    – shooqie
    Commented Jul 4, 2016 at 10:13

51 Answers 51

15
\$\begingroup\$

Mathematica, 5 bytes

Split

... there's a built-in for that.

\$\endgroup\$
2
  • 9
    \$\begingroup\$ …what a surprise! \$\endgroup\$
    – Fatalize
    Commented Jul 4, 2016 at 10:08
  • 13
    \$\begingroup\$ @Fatalize The real surprise is how short it is. \$\endgroup\$ Commented Jul 4, 2016 at 12:07
9
\$\begingroup\$

Jelly, 5 bytes

I0;œṗ

Works for all numeric types. Try it online! or verify all numeric test cases.

How it works

I0;œṗ  Main link. Argument: A (array)

I      Increments; compute the differences of consecutive elements.
 0;    Prepend a zero.
   œṗ  Partition; split A at truthy values in the result to the left.
\$\endgroup\$
8
\$\begingroup\$

Retina, 15 8 bytes

Thanks to Lynn for suggesting a simpler I/O format.

!`(.)\1*

Treats the input as a list of characters (and uses linefeeds to separate groups).

Try it online!

This simply works by matching groups and printing them all (which uses linefeed separation automatically).

\$\endgroup\$
2
  • \$\begingroup\$ I asked about abbcccddda bb ccc ddd being an acceptable I/O format, and the OP approved of it, so I guess !`(.)\1* is fine? \$\endgroup\$
    – lynn
    Commented Jul 6, 2016 at 21:18
  • \$\begingroup\$ @Lynn Oh, that's indeed much simpler, thanks. \$\endgroup\$ Commented Jul 7, 2016 at 5:39
4
\$\begingroup\$

JavaScript (ES6), 39 37 bytes

f=
s=>s.replace(/(\w+) (?!\1\b)/g,`$1
`)
;
<input oninput=o.textContent=f(this.value);><pre id=o>

Works on any space-separated word-like tokens. Saved 2 bytes thanks to @MartinEnder♦. Best I could do for array input and return is 68:

a=>a.reduce((l,r)=>(l==r?c.push(r):b.push(c=[r]),r),b=[c=[a[0]]])&&b
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I added an array answer at 56 \$\endgroup\$
    – edc65
    Commented Jul 5, 2016 at 12:50
4
\$\begingroup\$

MATL, 9 bytes

Y'v"@Z}Y"

Y'     % Take input. Run-length encoding. Gives two row arrays: values and run lengths
v      % Concatenate vertically   
"      % For each column
  @Z}  %   Push column and split into its two elements
  Y"   %   Run-length decoding
       % End for. Implicitly display

Input is a row array of numbers, with spaces or commas as separators.

Try it online! Test with non-integer numbers.


MATL, 11 bytes

lidgvYsG7XQ

Input is a column array of either numbers or characters, using ; as separator.

Try it online! Test with arbitrary numbers. Test with characters.

l     % Push 1
i     % Take input, say [4;4;2;2;9;9]
d     % Consecutive differences of input: [0;-2;0;7;0]
g     % Convert to logical: gives 1 if consecutive entries were different: [0;1;0;1;0]
v     % Concatenate vertically with the initial 1: [1;0;1;0;1;0]
Ys    % Cumulative sum. Each value is a group label: [1;1;2;2;3;3]
G     % Push input again
7XQ   % Split into horizontal arrays as indicated by group labels: {[4 4];[2 2];[9 9]}
      % Implicitly display
\$\endgroup\$
3
\$\begingroup\$

J, 13 bytes

<;.1~1,2~:/\]

Since J does not support ragged arrays, each run of equal elements is boxed. The input is an array of values and the output is array of boxed arrays.

Usage

   f =: <;.1~1,2~:/\]
   f 4 4 2 2 9 9
┌───┬───┬───┐
│4 4│2 2│9 9│
└───┴───┴───┘
   f 1 1 1 3 3 1 1 2 2 2 1 1 3
┌─────┬───┬───┬─────┬───┬─┐
│1 1 1│3 3│1 1│2 2 2│1 1│3│
└─────┴───┴───┴─────┴───┴─┘
   f 'ABBBCDXYYZ'
┌─┬───┬─┬─┬─┬──┬─┐
│A│BBB│C│D│X│YY│Z│
└─┴───┴─┴─┴─┴──┴─┘
   f 0
┌─┐
│0│
└─┘

Explanation

<;.1~1,2~:/\]  Input: s
            ]  Identify function to get s
       2       The constant 2
           \   Operate on each overlapping sublist of size 2
        ~:/      Are the two values unequal, 1 if true else 0
     1,        Prepend a 1 to it
<;.1~          Using the list just made, chop s at each index equal to 1 and box it
               Return this as the result
\$\endgroup\$
0
3
\$\begingroup\$

Dyalog APL, 9 bytes

⊢⊂⍨1,2≠/⊢

the argument
⊂⍨ partitioned at
1 at the first element
, and then
2≠/ where subsequent pairs differ
in the argument

\$\endgroup\$
3
\$\begingroup\$

gs2, 2 bytes

c-

Try it online!

c is a grouping built-in that does exactly this, so we call it on STDIN (which is a string, i.e., a list of chars) and get a list of strings. Sadly, the result is indistinguishable from the input, so we need to add separators! - (join by spaces) does the trick.

An alternative answer is (2 bytes of CP437), which simply wraps c into an anonymous function.

\$\endgroup\$
2
\$\begingroup\$

Brachylog, 13 bytes

:{s.dl1}fs.c?

Warning: this is extremely inefficient, and you will understand why in the explanation.

This expects a list (e.g [1:1:2:2:2]) as input. The elements inside the list can be pretty much anything.

Explanation

:{     }f       Find all ordered subsets of the Input with a unique element in them
  s.                Output is a subset of the input
    dl1             Output minus all duplicates has a length of 1 (i.e. one unique value)
         s.     Output is an ordered subset of those subsets
           c?   The concatenation of those subsets is the Input

This works only because of the way s - Subset unifies: the smallest sets are at the end. Therefore the first thing it finds that concatenates to the Input are the longest runs, e.g. [[1:1]:[2:2:2]] and not for example [[1:1]:[2:2]:[2]].

\$\endgroup\$
2
\$\begingroup\$

Python 2, 43 bytes

p=-1
for x in input():print"|"[:x^p],x,;p=x

Works on lists of booleans. Example:

>> [True,True,False,False,False,True,False,True,False]
 True  True | False  False  False | True | False | True | False

Iterates through the input list, storing the last seen element. A separator bar is printed before each element that is different than the previous, checked as having bitwise xor ^ of 0. Initializing p=-1 avoids a separator before the first element.

\$\endgroup\$
1
  • \$\begingroup\$ Too bad groupby is such a pain... \$\endgroup\$
    – Sp3000
    Commented Jul 4, 2016 at 11:14
2
\$\begingroup\$

CJam, 9 bytes

Two solutions:

{e`:a:e~}
{e`{(*}%}

Test it here.

Explanation

e`   e# Run-length encode (gives a list of pairs [run-length value]).
:a   e# Wrap each pair in a singleton list.
:e~  e# Run-length decode each list.

Or

e`   e# Run-length encode.
{    e# Map this block over each pair...
  (  e#   Pull out the run length.
  *  e#   Repeat the list containing only the value that many times.
}%
\$\endgroup\$
2
\$\begingroup\$

Haskell, 22 bytes

import Data.List
group

There's a built-in. Works on any type that supports equality.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ Any reason why this is community wiki? \$\endgroup\$
    – Fatalize
    Commented Jul 5, 2016 at 11:56
  • \$\begingroup\$ @Fatalize Anyone who knows Haskell could have posted it. \$\endgroup\$
    – xnor
    Commented Jul 5, 2016 at 22:57
  • 1
    \$\begingroup\$ That's noble but since no one else is doing it, why don't you ask about that on meta? \$\endgroup\$
    – Fatalize
    Commented Jul 6, 2016 at 7:10
2
\$\begingroup\$

MATL, 8 7 bytes

Removed 1 byte thanks to @Suever

ly&Y'Y{

Works with integers/floats/chars/booleans/unicorn points/other imaginary inputs.
For booleans, inputs are T/F, outputs are 1/0.

Try it online!


Grouped and Repeated

ly&Y'Y{
l          % push 1 onto the stack
 y         % duplicate the input
  &Y'      % run-length encoding (secondary output only)
     Y{    % break up array into cell array of subarrays
\$\endgroup\$
2
\$\begingroup\$

Zsh, 28 bytes

>$1;for i {mv * $i&&echo;ls}

Try it online!

  • >$1: create the file named the first argument
  • for i {}: for each argument:
    • mv * $i: attempt to move all files in the current directory to the current item
    • If these are the same (i.e. this item is the same as the last), this will fail with mv: 'X' and 'X' are the same file.
    • &&: if this doesn't fail (i.e. this item is not the same as the last)
      • echo: print a blank line to separate the runs
    • ls: then list all the files in the current directory. In effect, this just prints $i.
\$\endgroup\$
2
\$\begingroup\$

K (ngn/k), 12 bytes

{(&~~':x)_x}

Try it online!

A relatively straightforward "idiom". A (verbose) q version is:

{(where differ x)cut x}
\$\endgroup\$
2
\$\begingroup\$

Husk, 1 byte

g

Try it online for all the integer test-cases, or here for the "True/False" one

From the Husk Wiki:
g group Group equal adjacent values


Husk, 10 bytes

CẊ-Θ:W≠¹L¹

Try it online!

Without g...

From the Husk wiki:

C            Cut off sublists of input, in lengths given by:
 Ẋ             Map over pairs of adjacent values:
  -              Subtract first argument from second
                 (so Ẋ- = differences)
   Θ           Prepends a falsy value (here = zero) to
    :   L¹     Append the length of the input to
     W≠¹       Indices of input that are not equal to their successor
\$\endgroup\$
2
\$\begingroup\$

JavaScript (Node.js), 32 bytes

s=>s.replace(/(.)(?!\1)/g,'$1 ')

Try it online!

Support char

\$\endgroup\$
1
\$\begingroup\$

C#, 117 bytes

void f(List<String>m){Console.Write(m[0]+String.Join("",m.GetRange(1,m.Count()-1).Select((i,j)=>i==m[j]?i:"\n"+i)));}

ungolfed (not really)

    public static void f(List<String>m)
    {
        Console.Write(m[0]+String.Join("",m.GetRange(1,m.Count()-1).Select((i,j)=>i==m[j]?i:"\n"+i)));
    }
\$\endgroup\$
1
\$\begingroup\$

Pyth, 9 7 bytes

mr9]dr8

Credit to @LeakyNun for 2 byte!

Explanation:

             input
     r8      run-length decode
m            for each...
   ]d        ...treat each run as standalone encoded form...
 r9          ...decode 
             print

Old answer, 12 bytes

hf.Am!t{dT./

Forgot about run length built-in, but I think this is an okay approach, so I kept it.

Explanation:

                input
          ./    all possible partitions
 f       T      filter by...
  .A            ...whether all groups of integers...
    m!t{d       ...have length one after deduplication
h               get the first element (first one has no adjacent [1,1] and [1])
                print
\$\endgroup\$
7
  • \$\begingroup\$ This is 7 bytes \$\endgroup\$
    – Leaky Nun
    Commented Jul 4, 2016 at 12:34
  • \$\begingroup\$ @LeakyNun Oh right! That's cool. \$\endgroup\$
    – busukxuan
    Commented Jul 4, 2016 at 12:41
  • 1
    \$\begingroup\$ I believe this works for 6. \$\endgroup\$ Commented Jul 4, 2016 at 12:48
  • \$\begingroup\$ @FryAmTheEggman Nice abuse of m. \$\endgroup\$
    – Leaky Nun
    Commented Jul 4, 2016 at 12:49
  • \$\begingroup\$ @FryAmTheEggman Wow, I don't understand o.O \$\endgroup\$
    – busukxuan
    Commented Jul 4, 2016 at 12:58
1
\$\begingroup\$

Pyth, 36 35 bytes

VQIqNk=hZ).?=+Y]*]kZ=Z1=kN;t+Y]*]kZ

Test link

Edit: explanation:

                                      standard variables: Y=[], Z=0, k='', Q=input
VQ                                    iterate over input
  IqNk                                if the current entity is equal to k:
      =hZ)                            increase Z.
          .?                          else:
               ]*]kZ                  list of length Z filled with k
            =+Y                       add it to Y
                    =Z1               set Z to 1
                       =kN            set k to the current entity
                          ;           end loop
                              ]*]kZ   list of length Z filled with k
                            +Y        add it to Y
                           t          implicitly print the tail of Y (removing the first element)
\$\endgroup\$
1
\$\begingroup\$

Retina, 24 22 bytes

2 bytes thanks to Martin Ender.

A 15-byte answer already exists, so this is just another approach which costs more bytes.

S-`(?<=(\d+)) (?!\1\b)

Try it online!

It splits on spaces whose preceding number differ from the proceeding.

This is a demonstration of lookarounds.

\$\endgroup\$
0
1
\$\begingroup\$

05AB1E, 13 bytes

¬svyÊi¶}yðJ?y

Explained

¬s             # push first element of list to stack and swap with input
  v            # for each X in input
   yÊi¶}       # if X is different from last iteration, push a newline
        yðJ?   # push X followed by a space to stack and join stack to string
            y  # push X to stack for next iterations comparison

Should work for any list.
Tested on int and char.

Try it online

\$\endgroup\$
1
\$\begingroup\$

Swift, 43 bytes

var p=0;i.map{print($0==p ?"":",",$0);p=$0}

Assumes i to be an array of equatable objects; works for anything from ints to strings to custom objects. Kind of cheeky in that the output contains lots of newlines, but making that prettier would cost bytes.

Prettier, ungolfed version:

var prev = Int.max // unlikely to be the first element, but not the end of the world if it happens to be.
i.map { n in
    print(n == prev ? " " : "\n•", n, terminator: "")
    prev = n
}

This version prints every group on a new line at the expense of more code.

Ideas for Improvement

i.reduce(0){print($0==$1 ?"":"•",$1);return $1}

This version has 47 bytes, but it's a different approach, so maybe there's something to optimize away there? The biggest problem is the return statement.

\$\endgroup\$
1
\$\begingroup\$

C, 88 77 bytes

Moved the strmcmp inside the printf saving 11 bytes

f(char**a){*a++;char*x;for(;*a;x=*a++)printf(strcmp(*a,x)?"\n%s ":"%s ",*a);}

Usage:

f(char**a){*a++;char*x;for(;*a;x=*a++)printf(strcmp(*a,x)?"\n%s ":"%s ",*a);}
main(c,v)char**v;{f(v);}

Sample Input:

(command line parameters)

1 1 1 1 2 2 2 2 3 3 3 3 4 5 6 7777

Sample Output:

1 1 1 1
2 2 2 2
3 3 3 3
4
5
6
7777

Tested on:

gcc 4.4.7 (Red Hat 4.4.7-16)  - OK
gcc 5.3.0 (Cygwin)            - Segmetation Fault
gcc 4.8.1 (Windows)           - OK

I'm trying to fix the 5.3.0 Segmetation Fault.

88 Version

f(char**a){*a++;char*x;for(;*a;x=*a++)strcmp(*a,x)?printf("\n%s ",*a):printf("%s ",*a);}
\$\endgroup\$
1
\$\begingroup\$

Java 134 bytes

void a(String[]a){int i=0,l=a.length;for(;i<l-1;i++)System.out.print(a[i]+((a[i].equals(a[i+1]))?" ":"\n"));System.out.print(a[l-1]);}

iterates through, and decides whether to separate with a new line or a space.

\$\endgroup\$
2
  • \$\begingroup\$ for starter you could remove public and static keywords. also you could remove curly brackets in for loop \$\endgroup\$
    – user902383
    Commented Jul 5, 2016 at 8:18
  • \$\begingroup\$ Done @user902383 \$\endgroup\$ Commented Jul 5, 2016 at 12:10
1
\$\begingroup\$

ListSharp, 134 bytes

STRG l = READ[<here>+"\\l.txt"]
[FOREACH NUMB IN 1 TO l LENGTH-1 AS i]
{
[IF l[i] ISNOT l[i-1]]
STRG o=o+"\n"
STRG o=o+l[i]
}
SHOW = o

ListSharp doesnt support functions so the array is saved in a local file called l.txt file

\$\endgroup\$
1
\$\begingroup\$

Ruby, 24 bytes

In ruby Array instances have built-in method group_by

So solution will be:

a.group_by{|x| x}.values
\$\endgroup\$
1
\$\begingroup\$

Jelly, 2 bytes

Œg

Try it online!

Alternatively, a non-builtin approach:

Ik

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ "Alternatively, a non-builtin approach". Nonsense. Even if you expand every single step to the most basic of operations, Jelly will always be a builtin. \$\endgroup\$
    – EasyasPi
    Commented Feb 11, 2021 at 2:23
  • 1
    \$\begingroup\$ @EasyasPi Yeah, but the same applies for all languages. str.replace in Python is just as much a builtin as I in Jelly. The second answer just shows that there is a way to do the task without a single command that does what’s asked for \$\endgroup\$ Commented Feb 11, 2021 at 2:29
  • \$\begingroup\$ It was a joke, but yeah, you are right. \$\endgroup\$
    – EasyasPi
    Commented Feb 11, 2021 at 2:30
1
\$\begingroup\$

PowerShell, 49 bytes

$args|%{,$a*!($i=$_-in$a-or!$a)
$a=$a*$i+,$_}
,$a

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Vyxal, 1 byte

Ġ

Try it Online!

Ah yes, the power of triviality.

\$\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.