g | x | w | all
Bytes Lang Time Link
054Raku Perl 6 rakudo250428T192810Zxrs
063AWK241212T151957Zxrs
094Tcl180415T003216Zsergiol
015Japt mR180514T141931ZShaggy
077Go231128T155305Zbigyihsu
714Nibbles221220T092553ZDominic
036><>221219T172543ZEmigna
021Ly220804T082225Zcnamejj
054Knight220804T032720ZnaffetS
01005AB1E190806T084903ZKevin Cr
008Vyxal aj220723T084920Ztybocopp
052Jq r210408T162725ZWezl
012Jelly201206T173912Zcaird co
106Swift 5190806T140600ZTiziano
017APL Dyalog Unicode200912T074909ZRazetime
017Pyth190812T101803Zar4093
050Python 3190806T170116ZTriggern
076Python 3190806T094308ZJitse
062Python 2190806T151504ZHenry T
011Stax190806T142613Zrecursiv
9229Julia190806T105311ZSimeon S
016K ngn/k190806T112152Zmkst
011MathGolf190806T104034Zmaxb
085C gcc180415T005206ZJonathan
519c110326T231213Zdmckee -
083Bash+coreutils180507T033003ZChris
047JavaScript180424T205326ZOliver
721PHP180504T155209ZTitus
028Japt180425T175318ZEtheryte
015Husk180415T183607Zბიმო
082Python 3180415T145729ZPieCot
079Java OpenJDK 8180415T022852ZX1M4L
065Perl 5180415T013808ZXcali
nan110523T042456Zuser unk
093Python110326T061045ZQuixotic
077Perl110327T021205Zjho
074J110326T025318ZEelvex
100Haskell110327T055710ZMtnViewM
078J110326T233017ZJesse Mi
095Javascript110326T220041Zt123
029K 29 Chars110326T063337Zisawdron
084Python 84 Chars110326T034602ZfR0DDY
045J 45 Chars110326T072428Zisawdron
040Golfscript110326T055408ZYOU
101PARI/GP 101 Chars110326T044050Zst0le
085Ruby110326T043541ZEzran
114Haskell110326T042639ZJoey Ada
nan110326T021820ZAlex Bar
105bash110325T234412ZPeter Ta

Raku (Perl 6) (rakudo), 54 bytes

{my ($t,$c)=$^a,0;while $t>9 {$t=[+] $t.comb;$c++};$c}

Attempt This Online!

AWK, 63 bytes

{for(;1<l=split($1,a,X);i++){$1=0;for(j=0;j++<l;)$1+=a[j]}}$0=i

Attempt This Online!

Tcl, 94 bytes

proc P {v n\ 0} {set s $v
while \$s>9 {set s [expr [join [split $s ""] +]]
incr n}
list $v $n}

Try it online!

Japt -mR, 21 19 15 bytes

+S+Uì Å£=ìxÃâ Ê

Try it

+S+Uì Å£=ìxÃâ Ê     :Implicit map of each U in input array
+S+                 :Append a space and
   Uì               :  Convert U to digit array
      Å             :  Slice off the first element
       £            :  Map
        =           :    Reassign to U
         ìx         :    Convert to digit array and reduce by addition
           Ã        :  End map
            â       :  Deduplicate
              Ê     :  Length
                    :Implicit output joined with newlines

Go, 77 bytes

func f(n int)int{s:=0
if n<10{return 0}
for;n>0;n/=10{s+=n%10}
return 1+f(s)}

Attempt This Online!

Nibbles, 7 bytes (14 nibbles)

:$,>>`.$/`@~$+
                    # (implicitly map over input):
:$                  # prepend input onto
  ,                 # length  
   >>               # (without first item) of
     `.             # iterate while unique
       $            # starting with input number:
         `@~$       #   convert to base-10 digits
        /           #   and fold over this list
             +      #     adding its elements

enter image description here

><>, 36 bytes

0{:a(7$.0}\~1+!
~n
1:,a}+{%a:/?(1:-%

Try it online!

Ly, 21 bytes

0s+1[pSy,![lu;]&+l`s]

Try it online!

A pretty straight forward interpretation of the challenge rules this time.

0s+1[pSy,![lu;]ç]
0s                    - initialize the backup cell to 0 (iteration count)
  +                   - load input number, absorbing the 0 on the stack
   1                  - push a truthy value to enter loop
    [p              ] - infinite loop
      S               - convert number on top of stack to digits
       y              - push the number of digit (stack size)
        `!            - decrement and convert truthiness
          [   ]       - if/then, executes is number is a single digit
           lu;        - load backup cell, print as number, end program
               &+     - sum the digits on the stack
                 l`s  - load backup cell (iterations) increment and save

Knight, 54 bytes

;=iP;=r 0;W<1Li;=s 0;Wi;=s+sA Ai=iGi 1Li;=i+""s=r+1rOr

Try it online!

05AB1E, 13 10 bytes

ε.ΓSO}g}ø»

-3 bytes thanks to @Steffan

Input as a list of integers.

Try it online.

Explanation:

ε      # Map each integer in the (implicit) input to:
 .Γ    #  Loop until the integer no longer changes,
       #  keeping all intermediate steps in a list:
   S   #   Convert the integer to a list of digits
    O  #   Sum those digits together
  }g   #  After the inner loop: pop and push the length
}ø     # After the outer map: zip/transpose it with the (implicit) input to create a
       # list of pairs
  »    # Join each pair by a space, and then the list of strings by newlines
       # (after which the result is output implicitly)

Vyxal aj, 9 8 bytes

ƛ⁽∑↔L‹"Ṅ

Try it Online!

Explanation:

          # Treat all the inputs as a list (`a` flag)
ƛ         # On each item (n) in that list
 ⁽        # Create a single element lambda
  ∑       # That sums the digits of a number
   ↔      # Apply that function on n until it doesn't change 
          # and return the intermediate values in a list
    L     # Get the length of that list
     ‹    # Decrement it to ignore the last time the function is called
      "   # Pair that with n
       Ṅ  # Join the pair by a space
          # Join the mapped inputs by new lines (`j` flag)
          # Implicitly print

Jq -r, 52 bytes

[while(length>1;explode|map(.-48)|add|@text)]|length

-r                    # take one number per line, converting it to a string

                explode                              # the character codes
                       |map(.-48)                    # subtract ascii zero from each
                                 |add                # sum the elements
                                     |@text          # back to text, (shorter than
                                                     # tostring and tojson)
 while(length>1;                           )         # produces *all* the intermediate
                                                     # results while the string length>1
[                                           ]        # collected into an array
                                             |length # the length of these results

Not answering the multiplicative persistence now because jq doesn't have a product builtin :)

Jq play it!

Jelly, 12 bytes

żDS$Ƭ€Ẉ’ƊK€Y

Try it online!

Takes input as a list of integers. +3 bytes to input as a multiline string.

+3 bytes (or +6) for restrictive I/O formats, yay

How it works

żDS$Ƭ€Ẉ’ƊK€Y - Main link. Takes a list l on the left
        Ɗ    - To l:
   $         -   Group the previous 2 links into a monad f(n):
 D           -     Digits
  S          -     Sum
    Ƭ€       -   Over each n in l, repeatedly apply f(n) until a fixed point,
                  yielding [n, f(n), f(f(n)), ...]
      Ẉ      -   Get the length of each loop
       ’     -   Decrement each
ż            - Zip the loop lengths with l
         K€  - Join each by spaces
           Y - Join by newlines

Swift 5, 106 bytes

func a(_ s:S,_ i:I)->(S,I){if s.count<=1{return(s,i)};return a(S(s.compactMap{I(S($0))}.reduce(0,+)),i+1)}

Try it online!

APL (Dyalog Unicode), 21 17 bytes

{⍵≤9:0⋄1+∇+/⍎¨⍕⍵}

-4 bytes from Jo King.

Try it online!

{s←+/⍎¨⍕⍵⋄⍵≤9:0⋄1+∇s}

Try it online!

Explanation

{s←+/⍎¨⍕⍵⋄⍵≤9:0⋄1+∇s} ⍵ → input
       ⍕⍵             convert ⍵ to string
     ⍎¨               execute each character(getting digits)
   +/                 reduce to sum of digits
 s←                   assign to s
          ⍵≤9:        if number is single digit
              0       return 0, stop recursion
                1+∇s  Otherwise return 1+f(sum)

Pyth, 17 bytes

FG.Qs[Gdtl.usjNTG

Try it online!

If I can instead of values on different lines, take a list of numbers (in the format [9999999999, 10, 8, etc.]), then -1 byte by replacing .Q with Q

F                  # For
 G.Q               #   G in the complete input (split by newlines)
    s[             #     join the list as string, create list from the following values:
      Gd           #       G, " " (for output formatting),
        tl         #       decrement length of
          .u    G  #          List of all intermediate results until there's a returning result, with starting value G
            s      #            reduce on + (add all list elements) the list:
             j     #              convert to integer as list:
              N    #                The current value (implicit input to .u)
               T   #                in base 10 (T=10)

Python 3, 50 bytes

f=lambda n:0if n<10else-~f(eval('+'.join(str(n))))

Recursive function. Takes an integer, returns an integer.

Explanation:

# create a lambda function which takes one argument, and assign it to f
f=lambda n:\
    # if n is 0-9, it's persistence 0
    0if n<10\
        # otherwise, add one to the running total and recursively call f
        # ( ~ will invert the returned number, equivalent to -n-1)
        # (negating that gives you -(-n-1) = n+1)
        else-~f(
            # convert integet to string, join each character with a '+'
            # gives a string like '1+2+3+4+...+n'
            # evaluate the string as an expression, giving a new integer
            # pass that integer back into f
            eval('+'.join(str(n)))
        )

Python 3, 76 bytes

def f(n,i=0,p=0):p=p or n;f(sum(map(int,str(n))),i+1,p)if n>9else print(p,i)

Try it online!


Without I/O restrictions:

Python 3, 54 bytes

f=lambda n,i=0:f(sum(map(int,str(n))),i+1)if n>9else i

Try it online!

Python 2, 62 bytes

f=lambda x,i=0:f(`sum(int(i)for i in x)`,i+1)if len(x)>1else i

Stax, 8 11 bytes

ªwæMε∞ö?îm⌐

Run and debug it

+3 bytes thanks to @Khuldraeseth (the first answer didn't have compliant output)

Julia, 92 (29) bytes

f(n)=n>9&&(f∘sum∘digits)(n)+1

Edit: With correct printing it's 92:

f(n)=n>9&&(f∘sum∘digits)(n)+1
while(n=parse(Int128,readline()))≢π
println("$n ",f(n)%Int)end

K (ngn/k), 16 bytes

Solution:

{x,#1_(+/10\)\x} 

Try it online!

Explanation:

{x,#1_(+/10\)\x} / the solution
{              } / lambda taking implicit x
      (     )\x  / iterate until convergence
         10\     / split into base-10 (123 => 1 2 3)
       +/        / sum
    1_           / drop first result (iterate returns input as first result)
   #             / count length of result
 x,              / prepend x (original input)

MathGolf, 11 bytes

hÅ_Σ]▀£(k ?

Try it online!

Incredibly inefficient, but we don't care about that. Basically, using the fact that the additive persistence of a number is smaller than or equal to the number itself.

Uses the fact that the additive persistence is less than or equal to the number of digits of the number. Passes all test cases with ease now.

The input format, while suboptimal for some languages, is actually the standard method of taking multiple test cases as input in MathGolf. Each line of the input is processed as its own program execution, and output is separated by a single newline for each execution.

Explanation (using n = 6234)

h             push length of number without popping (6234, 4)
 Å            loop 4 times using next 2 operators
  _           duplicate TOS
   Σ          get the digit sum
    ]         wrap stack in array
              this gives the array [6234, 15, 6, 6, 6]
     ▀        unique elements of string/list ([6234, 15, 6])
      £       length of array/string with pop (3)
       (      decrement (2)
        k ?   push input, space, and rotate top 3 elements to produce output (6234 2)

C (gcc), 87 85 bytes

f(n,p){char*t,s[99];for(p=0;sprintf(s,"%d",n),1[t=s];p++)for(n=0;*t;n+=*t++-48);n=p;}

Try it online!

c -- 519

(or 137 if you credit me for the framework...)

Rather than solving just this one operation, I decided to produce a framework for solving all persistence problems.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char*(*O)(char*);
char*b(char*s){long long int v=0,i,l=0;char*t=0;l=strlen(s);t=malloc(l+2);
for(i=0;i<l;i++)v+=s[i]-'0';snprintf(t,l+2,"%lld",v);return t;}
int a(char**s,O o){int r;char*n;n=o(*s);r=!strcmp(*s,n);free(*s);
*s=n;return r;}
int main(int c, char**v){size_t l, m=0;char *d,*n=0;O o=b;FILE*f=stdin;
while(((l=getline(&n,&m,f))>1)&&!feof(f)){int i=0;n=strsep(&n,"\n");
d=strdup(n);while(!a(&n,o))i++;printf("%s %d\n",d,i);free(d);free(n);n=0;m=0;}}

Only the two lines starting from char*b are unique to this problem.

It treats the input as strings, meaning that leading "0"s are not strip before the output stage.

The above has had comments, error checking and reporting, and file reading (input must come from the standard input) striped out of:

/* persistence.c
 *
 * A general framework for finding the "persistence" of input strings
 * on opperations.
 *
 * Persistence is defined as the number of times we must apply
 *
 *    value_n+1 <-- Opperation(value_n)
 *
 * before we first reach a fixed point.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../getline.h"

/* A function pointer type for operations */
typedef char*(op_func)(char*);
typedef op_func* op_ptr;
/* Op functions must
 * + Accept the signature above
 * + return a point to a newly allocated buffer containing the updated str
 */

char* addop(char*s){
  int i,l=0;
  long long int v=0;
  char *t=NULL;
  /* protect against bad input */
  if (NULL==s) return s;
  /* allocate the new buffer */
  l = strlen(s);
  t = malloc(l+2);
  if (NULL==t) return t;
  /* walk the characters of the original adding as we go */
  for (i=0; i<l; i++) v += s[i]-'0';
  //fprintf(stderr,"   '%s' (%d) yields %lld\n",s,l,v);
  snprintf(t,l+2,"%lld",v);
  //fprintf(stderr,"   %lld is converted to '%s'\n",v,t);
  return t;
}

/* Apply op(str), return true if the argument is a fixed point fo
 * falsse otherwise,
 */ 
int apply(char**str, op_ptr op){ 
  int r;
  char*nstr;
  /* protect against bad input */
  if ( NULL==op ) exit(1); 
  if ( NULL==*str ) exit(4); 
  /* apply */
  nstr = op(*str); 
  /* test for bad output */
  if ( NULL==nstr ) exit(2); 
  r = !strcmp(*str,nstr); 
  /* free previous buffer, and reasign the new one */
  free(*str); 
  *str = nstr; 
  return r; 
}

int main(int argc, char**argv){
  size_t len, llen=0;
  char *c,*line=NULL;
  op_ptr op=addop;
  FILE *f=stdin;
  if (argc > 1) f = fopen(argv[1],"r");
  while( ((len=getline(&line,&llen,f))>1) && line!=NULL && !feof(f) ){
    int i=0;
    line=strsep(&line,"\n"); // Strip the ending newline
    /* keep a copy for later */
    c = strdup(line);
    /* count necessary applications */
    while(!apply(&line,op)) i++;
    printf("%s %d\n",c,i);
    /* memory management */
    free(c);
    free(line);
    line=NULL;
    llen=0;
  }
}

A little more could be saved if we were willing to leak memory like a sieve. Likewise by #defineing return and the like, but at this point I don't care to make it any uglier.

Bash+coreutils, 83 bytes

[ $1 -le 9 ]&&exit $2
let x=$2+1
for z in `fold -w1<<<$1`
do let y+=$z
done
a $y $x

Try it online!

Should be saved to a script called a and placed in the system's PATH, as it calls itself recursively. Takes input from command line, like a 1999. Returns by exit code.

TIO has some limitations on what you can do with a script, so there's some boilerplate code to make this run in the header.

Prints an error to stderr for input larger than bash integers can handle, but since the actual computation is done with strings, it still gives the right result anyway.

JavaScript, 57 47 bytes

-10 bytes thanks to @l4m2!

f=(s,c=0)=>s>9?f(eval([...s+""].join`+`),++c):c

Try it online!

PHP, 72+1 bytes

+1 for -R flag.

for($i=0,$a=$argn;$a>9;$i++)$a=array_sum(str_split($a));echo"$argn $i
";

Run as pipe with -R.

Japt, 28 bytes

Ë+S+(@D=X©A<D©ì x ªD D<AÃa÷
Ë                            // Map over the inputs and return each, followed by
 +S+                         // a space, followed by the number's persistence.
      D=     ©ì x            // To find it, fold the number up
        X©A<D     ªD         // if we can (handles unfoldable cases),
    (@               D<AÃa   // until it can't be folded up any further.
                          ÷ // Then, join everything up with newlines.

Try it online!

Husk, 10 15 bytes

+5 bytes for horrible I/O requirement

m(wΓ·,LU¡oΣdr)¶

Try it online!

Explanation

To support multiple inputs, we need to use m(₁r)¶ (where is the function doing the interesting computation):

m(₁r)¶  -- expects newline-separated inputs: "x₁␤x₂␤…␤xₙ"
     ¶  -- split on newlines: ["x₁","x₂",…,"xₙ"]
m(  )   -- map over each string
 ( r)   -- | read integer: [x₁,x₂,…,xₙ]
 (₁ )   -- | apply the function described below

The function does the following:

wΓ·,LU¡(Σd)  -- input is an integer, eg: 1234
      ¡(  )  -- iterate the following forever and collect results in list:
       ( d)  -- | digits: [1,2,3,4]
       (Σ )  -- | sum: 10
             -- : [1234,10,1,1,1,…
     U       -- keep longest prefix until repetition: [1234,10,1]
 Γ           -- pattern match (x = first element (1234), xs = tail ([10,1])) with:
  · L        -- | length of xs: 2
   ,         -- | construct tuple: (1234,2)
w            -- join with space: "1234 2"

Python 3, 82 bytes

while 1:f=lambda n:n//10and 1+f(sum(map(int,str(n))));i=input();print(i,f(int(i)))

Java (OpenJDK 8), 79 bytes

a->{int d=0;while(a/10>0){int c=0;d++;while(a>0){c+=a%10;a/=10;}a=c;}return d;}

Try it online!

There's probable potential to golf it further, but I'll look into that in the future, but for now, I'm pretty happy with this little result.

Perl 5, 65 bytes

$b=0;$q=s/\n//r;$_=eval s/./+$&/gr while y///c>1&&++$b;say"$q $b"

Try it online!

scala 173:

def s(n:BigInt):BigInt=if(n<=9)n else n%10+s(n/10)
def d(n:BigInt):Int=if(n<10)0 else 1+d(s(n))
Iterator.continually(readInt).takeWhile(_>0).foreach(i=>println(i+" "+d(i)))

Python (93 bytes)

f=lambda n,c:n>9and f(sum(map(int,str(n))),c+1)or c
while 1:n=int(raw_input());print n,f(n,0)

Perl - 77 characters

sub'_{split//,shift;@_<2?0:1+_(eval join'+',@_)}chop,print$_,$",(_$_),$/for<>

J, 74 chars

i=:<;._2(1!:1)3
i&((],' ',":@(0 i.~9<[:".([:":[:+/"."0)^:(i.9)))@>@{~)i.#i

Edits

E.g

i=:<;._2(1!:1)3
74621
39
2677889
0
i&((],' ',":@(0 i.~9<[:".([:":[:+/"."0)^:(i.9)))@>@{~)i.#i
74621 2  
39 2     
2677889 3
0 0  

Haskell, 100 characters

p[d]=0
p d=1+(p.show.sum$map((-48+).fromEnum)d)
f n=n++' ':shows(p n)"\n"
main=interact$(f=<<).lines

J, 78

f=:[:+/"."0&":
r=:>:@$:@f`0:@.(=f)
(4(1!:2)~LF,~[:":@([,r)".@,&'x');._2(1!:1)3

Recursive solution. Reads from stdin. Writes to stdout, so cut me some slack - it does take an extra 18-ish characters.

Javascript - 95

i=prompt();while(i>9){i=''+i;t=0;for(j=0;j<i.length;j++)t+=parseInt(i.charAt(j));i=t;}alert(t);

EDIT: Whoops does'nt do the multi-lines

K - 29 Chars

Input is a filename passed as an argument, 29 chars not including filename.

`0:{5:x,-1+#(+/10_vs)\x}'.:'0:"file"

Python 84 Chars

while 1:
 m=n=int(raw_input());c=0
 while n>9:c+=1;n=sum(map(int,str(n)))
 print m,c

J - 45 Chars

Reads from stdin

(,' ',[:":@<:@#+/&.:("."0)^:a:)&><;._2(1!:1)3

Golfscript, 40 chars

n%{.:${;${48-}%{+}*`:$,}%.,1>\1?+' '\n}%

PARI/GP 101 Chars

s(n)=r=0;while(n>0,r+=n%10;n\=10);r
f(n)=c=0;while(n>9,c++;n=s(n));c
while(n=input(),print(n," ",f(n)))

Unfortunately, there's no input function for GP, so i guess this lacks the IO part. :( Fixed: Thanks Eelvex! :)

Ruby, 85 Chars

puts $<.map{|n|v=n.chop!;c=0;[c+=1,n="#{n.sum-n.size*48}"] while n[1];[v,c]*' '}*"\n"

I had to borrow the "sum-size*48" idea from Alex, because it's just too neat to miss (in Ruby at least).

Haskell - 114

s t n|n>9=s(t+1)$sum$map(read.(:[]))$show n|1>0=show t
f n=show n++" "++s 0n++"\n"
main=interact$(f.read=<<).lines

I think this is about the best I can come up with.

Ruby 101 Chars

f=->(n){n.sum-n.size*48}
$<.each{|l|i=0;i+=1 while(i+=1;n=f[(n||l.chop!).to_s])>10
puts "#{l} #{i}"}

bash, 105 chars

while read x
do
for((i=0,z=x;x>9;i++))do
for((y=0;x>0;y+=x%10,x/=10))do :
done
x=$y
done
echo $z $i
done

Hardly any golfing actually involved, but I can't see how to improve it.