18
\$\begingroup\$

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.

\$\endgroup\$
16
  • 9
    \$\begingroup\$ Any particular reason for the strict input and output format? \$\endgroup\$ Commented Aug 13, 2019 at 21:26
  • 2
    \$\begingroup\$ @UnrelatedString Hmm, I shall loosen them. \$\endgroup\$ Commented Aug 13, 2019 at 21:27
  • 9
    \$\begingroup\$ 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? \$\endgroup\$
    – Jo King
    Commented Aug 14, 2019 at 3:35
  • 2
    \$\begingroup\$ Can we assume the list is non-empty? \$\endgroup\$
    – Jo King
    Commented Aug 14, 2019 at 4:14
  • 2
    \$\begingroup\$ 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? \$\endgroup\$
    – Jo King
    Commented Aug 15, 2019 at 0:47

43 Answers 43

7
\$\begingroup\$

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!

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

Python 2, 44 bytes

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

Try it online!

\$\endgroup\$
5
\$\begingroup\$

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

\$\endgroup\$
4
\$\begingroup\$

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]
\$\endgroup\$
2
  • \$\begingroup\$ 5 bytes \$\endgroup\$ Commented Aug 13, 2019 at 21:30
  • 1
    \$\begingroup\$ @UnrelatedString all these new-fangled atoms! \$\endgroup\$ Commented Aug 13, 2019 at 21:34
3
\$\begingroup\$

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]
\$\endgroup\$
0
2
\$\begingroup\$

Octave / MATLAB, 25 bytes

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

Try it online!

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

Wolfram Language (Mathematica), 29 bytes

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

Try it online!

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

05AB1E, 5 bytes

¥Ā.¥>

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Minor 5-bytes alternative: ¥Ā could also be üÊ. \$\endgroup\$ Commented Aug 14, 2019 at 6:55
  • 1
    \$\begingroup\$ 4 bytes \$\endgroup\$
    – Grimmy
    Commented Aug 14, 2019 at 12:03
2
\$\begingroup\$

Haskell, 40 bytes

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

Try it online!

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

Perl 6, 21 bytes

{+<<[\+] $,|$_ Zne$_}

Try it online!

Anonymous code block that takes a list and returns a list. This works by comparing whether each pair of adjacent elements are not equal, than taking the cumulative sum of the list.

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

05AB1E, 4 bytes

γdƶ˜

Try it online!

γ       # group adjacent equal digits together
 d      # replace all digits with 1
  ƶ     # multiply each group by its 1-based index
   ˜    # flatten
\$\endgroup\$
2
  • \$\begingroup\$ I keep forgetting that 05ab1e has that ƶ... +1 \$\endgroup\$
    – Mr. Xcoder
    Commented Aug 14, 2019 at 12:05
  • 1
    \$\begingroup\$ Here an alternative 4-byter: ηεγg \$\endgroup\$ Commented Aug 15, 2019 at 16:01
2
\$\begingroup\$

R, 33 bytes

function(x)cumsum(c(1,!!diff(x)))

Try it online!

Uses the same cumulative sum method as Luis Mendo and others.

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

MATL, 8 bytes

Y'wn:wY"

Try it online!

Explanation:

    Y'      % run-length encoding
    w       % swap elements in stack
    n       % number of elements in array / size along each dimension
    :       % range; vector of equally spaced values
    w       % swap elements in stack
    Y"      % replicate elements of array
            % (implicit) convert to string and display
\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6), 30 bytes

Takes input as an array of integers.

a=>a.map(p=n=>i+=p!=(p=n),i=0)

Try it online!

Commented

a =>                // a[] = input array
  a.map(p =         // initialize p to a non-numeric value
  n =>              // for each value n in a[]:
    i +=            //   increment i if:
      p != (p = n), //     p is not equal to n; and update p to n
    i = 0           //   start with i = 0 (chunk counter)
  )                 // end of map()
\$\endgroup\$
2
\$\begingroup\$

Oracle SQL, 121 bytes

select m from t match_recognize(order by i measures match_number()m all rows per match pattern(p+)define p as x=first(x))

Test in SQL*PLus.

SQL> with t(i,x) as (select rownum,value(v) from table(sys.odcinumberlist(4, 4, 4, 7, 7, 9, 9, 9, 9, 2, 2, 2, 4, 4))v)
  2  select m from t match_recognize(order by i measures match_number()m all rows per match pattern(p+)define p as x=first(x))
  3  /

         M
----------
         1
         1
         1
         2
         2
         3
         3
         3
         3
         4
         4
         4
         5
         5

14 rows selected.
\$\endgroup\$
1
\$\begingroup\$

Stax, 10 bytes

▓ª2ªmD?Ä╧╖

Run and debug it

The output uses space as a delimiter. The input follows the precise specifications using commas as separators, and now enclosing braces.

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

C (gcc), 62 61 bytes

This is one of the few entries I've done where a complete program is shorter than a function submission!

On the first pass, I don't care about the previous value, so I get to rely on the fact that argv is a pointer to somewhere and is extremely unlikely to be between [0..9]!

s;main(i,j){for(;~scanf("%d,",&i);j=i)printf("%d ",s+=j!=i);}

Try it online!

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

Haskell, 46 43 bytes

scanl(+)1.map fromEnum.(zipWith(/=)=<<tail)

Try it online!

Anonymous pointfree function that takes a list and returns a list

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

J, 12 bytes

1+/\@,2~:/\]

Try it online!

Similar to Adám's APL answer

      2~:/\]  - pair-wise inequality
1    ,        - prepend 1
    @         - and   
+/\           - find the cumulative sum
\$\endgroup\$
1
\$\begingroup\$

Perl 5, 27 bytes

s/\d/$i+=$&!=$p;$p=$&;$i/ge

Try it online!

The command line option -p makes perl read the input line from STDIN into the "default variable" $_. It then search-replaces all digits in $_ with the counter $i. And $i is increased for each digit which is different than the previous digit, which it also is at the first digit so the counter starts at 1. The previous digit is stored in $p.

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

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

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

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!

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

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(", ")
\$\endgroup\$
1
\$\begingroup\$

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.

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

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

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

x86-16, 12 bytes

Unassembled listing:

        NUM_LOOP: 
AC          LODSB                   ; load [SI] into AL, advance SI 
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

enter image description here

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

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.

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

PHP, 52 bytes

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!

\$\endgroup\$
1
  • \$\begingroup\$ @Night2 good catch! Updated and fixed. Thx! \$\endgroup\$
    – 640KB
    Commented Aug 15, 2019 at 17:42
1
\$\begingroup\$

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!

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

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.

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