24
\$\begingroup\$

Given a list of strictly positive integers, go through each distinct number and replace all occurrences of it with successive indices (zero or one based) of a new series.

Examples

[][]/[]

[42][0]/[1]

[7,7,7][0,1,2]/[1,2,3]

[10,20,30][0,0,0]/[1,1,1]

[5,12,10,12,12,10][0,0,0,1,2,1]/[1,1,1,2,3,2]

[2,7,1,8,2,8,1,8,2,8][0,0,0,0,1,1,1,2,2,3]/[1,1,1,1,2,2,2,3,3,4]

[3,1,4,1,5,9,2,6,5,3,5,9][0,0,0,1,0,0,0,0,1,1,2,1]/[1,1,1,2,1,1,1,1,2,2,3,2]

\$\endgroup\$
  • 2
    \$\begingroup\$ So basically the number of times it has appeared the sequence so far? \$\endgroup\$ – Jo King Jan 8 at 9:41
  • 1
    \$\begingroup\$ @JoKing Yes, that's another way to state it, but "so far" implies zero-based, and "until and including this" implies one-based. I wanted to keep the choice. \$\endgroup\$ – Adám Jan 8 at 9:42

38 Answers 38

23
\$\begingroup\$

JavaScript (ES6), 26 bytes

1-indexed.

a=>a.map(o=x=>o[x]=-~o[x])

Try it online!

Commented

a =>                // a[] = input array
  a.map(o =         // assign the callback function of map() to the variable o, so that
                    // we have an object that can be used to store the counters
    x =>            // for each value x in a[]:
      o[x] = -~o[x] //   increment o[x] and yield the result
                    //   the '-~' syntax allows to go from undefined to 1
  )                 // end of map()
\$\endgroup\$
  • 1
    \$\begingroup\$ I have no idea how that works, but it sure looks elegant. \$\endgroup\$ – Adám Jan 8 at 9:33
  • \$\begingroup\$ I've not seen -~ before - that is an absolute gem. \$\endgroup\$ – DaveMongoose Jan 8 at 16:12
  • \$\begingroup\$ Alternatively, it's possible to use a to store the values, but it's required to -/~ the index so no byte is saved. \$\endgroup\$ – user202729 Jan 9 at 4:25
  • \$\begingroup\$ @DaveMongoose Tips for golfing in JavaScript \$\endgroup\$ – user202729 Jan 9 at 4:25
  • 1
    \$\begingroup\$ @DaveMongoose -~ is actually a commonly used alternative to +1 (since it has different precedence) in many languages \$\endgroup\$ – ASCII-only Jan 9 at 8:45
9
+200
\$\begingroup\$

R, 27 bytes

function(x)ave(x,x,FUN=seq)

Try it online!

Explanation :

ave(x,x,FUN=seq) splits vector x into sub-vectors using values of x as grouping keys. Then seq function is called for each group and each result is re-arranged back in the original group position.

Better see an example :

x <- c(5,7,5,5,7,6)
ave(x, x, FUN=seq) # returns 1,1,2,3,2


 ┌───┬───┬───┬───┬───┐
 │ 5 │ 7 │ 5 │ 5 │ 7 │
 └───┴───┴───┴───┴───┘            
   |   |   |    |  |     
   ▼   |   ▼    ▼  |
 GROUP A : seq(c(5,5,5)) = c(1,2,3)
   |   |   |    |  |     
   ▼   |   ▼    ▼  |
 ┌───┐ | ┌───┬───┐ |
 │ 1 │ | │ 2 │ 3 │ |
 └───┘ | └───┴───┘ |
       ▼           ▼
 GROUP B : seq(c(7,7)) = c(1,2)
       |           |
       ▼           ▼
     ┌───┐       ┌───┐
     │ 1 │       │ 2 │
     └───┘       └───┘ 

   |   |   |   |   |
   ▼   ▼   ▼   ▼   ▼ 
 ┌───┬───┬───┬───┬───┐
 │ 1 │ 1 │ 2 │ 3 │ 2 │
 └───┴───┴───┴───┴───┘  

Note :

seq(y) function returns a sequence 1:length(y) in case y has length(y) > 1, but returns a sequence from 1:y[1] if y contains only one element.
This is fortunately not a problem because in that case R - complaining with a lot of warnings - selects only the first value which is incidentally what we want :)

\$\endgroup\$
  • 1
    \$\begingroup\$ Brilliant! I'll add a bounty for this. Never seen ave before. \$\endgroup\$ – Giuseppe Jan 13 at 19:55
  • \$\begingroup\$ I'm honored, thanks a lot ! :) \$\endgroup\$ – digEmAll Jan 14 at 6:36
6
\$\begingroup\$

MATL, 4 bytes

&=Rs

This solution is 1-based

Try it out at MATL Online!

Explanation

Uses [1,2,3,2] as an example

    # Implicitly grab the input array of length N
    #
    #   [1,2,3,2]
    #
&=  # Create an N x N boolean matrix by performing an element-wise comparison
    # between the original array and its transpose:
    #
    #     1 2 3 2
    #     -------
    # 1 | 1 0 0 0
    # 2 | 0 1 0 1
    # 3 | 0 0 1 0
    # 2 | 0 1 0 1
    #
R   # Take the upper-triangular portion of this matrix (sets below-diagonal to 0)
    #
    #   [1 0 0 0
    #    0 1 0 1
    #    0 0 1 0
    #    0 0 0 1]
    #
s   # Compute the sum down the columns
    #
    #   [1,1,1,2]
    #
    # Implicitly display the result
\$\endgroup\$
  • 1
    \$\begingroup\$ ah, I knew there was an old problem that made me think of something similar, it's Unique is Cheap, and the MATL solution there is one character different! \$\endgroup\$ – Giuseppe Jan 8 at 15:33
5
\$\begingroup\$

APL (Dyalog Unicode), 7 bytes

Many, many thanks to H.PWiz, Adám and dzaima for all their help in debugging and correcting this.

+/¨⊢=,\

Try it online!

Explanation

The 10-byte non-tacit version will be easier to explain first

{+/¨⍵=,\⍵}

{         } A user-defined function, a dfn
      ,\⍵  The list of prefixes of our input list ⍵
           (⍵ more generally means the right argument of a dfn)
           \ is 'scan' which both gives us our prefixes 
           and applies ,/ over each prefix, which keeps each prefix as-is
    ⍵=     Checks each element of ⍵ against its corresponding prefix
           This checks each prefix for occurrences of the last element of that prefix
           This gives us several lists of 0s and 1s
 +/¨       This sums over each list of 0s and 1s to give us the enumeration we are looking for

The tacit version does three things

  • First, it removes the instance of used in ,\⍵ as ,\ on the right by itself can implicitly figure out that it's supposed to operate on the right argument.
  • Second, for ⍵=, we replace the with , which stands for right argument
  • Third, now that we have no explicit arguments (in this case, ), we can remove the braces {} as tacit functions do not use them
\$\endgroup\$
5
\$\begingroup\$

J, 7 bytes

1#.]=]\

Try it online!

1-indexed.

Explanation:

]\ all the prefixes (filled with zeros, but there won't be any 0s in the input):
   ]\ 5 12 10 12 12 10
5  0  0  0  0  0
5 12  0  0  0  0
5 12 10  0  0  0
5 12 10 12  0  0
5 12 10 12 12  0
5 12 10 12 12 10

]= is each number from the input equal to the prefix:
   (]=]\) 5 12 10 12 12 10
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
0 1 0 1 0 0
0 1 0 1 1 0
0 0 1 0 0 1

1#. sum each row:
   (1#.]=]\) 5 12 10 12 12 10
1 1 1 2 3 2

K (oK), 11 10 bytes

-1 byte thanks to ngn!

{+/'x=,\x}

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Heh, you're happy that I made the data strictly positive… \$\endgroup\$ – Adám Jan 8 at 15:06
  • \$\begingroup\$ @Adám Yes, otherwise I'd need to box the prefixes :) \$\endgroup\$ – Galen Ivanov Jan 8 at 15:16
  • 1
    \$\begingroup\$ in k: =' -> = \$\endgroup\$ – ngn Jan 31 at 13:17
4
\$\begingroup\$

Python 2, 48 bytes

lambda a:[a[:i].count(v)for i,v in enumerate(a)]

Try it online!

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

AWK, 14

  • 1 byte saved thanks to @NahuelFouilleul
{print++a[$1]}

Try it online!

The above does one-based indexing. If you prefer zero-based indexing, its an extra byte:

{print a[$1]++}

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ note that second can save one byte {print++a[$1]} without space seems to be working \$\endgroup\$ – Nahuel Fouilleul Jan 11 at 8:20
  • \$\begingroup\$ @NahuelFouilleul Thanks! \$\endgroup\$ – Digital Trauma Jan 11 at 18:48
3
\$\begingroup\$

05AB1E, 4 bytes

ηε¤¢

Try it online! or as a Test Suite

Explanation

ηε     # apply to each prefix of the input list
  ¤¢   # count occurrences of the last element
\$\endgroup\$
3
\$\begingroup\$

C# (Visual C# Interactive Compiler), 44 bytes

x=>x.Select((y,i)=>x.Take(i).Count(z=>z==y))

Try it online!

\$\endgroup\$
  • \$\begingroup\$ 22 bytes \$\endgroup\$ – LiefdeWen Jan 8 at 13:17
  • \$\begingroup\$ You have the inversed of the challenge right now.. [7,7,7] should output [0,1,2], and not [0,0,0]. \$\endgroup\$ – Kevin Cruijssen Jan 8 at 15:42
  • 1
    \$\begingroup\$ @KevinCruijssen - Thanks :) Looks like I misread things, it should be fixed now. \$\endgroup\$ – dana Jan 8 at 15:59
2
\$\begingroup\$

Python 2, 47 43 bytes

f=lambda a:a and f(a[:-1])+[a.count(a[-1])]

Try it online!

A recursive 'one-based' solution.

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

Jelly, 4 bytes

ċṪ$Ƥ

Try it online!

For each prefix of the input list, it counts the number of occurrences of its last element in itself.

\$\endgroup\$
  • \$\begingroup\$ Alternatively the old-school ;\ċ" is also 4. \$\endgroup\$ – Jonathan Allan Jan 8 at 14:39
2
\$\begingroup\$

R, 41 bytes

function(x)diag(diffinv(outer(x,x,"==")))

Try it online!

Oddly, returning a zero-based index is shorter in R.

\$\endgroup\$
  • \$\begingroup\$ Once again Giuseppe, your superior knowledge of R has beaten me. I had a decently ingenious method at 60 bytes, but alas, it wasn't enough! \$\endgroup\$ – Sumner18 Jan 8 at 17:21
  • \$\begingroup\$ @Sumner18 post it anyway! I always learn a lot from other peoples' approaches, and getting feedback is the fastest way to learn! \$\endgroup\$ – Giuseppe Jan 8 at 17:23
  • \$\begingroup\$ thanks for the encouragement! I've posted mine now and am always open to suggestions for improvement! \$\endgroup\$ – Sumner18 Jan 8 at 17:45
2
\$\begingroup\$

Ruby, 35 bytes

->a{f=Hash.new 0;a.map{|v|f[v]+=1}}

It's pretty mundane, unfortunately - build a hash that stores the total for each entry encountered so far.

Some other, fun options that unfortunately weren't quite short enough:

->a{a.dup.map{a.count a.pop}.reverse}   # 37
->a{i=-1;a.map{|v|a[0..i+=1].count v}}  # 38
\$\endgroup\$
2
\$\begingroup\$

R, 62 43 bytes

x=z=scan();for(i in x)z[y]=1:sum(y<-x==i);z

-19 bytes thanks to Giuseppe, by removing which, and table, and only slight changes to the implementation

Original

x=z=scan();for(i in names(r<-table(x)))z[which(x==i)]=1:r[i];z

I can't compete with Giuseppe's knowledge, so my submission is somewhat longer than his, but using my basic knowledge, I felt that this solution was rather ingenious.

r<-table(x) counts the number of times each number appears and stores it in r, for future reference

names() gets the values of each unique entry in the table, and we iterate over these names with a for loop.

The remaining portion checks which entries are equal to the iterations and stores a sequence of values (from 1 to the number of entries of the iteration)

Try it online!

\$\endgroup\$
  • \$\begingroup\$ you can remove the which() to save 7 bytes. \$\endgroup\$ – Giuseppe Jan 8 at 18:09
  • \$\begingroup\$ Your use of 1:r[i] gave me the idea to just remove table() entirely: x=z=scan();for(i in x)z[y]=1:sum(y<-x==i);z is 43 bytes! This is a nice approach! \$\endgroup\$ – Giuseppe Jan 8 at 18:16
  • \$\begingroup\$ Looks like neither of us can compete with digEmAll's R knowledge! \$\endgroup\$ – Giuseppe Jan 14 at 23:25
  • \$\begingroup\$ I saw that and was absolutely flabbergasted! \$\endgroup\$ – Sumner18 Jan 15 at 13:51
2
\$\begingroup\$

Haskell, 44 bytes

([]#)
x#(y:z)=sum[1|a<-x,a==y]:(y:x)#z
_#e=e

Try it online!

Explanation

Traverses the list from left to right keeping the list x of visited elements, initially []:

For every encounter of a y count all equal elements in the list x.

\$\endgroup\$
  • 1
    \$\begingroup\$ A bit longer but maybe nevertheless interesting: (#(0*));(x:r)#g=g x:r# \y->0^abs(y-x)+g y;e#g=e Try it online! \$\endgroup\$ – Laikoni Jan 10 at 18:57
  • \$\begingroup\$ @Laikoni: How did you even come up with that, you should totally post it! \$\endgroup\$ – ბიმო Jan 10 at 19:15
  • 1
    \$\begingroup\$ Done: codegolf.stackexchange.com/a/178629/56433 \$\endgroup\$ – Laikoni Jan 10 at 19:50
2
\$\begingroup\$

Perl 6, 15 bytes

*>>.&{%.{$_}++}

Try it online!

You can move the ++ to before the % for a one based index.

Explanation:

*>>.&{        }  # Map the input to
      %          # An anonymous hash
       .{$_}     # The current element indexed
            ++   # Incremented
\$\endgroup\$
2
\$\begingroup\$

Haskell, 47 46 bytes

(#(*0))
(x:r)#g=g x:r# \y->0^(y-x)^2+g y
e#g=e

Try it online!

A different approach than BMO's answer which turned out a bit longer. (And kindly borrows their nice test suit.)

The idea is to iterate over the input list and keep track of the number of times each element has occurred by updating a function g. Ungolfed:

f (const 0)
f g (x:r) = g x : f (\ y -> if x==y then 1 + g y else g y) r
f g []    = []

Two interesting golfing opportunities arose. First for the initial value of g, a constant function which disregards its argument and returns 0:

const 0  -- the idiomatic way
(\_->0)  -- can be shorter if parenthesis are not needed
min 0    -- only works as inputs are guaranteed to be non-negative
(0*)     -- obvious in hindsight but took me a while to think of

And secondly an expression over variables x and y which yields 1 if x equals y and 0 otherwise:

if x==y then 1else 0  -- yes you don't need a space after the 1
fromEnum$x==y         -- works because Bool is an instance of Enum
sum[1|x==y]           -- uses that the sum of an empty list is zero
0^abs(x-y)            -- uses that 0^0=1 and 0^x=0 for any positive x
0^(x-y)^2             -- Thanks to  Christian Sievers!

There still might be shorter ways. Anyone got an idea?

\$\endgroup\$
  • 1
    \$\begingroup\$ You can use 0^(x-y)^2. \$\endgroup\$ – Christian Sievers Jan 10 at 23:02
1
\$\begingroup\$

Java (JDK), 76 bytes

a->{for(int l=a.length,i,c;l-->0;a[l]=c)for(c=i=0;i<l;)c+=a[l]==a[i++]?1:0;}

Try it online!

Credits

\$\endgroup\$
  • 1
    \$\begingroup\$ -2 bytes by changing for(c=0,i=l;i-->0;)c+=a[l]==a[i]?1:0; to for(c=i=0;i<l;)c+=a[l]==a[i++]?1:0;. \$\endgroup\$ – Kevin Cruijssen Jan 8 at 15:53
1
\$\begingroup\$

Ruby, 34 bytes

->a{r=[];a.map{|x|(r<<x).count x}}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ I can't believe I tried ->a{i=-1;a.map{|v|a[0..i+=1].count v}} and didn't think of just building a new array, lol. Nice work. \$\endgroup\$ – DaveMongoose Jan 9 at 10:23
1
\$\begingroup\$

bash, 37 24 bytes

f()(for x;{ r+=$[a[x]++]\ ;};echo $r)

TIO

if valid, there is also this variation, as suggested by DigitalTrauma

for x;{ echo $[a[x]++];}

TIO

\$\endgroup\$
  • 1
    \$\begingroup\$ Pass the list as command line args - tio.run/##S0oszvj/Py2/SKHCuporNTkjX0ElOjG6IlZbO5ar9v///8b/… - only 24 bytes. \$\endgroup\$ – Digital Trauma Jan 8 at 20:17
  • \$\begingroup\$ @DigitalTrauma, thanks however i don't know if it broke the rules. also as it was asked to replace list and maybe should be something like tio.run/… \$\endgroup\$ – Nahuel Fouilleul Jan 9 at 8:28
  • 2
    \$\begingroup\$ @NahuelFouilleul It's fine, full programs are allowed too, and that's a valid method of inputting/outputting a list (IMO) \$\endgroup\$ – ASCII-only Jan 9 at 8:44
1
\$\begingroup\$

Perl 5, 11 bytes

$_=$h{$_}++

TIO

explanations following comment

  • $_ perl's special variable containing current line when looping over input (-p or -n switches)
  • $h{$_}++ autovivifies the map %h and creates an entry with key $_ and increments and gives the value before increment
  • the special variable is printed because of -p switch, -l switch removes end of line on input and adds end of line on output
\$\endgroup\$
  • \$\begingroup\$ That looks amazing. Care to explain? \$\endgroup\$ – Adám Jan 11 at 10:42
  • \$\begingroup\$ @Adám, thank you for your feedback, sure, done \$\endgroup\$ – Nahuel Fouilleul Jan 11 at 10:47
1
\$\begingroup\$

Pari/GP, 32 bytes

a->p=0;[polcoeff(p+=x^t,t)|t<-a]

The \$k\$-th element in the answer is the coefficient of the \$x^{a_k}\$ term in the polynomial \$\sum_{i=1}^kx^{a_i}\$.

Try it online!

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

Wolfram Language (Mathematica), 33 bytes

Accumulate@#~Coefficient~#&[x^#]&

The \$k\$-th element in the answer is the coefficient of the \$x^{a_k}\$ term in the polynomial \$\sum_{i=1}^kx^{a_i}\$.

Try it online!

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

Attache, 23 bytes

{`~&>Zip[_,_[0:#_::0]]}

Try it online!

Explanation

{`~&>Zip[_,_[0:#_::0]]}
{                     }    _: input (e.g., [5, 12, 10, 12, 12, 10])
             0:#_          range from 0 to length of input (inclusive)
                           e.g., [0, 1, 2, 3, 4, 5, 6]
                 ::0       descending range down to 0 for each element
                           e.g., [[0], [1, 0], [2, 1, 0], [3, 2, 1, 0], [4, 3, 2, 1, 0], [5, 4, 3, 2, 1, 0], [6, 5, 4, 3, 2, 1, 0]]
           _[       ]      get input elements at those indices
                           e.g., [[5], [12, 5], [10, 12, 5], [12, 10, 12, 5], [12, 12, 10, 12, 5], [10, 12, 12, 10, 12, 5], [nil, 10, 12, 12, 10, 12, 5]]
     Zip[_,          ]     concatenate each value with this array
                           e.g., [[5, [5]], [12, [12, 5]], [10, [10, 12, 5]], [12, [12, 10, 12, 5]], [12, [12, 12, 10, 12, 5]], [10, [10, 12, 12, 10, 12, 5]]]
   &>                      using each sub-array spread as arguments...
 `~                            count frequency
                               e.g. [12, [12, 10, 12, 5]] = 12 ~ [12, 10, 12, 5] = 2
\$\endgroup\$
1
\$\begingroup\$

C (gcc), 65 62 bytes

c,d;f(a,b)int*a;{for(;c=d=b--;a[b]=d)for(;c--;d-=a[c]!=a[b]);}

Try it online!

-2 bytes thanks to ASCII-only


This felt too straightforward, but I couldn't seem to get any shorter with a different approach.

\$\endgroup\$
  • \$\begingroup\$ 63 \$\endgroup\$ – ASCII-only Jan 14 at 4:59
  • \$\begingroup\$ @ASCII-only is this a valid answer? No header included, no declarations, it's a snippet plus many warnings although it outputs. \$\endgroup\$ – AZTECCO Jan 14 at 15:16
  • \$\begingroup\$ @AZTECCO warnings are fine (stderr is ignored), as long as it does what it should it's acceptable. note that this is a function declaration, plus some variable declarations - you can put it anywhere as a top level expression and it will compile fine. a lot of c answers (and those in languages with less strict syntax) do generally have quite a few warnings because of bytesaves that aren't good code style \$\endgroup\$ – ASCII-only Jan 14 at 23:33
  • \$\begingroup\$ Ok I can understand, but there's still something not right to me. If we want to test with a different set(in size) we have to modify the code, even in the print loop, plus the input should be just the set, not its size."Given a list of strictly positive integers..." so I think input should be just the list. \$\endgroup\$ – AZTECCO Jan 15 at 15:37
  • \$\begingroup\$ @AZTECCO not sure if this discussion should belong in this answer's comments, but you might want to take a look at meta - specifically on I/O and answer formats. \$\endgroup\$ – attinat Jan 15 at 22:58
0
\$\begingroup\$

Retina 0.8.2, 30 bytes

\b(\d+)\b(?<=(\b\1\b.*?)+)
$#2

Try it online! Link includes test cases. 1-indexed. Explanation: The first part of the regex matches each integer in the list in turn. The lookbehind's group matches each occurrence of that integer on that line up to and including the current integer. The integer is then substituted with the number of matches.

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

Batch, 61 bytes

@setlocal
@for %%n in (%*)do @set/ac=c%%n+=1&call echo %%c%%

1-indexed. Because variable substitution happens before parsing, the set/a command ends up incrementing the variable name given by concatenating the letter c with the integer from the list (numeric variables default to zero in Batch). The result is then copied to another integer for ease of output (more precisely, it saves a byte).

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

Tcl, 48 bytes

proc C L {lmap n $L {dict g [dict inc D $n] $n}}

Try it online!

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

Japt, 8 bytes

£¯YÄ è¶X

Try it here

£¯YÄ è¶X
             :Implicit input of array U
£            :Map each X at 0-based index Y
 ¯           :  Slice U to index
  YÄ         :    Y+1
     è       :  Count the elements
      ¶X     :    Equal to X
\$\endgroup\$
0
\$\begingroup\$

Haxe, 58 bytes

l->{var x=[0=>0];l.map(e->++x[(x[e]==null?x[e]=0:0)+e]);};

(Requires arrow functions, so 4.0+)

var x=[0=>0] declares a new IntMap, with 0 as its only key (since the question say inputs are strictly positive). Unfortunately most targets throw when adding null to a number, hence the explicit check to make sure each key is in the map before incrementing.

Also a cheeky rip off based on the JS answer:

Haxe (JS target), 41 bytes

l->{var x=[0=>0];l.map(e->x[e]=-~x[e]);};

Try both online

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