\ Solution proposed by A. Vidovic - 2021-12-12 - vido@ldh.org [IFDEF] my-code my-code [ENDIF] marker my-code init-included-files \ We will reserve a buffer for up to 255 digits. This is enough for 140! \ the first byte contains the number of digits variable factbuf 256 allot : store-digit ( n pos -- ) factbuf + c! ; \ append one or two digits to the factbuf and updates its length : append-digits-to-factbuf ( n -- ) factbuf c@ 1+ swap dup 10 < if over store-digit factbuf c! else dup 10 / swap over 10 * - rot dup 1+ -rot store-digit dup factbuf c! store-digit then ; \ Encode the input into the buffer as the starting value. \ Note : zero and negative is set to give a result of 1. : init-factbuf ( n -- ) 0 factbuf c! dup 0<= if drop 1 then dup 100 < if append-digits-to-factbuf else dup 140 < if 100 - append-digits-to-factbuf 1 append-digits-to-factbuf else drop cr ." Overflow error" then then ; \ Write the number encoded in factbuf. : print-fact ( -- ) factbuf c@ dup 0<= if drop cr ." Nothing to display." else factbuf swap over + do i c@ 48 + emit 1 -loop cr then ; \ Core atom : multiply current digit by current multiplicator, add previous carry and prepare next carry : fact-atom ( carry0 multiplicator digit -- carry1 result-digit ) * + dup 10 / swap over 10 * - ; \ One iteration with one multiplicator, using the factbuf : fact-iteration ( multiplicator -- ) 0 swap factbuf dup c@ swap 1+ dup rot + swap do swap over i c@ fact-atom i c! swap loop drop dup 0> if append-digits-to-factbuf else drop then ; \ Computes the full factorial of the input into the buffer : compute-factorial ( n -- ) dup init-factbuf dup 1 > if 1 do i fact-iteration loop else drop then ; \ Compute and display the result : factorial ( n -- ) compute-factorial print-fact ; --- \ the "extra credit" thing. Just count the number of zeroes at the reverse-end of the buffer. : number-of-trailing-zeroes ( -- n ) 0 factbuf c@ 0> if factbuf 1+ begin dup c@ 0= while swap 1+ swap 1+ repeat drop then ;