21
\$\begingroup\$

Monday Mini-Golf: A series of short questions, posted (hopefully!) every Monday.
(Sorry I'm late again; I was away from my computer basically all of yesterday and today.)

Us programmers (especially the code-golfers) sure love arbitrary integer sequences. We even have an entire site dedicated to these sequences that currently has around 200,000 entries. In this challenge, we'll be implementing yet another set of these sequences.

Challenge

Your challenge is to write a program or function that takes in an integer N, and outputs a sequence of base 10 integers, where each next integer is determined in this way:

  • Start at 1.
  • For each digit D in the previous integer's base 10 representation:

    • If D is 0, add one to the current integer.
    • Otherwise, multiply the current integer by D.

Details

  • You may assume that 0 < N < 231.
  • You must output each integer in the sequence, starting with the input number, until a number less than 10 is reached.
  • The output may be an array, or a string separated by spaces, commas, newlines, or a combination of these.
  • A trailing space and/or newline is allowed, but not a trailing comma.
  • There should never be any leading zeroes.

Examples

Example 1: 77

This example is fairly straightforward:

77 = 1*7*7 = 49
49 = 1*4*9 = 36
36 = 1*3*6 = 18
18 = 1*1*8 = 8

Thus, the proper output is 77 49 36 18 8.

Example 2: 90

Here we have:

90 = 1*9+1 = 10
10 = 1*1+1 = 2

So the output would be 90 10 2.

Example 3: 806

Read the equations left-to-right:

806 = 1*8+1*6 = 54 (((1*8)+1)*6)
 54 = 1*5*4   = 20
 20 = 1*2+1   = 3

Output should be 806 54 20 3.

Test-cases

The first number in each line is the input, and the full line is the expected output.

77 49 36 18 8
90 10 2
249 72 14 4
806 54 20 3
1337 63 18 8
9999 6561 180 9
10000 5
8675309 45369 3240 25 10 2
9999999 4782969 217728 1568 240 9
1234567890 362881 2304 28 16 6

As a reference, here's the proper next integers from 10 to 100:

Current | Next
--------+-----
     10 |  2
     11 |  1
     12 |  2
     13 |  3
     14 |  4
     15 |  5
     16 |  6
     17 |  7
     18 |  8
     19 |  9
     20 |  3
     21 |  2
     22 |  4
     23 |  6
     24 |  8
     25 | 10
     26 | 12
     27 | 14
     28 | 16
     29 | 18
     30 |  4
     31 |  3
     32 |  6
     33 |  9
     34 | 12
     35 | 15
     36 | 18
     37 | 21
     38 | 24
     39 | 27
     40 |  5
     41 |  4
     42 |  8
     43 | 12
     44 | 16
     45 | 20
     46 | 24
     47 | 28
     48 | 32
     49 | 36
     50 |  6
     51 |  5
     52 | 10
     53 | 15
     54 | 20
     55 | 25
     56 | 30
     57 | 35
     58 | 40
     59 | 45
     60 |  7
     61 |  6
     62 | 12
     63 | 18
     64 | 24
     65 | 30
     66 | 36
     67 | 42
     68 | 48
     69 | 54
     70 |  8
     71 |  7
     72 | 14
     73 | 21
     74 | 28
     75 | 35
     76 | 42
     77 | 49
     78 | 56
     79 | 63
     80 |  9
     81 |  8
     82 | 16
     83 | 24
     84 | 32
     85 | 40
     86 | 48
     87 | 56
     88 | 64
     89 | 72
     90 | 10
     91 |  9
     92 | 18
     93 | 27
     94 | 36
     95 | 45
     96 | 54
     97 | 63
     98 | 72
     99 | 81
    100 |  3

You can find this list expanded to 10000 here.

Scoring

This is , so shortest valid code in bytes wins. Tiebreaker goes to submission that reached its final byte count first. The winner will be chosen next Monday, Oct 19. Good luck!

Edit: Congrats to your winner, @isaacg, using Pyth yet again for 14 bytes!

\$\endgroup\$
0

16 Answers 16

10
\$\begingroup\$

Pyth, 15 14 bytes

.uu|*GHhGjNT1Q

1 byte thanks to Dennis

Test Suite

This challenge feels like it was made for Pyth's reduce functions. One reduce over the digits, one reduce until the value stops changing, and we're good.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ |*GHhG saves a byte over ?H*GHhG. \$\endgroup\$
    – Dennis
    Oct 14, 2015 at 5:28
4
\$\begingroup\$

PowerShell, 92 91 90 88 87 bytes

($n=$args);while($n-gt9){$x=1;[char[]]"$n"|%{$x=if($y=$_-48){$x*$y}else{$x+1}};($n=$x)}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ That's pretty slick, using (...) to leverage automatic output ... I'm going to need to remember that in the future. \$\endgroup\$ Oct 14, 2015 at 13:59
3
\$\begingroup\$

Pip, 28 25 23 bytes

Tt>Pa{Y1FdaYy*d|y+1a:y}

Takes a number as command-line argument and outputs the sequence on successive lines.

Explanation:

                         a is cmdline arg; t is 10 (implicit)
Tt>Pa{                }  Loop till a<10, printing it each time the test is made:
      Y1                   Yank 1 into variable y
        Fda                For each digit d in a:
           Yy*d|y+1          If y*d is truthy (nonzero), yank it; otherwise, yank y+1
                   a:y     Assign value of y back to a

Now I'm glad I changed P from a statement to an operator several revisions ago. Pa is an expression that evaluates to a's value but also outputs it, so I can print a and simultaneously test whether it's less than ten using t>Pa.

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

CJam, 26 25 24 22 bytes

riA,{_pAb{_2$*@)?}*j}j

or

ri{_pAb{_2$*@)?}*_9>}g

Try it online.

How it works

Both program essentially do the same; the first is a recursive approach, the second an iterative one. I'll explain the first, which I consider more interesting.

ri                     Read an integer from STDIN and push it on the stack.
  A,{               }j Initialize a memoized, recursive function j with the array
                       [0 ... 9] as "base cases". If j is called on an integer
                       below 10, it returns the element at that index of the base
                       cases (which is same integer) and does not execute the code
                       block. The base case array is filled with new values as j is
                       called again and again, but we do not use this feature.
     _p                Copy and print the integer on the stack.
       Ab              Convert it into its base-10 digits.
         {       }*    Fold; push the first digit, for each remaining digit:
          _2$*         Multiply copies of the accumulator and the current digit.
              @)       Increment the original accumulator.
                ?      Select the product if the digit is non-zero, else the sum.
                   j   Call j on the result.
                       If the result was less than 10, it is retrieved from the
                       base cases and pushed on the stack. CJam prints it before
                       exiting the program.
\$\endgroup\$
2
\$\begingroup\$

Minkolang 0.7, 52 46 bytes

ndN((d25*%1R25*:)r11(x2~gd4&x1+!*I1-)dNd9`,?).

Woohoo nested loops!

Explanation

ndN     Takes integer input and outputs it
(       Starts overall loop

 (        Starts loop that separates top of stack into digits
  d25*%   Modulus by 10
  1R      Rotates stack 1 unit to the right
  25*:    Divides by 10
 )

 r11   Reverses stack and pushes two 1s; 1 for the dump and 1 for the multiply
 (     Starts the multiply/add loop
  x    Dumps top value

      -This top-of-stack dump is because
       while loops end when the stack is
       empty or the top of stack is 0. The
       top of stack is *not* popped for
       this conditional check, so if the loop
       continues, I need to dump the left-over
       from the previous iteration.

  2~gd    Gets next-to-last stack value and duplicates for the conditional
  4&      Jumps 4 spaces if top of stack is positive
   x1+!   Dumps the 0 leftover, adds 1 to top of stack, and jumps the multiply
   *      Multiplies the top two elements of stack
  I1-     Pushes length of stack - 1
 )        Exits the loop if top of stack is 0 (i.e., len(stack)=1)
 dN       Outputs as integer
 d9`,?    Jumps out of the loop if top of stack <=9
)
.    Stop.
\$\endgroup\$
2
\$\begingroup\$

Mathematica, 66 bytes

Most@FixedPointList[Fold[If[#2<1,#+1,1##]&,1,IntegerDigits@#]&,#]&
\$\endgroup\$
2
\$\begingroup\$

Python 3, 74, 76 bytes

There was already a Python answer here with reduce, so I wanted to do one without it. It should be called with an int.

def j(n,m=1):
 print(n)
 if n>9:
  for d in str(n):m=m*int(d)or m+1
  j(m)
\$\endgroup\$
2
\$\begingroup\$

Python, 85 80 bytes

def g(n):y=reduce(lambda i,x:i*int(x)or i+1,`n`,1);return[n]+(g(y)if n>9else[])

This now properly prints out the entire list, instead of just the first value.

\$\endgroup\$
1
  • \$\begingroup\$ You can save two bytes by using an unnamed lambda, i.e. omitting g=. \$\endgroup\$
    – Alex A.
    Oct 14, 2015 at 5:42
1
\$\begingroup\$

K5, 24 bytes

(1{(x*y;x+1)@~y}/.:'$:)\

Gathering a list of items while iterating to a fixed point is precisely what the scan operator \ does. On each iteration I first cast the number to a string and then evaluate each character (.:'$:), exploding the number into its digits. Then I perform a reduction (/) starting with 1 and using the lambda {(x*y;x+1)@~y}. In this case x is the reducing value and y is each successive term of the sequence.

In action:

  f: (1{(x*y;x+1)@~y}/.:'$:)\

  f'77 90 249 806 1337 9999 10000 8685309 9999999 1234567890
(77 49 36 18 8
 90 10 2
 249 72 14 4
 806 54 20 3
 1337 63 18 8
 9999 6561 180 9
 10000 5
 8685309 51849 1440 17 7
 9999999 4782969 217728 1568 240 9
 1234567890 362881 2304 28 16 6)
\$\endgroup\$
1
\$\begingroup\$

Julia, 93 89 88 86 83 77 bytes

f(n)=(println(n);if(d=n>9)for i=reverse(digits(n)) i<1?d+=1:d*=i end;f(d)end)

This creates a recursive function f that prints the sequence elements on separate lines.

Ungolfed:

function f(n::Int)
    println(n)
    if (d = n > 9)
        for i in reverse(digits(n))
            i < 1 ? d += 1 : d *= i
        end
        f(d)
    end
end

Try it online

Saved 6 bytes thanks to Dennis!

\$\endgroup\$
2
  • \$\begingroup\$ It should be n>9 to comply with the second example. Also, f(n)=(println(n);if(d=n>9)for i=reverse(digits(n)) i<1?d+=1:d*=i end;f(d)end) is a bit shorter. \$\endgroup\$
    – Dennis
    Oct 15, 2015 at 3:19
  • \$\begingroup\$ @Dennis Excellent ideas, thanks! \$\endgroup\$
    – Alex A.
    Oct 15, 2015 at 3:50
1
\$\begingroup\$

Ruby 83, 72 bytes

Original declared as a function:

def f(d)loop{p d;break if d<10;d=d.to_s.bytes.inject(1){|r,i|i>48?r*(i-48):r+1}}end

I tried to use Enumerator.new but it uses so many bytes :-(

Improved using recursion:

def f(d)p d;f(d.to_s.bytes.inject(1){|r,i|i>48?r*(i-48):r+1})if d>10 end
\$\endgroup\$
0
\$\begingroup\$

C# & LINQ, 165 146 bytes

void j(int a){r.Add(a);var l=a.ToString().Select(d=>int.Parse(d.ToString()));int n=1;foreach(int i in l)n=i==0?n+1:n*i;if(n>9)j(n);else r.Add(n);}

j (for jarvis) is the recursive function. r is the List of int of the result.

tested in LINQPAD:

void Main()
{
    j(806);
    r.Dump();
}
List<int> r = new List<int>();

void j(int a){r.Add(a);var l=a.ToString().Select(d=>int.Parse(d.ToString()));int n=1;foreach(int i in l)n=i==0?n+1:n*i;if(n>9)j(n);else r.Add(n);}
\$\endgroup\$
3
  • \$\begingroup\$ You can save some bytes by removing the spaces surrounding operators, e.g. int n = 1 can be int n=1, etc. \$\endgroup\$
    – Alex A.
    Oct 14, 2015 at 2:15
  • \$\begingroup\$ Good catch @AlexA. reduced to 146. \$\endgroup\$
    – noisyass2
    Oct 14, 2015 at 2:45
  • \$\begingroup\$ You can also save a bit by doing a+"" instead of a.tostring () :) \$\endgroup\$ Feb 13, 2016 at 18:10
0
\$\begingroup\$

Haskell, 71 bytes

x!'0'=x+1
x!c=x*read[c]
g x|h>9=x:g h|1<2=[x,h]where h=foldl(!)1$show x

Usage: g 8675309 -> [8675309,45369,3240,25,10,2].

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

Matlab, 108

N=input('');disp(N)
k=1;while k
x=1;for n=num2str(N)-48
if n
x=x*n;else
x=x+1;end
end
disp(x)
N=x;k=x>9;
end
\$\endgroup\$
0
\$\begingroup\$

Java 8, 148 Bytes

String f(int j){String s="";Function r=i->(""+i).chars().map(x->x-48).reduce(1,(x,y)->y>0?x*y:x+1);while((j=(int)r.apply(j))>9)s+=j+" ";return s+j;}

formatted

String f(int j) {
    String s = "";
    Function r = i -> ("" + i).chars().map(x -> x - 48).reduce(1, (x, y) -> y>0 ? x*y : x+1);
    while ((j = (int)r.apply(j)) > 9) s += j+" ";
    return s+j;
}
\$\endgroup\$
0
\$\begingroup\$

Jelly, 9 bytes

Dבṛ?ƒ1ƊƬ

Try it online!

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