g | x | w | all
Bytes Lang Time Link
059POSIX Shell + Utilities221219T032051Zнабиячлэ
026dc250810T101428ZToby Spe
030APLNARS250809T085137ZRosario
004Vyxal 3.8250807T090615ZThemooni
005Nekomata250808T071226Zalephalp
065Setanta250806T215308Zbb94
067Tcl250807T112155Zsergiol
051AWK250806T175054Zxrs
01305AB1E231201T212414ZFlummox
087Go231128T155634Zbigyihsu
002Vyxal 3231128T143428Zpacman25
029><>221219T165120ZEmigna
038FunStack alpha221220T061809ZDLosc
047Python 3221220T040029ZU13-Forw
040Factor + math.unicode221220T022404Zchunes
nan221219T050434ZRARE Kpo
006Pyt221218T164944ZKip the
009Pip210501T020131ZDLosc
042Befunge98 FBBI210411T150432Zovs
039Wolfram Language Mathematica190321T151859ZZaMoC
055R210411T155202ZDominic
057R190321T145023ZGiuseppe
029V vim210408T110751ZRazetime
029V vim210408T154928ZDJMcMayh
003Vyxal210408T121228Zlyxal
005Husk201004T070535ZRazetime
083Scala190729T155440ZDr Y Wit
100Chevron190729T143233ZSuperloa
106Java190321T193942ZBenjamin
073Clojure190728T201125ZNikoNyrh
009Japt R190322T195709ZShaggy
072c++190422T072655Zjdt
023Perl 6190420T153655Zbb94
033Julia 0.7190321T144450ZKirill L
031TIBASIC TI84190321T162234Zabsolute
009Pyth190322T232850ZRK.
004Stax190325T161318Zrecursiv
180C# .NET Core190324T033309ZStackstu
027Attache190324T153433ZConor O&
115C190322T204026Zqookie
058C gcc190322T075235Zatt
107Racket190323T092315ZGalen Iv
010MathGolf190321T151255Zmaxb
015Japt190322T185552ZOliver
072PicoLisp190322T154402ZGalen Iv
009K ngn/k190321T151819Zngn
100SNOBOL4 CSNOBOL4190322T133302ZGiuseppe
087Python 2190322T132558Zakozi
00405AB1E190321T143029ZKevin Cr
043Python 2190321T173341ZJonathan
025perl 5 n M5.01190321T162135ZNahuel F
034Ruby190321T142944ZKirill L
072Factor190321T194728ZGalen Iv
004Jelly190321T150829ZNick Ken
115Swift190321T212612Zonnoweb
066ink190321T212538ZSara J
104java 8190321T170042ZNahuel F
011dzaima/APL190321T143718Zdzaima
059Python 2190321T153909ZTFeld
016J190321T190559ZGalen Iv
063PHP190321T162008Z640KB
045Haskell190321T174206Znimi
024Retina190321T170132ZNeil
013Charcoal190321T164853ZNeil
038APLNARS190321T164143Zuser5898
068C# Visual C# Interactive Compiler190321T153047ZGymhgy
051PowerShell190321T163155Zmazzy
059PowerShell190321T144912ZAdmBorkB
054PowerShell190321T155317ZKGlasier
023Perl 6190321T155017ZGrimmy
046JavaScript Babel Node190321T142904ZLuis fel
007Brachylog190321T143241ZFatalize
045JavaScript ES6190321T142425ZArnauld
047Wolfram Language Mathematica190321T142550ZZaMoC

POSIX Shell + Utilities, 59 bytes

echo $1
[ ${#1} = 1 ]||$0 $(echo $1|fold -w1|paste -sd*|bc)

Demo

$ 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

dc, 26 bytes

[p[A~rd9<x*]dsxxd9<y]dsyxp

Try it online!

There are two recursive functions (probably not surprisingly):

Function y is the main function. It prints the top of stack (where we found our input, then defines and runs function x, repeating while the result is greater than 9.

Function x is defined every time around the loop (which is a byte shorter than defining it just once at the beginning). It repeatedly divides by ten, leaving the remainder on the stack, then multiplies these remainders.

Finally, after executing y, we need to print the resulting product that's now less than ten.

APL(NARS), 30 chars

f w
⎕←w⋄→0×⍳w≤9⋄w←×/1x,⍎¨⍕w⋄→1

//4+26=30

I don't know if it is right, if number is too much big has need number x type=rational as input. It could be right if the w←×/1x,⍎¨⍕w extend the type big rational to w each time.

  f 1
1
  f 25
25
10 
0 
  f 327
327
42 
8 
  f 68889
68889
27648 
2688 
768 
336 
54 
20 
0 
  f 277777788888899
277777788888899
4996238671872 
438939648 
4478976 
338688 
27648 
2688 
768 
336 
54 
20 
0 
  f 1111111277777788888899
1.111111278E21
SYNTAX ERROR
  f 1111111277777788888899x      
1111111277777788888899 
4996238671872 
438939648 
4478976 
338688 
27648 
2688 
768 
336 
54 
20 
0 

Vyxal 3.8, 4 bytes

⑵fΠl

Vyxal It Online!

⑵fΠl­⁡​‎‎⁡⁠⁡‏⁠‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁢‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁣‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁤‏‏​⁡⁠⁡‌­
⑵     # ‎⁡next 2 as lambda:
 f    # ‎⁢split each digit
  Π   # ‎⁣product of that
   l  # ‎⁤apply lambda to implicit input until the result doesn't change, implicit print
💎

Created with the help of Luminespire.

<script type="vyxal3">
⑵fΠl
</script>
<script>
    args=[["277777788888899"],["25"],["68889"],["327"]]
</script>
<script src="https://themoonisacheese.github.io/snippeterpreter/snippet.js" type="module"/>

Nekomata, 5 bytes

ᶦ{ZƊ∏

Attempt This Online!

ᶦ{ZƊ∏
ᶦ{      Apply the following function zero or more times non-deterministically
  Z         Check that the input is nonzero
   Ɗ        Decimal digits
    ∏       Product

By default, Nekomata will print all possible results separated by newlines.

Setanta, 65 bytes

gniomh f(n){scriobh(n)ma n>9 {o:=1nuair-a n {o*=n%10n//=10}f(o)}}

try-setanta.ie link

Non-recursive solution, 77 bytes

gniomh(n){S:=scriobh S(n)nuair-a n>9 {o:=1nuair-a n {o*=n%10n//=10}n=o S(n)}}

try-setanta.ie link

Tcl, 67 bytes

proc P v {while \$v>9 {puts [set v [expr [join [split $v ""] *]]]}}

Try it online!

AWK, 51 bytes

{for(;$0>9;i=0){print;for(x=1;i++<NF;)x*=$i;$0=x}}1

Attempt This Online!

05AB1E, 13 bytes

,[1svy*}Ð,gΘ#

Try it online!

Explanation:

,            //Print input
[            //Begin infinite loop
    1s       //Set 1 to the item before the input in the stack
    v        //Loop over the input
        y*   //Add the current character to the stack and multiply
    }        //End loop
    Ð        //Triplicate result
    ,        //Print result
    gΘ       //Check if length == 1
#            //If so, end

Leaving out the two prints can save two bytes while still outputting the result, thanks to implicit output. Without that restriction this would be 11.

Go, 87 bytes

import."fmt"
func f(n int){Println(n)
s:=1
if n<10{return}
for;n>0;n/=10{s*=n%10}
f(s)}

Attempt This Online!

Vyxal 3, 2 bytes

ᵘΠ

Try it Online!

2 bytes with a new modifier. Come try Vyxal 3!

><>, 31 29 bytes

Saved 2 bytes thanks to Jo King

:nao:a),1}\~
1:,a}*{%a:/!?:-%

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

Python 3, 47 bytes

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

First Python 3 answer here.

Try it online!

Factor + math.unicode, 40 bytes

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

Try it online!

it's not efficient but gets the job done

echo 777777777777777777777777777777777779999999999999999999933333333333  |


gawk -M 'function __(_){return _*_==_?+$_:$_*__(--_)}($_=__(NF*=!/0/))_' FS=
815859530632739726716133814001433680647636177446909421

Pyt, 6 bytes

Đ`ҎĐłŕ

Try it online!

Đ         Implicit input; duplicate top of stack
 `  ł     do while top of stack is not 0 (consumes top of stack when checking)
  Ҏ       digit product of top of stack
   Đ      duplicate top of stack
     ŕ    remove top of stack (duplicate 0); implicit print

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.

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

Wolfram Language (Mathematica), 39 bytes

0Print@#+#>9&&#0@@Times@@@RealDigits@#&

Try it online!

-6 bytes from @att

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.

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.

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

V (vim), 29 bytes

qqlYp:s/./&*/g
C<C-r>=<C-r>"<BS>
<esc>|@qq@q

Try it online!

Vyxal, j, 3 bytes

⁽Π↔

Try it Online!

Very nice little 3 byter here. Uses the same method as the 05ab1e answer.

Explained

⁽Π↔
⁽Π  # lambda x: product(x) // treats numbers as a list of digits
 ↔ # repeat the above function until the result doesn't change, collecting intermediate results. 

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

Scala, 83 bytes

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

Try it online!

Chevron, 100 bytes

>^__>>^n
->+11?^n<10
>^n
^d<<1
^i<<1
^m<^i>^n
->+4??^m=^__
^d<<^d*^m
^i<<^i+1
->-4
^n<<^d
->-10
><^n

This is a fairly new language of my own creation - prototype interpreter, documentation, and example programs can be found at https://github.com/superloach/chevron.

Explanation:

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

Clojure, 73 bytes

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

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

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

Perl 6, 23 bytes

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

Try it online!

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.

TI-BASIC (TI-84), 30 32 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.

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.

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

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!

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, 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;);
}

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

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!

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)

Japt, 15 bytes

I got some help from Shaggy on this one.

@pUÌì × Ì>9}f U

Run it online

PicoLisp, 73 72 bytes

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

Try it online!

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

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

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!

05AB1E, 7 4 bytes

Δ=SP

Try it online or verify all test cases.

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

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!

perl 5 (-n -M5.01), 32 30 25 bytes

say$_=eval;s/\B/*/g&&redo

25 bytes

30 bytes

32 bytes

Ruby, 38 35 34 bytes

f=->n{p(n)>9&&f[eval n.digits*?*]}

Try it online!

1 byte saved by by G B.

Factor, 79 72 bytes

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

Try it online!

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.

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!

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.

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

dzaima/APL, 14 11 bytes

∪{×/⍎¨⍕⍵}⍡≡

Try it online!

Python 2, 61 62 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

J, 16 bytes

([:*/,.&.":)^:a:

Try it online!

PHP, 63 bytes

<?=$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

Haskell, 45 bytes

f n=n:[x|n>9,x<-f$product$read.pure<$>show n]

Try it online!

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

Charcoal, 13 bytes

θW⊖Lθ«≔IΠθθ⸿θ

Try it online! Link is to verbose version of code. Explanation:

θ

Print the input for the first time.

W⊖Lθ«

Repeat while the length of the input is not 1.

≔IΠθθ

Replace the input with its digital product cast to string.

⸿θ

Print the input on a new line.

APL(NARS), 19 chars, 38 bytes

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

test:

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

C# (Visual C# Interactive Compiler), 79 74 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!

PowerShell, 51 bytes

filter f{$_
if($_-gt9){("$_"|% t*y)-join'*'|iex|f}}

Try it online!

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.

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.

Perl 6, 23 bytes

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

Try it online!

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!

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

JavaScript (ES6), 45 bytes

Returns an array of integers.

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

Try it online!

Wolfram Language (Mathematica), 47 bytes

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

Try it online!