# 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:

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 '19 at 14:31
• You probably should include a few more tests cases that do not end with $0$. Mar 21 '19 at 14:33
• Came to make this post, found it already existing, gg
– cat
Mar 21 '19 at 14:55
• is a single digit valid input? Mar 21 '19 at 18:30
• In the Numberphile video, Matt Parker states that searches have been done to several hundred digits. Mar 21 '19 at 21:46

# Jelly, 4 bytes

DP$Ƭ  Try it online! ### Explanation D | convert to decimal digits P | take the product$  | previous two links as a monad
Ƭ | loop until no change, collecting all intermediate results


As a bonus, here's a TIO which will find the numbers with the largest number of steps for a given range of numbers of digits. It scales well even on TIO.

# TI-BASIC (TI-84), 3032 31 bytes

-1 byte thanks to @SolomonUcko!

While Ans>9:Disp Ans:prod(int(10fPart(Ans10^(seq(-X-1,X,0,log(Ans:End:Ans


Input is in Ans.
Output is displayed as the challenge requests. The trailing Ans is needed to print the last step.

I will admit, I did not think of this formula myself, rather I found it here and modified it to better fit the challenge.

EDIT: Upon rereading the challenge, I realized that the program must terminate if the product is one digit. Hence, 2 bytes were to be added to account for this.

Example:

24456756
24456756
prgmCDGF8
24456756
201600
0
11112
11112
prgmCDGF8
11112
2


Explanation:

While Ans>9               ;loop until the product is one digit
Disp Ans                  ;display the current product
prod(                     ;get the product of...
int(                     ; the integer part of...
10fPart(                ; ten times the fractional part of...
Ans                     ; each element in the following list times the
;  current product
10^(                    ; multiplied by the list generated by using each
;  element of the following list as an exponent
;  for 10^n
seq(-X-1),X,0,log(Ans  ; generate a list of exponents from -1 to -L where
;  L = the length of the current product
End
Ans                       ;leave the final product in "Ans" and implicitly
; print it


Visual Model:
Ans starts off as 125673.
This model only covers the logic behind multiplying the digits; everything else is easier to understand.

seq(-X-1,X,0,log(Ans  =>  seq(-X-1,X,0,5.0992
{-1 -2 -3 -4 -5 -6}
10^(...
{.1 .01 .001 1E-4 1E-5 1E-6}
Ans...
{12567.3 1256.73 125.673 12.5673 1.25673 .125673}
fPart(...
{.3 .73 .673 .5673 .25673 .125673}
10...
{3 7.3 6.73 5.673 2.5673 1.25673}
int(...
{3 7 6 5 2 1}
(the digits of the number, reversed)
prod(...
1260
(process is repeated again)

seq(-X-1,X,0,log(Ans  =>  seq(-X-1,X,0,3.1004
{-1 -2 -3 -4}
10^(...
{.1 .01 .001 1E-4}
Ans...
{126 12.6 1.26 .126}
fPart(...
{0 .6 .26 .126}
10...
{0 6 2.6 1.26}
int(...
{0 6 2 1}
prod(...
0
(product is less than 10.  loop ends)


Notes:

TI-BASIC is a tokenized language. Character count does not equal byte count.

10^( is this one-byte token.

This program will not provide the correct sequence of products with integers greater than 14 digits long due to the limitations of decimal precision on the TI calculators.

• Can you save a byte by moving 10^( outside seq( and omitting the closing parenthesis? Apr 1 '19 at 11:15
• Yes, I believe so! Apr 1 '19 at 13:08

# K (ngn/k), 9 bytes

{*/.'$x}\  Try it online! { }\ keep applying the function in curly braces until the sequence converges $x format the argument as a string (list of characters)

.' evaluate each (other dialects of k require a colon, .:')

*/ times over, i.e. product

# R, 59 57 bytes

n=scan();while(print(n)>9)n=prod(n%/%10^(0:log10(n))%%10)


Try it online!

Since print invisibly returns its input, we can use print(n) inside the while loop to simulate a do-while loop. This is inspired by one of my tips for golfing in R.

The header helps prevent large numbers from being printed in scientific notation.

• 55 bytes (with possibly room for improvement, if you can find a shorter way of converting to character). Apr 11 at 19:28

# dzaima/APL, 14 11 bytes

∪{×/⍎¨⍕⍵}⍡≡


Try it online!

# 05AB1E, 7 4 bytes

Δ=SP


Explanation:

Δ     # Loop until the number no longer changes:
=    #  Print the number with trailing newline (without popping the number itself)
#  (which will be the implicit input in the first iteration)
SP  #  Convert the number to a list of digits, and calculate its product


# Wolfram Language (Mathematica), 47 bytes

Most@FixedPointList[Times@@IntegerDigits@#&,#]&


Try it online!

{$_,{[*] .comb}…10>*}  Try it online! # Python 2, 46 43 bytes -3 thanks to xnor (chained comparison) def f(n):print n;n>9>f(eval('*'.join(n)))  Try it online! • You can do > in place of and. – xnor Mar 22 '19 at 5:42 • @xnor thanks, easy to forget that will work. Mar 22 '19 at 7:42 # Wolfram Language (Mathematica), 39 bytes 0Print@#+#>9&&#0@@Times@@@RealDigits@#&  Try it online! -6 bytes from @att • 42 bytes if you don't mind using Echo. Jul 28 '19 at 22:01 • 39 bytes – att Apr 12 at 3:56 # Julia 0.7, 36 33 bytes f(n)=n>9?[n;f(prod(digits(n)))]:n  Try it online! Thanks to H.PWiz for -3 bytes. • You can use [n;f(prod(digits(n)))] Apr 20 '19 at 1:32 # V (vim), 29 bytes qqlYp:s/./&*/g C<C-r>=<C-r>"<BS> <esc>|@qq@q  Try it online! • Looks like you can change the l to a h (as in Razetime's answer), to remove the | Apr 9 at 10:37 # PowerShell, 54 bytes for($a=$args;$a-gt9){$a;$a=("$a"|% t*y)-join"*"|iex}$a


Try it online!

Iterative method that first writes the input argument, then converts it into a string and pipes it into a character array. This array is joined by a single asterisks, and executed as a command with the invoke expression alias. Since this writes Starting number down to the last number greater than 0, (20, in the given test scenario), I add a final $a to the end to output. # PowerShell, 51 bytes filter f{$_
if($_-gt9){("$_"|% t*y)-join'*'|iex|f}}


Try it online!

# C# (Visual C# Interactive Compiler), 7974 68 bytes

void f(int a){Print(a);if(a>9)f((a+"").Aggregate(1,(j,k)=>k%48*j));}


I try to stay away from recursion in C# due to how long the method declaration is, but in this case it saves compared to a loop.

Try it online!

<?=$n=$argn;while($n>9)echo" ",$n=array_product(str_split($n));  Iterative version, call with php -nF input from STDIN. Try it online! # PHP, 72 71 bytes function h($n){echo"$n ",($n=array_product(str_split($n)))>9?h($n):$n;}  Try it online! Recursive version, as function. Input: 277777788888899 277777788888899 4996238671872 438939648 4478976 338688 27648 2688 768 336 54 20 0  Input: 23 23 6  # J, 16 bytes ([:*/,.&.":)^:a:  Try it online! • This doesn’t work for very large numbers as it then switches into floating point mode, even putting x on the end doesn’t help ([:*/,.&.":)^:a:3777788889999977777777777x 3.77779e24 3.4448e21 0 0 May 3 '20 at 14:12 • @RichardDonovan Yes, you're right - thank you for your obsrevation! I don't know how to fix it. May 3 '20 at 18:12 • @GalenIvanov ([:*&x:/,.&.":)^:a: fixes it (you also need the x on the input), though I think your existing answer is still legal. Apr 11 at 11:52 • @Jonah Thank you! Apr 11 at 14:01 # Python 2, 6162 59 bytes def f(n):print n;n>9and f(reduce(int.__mul__,map(int,n)))  Try it online! -3 bytes, thanks to Jonathan Allan • Doesn't work for inputs that don't end with a 0 on their last iteration, for example 23 Mar 21 '19 at 15:40 • int.__mul__ is three bytes less than lambda a,b:a*b Mar 21 '19 at 17:17 • @JonathanAllan Thanks! I knew there had to be something like that Mar 21 '19 at 19:05 • Change f(reduce(int.__mul__,map(int,n))) to f(eval('*'.join(n))) to save 13 bytes. Mar 21 '19 at 20:34 • @mypetlion ...I already did that in another post. Mar 21 '19 at 20:52 # perl 5 (-n-M5.01), 3230 25 bytes say$_=eval;s/\B/*/g&&redo


25 bytes

30 bytes

32 bytes

• You should mention that this uses -lpF// Mar 22 '19 at 8:24
• @Grimy i could save 2 bytes without using -lpF//, updating Mar 22 '19 at 8:42

# MathGolf, 9 10 bytes

h(ôo▒ε*h(→


Try it online!

Now it correctly handles inputs that are single digits. Not perfect, but at least it is correct.

## Explanation

h(            check length of input number and decrease by 1
ö       →   while true with pop using the next 6 operators
p          print with newline
▒         split to list of chars/digits
ε*       reduce list by multiplication
h(     length of TOS without popping, subtracted by 1 (exits when len(TOS) == 1)

• The output for a single digit input should be one copy of the number - clarified in the comments Mar 21 '19 at 18:38
• @dzaima I'll look into it, and update the answer when it's solved
– maxb
Mar 22 '19 at 8:11

# JavaScript (ES6), 45 bytes

Returns an array of integers.

f=n=>[n,...n>9?f(eval([...n+''].join*)):[]]


Try it online!

# APL(NARS), 19 chars, 38 bytes

{⍵≤9:⍵⋄∇×/⍎¨⍕⍵⊣⎕←⍵}


test:

   f←{⍵≤9:⍵⋄∇×/⍎¨⍕⍵⊣⎕←⍵}
f 23
23
6
f 27648
27648
2688
768
336
54
20
0


## Haskell, 45 bytes

f n=n:[x|n>9,x<-f$product$read.pure<$>show n]  Try it online! # Ruby, 3835 34 bytes f=->n{p(n)>9&&f[eval n.digits*?*]}  Try it online! 1 byte saved by by G B. # Japt-R, 9 bytes Horribly inefficient - don't even try to run the first test case! _ì ×}hN â  Try it _ì ×}hN â :Implicit input of integer U N :Starting with the array of inputs (i.e., [U]) h :Do the following U times, pushing the result to N each time _ :Take the last element in N and pass it through the following function ì : Convert to digit array × : Reduce by multiplication } :End function â :Deduplicate N :Implicitly join with newlines and output  # Brachylog, 7 bytes ẉ?Ḋ|ẹ×↰  Try it online! ### Explanation ẉ Write the input followed by a linebreak ?Ḋ If the input is a single digit, then it's over | Otherwise ẹ Split the input into a list of digits × Multiply them together ↰ Recursive call with the result of the multiplication as input  • I gave it a try myself. Forgot about the Ḋ. The rest i had the same. Mar 21 '19 at 19:33 # JavaScript (Babel Node), 46 bytes f=a=>a>9?[a,...f(eval([...a+''].join*))]:[a]  Try it online! # JavaScript (Babel Node), 44 bytes If the input can be taken as String f=a=>a>9?[a,...f(''+eval([...a].join*))]:a  Try it online! • @Arnauld Yes, I just edited and added the wrong code. Im still looking for something using only strings instead arrays Mar 21 '19 at 15:12 # PowerShell, 64 59 bytes for($a="$args";9-lt$a){$a;$a="$(($a|% t*y)-join'*'|iex)"}$a  Try it online! Iterative method. Takes input and stores it into $a, then enters a for loop so long as the length of $a is two or more (i.e., it's bigger than 9). Inside the loop we output $a and then recalculate it by converting it toCharArray, joining it together with *, and then iex (short for Invoke-Expression and similar to eval). Once we're out of the loop, we have a single digit left to print, so we place $a onto the pipeline again. -5 bytes thanks to KGlasier. • You could use the comparison 9-lt$a instead of $a.length-1 to save 5 bytes. And if you didn't go string based the whole time you could cut off a decent chunk. Check out my powershell attempt if you want! Mar 21 '19 at 16:22 # Charcoal, 13 bytes θＷ⊖Ｌθ«≔ＩΠθθ⸿θ  Try it online! Link is to verbose version of code. Explanation: θ  Print the input for the first time. Ｗ⊖Ｌθ«  Repeat while the length of the input is not 1. ≔ＩΠθθ  Replace the input with its digital product cast to string. ⸿θ  Print the input on a new line. # 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.
`