23
\$\begingroup\$

This is different from My Word can beat up your Word as it is less complex and only requires you to calculate it, and not compare them.

To find the digital root, take all of the digits of a number, add them, and repeat until you get a one-digit number. For example, if the number was 12345, you would add 1, 2, 3, 4, and 5, getting 15. You would then add 1 and 5, giving you 6.

Your task

Given an integer N (0 <= N <= 10000) through STDIN, print the digital root of N.

Test cases

1 -> 1
45 -> 9
341 -> 8
6801 -> 6
59613 -> 6
495106 -> 7

Remember, this is , so the code with the smallest number of bytes wins.

\$\endgroup\$
13
  • 1
    \$\begingroup\$ Maybe a subtask of this challenge. \$\endgroup\$
    – nimi
    Oct 27 '16 at 14:17
  • 3
    \$\begingroup\$ Very closely related to this challenge ... maybe close enough for a dupe. \$\endgroup\$ Oct 27 '16 at 14:22
  • 8
    \$\begingroup\$ Please be more precise when saying number. In particular. must input 0 be supported? \$\endgroup\$
    – Ton Hospel
    Oct 27 '16 at 14:28
  • 2
    \$\begingroup\$ @TimmyD I think that this one is the much cleaner challenge without adding letter to integer conversion, computing the function for two values and including the literal STALEMATE. It might be better to close the other one as a dupe of this. \$\endgroup\$ Oct 27 '16 at 14:42
  • 3
    \$\begingroup\$ @MartinEnder I retracted my close vote, I think it's unfair to close a good challenge as a dupe of another more complex challenge. \$\endgroup\$ Oct 27 '16 at 14:48

52 Answers 52

1
2
1
\$\begingroup\$

Perl 6, 29 bytes

{($_,*.comb.sum...10>*)[*-1]}

Expanded:

{ # bare block lambda with implicit parameter 「$_」
  ( # generate a sequence

    $_,         # starting with the input
    *.comb.sum  # Whatever lambda that splits into digits, and finds sum
    ...         # keep doing that
    10 > *      # until it is less than 10

  )[ * - 1 ] # get the last value
}
\$\endgroup\$
1
\$\begingroup\$

J, 8 bytes

**1+9|<:

Uses the formula d(n) = ((n-1) mod 9) + 1 with the case d(0) = 0.

Usage

   f =: **1+9|<:
   (,.f"0) 0 1 45 341 6801 59613 495106
     0 0
     1 1
    45 9
   341 8
  6801 6
 59613 6
495106 7

Explanation

**1+9|<:  Input: integer n
      <:  Decrement n
    9|    Take it modulo 9
  1+      Add 1 to it
*         Sign(n) = 0 if n = 0, else 1
 *        Multiply and return
\$\endgroup\$
1
\$\begingroup\$

Tcl, 57 bytes

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

Try it online!

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

dc, 37 bytes

[[A~rdZ1<D]dsDx[+z1<S]dsSxdZ1<M]dsMxp

Try it online!

[A~rdZ1<D]dsDx decompose. Divide by 10 leaving quotient & remainder on stack until the value on the top of the stack is a single digit.

[+z1<S]dsSx sum. Add two topmost stack values until stack depth is one.

Macro M contains both of those, and dZ1<M to keep running itself until the final result is a single digit. p to print.

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

JavaScript, 37 bytes

Input is taken as a string.

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

Try it online!

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

Forth (gforth), 69 bytes

: f begin 0 swap begin 10 /mod >r + r> ?dup 0= until dup 10 < until ;

Try it online!

Explanation

  1. Place sum (starting at 0) on stack
  2. Get remainder of number divided by 10
  3. Add to sum
  4. Replace number with itself divided by 10
  5. Repeat steps 2-4 until number equals 0
  6. Using sum as new starting number, repeat steps 1-5 until result is less than 10

Code Explanation

begin               \ start outer loop
  0 swap            \ place sum variable and move it down the stack
  begin             \ start inner loop
    10 /mod         \ get quotient and remainder of number/10
    >r +            \ temporarily "hide" quotient on return stack and add remainder to sum
    r> ?dup         \ retrieve quotient from return stack and duplicate if != 0
  0= until          \ end inner loop if sum is equal to 0
  dup 10 <          \ duplicate current "root" and check if less than 10
until               \ end outer loop if < 10 
\$\endgroup\$
1
\$\begingroup\$

Excel VBA, 69 bytes

An anonymous VBE immediate window function that takes input from range [A1] and outputs to the console.

n=[A1]:While n>9:s=0:For i=1To Len(n):s=s+Mid(n,i,1):Next:n=s:Wend:?n

Test Function

For each x in Array(1,45,341,6801,59613,495106):[A1]=x:n=[A1]:While n>9:s=0:For i=1To Len(n):s=s+Mid(n,i,1):Next:n=s:Wend:?x"->"n:Next
 1 -> 1
 45 -> 9
 341 -> 8
 6801 -> 6
 59613 -> 6
 495106 -> 7
\$\endgroup\$
1
\$\begingroup\$

QBasic 1.1, 66 bytes

INPUT N
WHILE N>9
M=N
N=0
WHILE M
N=N+M MOD 10
M=M\10
WEND
WEND
?N
\$\endgroup\$
1
\$\begingroup\$

K (oK), 9 bytes

Solution:

(+/.:'$)/

Try it online!

Explanation:

Super straightforward. Break number into digits and sum up - do this until the result converges:

(+/.:'$)/ / the solution
(      )/ / do this until result converges
      $   / string, 1234 => "1234"
   .:'    / value each, "1234" => 1 2 3 4
 +/       / sum over, 1 2 3 4 => 10
\$\endgroup\$
4
  • 1
    \$\begingroup\$ In my implementation of k I made x\y encode y in base x with as many digits as necessary, so it's slightly shorter: (+/10\)/ \$\endgroup\$
    – ngn
    Jun 21 '18 at 0:22
  • \$\begingroup\$ Nice. In the newer versions of kdb+ (I think from 3.4 and up) you can do 10\:.. but not in oK - and .:'$ is the same number of bytes - so I went with that :) \$\endgroup\$
    – mkst
    Jun 21 '18 at 5:42
  • \$\begingroup\$ oK uses \ and requires a list on the left: `(,10)` \$\endgroup\$
    – ngn
    Jun 21 '18 at 6:11
  • \$\begingroup\$ Indeed, your implementation adds "as many digits as necessary", which is what you get from \: in kdb+ (3.4+), but for oK I'd need to know how many 10s to put in my list. \$\endgroup\$
    – mkst
    Jun 21 '18 at 8:31
1
\$\begingroup\$

K (ngn/k), 8 bytes

(+/10\)/

Try it online!

this is based on @streetster's oK answer but uses a feature specific to ngn/k: 10\x is the list of digits of x

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

Ohm v2, 5 bytes

ì‹9%›

Explanation:

ì‹9%›
ì     Takes input as integer
 ‹    Decrements
  9%  Modulus 9
    › Increment

Try it online!

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

MBASIC, 105 94 bytes

1 INPUT N
2 A$=STR$(N):N=0:FOR I=1 TO LEN(A$):N=N+VAL(MID$(A$,I,1)):NEXT:IF N>9 THEN 2
3 PRINT N

Output:

? 495106
 7

? 59613
 6

? 6801
 6

Explanation:

Convert input to a string, then walk the string, adding each digit to a total. If the resulting total has more than 1 digit, repeat the process. Otherwise, print the total.

Okay, so it's not APL. But it will run on an 8-bit CP/M system. :-)

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

Keg, 6 bytes(SBCS on Keg wiki)

¿;9%1+

Explanation:

¿#      Take implicit input
 ;9%1+# Digital Root Formula
# Implicit output
\$\endgroup\$
1
\$\begingroup\$

TI-Basic, 11 bytes

1+9fPart((Ans-1)/9

Takes input in Ans.

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

Vyxal, 3 bytes

⁽∑Ẋ

Try it Online!

⁽ Ẋ # Until the result converges...
 ∑  # Sum digits
\$\endgroup\$
2
  • \$\begingroup\$ Your first answer does not work when the input is a multiple of 9. \$\endgroup\$
    – Yousername
    Oct 11 at 22:31
  • \$\begingroup\$ @Yousername Oops. Deleting. \$\endgroup\$
    – emanresu A
    Oct 11 at 22:31
1
\$\begingroup\$

COBOL (GNU), 131 bytes

PROGRAM-ID.A.DATA DIVISION.
	WORKING-STORAGE SECTION.
	01 N PIC 9(9).
PROCEDURE DIVISION.ACCEPT N.COMPUTE N=FUNCTION REM(N- 1,9)+ 1

Try it online!

Explanation :

PROGRAM-ID.A.DATA DIVISION.
       * The first line is necessary and can't be removed
        WORKING-STORAGE SECTION.
       * sadly so is this (accept input / output)
        01 N PIC 9(9).
       * This accepts input N that is upto 999,999,999 (output is via same)
        PROCEDURE DIVISION.
       * Time to start working on program itself.
        ACCEPT N.
       * Accepts the input from stdin.
        COMPUTE N = FUNCTION REM(N - 1, 9) + 1
       * compute n such that it is mod of n - 1 and 9 and then add one (standard forumla of --N%9+1

Output is via display N.

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

braingolf, 20 13 bytes

[Rdl1-M&+v>]R

Try it online!
Links to the braingolf JS interpreter in TIO

Explanation

[Rdl1-M&+v>]R   Implicit input from command-line args to stack
[..........]R   Loop. Always runs once, will continue to run as long as the bottom value on the active stack is > 0
 R              Return to main stack, does nothing if already on main stack
  d             Pop top of stack, split into digits, push digits
   l            Push length of stack
    1-          Decrement top of stack
      M         Pop top of stack and push to next stack
       &+       Sum entire stack (all digits of input)
         v      Switch active stack to next stack
          >     Move top of stack to bottom

Decrementing the stack length, moving it to the second stack, and switching to the second stack before the end of the loop serves to use the decremented length as the loop counter. ie when the length is 1 (decremented to 0) the loop terminates.

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

Groovy, 57 Bytes

{n->for(;(n=(""+n).collect{(int)it-48}.sum())/10>1;){};n}

Repeatedly converts to string, sums the ascii conversion of the digits and continues while the resultant integer divided by 10 is greater than 1. Then it returns the mutated input.

Tried recursion too, cost more bytes though:

x={i->i?i%10+x(i.intdiv(10)):0};y={i->x(i)/10<1?x(i):y(x(i))}
\$\endgroup\$
0
\$\begingroup\$

Perl 34 28 bytes

Includes +1 for -p

s/./+$&/g,$_=eval while/../

Uses the method described in the question.

Example:

$ echo -n 495106 | perl -p DigitalRoot.pl
7
\$\endgroup\$
4
  • \$\begingroup\$ You need to count -p in your bytecount. (in that case, it will count for 3 bytes, but if you replaces the '' with "" then it's only 1 byte). And you can golf it further : the same approach can be written like s/./+$&/g,$_=eval while/../. Or you could do s/(.)(.)/$1+$2/e&&redo which is even shorter. And a shorter code (the approach is totally different) : $_=--$_%9+1. \$\endgroup\$
    – Dada
    Oct 27 '16 at 17:19
  • \$\begingroup\$ @Dada I was trying to figure out why it wouldn't run on the command line for so long that I must have forgotten to add the extra bytes when I gave up (I don't use perl much). \$\endgroup\$
    – Riley
    Oct 27 '16 at 17:29
  • \$\begingroup\$ @Dada s/(.)(.)/$1+$2/e&&redo doesn't exactly follow the method given in the question either. \$\endgroup\$
    – Riley
    Oct 27 '16 at 17:29
  • \$\begingroup\$ perl -lpe 's%%s/\B/+/g;$_=eval%egr' \$\endgroup\$
    – Ton Hospel
    Oct 27 '16 at 22:31
0
\$\begingroup\$

Element, 32 bytes

_2:1-+9/3:0<!{1-+2:0<!}1+-+9-*+`

Try it online!

This is using the typical closed-form formula, although it is noticeably more painful since Element lacks any rounding functionality.

_2:1-+9/3:0<!{1-+2:0<!}1+-+9-*+`
_2:                               make two copies of input
   1-+9/                          for one copy, subtract 1 and divide by 9
        3:0<!{1-+2:0<!}1+-+       floor it
                           9-*    multiply by -9
                              +`  add to the original input value, then output
\$\endgroup\$
0
\$\begingroup\$

Racket 152 bytes

(let p((ol'())(n n))(let*-values(((q r)(quotient/remainder n 10))((l)(cons r ol)))
(if(= q 0)(begin(let((s(apply + l)))(if(< s 10)s(p'()s))))(p l q)))))

Ungolfed:

(define (f n)
  (let loop ((ol '())
             (n n))
    (let*-values (((q r) (quotient/remainder n 10))
                 ((l) (cons r ol)))
      (if (= q 0)
          (begin
            (let ((s (apply + l)))
              (if (< s 10)
                  s
                  (loop '() s))))
          (loop l q))
      )))

Simpler version:

(define (f1 N)
  (define (getDigitList n)                   ; sub-fn  to get digits
    (let loop ((ol '())
               (n n))
      (let-values (((q r) (quotient/remainder n 10)))
        (if (= q 0) (cons r ol)
            (loop (cons r ol) q)))))

    (let loop2 ((n N))                       ; actual fn
      (define s (apply + (getDigitList n)))  ; get sum of digits
      (if (< s 10)
          s
          (loop2 s))))

Testing:

(f 1)
(f 45)
(f 341)
(f 6801)
(f 59613)
(f 495106)

Output:

1
9
8
6
6
7
\$\endgroup\$
0
\$\begingroup\$

C#, 79 Bytes

Golfed:

string R(string i){while(i.Length>1){i=i.Sum(o=>int.Parse(o+""))+"";}return i;}

Ungolfed:

string R(string i)
{
  while (i.Length > 1)
  {
    i = i.Sum(o => int.Parse(o + ""))+"";
  }

  return i;
}

Testing:

var printTheDigitalRoot = new PrintTheDigitalRoot();
Console.WriteLine(printTheDigitalRoot.S("1")); //1
Console.WriteLine(printTheDigitalRoot.S("45")); //9
Console.WriteLine(printTheDigitalRoot.S("341")); //8
Console.WriteLine(printTheDigitalRoot.S("6801")); //6
Console.WriteLine(printTheDigitalRoot.S("59613")); //6
Console.WriteLine(printTheDigitalRoot.S("495106")); //7
\$\endgroup\$
1
  • \$\begingroup\$ string is already IEnumerable<char> so you don't need to ToCharArray() before calling Sum() on it. o-48 is a shorter than int.Parse(o+""). Having said these, the mod 9 trick will be much shorter than actually summing the digits. \$\endgroup\$
    – milk
    Oct 27 '16 at 21:06
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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