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

\$\endgroup\$
  • \$\begingroup\$ Maybe we output a list that has some special separator value? \$\endgroup\$ – xnor Jul 4 '16 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 Jul 4 '16 at 10:10
  • \$\begingroup\$ For example, [4, 4, '', 2, 2, '', 9, 9] or [4, 4, [], 2, 2, [], 9, 9]. \$\endgroup\$ – xnor Jul 4 '16 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 Jul 4 '16 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 Jul 4 '16 at 10:13

31 Answers 31

15
\$\begingroup\$

Mathematica, 5 bytes

Split

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

| improve this answer | |
\$\endgroup\$
  • 9
    \$\begingroup\$ …what a surprise! \$\endgroup\$ – Fatalize Jul 4 '16 at 10:08
  • 11
    \$\begingroup\$ @Fatalize The real surprise is how short it is. \$\endgroup\$ – Martin Ender Jul 4 '16 at 12:07
8
\$\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.
| improve this answer | |
\$\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).

| improve this answer | |
\$\endgroup\$
  • \$\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 Jul 6 '16 at 21:18
  • \$\begingroup\$ @Lynn Oh, that's indeed much simpler, thanks. \$\endgroup\$ – Martin Ender Jul 7 '16 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
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ I added an array answer at 56 \$\endgroup\$ – edc65 Jul 5 '16 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
| improve this answer | |
\$\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.

| improve this answer | |
\$\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]].

| improve this answer | |
\$\endgroup\$
2
\$\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
| improve this answer | |
\$\endgroup\$
2
\$\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

| improve this answer | |
\$\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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Too bad groupby is such a pain... \$\endgroup\$ – Sp3000 Jul 4 '16 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.
}%
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Haskell, 22 bytes

import Data.List
group

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

\$\endgroup\$
  • 2
    \$\begingroup\$ Any reason why this is community wiki? \$\endgroup\$ – Fatalize Jul 5 '16 at 11:56
  • \$\begingroup\$ @Fatalize Anyone who knows Haskell could have posted it. \$\endgroup\$ – xnor Jul 5 '16 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 Jul 6 '16 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
| improve this answer | |
\$\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)));
    }
| improve this answer | |
\$\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
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This is 7 bytes \$\endgroup\$ – Leaky Nun Jul 4 '16 at 12:34
  • \$\begingroup\$ @LeakyNun Oh right! That's cool. \$\endgroup\$ – busukxuan Jul 4 '16 at 12:41
  • 1
    \$\begingroup\$ I believe this works for 6. \$\endgroup\$ – FryAmTheEggman Jul 4 '16 at 12:48
  • \$\begingroup\$ @FryAmTheEggman Nice abuse of m. \$\endgroup\$ – Leaky Nun Jul 4 '16 at 12:49
  • \$\begingroup\$ @FryAmTheEggman Wow, I don't understand o.O \$\endgroup\$ – busukxuan Jul 4 '16 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)
| improve this answer | |
\$\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.

| improve this answer | |
\$\endgroup\$
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

| improve this answer | |
\$\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.

| improve this answer | |
\$\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);}
| improve this answer | |
\$\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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ for starter you could remove public and static keywords. also you could remove curly brackets in for loop \$\endgroup\$ – user902383 Jul 5 '16 at 8:18
  • \$\begingroup\$ Done @user902383 \$\endgroup\$ – Rohan Jhunjhunwala Jul 5 '16 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

| improve this answer | |
\$\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
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

TSQL, 132 bytes

This is a little different from the other answers - sql doesn't have arrays, the obvious input for sql is a table.

Golfed:

DECLARE @ table(i int identity, v varchar(20))
INSERT @ values(1),(1),(1),(3),(3),(1),(1),(2),(2),(2),(1),(1),(3)

SELECT REPLICATE(v+' ',COUNT(*))FROM(SELECT i,i-row_number()over(partition
by v order by i)x,v FROM @)z GROUP BY x,v ORDER BY max(i)

Ungolfed:

DECLARE @ table(i int identity, v varchar(20))
INSERT @ values(1),(1),(1),(3),(3),(1),(1),(2),(2),(2),(1),(1),(3)

SELECT
  REPLICATE(v+' ',COUNT(*))
FROM 
  (
     SELECT
       i,
       i-row_number()over(partition by v order by i)x,
       v
     FROM @
  )z
GROUP BY
  x,v
ORDER BY
  max(i)

Fiddle

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Perl 5 - 39 Bytes

print$_.($/)[$_ eq@a[++$-]]for@a=sort@a
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Pyke, 2 bytes (non competitive)

Only supports integers

$f

Try it here!

split_at(input, delta(input))

Added split_at node, splits input when 2nd arg is truthy

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

sed, 33 23+1=24 bytes

s/([^ ]+)( \1)* */&\n/g

It needs the -r option.

Usage example:

$ echo '1 1 1 2 2 3 3 3 4 9 9' | sed -r 's/([^ ]+)( \1)* */&\n/g'
1 1 1 
2 2 
3 3 3 
4 
9 9
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 56

Input: array of numbers or strings

Output: array of arrays

First time ever using exact comparisong in golfed code

a=>a.map(x=>x!==p?o.push(g=[p=x]):g.push(x),p=o=g=[])&&o
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Clojure, 19 bytes

#(partition-by + %)

It's a built-in, but it takes a mapping function. In this case, + serves as an identity function.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Javascript (using external library) (178 bytes)

(s)=>_.From(s).Aggregate((t,e)=>{if(0===t.Items.length)return t.Items.push([e]),t;var s=t.Items[t.Items.length-1];return s[0]===e?(s.push(e),t):(t.Items.push([e]),t)},{Items:[]})

Disclaimer: I am using a library I wrote to implement LINQ from C# into JS. It didn't exactly help me win but oh well

Image

Image2

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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