# Multiplicative persistence

## Multiplicative Persistence

1. Multiply all the digits in a number
2. Repeat until you have a single digit left

As explained by Numberphile:

### Example

1. 277777788888899 → 2x7x7x7x7x7x7x8x8x8x8x8x8x9x9 = 4996238671872
2. 4996238671872 → 4x9x9x6x2x3x8x6x7x1x8x7x2 = 438939648
3. 438939648 → 4x3x8x9x3x9x6x4x8 = 4478976
4. 4478976 → 4x4x7x8x9x7x6 = 338688
5. 338688 → 3x3x8x6x8x8 = 27648
6. 27648 → 2x7x6x4x8 = 2688
7. 2688 → 2x6x8x8 = 768
8. 768 → 7x6x8 = 336
9. 336 → 3x3x6 = 54
10. 54 → 5x4 = 20
11. 20 → 2x0 = 0

This is the current record, by the way: the smallest number with the largest number of steps.

## Golf

A program that takes any whole number as input and then outputs the result of each step, starting with the input itself, until we hit a single digit. For 277777788888899 the output should be

277777788888899
4996238671872
438939648
4478976
338688
27648
2688
768
336
54
20
0


(Counting the number of steps is left as an exercise to the user).

### More Examples

From A003001:

25
10
0


From A003001 as well:

68889
27648
2688
768
336
54
20
0


From the Numberphile video, showing that the single digit doesn't have to be 0:

327
42
8


So there has been a question about Additive Persistence, but this is Multiplicative Persistence. Also, that question asks for the number of steps as output, while I'm interested in seeing the intermediate results.

• Bonus: find a new record: smallest number with the largest number of steps. Caveat: conjecture has it that 11 is the largest possible.
– SQB
Mar 21, 2019 at 14:31
• You probably should include a few more tests cases that do not end with $0$. Mar 21, 2019 at 14:33
• Came to make this post, found it already existing, gg
– cat
Mar 21, 2019 at 14:55
• is a single digit valid input? Mar 21, 2019 at 18:30
• In the Numberphile video, Matt Parker states that searches have been done to several hundred digits. Mar 21, 2019 at 21:46

# Retina, 24 bytes

.+~(\

.
$&$*
^
.+¶$$.(  Try it online! Explanation: .+~(\  Print the current value on its own line at the start of every loop until it stops changing and don't print the unchanged value twice. Evaluate the current value at the end of each loop. . &*  Add a * after each digit. ^ .+¶$$.(


Finish turning the input into an expression that evaluates to the digital product.

Just for the record, Retina can do this in one line (25 bytes):

.+"¶"<~[".+¶$.("|'*]'*L.  # C (gcc), 58 bytes f(n,t){for(;n=printf("%d\n",t=n)>2;)for(;n*=t%10,t/=10;);}  Try it online! Iterative approach turns out to be 1 byte shorter. f(n,t){ for(;n=printf("%d\n",t=n) //print and update current number >2;) //until only one digit is printed for(;n*=t%10,t/=10;); //n*= product of digits of t (step) }  ## C (gcc), 61 59 bytes (recursive) f(n){printf("%d\n",n)>2&&f(p(n));}p(n){n=n?n%10*p(n/10):1;}  Try it online! Recursion seems to be shorter than iteration for both print and step... # Java, 112 106 bytes "Lossy conversion" thanks Java for the extra ~15 bytes -6 bytes thanks to @Kevin Cruijssen Obligatory stream abuse answer n->{for(long t=10;t>9;n=(n+"").chars().mapToLong(i->i).reduce(1,(x,y)->x*(y-48)))System.out.println(t=n);}  Try it online • I'm pretty sure you only need to support int Mar 23, 2019 at 0:28 • @EmbodimentofIgnorance then it fails for 277777788888899 since 4996238671872 is too large for an int Mar 23, 2019 at 18:31 • 106 bytes by making it non-recursive. Jul 29, 2019 at 12:09 • @KevinCruijssen thanks Jul 29, 2019 at 13:56 # V (vim), 43 30 29 bytes qqhYp:s/./*&/g x0C<C-r>=<C-r>" <esc>@qq@q  Try it online! -13 bytes from DJMcMayhem. Go upvote their answer! -1 byte from user41805. Takes advantage of the fact that this only stops on single digit numbers. ## Explanation qqhYp:s/./*&/g qq create a macro @q: l move one char right this is the break condition, since you cant move to the right from a single digit Yp duplicate the current line :s/./*&/g add "*" before each digit x0C<C-r>=<C-r>" x delete first char 0C cut the current line and store in " register <C-r>= evaluate the following string: <C-r>" the value in " register and paste in current line @qq@q @q recursively call macro q close macro @q call macro q  • You can use *& instead to save some bytes Apr 9, 2021 at 10:38 Swift, 115 bytes func m(a:Int){ print("\(a)") var b=1,c=a while c>0{ b*=c%10 c/=10} b>9 ? m(a:b):print("\(b)")} m(a:277777788888899)  Try it online! • I think you can move the call to m into the Footer portion of TIO, leaving this answer as 95 bytes Mar 22, 2019 at 0:33 • Also, 81 bytes by removing some whitespace/formatting redundancy. Mar 23, 2019 at 9:46 # PicoLisp, 73 72 bytes (de f(x)(if(> 10 x)(list x)(cons x(f(apply *(mapcar format(chop x)))))))  Try it online! # Japt, 15 bytes I got some help from Shaggy on this one. @pUÌì × Ì>9}f U  Run it online # Stax, 4 bytes ▒σ╛g  Run and debug it Unpacked, it's pretty simple. gu use the rest of the program to generate values until a duplicate is encountered output implicitly E:* calculate product of digits  # Perl 6, 23 bytes {$_,{[*] .comb}...10>*}


Try it online!

# Husk, 5 bytes

U¡oΠd


Try it online!

## Explanation

U¡oΠd
¡    iterate infinitely, collecting results of each iteration
o   combination of 2 functions
d get digits
Π  multiply all of them
U     cut at first duplicate value


# R, 59 55 bytes

Edit: -2 bytes thanks to Giuseppe, quickly superseded by -4 bytes (a different way) thanks to Robin Ryder

n=scan();while(print(n)>9)n=prod(utf8ToInt(c(n,""))-48)


Try it online!

A different method to Giuseppe's answer for the same number of bytes, here as a full recursive function instead of the (often-shorter) approach of taking input from the console using scan.

• This (and mine) can be shortened by using 0:log10(x) instead of the nchar thing, I believe. Apr 11, 2021 at 18:36

# POSIX Shell + Utilities, 59 bytes

echo $1 [${#1} = 1 ]||$0$(echo $1|fold -w1|paste -sd*|bc)  $ cat cg; echo; wc -c cg
echo $1 [${#1} = 1 ]||$0$(echo $1|fold -w1|paste -sd*|bc) 59 cg$ ./cg 277777788888899
277777788888899
4996238671872
438939648
4478976
338688
27648
2688
768
336
54
20
0
$./cg 25 25 10 0$ ./cg 327
327
42
8
$./cg 68889 68889 27648 2688 768 336 54 20 0  # java 8, 105 104 bytes -1 byte thanks to @Benjamin Urquhart, replacing '0' with 48 i->{String s="";for(;(s+=i+"\n")!=""&i>9;){long m=1;for(byte c:(""+i).getBytes())m*=c-48;i=m;}return s;}  TIO • -1 byte by replacing '0' with 48 Mar 21, 2019 at 19:41 • With java 10 you could save a few bytes by writing var instead of String and so on. Mar 21, 2019 at 20:48 # ink, 66 bytes =p(n) {n}{n<10:->->} ~temp v=1 -(a)~v=v*n%10 ~n=n/10 {n:->a}->p(v)  Try it online! # Explanation =p(n) // entry point - a stitch called p, with one parameter. {n} // print the value of n {n<10:->->} // if n is a single digit, divert to wherever we entered from ~temp v=1 // declate a variable v, where we keep track of the product, and set it to 1 -(a) // a labeled gather - we can jump here later ~v=v*n%10 // multiply v by (n mod 10) - the last digit in n ~n=n/10 // divide n by 10 - removing the last digit {n:->a} // if n is nonzero, go back to a ->p(v) // if we reach this, divert to the top, this time with n set to the value of v  Doesn't feel very golfed, but I have no idea how you'd improve it. # Factor, 79 72 bytes : f ( x -- ) [ 10 >base [ 48 - ] map product dup dup . 9 > ] loop drop ;  Try it online! # Python 2, 87 bytes b=input() while 1: a=str(b);print a;b=1 if len(a)<2:break for d in list(a):b*=int(d)  Try it online! # SNOBOL4 (CSNOBOL4), 100 bytes  P =INPUT O OUTPUT =N =P :(S) S P =GT(N,9) 1 :F(END) D N LEN(1) . D REM . N :F(O) P =P * D :(D) END  Try it online! A nice round 100 bytes!  P =INPUT ;* Store input to P O OUTPUT =N =P :(S) ;* print P and set N to P S P =GT(N,9) 1 :F(END) ;* if N > 9, set P (the digit product) to 1 D N LEN(1) . D REM . N :F(O) ;* take the first digit of N as D and set remaining digits to N ;* if N is an empty string, goto label O P =P * D :(D) ;* calculate the digit product, then return to D END  # Racket, 107 bytes (define(f n)(if(> 10 n)(list n)(cons n(f(apply *(map(λ(x)(-(char->integer x)48))(string->list(~v n))))))))  Try it online! # C, 138 115 bytes long atol(char*);main(c,v)char**v;{long z=1,n=atol(v);for(;printf("%ld\n",n),n>9;n=z,z=1)for(;z*=n%10,n/=10;);}  Pass the number as a first command line argument. Thanks to attinat for help with saving some bytes. Ungolfed and prettyified: long atol(char *); main(c, v) char **v; { long z = 1,n = atol(v); for(; printf("%ld\n", n), n > 9; n = z, z = 1) for(; z *= n % 10, n /= 10;); }  • for can save you quite a few bytes. – att Mar 24, 2019 at 6:14 • Suggest int**v instead of char**v Apr 21, 2019 at 6:37 # Attache, 28 27 bytes {If[_>9,_'$@Prod@List@_,_]}


Try it online!

Oddly enough, the recursive approach, rather than a tacit approach, seems to be shortest. (There is a bug in NestListWhile involving currying, but even with the bugfix it'd be 3 bytes longer.)

## Explanation

{
If[ _ > 9 ,
?? if this is true, return a list
[
?? with the current number
_,
?? followed by this function called on the digital product
...$[ Prod[Digits[_]] ] ], ?? otherwise, return _ _ ] }  ## Alternative 32 bytes: NestListWhile<~Prod@List,{_>9}~> # C# (.NET Core), 192 191 180 bytes using C=System.Console;class A{static void Main(string[] a){long i,k;var b=a;for(C.WriteLine(b);(k=b.Length)>1;C.WriteLine(b=i.ToString())){i=1;for(int j=0;j<k;)i*=b[j++]-48;}}}  Try it online! Pretty much just naive looping. I feel like that's a bit of a silly way to do it but here we are. Had a weird issue early on where the input didn't match the output, because it was overflowing an int, so here we are with longs. I could upgrade it to BigInteger if I needed to, though that would cost a few bytes. I swear I always end up with off by ones when I do loops here, and it annoys me to no end. Ungolfed-ish version: using C=System.Console; class A{ static void Main(string[] a){ long i,k; var b=a; for(C.WriteLine(b);(k=b.Length)>1;C.WriteLine(b=i.ToString())){ i=1; for(int j=0;j<k;)i*=b[j++]-48; } } }  # Works for all integers less than int.MAX_VALUE digits long, C# (.NET Core), 204 bytes using C=System.Console;class A{static void Main(string[] a){System.Numerics.BigInteger i;int j,k;var b=a;for(C.WriteLine(b);(k=b.Length)>1;C.WriteLine(b=i.ToString())){i=1;for(j=0;j<k;)i*=b[j++]-48;}}}  Try it online! • Saved 1 byte - moved C.WriteLine(b) into loop opening as well as iterator Mar 24, 2019 at 4:01 • Saved 11 bytes with assorted rearrangements. Mar 25, 2019 at 15:16 # Pyth, 9 bytes j.u*FsMN  Try it here! If we're allowed to output as an array, the j at the start is unnecessary, giving 8 bytes. • You can also omit the N at the end, since Pyth implicitly adds lambda variables at the end of a program if needed. Jul 28, 2019 at 22:42 ## c++, lambda function, 72 bytes [](auto n){while(cout<<n<<endl&&n>9){auto t=n;for(n=1;n*=t%10,t/=10;);}}  try it online ## Clojure, 73 bytes #(loop[i %](prn i)(if(> i 9)(recur(apply *(for[c(str i)](-(int c)48))))))  # Scala, 83 bytes def^(n:Long):Long={println(n);if(n>9)^((n+"").map(x=>(x-48).toLong).product)else n}  Try it online! # Befunge-98 (FBBI), 43 42 bytes &;1\v>#;:.:9!#@_; >$$^ ^#::< '*%ap25/a_  Try it online! The first line takes input, prints the values and runs until a value <=9 is reached. The third line computes the product of digits of an integer (26 bytes on its own). # Pip, 9 bytes W9<Pa$*:a


Try it online!

### Explanation

           a is command-line argument (implicit)
W          While...
Pa      (print a's value)
9<        ... a is greater than 9, i.e. more than one digit:
\$      Fold
a   (the digits of) a
*     on multiplication
:    and assign back to a


Printing a in the loop header lets us output its value both before the loop and when the loop terminates.

# Factor + math.unicode, 40 bytes

[ [ .s >dec 48 v-n Π dup 9 > ] loop . ]


Try it online!

• [ ... dup 9 > ] loop loop while top of stack is greater than nine
• .s print stack non-destructively
• >dec convert number to string
• 48 v-n convert string to list of digits
• Π product of a list of numbers
• . print the leftover number (which will be the final output)

# Python 3, 47 bytes

def f(n):print(n);n>9>f(eval('*'.join(str(n))))


Try it online!

# FunStack alpha, 38 bytes

Product Minus 48 Show compose3 fixiter


Try it at Replit: pass the input number as a command-line argument and enter the program on stdin.

### Explanation

The fixiter modifier iterates a function until it reaches a fixed value, returning the full list of intermediate values. This is exactly what we want; there is a slight complication because the builtin ToBase function, which returns a list of digits, converts zero to an empty list rather than a list containing 0. So instead, we convert the number to a string and then convert each character to the corresponding digit.

                      compose3          Compose these three functions:
Show                     Convert number to string
Minus 48                          Subtract 48 from each character
Product                                   Take the product of the character codes
fixiter  Iterate that function, stopping when a fixed point
is reached, and return a list of intermediate values
`