# Chunk + Enumerate a list of digits

I have a list of decimal digits:

4, 4, 4, 7, 7, 9, 9, 9, 9, 2, 2, 2, 4, 4

The list of decimal digits are known as items. We can form "chunks" from these items by grouping together identical and adjacent numbers. I want to assign each chunk a unique number, starting from 1, and increasing by 1 in the order the chunks appear in the original list. So, the output for the given example would look like this:

1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5

## Input format

A list of digits. (0-9) You may use your language built-ins to read this list however you want. Encoding: ASCII

# Output format

A series of decimal numbers, separated by a delimiter. Your program must always use the same delimiter. The delimiter must be longer than 0 bits. Encoding: ASCII

Standard loopholes apply.

• Any particular reason for the strict input and output format? Aug 13, 2019 at 21:26
• @UnrelatedString Hmm, I shall loosen them. Aug 13, 2019 at 21:27
• The IO is still rather strict. Can't you just say "input and output is as a list" and let the site defaults take care of it for you?
– Jo King
Aug 14, 2019 at 3:35
• Can we assume the list is non-empty?
– Jo King
Aug 14, 2019 at 4:14
• A list by definition has delimiters already. That's why it's a list. I also don't understand what you mean by You may use your language built-ins to read this list however you want.. Does that mean we have to include a string to list converter in our submission? And are we allowed to output as a list?
– Jo King
Aug 15, 2019 at 0:47

# Python 3.8 (pre-release), 41 bytes

lambda l,n=0:[n:=n+(l!=(l:=x))for x in l]


Try it online!

Praise the magic walrus := of assignment expressions.

# Python 2, 42 bytes

n=0
for x in input():n+=x!=id;id=x;print n


Try it online!

• Hmm, how long would this be in Pyth? Aug 14, 2019 at 0:05
• Huh, I avoided id because it's 2 bytes long... Aug 14, 2019 at 7:54
• Oof nice idea of id Aug 14, 2019 at 12:23
• @noɥʇʎԀʎzɐɹƆ 8 bytes for a straightforward translation: Try it online! Dec 14, 2019 at 1:16

# Python 2, 44 bytes

l=input()
n=0
for i in l:n+=i!=l;l=i;print n


Try it online!

# APL (dzaima/APL), 7 bytesSBCS

Anonymous tacit prefix function. Prints space-separated.

+\1,2≠/


Try it online!

2≠/ pair-wise inequality

1, prepend 1

+\ cumulative sum

# Jelly, 6 5 bytes

ŒɠµJx


Try it online!

Saved one byte thanks to UnrelatedString!

Inputs and outputs as array's (with opening/closing brackets)

## How it works

ŒɠµJx - Main link, takes one argument:                       [7, 7, 5, 5, 5, 1]
Œɠ    - Get the lengths of consecutive elements:             [2, 3, 1]
µ   - Call these lengths A
J  - range(length(A))                                     [1, 2, 3]
x - Repeat each element by the corresponding value in A: [1, 1, 2, 2, 2, 3]

• 5 bytes Aug 13, 2019 at 21:30
• @UnrelatedString all these new-fangled atoms! Aug 13, 2019 at 21:34

# Jelly, 4 bytes

ŒgƤẈ


Try it online!

### How?

ŒgƤẈ - Link: list of integers  e.g. [7,7,2,7,7]
Ƥ  - for prefixes:     [7]   [7,7]   [7,7,2]      [7,7,2,7]        [7,7,2,7,7]
Œg   -   group runs      [[7]] [[7,7]] [[7,7],[2]]  [[7,7],[2],[7]]  [[7,7],[2],[7,7]]
Ẉ - length of each    [1,   1,      2,           3,               3]


# Octave / MATLAB, 25 bytes

@(x)cumsum([1 ~~diff(x)])


Try it online!

# Wolfram Language (Mathematica), 29 bytes

Join@@(i=1;0#+i++&/@Split@#)&


Try it online!

# 05AB1E, 5 bytes

¥Ā.¥>


Try it online!

• Minor 5-bytes alternative: ¥Ā could also be üÊ. Aug 14, 2019 at 6:55
• 4 bytes Aug 14, 2019 at 12:03

f(a:t)=1:map(+sum[1|a/=t!!0])(f t)
f e=e


Try it online!

# Pyth, 13 11 bytes

s.e*]hkhbr8


Try it online!

         r8  # Run-length encode (implicit argument is the input) (-> [[frequency, char], ...]
.e          # Enumerated map (current element is b, index is k) over rQ8
*]hk      # [ k+1 ] *
hb    #           b[0]
s            # Reduce list on + ([a]+[b] = [a,b])


-2 bytes thanks to Mr. Xcoder

• hMsM._+0nVt for -2 bytes. Aug 14, 2019 at 7:56
• Or if you want to keep your approach, rQ8 is the same as r8 and .n can be s for -2 as well Aug 14, 2019 at 7:57
• Ah nice, the docs didn't mention what functions take an implicit Q Aug 14, 2019 at 8:39

# Scala, 114 bytes

s.split(", ").zipWithIndex.scan(s.head,0){(a,b)=>if(a._1==b._1)a else b._1->(a._2+1)}.tail.unzip._2.mkString(", ")


Try it online!

# Scala, 75 bytes

s=>s.scanLeft(("",0))((x,y)=>(y,x._2+(if(x._1!=y)1 else 0))).tail.map(_._2)


Try it online!

If input and output must be comma separated String (and not List) then 102 bytes.

s=>s.split(", ").scanLeft(("",0))((x,y)=>(y,x._2+(if(x._1!=y)1 else 0))).tail.map(_._2).mkString(", ")


# Jelly, 5 bytes

nƝÄŻ‘


Try it online!

I initially aimed for a 4-byter (the same program but without the Ż) but then quickly realized that a 1 had to be prepended every time due to an oversight... Even though there is another 5-byter in Jelly, I'll actually keep this because it uses a different method.

For each pair of neighbouring items of the input list $$\L\$$, test if $$\L_i\ne L_{i+1}, \forall 1\le i<|L|\$$ and save these results in a list. Then take the cumulative sum of this list and increment them by 1 to match the chunk indexing system. TL;DR. Whenever we encounter different neighbouring items, we increment the chunk index by 1.

# C (gcc), 62 bytes

f(_,l)int*_;{printf("%d ",l=--l?f(_,l)+(_[l]!=_[l-1]):1);_=l;}


Try it online!

A function that takes the list and its length as arguments.

### C (gcc), 60 bytes

f(_,l)int*_;{_=printf("%*d",--l?f(_,l)+(_[l]!=_[l-1]):2,0);}


Try it online!

Outputs in unary, delimited by 0s

# x86-16, 12 bytes

Unassembled listing:

        NUM_LOOP:
3A C2       CMP  AL, DL             ; is this char same as last?
74 01       JZ   SAME               ; if so, same index
43          INC  BX                 ; otherwise increment index
SAME:
92          XCHG AX, DX             ; save current char for next compare
8A C3       MOV  AL, BL             ; put index value in AL to store
AA          STOSB                   ; store AL into [DI], advance DI
E2 F4       LOOP NUM_LOOP           ; keep looping


Input is byte array at SI, length in CX. Output is byte array at DI. Of course, this is if default I/O rules apply now.

Example: SI = 120H, DI = 130H

# Ruby, 38 bytes

->a{i=0;a.map{|x,y|p i+=(a==a=x)?0:1}}


Try it online!

On the first iteration, a is equal to the input list, so we always increment the chunk count. On subsequent iterations it's equal to the previous element.

while(''<$d=$argv[++$x])echo$i+=$argv[$x-1]!=$d,' ';  Try it online! Input via command line, output to STDOUT. Thx to @Night2 for the pesky '0' == 0 comparison bugfix! • @Night2 good catch! Updated and fixed. Thx! Aug 15, 2019 at 17:42 # Julia 1.0, 56 bytes l->foldl(l,init=(0,0))do(p,i),c println(i+=p!=c) c,i end  Try it online! # R, 37 bytes function(x,r=rle(x)$l)rep(seq(a=r),r)


Try it online!

Not as golfy as this answer, but an alternative method using rep.