29
\$\begingroup\$

The shortest code to pass all possibilities wins.

In mathematics, the persistence of a number measures how many times a certain operation must be applied to its digits until some certain fixed condition is reached. You can determine the additive persistence of a positive integer by adding the digits of the integer and repeating. You would keep adding the digits of the sum until a single digit number is found. The number of repetitions it took to reach that single digit number is the additive persistence of that number.

Example using 84523:

84523
8 + 4 + 5 + 2 + 3 = 22
2 + 2 = 4

It took two repetitions to find the single digit number.
So the additive persistence of 84523 is 2.

You will be given a sequence of positive integers that you have to calculate the additive persistence of. Each line will contain a different integer to process. Input may be in any standard I/O methods.

For each integer, you must output the integer, followed by a single space, followed by its additive persistence. Each integer processed must be on its own line.

Test Cases


Input Output

99999999999 3
10 1
8 0
19999999999999999999999 4
6234 2
74621 2
39 2
2677889 3
0 0
\$\endgroup\$
10
  • 1
    \$\begingroup\$ Your test cases include some values which are over 2^64, and your spec says that the program only has to handle values up to 2^32. Might be worth clearing that up. \$\endgroup\$ Mar 25, 2011 at 23:40
  • \$\begingroup\$ @Peter Taylor, forgot to remove those limits. If a program can handle the input I have provided, it shouldn't have an issue with limits. \$\endgroup\$ Mar 25, 2011 at 23:49
  • 5
    \$\begingroup\$ Isn't 999999999999's persistence 2 instead of 3? \$\endgroup\$
    – Eelvex
    Mar 26, 2011 at 2:13
  • \$\begingroup\$ @Evelex, that was an incorrect last minute change I guess. Fixed. \$\endgroup\$ Mar 26, 2011 at 21:45
  • \$\begingroup\$ Several answers here aren't doing output on stdout but rather use J's "interactive" output by returning results after taking command line input. (This includes 2 other J answers and, I'm guessing, the K answer.) Is this considered legit? Because I can shed 18-ish characters if so. \$\endgroup\$ Mar 27, 2011 at 1:29

47 Answers 47

7
\$\begingroup\$

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"
  • 35 -> 31: Remove outside function.
  • 31 -> 29: Remove parens.
\$\endgroup\$
1
  • 1
    \$\begingroup\$ -1+# => #1_ \$\endgroup\$
    – mkst
    Aug 6, 2019 at 11:24
4
\$\begingroup\$

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
\$\endgroup\$
1
  • \$\begingroup\$ Challenge case:06234 .. result successful challenge :-) \$\endgroup\$
    – Quixotic
    Mar 26, 2011 at 6:01
4
\$\begingroup\$

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
\$\endgroup\$
1
  • \$\begingroup\$ You can save 6 bytes by using read.pure instead of (-48+).fromEnum, try it online! \$\endgroup\$ Apr 25, 2018 at 15:17
4
\$\begingroup\$

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)
\$\endgroup\$
3
  • \$\begingroup\$ i think you can remove the space between 9 and err...and \$\endgroup\$
    – st0le
    Mar 26, 2011 at 8:52
  • \$\begingroup\$ and input() instead of int(raw_input()).... \$\endgroup\$
    – st0le
    Mar 28, 2011 at 6:48
  • \$\begingroup\$ @st0le:Try this input with that modification:06234. \$\endgroup\$
    – Quixotic
    Mar 28, 2011 at 7:12
4
\$\begingroup\$

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"
\$\endgroup\$
0
3
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

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
\$\endgroup\$
1
  • 1
    \$\begingroup\$ You can save 4 bytes by using pure over (:[]) and defining an operator instead of s, try it online! \$\endgroup\$ Apr 25, 2018 at 15:22
3
\$\begingroup\$

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).

\$\endgroup\$
3
\$\begingroup\$

Golfscript, 40 chars

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

J - 45 Chars

Reads from stdin

(,' ',[:":@<:@#+/&.:("."0)^:a:)&><;._2(1!:1)3
\$\endgroup\$
5
  • \$\begingroup\$ I was trying to use ^:a: myself but I couldn't find some proper documentation... any hints? \$\endgroup\$
    – Eelvex
    Mar 26, 2011 at 16:12
  • 1
    \$\begingroup\$ The dictionary entry for u^:n has info on its usage but it is a bit dense. ^:a: is like any other call to power but it collects the results and ends when the argument to consecutive calls is the same(converges). \$\endgroup\$
    – isawdrones
    Mar 26, 2011 at 17:21
  • 1
    \$\begingroup\$ @Eelvex FWIW I discovered a: through the ^:a: trick in the J Reference Card[PDF] \$\endgroup\$
    – J B
    Mar 27, 2011 at 0:55
  • \$\begingroup\$ @JB: That's the only reference on ^:a: that I knew :D \$\endgroup\$
    – Eelvex
    Mar 27, 2011 at 0:59
  • \$\begingroup\$ @Eelvex Oh. I had the opposite experience then. I discovered the functionality in the dictionary, and used it as some variant of ^:(<'') at first (probably for Kaprekar), until I spotted it in the card, and learned about a: for the occasion. \$\endgroup\$
    – J B
    Mar 27, 2011 at 10:43
3
\$\begingroup\$

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.

\$\endgroup\$
1
3
+100
\$\begingroup\$

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)
\$\endgroup\$
1
  • \$\begingroup\$ Bad habits..... \$\endgroup\$
    – Razetime
    Sep 12, 2020 at 8:11
2
\$\begingroup\$

J, 74 chars

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

Edits

  • (86 → 83) Some Caps [: to Ats @
  • (83 → 79) Unneeded parentheses
  • (79 → 75) Changing 0". to ". simplifies things
  • (75 → 74) Better Cutting

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  
\$\endgroup\$
3
  • \$\begingroup\$ Output is formatted wrong for multiple inputs. See "single space" \$\endgroup\$ Mar 27, 2011 at 1:54
  • \$\begingroup\$ @Jesse: I see nothing wrong. Could you write an example please? \$\endgroup\$
    – Eelvex
    Mar 27, 2011 at 2:09
  • \$\begingroup\$ I have no idea, I'm seeing things I guess. \$\endgroup\$ Mar 27, 2011 at 2:18
2
\$\begingroup\$

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

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

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
\$\endgroup\$
5
  • \$\begingroup\$ @Steffan Dammit, I misread those rules. \$\endgroup\$ Jul 23, 2022 at 21:39
  • \$\begingroup\$ @Steffan I don't think the İ approach works, for 8 it outputs 1 but it should be 0 \$\endgroup\$ Jul 23, 2022 at 22:00
  • \$\begingroup\$ Steffan's approach works with the A flag. \$\endgroup\$
    – emanresu A
    Jul 24, 2022 at 1:46
  • \$\begingroup\$ @emanresuA Hmm, can you show me? \$\endgroup\$ Jul 24, 2022 at 2:28
  • \$\begingroup\$ Wait nvm, that separates by ‍ => ‍ \$\endgroup\$
    – emanresu A
    Jul 24, 2022 at 2:34
1
\$\begingroup\$

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}"}
\$\endgroup\$
2
  • \$\begingroup\$ Actually, chop! instead of chomp! gives me a one character savings. 97 chars. \$\endgroup\$ Mar 26, 2011 at 2:20
  • \$\begingroup\$ Just did some more golfing at it - 91 chars. \$\endgroup\$ Mar 26, 2011 at 2:26
1
\$\begingroup\$

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! :)

\$\endgroup\$
2
  • \$\begingroup\$ Sure there is: input() :) \$\endgroup\$
    – Eelvex
    Mar 26, 2011 at 5:23
  • \$\begingroup\$ @Eelvex, done. :) \$\endgroup\$
    – st0le
    Mar 26, 2011 at 5:53
1
\$\begingroup\$

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

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Just noticed this doesn't output it correctly. \$\endgroup\$ Mar 30, 2011 at 19:04
1
\$\begingroup\$

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.

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

Perl - 77 characters

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

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

JavaScript, 57 47 bytes

-10 bytes thanks to @l4m2!

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

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ f=(s,c=0)=>s>9?f([...s+""].reduce((x,y)=>x*1+y*1),++c):c \$\endgroup\$
    – l4m2
    May 5, 2018 at 11:10
  • \$\begingroup\$ f=(s,c=0)=>s>9?f([...s+""].reduce((x,y)=>x- -y),++c):c \$\endgroup\$
    – l4m2
    May 5, 2018 at 11:11
  • 1
    \$\begingroup\$ f=(s,c=0)=>s>9?f(eval([...s+""].join`+`)),++c):c \$\endgroup\$
    – l4m2
    May 5, 2018 at 11:11
  • \$\begingroup\$ @l4m2 Thanks! s>9 and eval were great ideas. I think you had an extra paren in there, making it a total of 10 bytes you saved me :-) \$\endgroup\$
    – Oliver
    May 7, 2018 at 0:35
  • \$\begingroup\$ Note the strict I/O ;) \$\endgroup\$
    – Shaggy
    May 14, 2018 at 14:28
1
\$\begingroup\$

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

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
\$\endgroup\$
1
\$\begingroup\$

Stax, 8 11 bytes

ªwæMε∞ö?îm⌐

Run and debug it

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

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I reached the same solution, but with i in place of u. Adhering to the draconian IO specifications, this becomes 11 bytes. \$\endgroup\$ Aug 6, 2019 at 14:58
  • \$\begingroup\$ Oops. I guess I didn't read the IO requirements very well. I'll update my answer. \$\endgroup\$
    – recursive
    Aug 6, 2019 at 15:04
1
\$\begingroup\$

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!

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

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

Knight, 54 bytes

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

Try it online!

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

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