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
    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
    Jul 4, 2016 at 10:10
  • \$\begingroup\$ For example, [4, 4, '', 2, 2, '', 9, 9] or [4, 4, [], 2, 2, [], 9, 9]. \$\endgroup\$
    – xnor
    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
    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
    Jul 4, 2016 at 10:13

51 Answers 51

1
2
1
\$\begingroup\$

Thunno 2, 1 byte

ġ

Try it online!

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

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

Perl 5 - 39 Bytes

print$_.($/)[$_ eq@a[++$-]]for@a=sort@a
\$\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

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

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

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

Befunge, 47 41 38 Bytes

&:&:.92pv.<
g29:&:-1_@|!-
92p25*,.^ >:

Input format:

number_of_values-1         values (separated by a space)

You may test the code here


Previous version with explanations :

&:&:.00pv.<
g00:&:-1_@|!-
v*52p00:  <
>,.     ^

The interpet's cursor follows the symbols > v < ^. If the cursor is at the end of a line and is going to the right, it will loop back to the beginning (same principle for other directions).

&: : Gets the first input put it to the stack and duplicates it (to the stack)

&:.00pv : Gets the second input, prints it and saves it into the code, at the coordinates (0,0) [erasing the first '&']. Then, go down

_ : Test if last value of the stack (the number of values) is equals to 0 and set the cursor's direction to the right if it is, to the left if it isn't

1-: : Removes 1 from the number of values

&:00g-!| : Compares the next input with the one stored at (0,0). Set the cursor's direction to up if they are equal, to down if they aren't

. : Displays a numeric value

:00p52*,. : Override the last saved value to the current value, then displays \n (ascii 10, 5*2) followed by the value

@ : Terminates the program

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

05AB1E, 1 byte

γ

Builtins ftw ¯\_(ツ)_/¯

Try it online or verify all test cases.

Here an alternative without builtins (6 bytes):

üÊ0šÅ¡

Try it online or verify all test cases.

Explanation:

γ       # Split the (implicit) input-list into chunks of equal adjacent values
        # (after which the resulting list of lists is output implicitly)

ü       # For each overlapping pair of values in the (implicit) input-list:
 Ê      #  Check that they are NOT equal (0 if equal; 1 if not)
  0š    # Prepend a 0 to this list
    Å¡  # Split the (implicit) input-list at the truthy indices
        # (after which the resulting list of lists is output implicitly)
\$\endgroup\$
0
\$\begingroup\$

Charcoal, 35 bytes

≔⁰ξ≔⁺θ θF⊖Lθ«¿¬⁼§θι§θ⊕ι«P✂θξ⊕ι↓≔⊕ιξ

Try it online! Link is to verbose version of code.

Input as a list of characters.

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

Brachylog v2, 1 byte

Try it online!

Less built-in and far, far slower:

Brachylog v2, 4 bytes

~c=ᵐ

Try it online!

~c      The output is a partitioning of the input (with as few partitions as possible)
   ᵐ    such that each partition
  =     contains only one unique element.
\$\endgroup\$
0
\$\begingroup\$

C (gcc), 54 bytes

f(char*s){printf("%c%c",*s,*s-s[1]?10:32),*++s&&f(s);}

Try it online!

or 55 bytes iteratively

f(char*s){while(printf("%c%c",*s,*s-s[1]?10:32),*++s);}

Try it online!

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

Factor, 23 bytes

[ [ ] group-by values ]

Try it online!

[                        ! begin quotation (anonymous function)
  [ ]                    ! A quotation that returns its input
      group-by           ! group adjacent elements with a ( key -- value ) quotation
               values    ! obtain the values of an associative array
                      ]  ! end quotation

Factor actually has a combinator called monotonic-split that can do this more directly, but it's more bytes.

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

Arturo, 16 bytes

$=>[chunk&=>[&]]

Try it

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

Thunno, \$ 2 \log_{256}(96) \approx \$ 1.65 bytes

zy

Attempt This Online!

Built-in solution.

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

Java 8, 83 bytes

s->{char a=0;for(char b:s.toCharArray())System.out.print((a<1|a==b?"":" ")+(a=b));}

Try it online!


Alternative solution using Streams (85 bytes) :

s->s.chars().reduce(0,(a,b)->{System.out.print((a<1|a==b?"":" ")+(char)b);return b;})

Don't hesitate to ask if this needs any explanation!

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

Japt, 2 bytes

Can handle all data types.

òÀ

Try it

òÀ     :Implicit input of array
ò      :Partition between elements
 À     :That are not strictly equal
\$\endgroup\$
0
\$\begingroup\$

F#, 196 bytes

let g x=Seq.foldBack(fun n c->Seq.tryHead c|>function|None->[n,1];|Some i when fst i<>n->(n,1)::c;|_->Seq.head c|>fun h->(fst h,(snd h)+1)::(List.tail c))x []|>Seq.map(fun(i,c)->Seq.replicate c i)

Try it online! (includes character and boolean tests cases in the footer, but others must be commented out first).

Essentially, it counts the number of sequential items in the collection, then creates a new collection of each item replicated for their respective counts.

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

TypeScript (Type System) 4.9.5 - 156 121 Bytes

  • 35 Bytes thanks to ASCII-only
type F<X,Y=[],Z=any>=X extends[infer A,...infer B]?[Z]extends[A]?Y extends[...infer C,infer D]?F<B,[...C,[...D, A]],A>:F<B,[...Y,[A]],A>:F<B,[...Y,[A]],A>:Y

Un-golfed version

type DistinctGroups<
  Input extends number[],
  Output extends number[][] = [],
  LastElement extends any = never
>=
  Input extends [infer First, ...infer Rest] ?
    [LastElement] extends [First] ?
      Output extends [...infer Head, infer Tail] ?
        DistinctGroups<Rest, [...Head, [...Tail, First]], First> :
        DistinctGroups<Rest, [...Output, [First]], First>
    : DistinctGroups<Rest, [...Output, [First]], First>
  : Output

Try it on the TypeScript playground!

\$\endgroup\$
3
  • \$\begingroup\$ 121? \$\endgroup\$
    – ASCII-only
    Feb 19, 2023 at 14:16
  • \$\begingroup\$ @ASCII-only just updated! \$\endgroup\$
    – Asleepace
    Feb 20, 2023 at 2:07
  • \$\begingroup\$ missing byte count?! (you might've also forgotten to update the code in the snippet, and the explanation) \$\endgroup\$
    – ASCII-only
    Feb 20, 2023 at 3:07
0
\$\begingroup\$

J-uby, 15 bytes

Returns an Enumerator.

:slice_when+:!=

Attempt This Online!

\$\endgroup\$
1
2

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.