# Find the k-th order summary of a number

### Background

The summary of a non-negative integer $$\n\$$ is the concatenation of all digits that appear in $$\n\$$ in increasing order, with each digit being preceded by the number of times it appears in $$\n\$$.

Some Examples:

n            -> summary(n)
1221         -> 2122 (2 ones, 2 twos)
1212         -> 2122 (2 ones, 2 twos)
912334       -> 1112231419 (1 one, 1 two, 2 threes, 1 four, 1 nine)
888888888888 -> 128 (12 eights)


The $$\k\$$-th order summary is result repeatedly applying the summary operation on a number $$\k\$$ times (i.e. $$\2\$$nd order summary of $$\n\$$ is summary(summary(n)), $$\3\$$rd order summary of $$\n\$$ is summary(summary(summary(n))), etc.).

Note: The $$\0\$$th order summary of a number is itself

Write a program/function that outputs the $$\k\$$-th order summary of a non-negative integer $$\n\$$.

### Scoring

This is so shortest bytes wins

### Sample Testcases

n, k             -> answer
0, 1             -> 10
1, 10            -> 41122314
1221, 0          -> 1221
1221, 1          -> 2122
1212, 1          -> 2122
912334, 1        -> 1112231419
912334, 3        -> 412213141519
21322314, 1      -> 21322314
21322314, 123    -> 21322314
21322314, 2222   -> 21322314
888888888888, 1  -> 128
888888888888, 2  -> 111218
1888888888888, 1 -> 11128


Inspired by A005151

• Similar question: codegolf.stackexchange.com/questions/70837/say-what-you-see Nov 6, 2021 at 4:12
• Please add 1888888888888, 1 as a test case (outputs 11128) as my program failed for it (as will any method that concatenates by converting from base 10) Nov 6, 2021 at 4:25
• Suggested test case: 21322314, anything -> 21322314 (a stable input). Nov 6, 2021 at 15:02
• Another interesting input is 9009 with a run of 21 distinct values before it starts repeating. Nov 6, 2021 at 16:48
• @KevinCruijssen, digit-lists are allowed. Nov 8, 2021 at 14:08

# Vyxal, 7 bytes

(søeRf∑


Try it Online!

(       # k times...
s      # Sort
øe    # Run length encode
R   # Reverse each
f  # Flatten
∑ # Sum


# Jelly, 8 bytes

ṢŒrUFVµ¡


Try it online!

Credit to hyper-neutrino for the µ trick, and for telling me I was wrong :P

Full program. Takes n then k on the command line

## How it works

ṢŒrUFVµ¡ - Main link. Takes n on the left, k on the right
Ṣ        -   Sort the digits of n
Œr      -   Run length encode
UF    -   Reverse each and flatten
V   -   Eval as a single number
¡ - Iterate f(n) k times


# Proton, 67 bytes

f=(n,k)=>k?f("".join(str(n.count(x))+x for x:sorted(set(n))),k-1):n


Try it online!

# Python 3, 78 bytes

f=lambda n,k:k and f("".join(str(n.count(x))+x for x in sorted({*n})),k-1)or n


Try it online!

-7 bytes thanks to Mukundan314

• -7 byte for the python solution Nov 6, 2021 at 5:01
• @Mukundan314 Ah, nice! Thanks Nov 6, 2021 at 5:03
• Do you really need the str in the Proton function? Seems to work fine without it
– ovs
Nov 6, 2021 at 11:02

# Wolfram Language (Mathematica), 55 bytes

ToString@#2<>#&@@@Sort@Tally@Characters@#<>""&~Nest~##&


Try it online!

Input ["n", k].

# JavaScript (ES6), 73 bytes

Expects (k)(n), where n is given as a string. Returns a string.

k=>g=n=>k--?g([...n].sort().join.replace(/(.)\1*/g,s=>s.length+s)):n


Try it online!

### Commented

k =>                 // outer function taking k
g = n =>             // inner recursive function taking n as a string
k-- ?              // decrement k; if it was not 0:
g(               //   do a recursive call:
[...n]         //     split n into a list of digits
.sort()        //     sort this list in ascending order
.join        //     join the digits again
.replace(      //     replace ...
/(.)\1*/g,   //       ... runs of consecutive identical digits ...
s =>         //       ... with:
s.length + //         the number of occurrences
s       //         followed by the digit
)              //     end of replace()
)                //   end of recursive call
:                  // else:
n                //   we're done: return n

• Love it. I've never considered using  join  in place of join('') before. I'm going to have to start doing that in my own code. May 12 at 22:07

# Husk, 15 bytes

d!¡oṁoṁd§eL←kDd


Try it online!

Order is taken 1-indexed.

## Explanation

d!¡oṁoṁd§eL←kDd
d digits
¡             apply the following repeatedly and collect results:
kD   group digits into lists
ṁ            map each list and join:
§e        two element list with:
L        length
←       first element
oṁd          convert each to individual digits
!              index into that using order
d               convert back to integer.


• You program fails for n = 1888888888888, k = 1 (2 if 1 indexed) Nov 6, 2021 at 4:47
• fixed it. my bad. Nov 6, 2021 at 5:10

# R, 94 bytes

Or R>=4.1, 87 bytes by replacing the word function with \.

function(n,k){while(k<-k-1)n=Reduce(paste0,c(rbind(r<-table(el(strsplit(n,""))),names(r))));n}


Try it online!

Expects n as a string and k 1-indexed. Outputs a string.

Creates table of digits and interleaves resulting values (counts) with their names (digits) using this trick from SO.

The rest is just string manipulation which is quite cumbersome in R.

Recursive approach results in the same byte-count:

### R, 94 bytes

Or R>=4.1, 87 bytes by replacing the word function with \.

f=function(n,k)"if"(k,f(Reduce(paste0,c(rbind(r<-table(el(strsplit(n,""))),names(r)))),k-1),n)


Try it online!

Here k is 0-indexed.

# Retina, 25 bytes

1A
"$+"{O. (.)\1*$.&$1  Try it online! Takes input in the order k, n. No test suite due to the program's use of history. Explanation: 1A  Delete k from the input. "$+"{


Retrieve k from the history and repeat the rest of the program k times.

O.


Sort the digits in ascending order.

(.)\1*
$.&$1


Precede each distinct digit by its count.

The best I could do in # Retina 0.8.2 is 45 bytes:

,\d+
$*_ {O.(?=.*_) (\d)\1*(?=.*_)$.&$1 _$



Try it online! Link includes test cases. Explanation:

,\d+
$*_  Convert k to unary, using _ because they sort after digits, saving a byte. {  Repeat (until k is zero, at which point the loop converges). O.(?=.*_)  If k is not zero, sort the digits in ascending order. (If k>1, k is also sorted, but it always sorts after digits.) (\d)\1*(?=.*_)$.&$1  If k is not zero, precede each distinct digit by its count. _$



If k is not zero, then decrement k.

# Ruby, 74 66 bytes

->n,k{k.times{a=n.chars
n=(a|a).sort.map{|d|[a.count(d),d]}*''}
n}


Try it online!

• Thanks to @ovs for actually golfing thus saving 8 Bytes!
.uniq => a|a and join by *'' instead of appending values

• takes n as string, k as int

• reconstruct n by appending each (count,digit) k times

• uses a=n.split n='' instead of a,n=n.chars,'' which is the same byte count

• (a|a) is a byte shorter than a.uniq and building n by joining a nested array saves a few more bytes: Try it online!
– ovs
Nov 6, 2021 at 16:38

# Raku, 44 bytes

{($^a,{[R~] .comb.Bag{~9...0}:kv}...*)[$^k]}


Try it online!

• ($^a, { ... } ... *)[$^k] selects the $^k-th element of the infinite sequence starting with $^a, where $^a and $^k are the first and second arguments to the function, respectively. The bracketed expression is an anonymous function that generates each summary number from the previous one, passed as $_. • .comb splits the number $_ into its (string) digits.
• .Bag assembles those digits into a Bag--a set with multiplicity.
• {~9...0} slices into that bag with the digits from 9 to 0. The leading ~ stringifies the 9 and gives us a sequence of strings, not numbers. (The Bag knows the difference.)
• The :kv adverb on the slicing subscript {...} does two things: it returns a flat list of key-value pairs (ie, each digit along with its multiplicity, in order from 9 to 0), and it omits elements from the slice which don't exist in the Bag.
• [R~] reduces that list with the operator R~, which is the Reversed string concatenation operator ~. That gives us the required summary of the previous number in the series.

# 05AB1E, 98 7 bytes

F{Åγøí˜J


-1 byte thanks to a tip of @ovs

Inputs in the order $$\k,n\$$. Outputs as a digit-list (unless $$\k=0\$$, in which case it outputs $$\n\$$ as is - although we could take input $$\n\$$ as digit-list as well to be consistent).

Explanation:

F        # Loop the first (implicit) input amount of times:
{       #  Sort the digits of the current number
#  (which is the second implicit input-integer in the first iteration)
Åγ     #  Pop and run-length encode, pushing a list of digits and a list of lengths
#  separated to the stack
ø    #  Create pairs of these two lists
í   #  Reverse each pair
S  #  Convert the list of integer-pairs to a flattened list of digits
# (after which the result is output implicitly)

• I think Åγ should be able to save a byte here
– ovs
Nov 8, 2021 at 9:32
• @ovs EDIT: I'm an idiot.. it pushes both lists separated :/ Thanks for -1 Nov 8, 2021 at 10:09

# PowerShell Core, 73 bytes

param($n,$k)for(;$k--){$n=-join("$n"|% t*y|group|%{$_.Count,$_.Name})}$n


Try it online!

Same byte count using $ofs: Try it online! Takes two integer parameters and returns a string or an integer # Charcoal, 18 bytes ＦＮ≔⭆Φ⭆χκ№ηκ⁺№ηκκηη  Try it online! Link is to verbose version of code. Takes input in the order k, n. Explanation: ＦＮ  Input k and loop that many times. ≔⭆Φ⭆χκ№ηκ⁺№ηκκη  Filter the characters 0-9 that are present in n, prefixing them with their count and joining the result. η  Output the final value of n. # Excel (Insider Beta), 108 bytes =LAMBDA(q,k,IF(k,LET(a,f(q,k-1),x,SEQUENCE(10)-1,y,LEN(a)-LEN(SUBSTITUTE(a,x,"")),CONCAT(FILTER(y&x,y))),q))  Link to Spreadsheet Set name f equal to the above formula. Spreadsheet requires Insider Beta version of Excel to work currently because of LAMBDA. ### Explanation =LAMBDA(q,k, IF(k, # if k <> 0 then LET(a,f(q,k-1), # a = f(q,k-1) x,SEQUENCE(10)-1, # x = [0..9] y,LEN(a)-LEN(SUBSTITUTE(a,x,"")), # y = count of each x in a CONCAT(FILTER(y&x,y))) # concatenate y&x if y > 0 ,q)) # else q  # Core Maude, 354 bytes mod R is pr LIST{Nat}+ CONVERSION . ops k s : Nat Nat ~> Nat . op f : Nat ~> String . var N K : Nat . var X Y :[Nat]. eq k(N,0)= N . eq k(N,s K)= k(rat(f(s(N,0 0 0 0 0 0 0 0 0 0)),10),K). eq s(0,X)= X . ceq s(N,X K Y)= s(N quo 10,X(s K)Y)if size(X)= N rem 10[owise]. eq f(nil)= "" . eq f(X 0)= f(X). eq f(X s N)= f(X)+ string(10 * s N + size(X),10). endm  The result is obtained by reducing the k function with $$\n\$$ and $$\k\$$. ### Example Session Maude> red k(1, 10) . --- Expected: 41122314 result NzNat: 41122314 Maude> red k(1221, 0) . --- Expected: 1221 result NzNat: 1221 Maude> red k(1221, 1) . --- Expected: 2122 result NzNat: 2122 Maude> red k(1212, 1) . --- Expected: 2122 result NzNat: 2122 Maude> red k(912334, 1) . --- Expected: 1112231419 result NzNat: 1112231419 Maude> red k(912334, 3) . --- Expected: 412213141519 result NzNat: 412213141519 Maude> red k(21322314, 1) . --- Expected: 21322314 result NzNat: 21322314 Maude> red k(21322314, 123) . --- Expected: 21322314 result NzNat: 21322314 Maude> red k(21322314, 2222) . --- Expected: 21322314 result NzNat: 21322314 Maude> red k(888888888888, 1) . --- Expected: 128 result NzNat: 128 Maude> red k(888888888888, 2) . --- Expected: 111218 result NzNat: 111218 Maude> red k(1888888888888, 1) . --- Expected: 11128 result NzNat: 11128  ### Ungolfed mod R is pr LIST{Nat} + CONVERSION . ops k s : Nat Nat ~> Nat . op f : Nat ~> String . var N K : Nat . var X Y : [Nat] . eq k(N, 0) = N . eq k(N, s K) = k(rat(f(s(N, 0 0 0 0 0 0 0 0 0 0)), 10), K) . eq s(0, X) = X . ceq s(N, X K Y) = s(N quo 10, X (s K) Y) if size(X) = N rem 10 [owise] . eq f(nil) = "" . eq f(X 0) = f(X) . eq f(X s N) = f(X) + string(10 * s N + size(X), 10) . endm  Maude doesn't have logarithms for integers, only for floating-point numbers, so the only good way I could find to "concatenate" integers is to convert them to strings, concatenate, and convert back. # Core Maude + Cheating, 331 bytes mod R is pr CONVERSION . ops k s : Nat Nat -> Nat . op f : Nat Nat -> String . var N K S : Nat . eq k(N,0)= N . eq k(N,s K)= k(rat(f(0,s(N,0)),10),K). eq s(0,S)= S . eq s(N,S)= s(N quo 10,S + 512 ^(N rem 10))[owise]. eq f(10,S)= "" . eq f(N,S)= if(S & 511)> 0 then string(10 *(S & 511)+ N,10)else "" fi + f(s N,S >> 9)[owise]. endm  ### Ungolfed mod R is pr CONVERSION . ops k s : Nat Nat -> Nat . op f : Nat Nat -> String . var N K S : Nat . eq k(N, 0) = N . eq k(N, s K) = k(rat(f(0, s(N, 0)), 10), K) . eq s(0, S) = S . eq s(N, S) = s(N quo 10, S + 512 ^ (N rem 10)) [owise] . eq f(10, S) = "" . eq f(N, S) = if (S & 511) > 0 then string(10 * (S & 511) + N, 10) else "" fi + f(s N, S >> 9) [owise] . endm  If we make the small assumption that no digit occurs more than 511 times, we can avoid having to import LIST and keep the intermediate summary packed in an integer with 9 bits per digit tracked. The bit size is sort of arbitrary since Maude has unbounded integers, so I picked 9 bits to avoid paying 4 extra bytes for 10 and 1024. # C (gcc), 112 $$\\cdots\$$ 123 125 bytes f(n,k){int c={!n},t=n,i=-1,l;for(;t;t/=10)++c[t%10];for(;i++<9;t=l?i+l*10+t*exp10(l=log10(l)+2):t)l=c[i];n=k?f(t,k-1):n;}  Try it online! Saved a 2 bytes thanks to ceilingcat!!! Added 21 bytes to fix an error kindly pointed out by Arnauld. Saved 8 bytes thanks to att!!! Added 2 bytes to handle $$\n=0\$$. • Hello! I posted mine instead of suggesting because I think it's slightly different approach, Idk if I have to apologize but I feel so because usually I suggest, but sometimes I'm greedy and don't want to give away my codes :-p Nov 7, 2021 at 10:33 • @AZTECCO Yeah, I've noticed you started doing that now. If you post a C answer before I do I either help you or refrain from posting in that challenge. Nov 7, 2021 at 12:44 • Wait.. I coded it completely on my own without see yours before, that's the main reason I choose to post separately.. If you feel I compete with you well it's right, that's a competition after all, but if I golf your answer then I suggest instead of posting separately.. That's for sure. Nov 7, 2021 at 12:56 • Btw since I have to steal your pow(log10..) to correct my answer I live my attempt at your disposal as a suggestion Try it online! Nov 7, 2021 at 12:59 • in the future feel free to post your own answer if you find a different and better approach, I think it's fine and interesting to compete in the same language, and it happens to other languages too. :) Nov 7, 2021 at 13:04 # Perl 5, 72 bytes sub g{($c,$d)=@_;$c=join"",map{(@e=$c=~/$_/g)?@e.$_:""}0..9for 1..$d;$c}  Try it online! Ungolfed: sub g{ ($c, $d) = @_; for (1 ..$d) {
$c = join('', map {(@e =$c =~ /$_/g) ? @e .$_ : ""} 0 .. 9);
}
\$c;
}


# C (gcc), 121 125 117 116 bytes

E=10,r,c,t,i;g(n,k){for(;k--;n=n?r:E)for(r=i=0;i<E;r=c?r*E*E+c*E+i:r,i++)for(c=0,t=n;t;t/=E)r*=t%E-i||++c%E?:E;r=n;}


Try it online!

• Saved 1 thanks to @ceilingcat
• Fixed: now works with n=0 , k>0 as required.

Try it uint64_t

# Lua, 112 bytes

Chunk function (can be executed using loadstring(code)("42",0)). Expects n as a string and k as either number or string. Doesn't play well with TIO; replace the return n with print(n) to test.

n,k=...for _=1,k do m=""for j=1,9 do c=""..#n:gsub("[^"..j.."]","")m=m..(c>"0"and c..j or"")end n=m end return n


Try it online!