28
\$\begingroup\$

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

Note: Treat the digit 0 in numbers as 1.

Test Cases

1 => 1
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!

\$\endgroup\$
6
  • 6
    \$\begingroup\$ I'd rather call this non-zero digital product. "root" suggests it reduces to a single digit, which isn't always true here. \$\endgroup\$ Jan 15, 2018 at 20:46
  • 1
    \$\begingroup\$ Can we take input as a string? Or (pushing it) an array of digits? \$\endgroup\$
    – Shaggy
    Jan 15, 2018 at 21:19
  • \$\begingroup\$ @EriktheOutgolfer Yes, however, if you repeat the process enough times, it does appear to always go to a single digit. \$\endgroup\$
    – DJMcMayhem
    Jan 15, 2018 at 21:21
  • \$\begingroup\$ You can take quoted input, but no, you can't take a pre-parsed list of digits if that's what you're asking \$\endgroup\$
    – qqq
    Jan 15, 2018 at 21:21
  • 8
    \$\begingroup\$ 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). \$\endgroup\$ Jan 16, 2018 at 8:27

69 Answers 69

11
\$\begingroup\$

Haskell, 27 bytes

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

I'll start with what I initially had:

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.

\$\endgroup\$
9
\$\begingroup\$

Python 2, 34 bytes

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

Try it online!

\$\endgroup\$
0
7
\$\begingroup\$

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

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

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!

\$\endgroup\$
4
  • \$\begingroup\$ 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. \$\endgroup\$
    – tomsmeding
    Jan 16, 2018 at 23:34
  • 1
    \$\begingroup\$ @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. \$\endgroup\$
    – Steadybox
    Jan 16, 2018 at 23:40
  • \$\begingroup\$ You might want to specify the exact version of GCC it works with, for future proofing. \$\endgroup\$ Mar 1, 2018 at 14:32
  • \$\begingroup\$ @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. \$\endgroup\$
    – Steadybox
    Mar 2, 2018 at 20:13
5
+100
\$\begingroup\$

Brain-Flak, 74 72 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
\$\endgroup\$
5
  • 2
    \$\begingroup\$ You can golf two more bytes by computing the negation of the actual digit, then counting up to 0 instead of down to 0. \$\endgroup\$
    – Nitrodon
    Jan 18, 2018 at 5:21
  • \$\begingroup\$ Dang it. I thought with the compression I finally beat a brain-flak answer, but then I ran the same algorithm on yours and got only 26.25 bytes \$\endgroup\$
    – Dadsdy
    Jun 16, 2023 at 3:15
  • \$\begingroup\$ @Dadsdy further brain-flak compression can get it down to ~19.81 bytes actually \$\endgroup\$
    – Jo King
    Jun 16, 2023 at 7:15
  • \$\begingroup\$ @JoKing huh. How? I might steal that algorithm and shrink mine down more \$\endgroup\$
    – Dadsdy
    Jun 16, 2023 at 12:52
  • \$\begingroup\$ @Dadsdy Compressed brain-flak drops it down to 50 bytes, times log_256(9). I'm not sure it's relevant, though perhaps you could replace ()s with a single char \$\endgroup\$
    – Jo King
    Jun 17, 2023 at 3:51
4
\$\begingroup\$

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!

\$\endgroup\$
2
  • \$\begingroup\$ Surprised that this relatively new golfing lang is the only one that appears to be capable of solving this challenge in 3 bytes! \$\endgroup\$ Jan 15, 2018 at 21:55
  • \$\begingroup\$ I was surprised by that too! \$\endgroup\$
    – mudkip201
    Jan 15, 2018 at 23:58
4
\$\begingroup\$

05AB1E, 4 bytes

0KSP

Try it online!

Explanation

0K     # remove zeroes
  S    # split to list of digits
   P   # product
\$\endgroup\$
1
  • \$\begingroup\$ I accepted this answer because it was a four way tie between Jelly, husk, and 05AB1E, and you answered first. \$\endgroup\$
    – qqq
    Jan 29, 2018 at 2:05
4
\$\begingroup\$

J, 17 14 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).

\$\endgroup\$
4
  • 1
    \$\begingroup\$ You can save a byte by changing +0=] to *#] Try it online \$\endgroup\$ Jan 16, 2018 at 8:18
  • 1
    \$\begingroup\$ [:*/0-.~,.&.": for 14 bytes. Try it online \$\endgroup\$ Jan 16, 2018 at 12:22
  • \$\begingroup\$ @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! \$\endgroup\$
    – cole
    Jan 16, 2018 at 16:30
  • 1
    \$\begingroup\$ 1>. does the job of 0-.~ for a byte less. [:*/1>.,.&.": Try it! \$\endgroup\$ Jan 16, 2018 at 18:25
3
\$\begingroup\$

Python 2, 43 bytes

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

Try it online!

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

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

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

Bash + coreutils + sed + bc, 27 24 23 bytes

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

Try it online!

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

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.

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

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

$\=1;s/./$\*=$&||1/ge}{

Try it online!

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

Java 8, 55 54 53 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.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ you can save parens like this: long f(long n){return n>0?(n%10>0?n%10:1)*f(n/10):1;} \$\endgroup\$
    – RiaD
    Jan 16, 2018 at 10:16
  • 1
    \$\begingroup\$ Sorry, I'm claiming this one (45 bytes) because the algorithm is totally different ;-) \$\endgroup\$ Jan 17, 2018 at 13:45
3
\$\begingroup\$

Julia 0.6, 26 bytes

!x=prod(max.(digits(x),1))

Example of use:

julia> !54
20

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ could you add an example of how to call this, as well as a byte count? you can use TIO! \$\endgroup\$
    – Giuseppe
    Jan 17, 2018 at 14:56
  • \$\begingroup\$ @Giuseppe oops, I got distracted. I counted the length but didn't add it. Huh TIO supports julia now. Neat. \$\endgroup\$ Jan 17, 2018 at 15:15
  • \$\begingroup\$ In fact, TIO supports Julia 0.4-0.6! very nice, +1. \$\endgroup\$
    – Giuseppe
    Jan 17, 2018 at 15:22
3
\$\begingroup\$

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

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

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!

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

Vyxal, 3 bytes

fꜝΠ

Try it Online!

Pyt isn't the only language to do 3 bytes :3

Explained

fꜝΠ
f   # flatten to a list
 ꜝ  # remove all 0's
  Π # product
\$\endgroup\$
2
\$\begingroup\$

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!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 74 bytes \$\endgroup\$
    – Jo King
    Jan 16, 2018 at 2:06
  • \$\begingroup\$ I literally forgot I posted that comment, and rewrote it from scratch. I'm just going to post separately \$\endgroup\$
    – Jo King
    Jan 18, 2018 at 1:15
2
\$\begingroup\$

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

MATL, 5 bytes

!UXzp

Input is taken as a string

Try it at MATL Online! Or verify test cases in Try It Online!

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

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

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!

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

Ruby, 42 40 35 32 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

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

Java (OpenJDK 8), 45 bytes

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

Try it online!

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

Ruby + -n, 25 bytes

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

Try it online!

Ruby (vanilla), 27 bytes

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

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ Using ruby -n you can use $_ instead of gets for -2! \$\endgroup\$ Mar 1, 2018 at 12:19
  • \$\begingroup\$ @DomHastings Thanks, I'm pretty sure that flag still counts for 1 byte though \$\endgroup\$ Mar 1, 2018 at 12:36
  • \$\begingroup\$ I believe the new consensus is Ruby + -n is counted as a different lang without the +1 for -n. Meta \$\endgroup\$ Mar 1, 2018 at 13:23
  • \$\begingroup\$ @DomHastings it's a proposal but I'm not going to argue with fewer bytes \$\endgroup\$ Mar 1, 2018 at 13:45
2
\$\begingroup\$

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.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ Welcome to PPCG! I no nothing of C#, but this should help you understand the rules for golfing in it. \$\endgroup\$
    – H.PWiz
    Mar 1, 2018 at 17:00
  • \$\begingroup\$ 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. \$\endgroup\$
    – James m
    Mar 15, 2018 at 11:47
  • \$\begingroup\$ 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. \$\endgroup\$
    – auhmaan
    Sep 23, 2019 at 16:56
2
\$\begingroup\$

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

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

Try it online!

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

Rockstar, 61 bytes

Listen to N
Cut N
O's 1
While N
Let O be*roll N-0 or 1

Say O

Try it (Code will need to be pasted in)

\$\endgroup\$

Your Answer

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

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