53
\$\begingroup\$

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.

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

64 Answers 64

3
\$\begingroup\$

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`.
\$\endgroup\$
3
\$\begingroup\$

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

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

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

\$\endgroup\$
4
  • \$\begingroup\$ I'm pretty sure you only need to support int \$\endgroup\$
    – Gymhgy
    Mar 23, 2019 at 0:28
  • \$\begingroup\$ @EmbodimentofIgnorance then it fails for 277777788888899 since 4996238671872 is too large for an int \$\endgroup\$ Mar 23, 2019 at 18:31
  • \$\begingroup\$ 106 bytes by making it non-recursive. \$\endgroup\$ Jul 29, 2019 at 12:09
  • \$\begingroup\$ @KevinCruijssen thanks \$\endgroup\$ Jul 29, 2019 at 13:56
3
\$\begingroup\$

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

\$\endgroup\$
1
  • \$\begingroup\$ You can use *& instead to save some bytes \$\endgroup\$
    – user41805
    Apr 9, 2021 at 10:38
2
\$\begingroup\$

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!

\$\endgroup\$
2
  • 3
    \$\begingroup\$ I think you can move the call to m into the Footer portion of TIO, leaving this answer as 95 bytes \$\endgroup\$
    – Giuseppe
    Mar 22, 2019 at 0:33
  • 1
    \$\begingroup\$ Also, 81 bytes by removing some whitespace/formatting redundancy. \$\endgroup\$
    – Kirill L.
    Mar 23, 2019 at 9:46
2
\$\begingroup\$

PicoLisp, 73 72 bytes

(de f(x)(if(> 10 x)(list x)(cons x(f(apply *(mapcar format(chop x)))))))

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Japt, 15 bytes

I got some help from Shaggy on this one.

@pUÌì × Ì>9}f U

Run it online

\$\endgroup\$
2
\$\begingroup\$

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

Perl 6, 23 bytes

{$_,{[*] .comb}...10>*}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

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

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.

\$\endgroup\$
1
  • \$\begingroup\$ This (and mine) can be shortened by using 0:log10(x) instead of the nchar thing, I believe. \$\endgroup\$
    – Giuseppe
    Apr 11, 2021 at 18:36
2
\$\begingroup\$

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

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

\$\endgroup\$
2
  • \$\begingroup\$ -1 byte by replacing '0' with 48 \$\endgroup\$ Mar 21, 2019 at 19:41
  • 1
    \$\begingroup\$ With java 10 you could save a few bytes by writing var instead of String and so on. \$\endgroup\$
    – Socowi
    Mar 21, 2019 at 20:48
1
\$\begingroup\$

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.

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

Factor, 79 72 bytes

: f ( x -- ) [ 10 >base [ 48 - ] map product dup dup . 9 > ] loop drop ;

Try it online!

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

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!

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

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

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!

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

C, 138 115 bytes

long atol(char*);main(c,v)char**v;{long z=1,n=atol(v[1]);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[1]);
    for(; printf("%ld\n", n), n > 9; n = z, z = 1)
        for(; z *= n % 10, n /= 10;);
}
\$\endgroup\$
2
  • \$\begingroup\$ for can save you quite a few bytes. \$\endgroup\$
    – att
    Mar 24, 2019 at 6:14
  • \$\begingroup\$ Suggest int**v instead of char**v \$\endgroup\$
    – ceilingcat
    Apr 21, 2019 at 6:37
1
\$\begingroup\$

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}~>

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

C# (.NET Core), 192 191 180 bytes

using C=System.Console;class A{static void Main(string[] a){long i,k;var b=a[0];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[0];
        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[0];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!

\$\endgroup\$
2
  • \$\begingroup\$ Saved 1 byte - moved C.WriteLine(b) into loop opening as well as iterator \$\endgroup\$
    – Stackstuck
    Mar 24, 2019 at 4:01
  • \$\begingroup\$ Saved 11 bytes with assorted rearrangements. \$\endgroup\$
    – Stackstuck
    Mar 25, 2019 at 15:16
1
\$\begingroup\$

Pyth, 9 bytes

j.u*FsM`N

Try it here!

If we're allowed to output as an array, the j at the start is unnecessary, giving 8 bytes.

\$\endgroup\$
1
  • \$\begingroup\$ You can also omit the N at the end, since Pyth implicitly adds lambda variables at the end of a program if needed. \$\endgroup\$
    – hakr14
    Jul 28, 2019 at 22:42
1
\$\begingroup\$

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

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

Clojure, 73 bytes

#(loop[i %](prn i)(if(> i 9)(recur(apply *(for[c(str i)](-(int c)48))))))
\$\endgroup\$
1
\$\begingroup\$

Scala, 83 bytes

def^(n:Long):Long={println(n);if(n>9)^((n+"").map(x=>(x-48).toLong).product)else n}

Try it online!

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

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

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

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.

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

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

Python 3, 47 bytes

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

First Python 3 answer here.

Try it online!

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

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.