The Non-Zero Digital Product Challenge

Originally the Multiplicative digital root

Challenge

Basically do what the title says

Method

Given a positive integer 1 <= N <= 100000000 through one of our standard input methods, multiply every digit together, ignoring zeroes.

Ex: Take a number, say 361218402:

• 3 * 6 = 18
• 18 * 1 = 18
• 18 * 2 = 36
• 36 * 1 = 36
• 36 * 8 = 288
• 288 * 4 = 1152
• 1152 * 1 (ignore zeroes or turn them into ones) = 1152
• 1152 * 2 = 2304

The output for 361218402 is 2304

Test Cases

1 => 1
every other digit > 0 => itself
10 => 1
20 => 2
100 => 1
999 => 729
21333 => 54
17801 => 56
4969279 => 244944
100000000 => 1


Standard Loopholes are disallowed, and this is , so shortest byte count wins!

Congrats to Jo King who got the bounty with his 70 byte brain-flak answer!

• I'd rather call this non-zero digital product. "root" suggests it reduces to a single digit, which isn't always true here. Jan 15, 2018 at 20:46
• Can we take input as a string? Or (pushing it) an array of digits? Jan 15, 2018 at 21:19
• @EriktheOutgolfer Yes, however, if you repeat the process enough times, it does appear to always go to a single digit. Jan 15, 2018 at 21:21
• You can take quoted input, but no, you can't take a pre-parsed list of digits if that's what you're asking Jan 15, 2018 at 21:21
• If we have to support to a max of 100000000000 I suggest the test case 99999999999 => 31381059609, since it doesn't fit in a default 32-bit integer. Perhaps better would be to lower the maximum output to a 32-bit maximum (2147483647). Jan 16, 2018 at 8:27

foldr((*).max 1.read.pure)1


Try it online!

Ungolfed with UniHaskell and -XUnicodeSyntax

import UniHaskell

f ∷ String → Int
f = product ∘ map (max 1 ∘ read ∘ pure)


Explanation

product.map(max 1.read.pure)


This is a point-free expression that evaluates to a function taking a string (or a list of characters) s ("301") as an argument. It maps max 1.read.pure over s, essentially taking each character i, injecting it into a list (which makes it a string) (["3", "0", "1"]), then reading it, which evaluates the string ([3, 0, 1]) and finally taking the greater of i and 1 ([3, 1, 1]). Then it takes the product of the resulting list of integers (3).

I then golfed it by a byte with:

foldr((*).max 1.read.pure)1


This works because product is equivalent to foldr (*) 1. Instead of mapping and folding, I combined the two by folding with (*).max 1.read.pure which takes each non-zero digit and multiplies it with the accumulator.

Python 2, 34 bytes

f=lambda n:n<1or(n%10or 1)*f(n/10)


Try it online!

Jelly, 4 bytes

Do1P


Try it online! or see the test suite

How it works

Do1P - Main link. Argument: n (integer)  e.g. 1230456
D    - Digits                                 [1, 2, 3, 0, 4, 5, 6]
o1  - Replace 0 with 1                       [1, 2, 3, 1, 4, 5, 6]
P - Product                                720


R, 40 bytes

cat(prod((x=scan()%/%10^(0:12)%%10)+!x))


Try it online!

Since input is guaranteed to have no more than 12 digits, this should work nicely. Computes the digits as x (including leading zeros), then replaces zeros with 1 and computes the product.

cat(					#output
prod(				#take the product of
(x=				#set X to
scan()			#stdin
%/%10^(0:12)%%10)	#integer divide by powers of 10, mod 10, yields digits of the input, with leading zeros. So x is the digits of the input
+!x  #add logical negation, elementwise. !x maps 0->1 and nonzero->0. adding this to x yields 0->1, leaving others unchanged
))

• So this is how to codegolf with R... Nice one ;) Still trying to figure out how this one works though! Jan 20, 2018 at 9:23
• @Florian I've added a more verbose explanation. Jan 20, 2018 at 15:01
• That's a new way to split digits that I'll have to try!
– BLT
Mar 1, 2018 at 13:56
• @BLT that's one of my tips for golfing in R! Mar 1, 2018 at 14:01

C (gcc), 39 bytes

k;f(n){for(k=1;n;n/=10)k*=n%10?:1;k=k;}


Needs to be compiled without optimizations (which is the default setting for gcc, anyway).

Try it online!

• That k=k; putting k in the return register accidentally is just plain evil. You should probably add that this only works without optimisations on possibly only x86/x64. +1. Jan 16, 2018 at 23:34
• @tomsmeding Somewhat surprisingly, it does work on architectures other than x86. No optimizations (O0) is the default for gcc, so there is no need for explicitly using that flag. I guess I'll add a mention of it to the post anyway. Jan 16, 2018 at 23:40
• You might want to specify the exact version of GCC it works with, for future proofing. Mar 1, 2018 at 14:32
• @moonheart08 I doubt that it would stop working after some version. Anyway, it works with the latest version, so the time of posting can be used to find a version with which it at least works. Mar 2, 2018 at 20:13

Brain-Flak, 7472 70 bytes

-2 thanks to Nitrodon for suggesting getting the negation of the number so that you only have to increment rather than decrement later

{([{}]((((()()()){}){}){}){}){({<({}())><>([[]](){})<>}<><{}>)<>}{}}<>


Try it online!

There might be a few ways to golf this further, such as redoing the multiplication to avoid having to initialise the total with 1. (-2 bytes)

How It Works:

{ Loop over every number
([{}]((((()()()){}){}){}){}) Add 48 to the negative of the ASCII to get the negation of the digit
{ If the number is not 0
({<({}())><>([[]](){})<>}<><{}>)<> Multiply the total by the number
If the total is on an empty stack, add 1
}
{} Pop the excess 0
}<> Switch to the stack with the total

• You can golf two more bytes by computing the negation of the actual digit, then counting up to 0 instead of down to 0. Jan 18, 2018 at 5:21

05AB1E, 4 bytes

0KSP


Try it online!

Explanation

0K     # remove zeroes
S    # split to list of digits
P   # product

• I accepted this answer because it was a four way tie between Jelly, husk, and 05AB1E, and you answered first. Jan 29, 2018 at 2:05

J, 1714 13 bytes

-4 bytes courtesy of @GalenIvanov

[:*/1>.,.&.":


Try it online!

Probably can be improved some. Edit: and so it was.

Explanation

[: */ 1 >. ,.&.":
": Convert to string
,.     Convert row to column vector
&.   Convert to numbers
1 >.        Maximum of each element with 1 (convert 0 to 1)
*/              Product
[:                 Cap fork


&.-under is a nifty adverb that applies the verb on the right, then the verb on the left, then the inverse of the verb on the right. Also converting back to numbers is technically using eval (".-do).

• You can save a byte by changing +0=] to *#] Try it online Jan 16, 2018 at 8:18
• [:*/0-.~,.&.": for 14 bytes. Try it online Jan 16, 2018 at 12:22
• @GalenIvanov I knew that signum would be useful! My original thought was (+-.@*), guess I'm inclined to add. I had tried using '0'-.~ assuming an input of a string, not sure why it didn't cross my mind to do it on the split digits. Thanks!
– cole
Jan 16, 2018 at 16:30
• 1>. does the job of 0-.~ for a byte less. [:*/1>.,.&.": Try it! Jan 16, 2018 at 18:25

Pyt, 3 bytes

ąžΠ


Explanation:

ą       Convert input to array of digits (implicit input as stack is empty)
ž      Remove all zeroes from the array
Π     Get the product of the elements of the array


Try it online!

• Surprised that this relatively new golfing lang is the only one that appears to be capable of solving this challenge in 3 bytes! Jan 15, 2018 at 21:55
• I was surprised by that too! Jan 15, 2018 at 23:58
• I didn't see your answer when I first accepted, but this is the shortest one! Feb 17, 2018 at 17:24

Python 2, 43 bytes

lambda n:eval('*'.join(n.replace(*'01')))


Try it online!

JavaScript (ES6), 28 bytes

Designed for 32-bit integers.

f=n=>!n||(n%10||1)*f(n/10|0)


Test cases

f=n=>!n||(n%10||1)*f(n/10|0)

console.log(f(1))        // => 1
console.log(f(10))       // => 1
console.log(f(20))       // => 2
console.log(f(100))      // => 1
console.log(f(999))      // => 729
console.log(f(21333))    // => 54
console.log(f(17801))    // => 56
console.log(f(4969279))  // => 244944

Bash + coreutils + sed + bc, 2724 23 bytes

tr 0 1|sed s/\\B/*/g|bc


Try it online!

Brachylog, 5 bytes

⊇ẹ×ℕ₁


Try it online!

Explanation

⊇        Take a subset of the input
ẹ       Split the subset into a list of digits
×      Product
ℕ₁    This product must be in [1, +∞)


This works because ⊇ unifies from large subsets to small subsets, so the first one that will result in a non-zero product is when all zeroes are excluded and nothing else.

Perl 5, 23 + 1 (-p) = 24 bytes

$\=1;s/./$\*=$&||1/ge}{  Try it online! Java 8, 555453 51 bytes int f(int n){return n>0?(n%10>0?n%10:1)*f(n/10):1;}  Port of @Dennis' Python 2 answer. -1 byte thanks to @RiaD. Try it here. 55 54 bytes version: n->{int r=1;for(;n>0;n/=10)r*=n%10>0?n%10:1;return r;}  Try it online. • you can save parens like this: long f(long n){return n>0?(n%10>0?n%10:1)*f(n/10):1;} – RiaD Jan 16, 2018 at 10:16 • Sorry, I'm claiming this one (45 bytes) because the algorithm is totally different ;-) Jan 17, 2018 at 13:45 Julia 0.6, 26 bytes !x=prod(max.(digits(x),1))  Example of use: julia> !54 20  Try it online! • could you add an example of how to call this, as well as a byte count? you can use TIO! Jan 17, 2018 at 14:56 • @Giuseppe oops, I got distracted. I counted the length but didn't add it. Huh TIO supports julia now. Neat. Jan 17, 2018 at 15:15 • In fact, TIO supports Julia 0.4-0.6! very nice, +1. Jan 17, 2018 at 15:22 JavaScript (Node.js), 30 bytes f=([a,...b])=>a?(+a||1)*f(b):1  Try it online! Takes string as an input, treats it as array, and by array destructuring separates the first element [a,...b]. +a||1 returns digit corresponding to a character. I guess that rest is self explaining.. Octave, 21 bytes Thanks to @Luis Mendo for saving a byte and thanks to @alephalpha for saving another byte! @(n)prod((k=n-48)+~k)  Takes input as a string of digits. Try it online! 30 bytes: @(n)prod((k=num2str(n)-48)+~k)  Takes input as a number. Try it online! Brain-Flak, 88 bytes Readable version: #Push a 1 onto the alternate stack. Return to the main stack (<>())<> #While True: { #Push the current digit minus 48 (the ASCII value of '0') onto the alternate stack ({}[((((()()()){}){}){}){}]<>) #If it's not 0... { (< #Multiply the top two values (the current digit and the current product that started at 1) ({}<>)({<({}[()])><>({})<>}{}<><{}>) #Also push a 0 >) #Endwhile } #Pop the 0 {} #Return to the main stack <> #Endwhile } #Toggle to the alternate stack, and implicitly display <>  Try it online! • 74 bytes – Jo King Jan 16, 2018 at 2:06 • I literally forgot I posted that comment, and rewrote it from scratch. I'm just going to post separately – Jo King Jan 18, 2018 at 1:15 Clojure, 56 bytes (fn[n](apply *(replace{0 1}(map #(-(int %)48)(str n)))))  Pretty basic. Turns the number into a string, then subtracts 48 from each character to turn them back into numbers. It then replaces each 0 with a 1, and applies * to the resulting list of numbers (which reduces * over the list). Can accept a number, or a stringified number. Try it online! (defn non-zero-prod [n] (let [; Abusing strings to get each digit individually str-n (str n) ; Then turn them back into numbers digits (map #(- (int %) 48) str-n) ; Substitute each 0 for a 1 replaced (replace {0 1} digits)] ; Then get the product (apply * replaced)))  MATL, 5 bytes !UXzp  Input is taken as a string Explanation ! % Implicit input: string (row vector of chars). Transpose into % a column vector of chars U % Convert from string to number. Treats each row independently, % producing a column vector of numbers Xz % Keep only nonzeros p % Product. Implicit display  Befunge, 23 22 bytes 1<*_$#.#0@#:+!:-"0"~$ Try it online! Explanation 1< Push 1, turn back left, and push a second 1.$    Drop one of them, leaving a single 1, the initial product.

-"0"~     Read a char and subtract ASCII '0', converting to a number.
+!:          If it's 0, make it 1 (this is n + !n).
0  :             Then test if it's greater than 0, to check for EOF.
_                      If it is greater than 0, it wasn't EOF, so we continue left.
*                       Multiply with the current product, becoming the new product.
1<                        Now we repeat the loop, but this time push only a single 1...
$...which is immediately dropped, leaving the current product. _ On EOF, the input value will be negative, so we branch right.$                     We don't need the input, so drop it.
.  @               Leaving us with the product, which we output, then exit.


JavaScript (Node.js), 36 33 bytes

Simple Javascript (ES6) method that takes input as number string, spreads it into an array, then reduces it through multiplication or returns the value if the result is 0.

3 bytes saved thanks to Shaggy

s=>[...s].reduce((a,b)=>b*a||a,1)


Try it online!

• Save 3 bytes by taking input as a string. Jan 16, 2018 at 8:18
• I don't know why I thought it had to be converted, thanks :D Jan 16, 2018 at 15:27

Ruby, 42403532 27 bytes

p eval (gets.chars-[?0])*?*


Assumes no newlines in input Major influence

-2 bytes thanks to @GolfWolf

-5 bytes thanks to @Conor O'Brien

• Even shorter than tr: 32 bytes Jan 16, 2018 at 6:50
• @GolfWolf Clever :) Jan 16, 2018 at 7:19
• Might your perhaps use * to join? p eval (gets.chars-[?0])*?* ? Jan 16, 2018 at 23:20

Java (OpenJDK 8), 45 bytes

s->s.chars().reduce(1,(a,b)->b<49?a:a*(b-48))


Try it online!

C#, 97 Bytes (First code golf)

static int X(int y){var z=y.ToString();int r=1;foreach(var q in z){if(q!=48){r*=q-48;}}return r;}


Not sure if i had to wrap it in a method or not so just included it to be safe.

Takes an Int in, converts it to a string and returns the multiple of each of the characters ignoring 0's. Had to minus 48 due to the program using the ascii value as it reads it as a char.

• Welcome to PPCG! I no nothing of C#, but this should help you understand the rules for golfing in it. Mar 1, 2018 at 17:00
• Thanks @H.PWiz I really am starting to love these little challenges, definitely making me change my regular programming to be more concise and efficient. Mar 15, 2018 at 11:47
• Welcome and nice first try :D Some tips for your answer: you can remove the var z=y.ToString(); and place it directly in the foreach, like so: foreach(var q in y.ToString()); and to get the result you can save more bytes by replacing {if(q!=48){r*=q-48;}} with r*=(q>48?q:1);, shaving off the brackets and the if. Sep 23, 2019 at 16:56

C# (Visual C# Interactive Compiler), 46 bytes

i.Select(c=>c>48?c-48:1).Aggregate((p,c)=>p*c)


Try it online!

f n=product[read[d]|d<-show n,d>'0']


Same byte count:

f n=product[max 1\$read[d]|d<-show n]


Try it online!

• Also 36 Jan 15, 2018 at 20:56

Jelly, 6, 5 bytes

ṢU×\Ṁ


Try it online!

• 5 mins, not bad! Jan 15, 2018 at 20:26
• DTịDP would save a byte, but there are better ways to strip zeroes or replace them with something else. Jan 15, 2018 at 20:34
• Multiplicative root with ṢUṀ Jan 15, 2018 at 20:44

><>, 19 bytes

1i:&0(?n&c4*-:0=+*!


Try it online!