Monday Mini-Golf # 4: JARVIS (Just Another Piuttosto Vast set di Integer Sequences)


22

Mini-golf del lunedì: una serie di domande sul corto , pubblicate (si spera!) Ogni lunedì.
(Mi dispiace, sono di nuovo in ritardo; ero lontano dal mio computer praticamente tutto ieri e oggi.)

Noi programmatori (specialmente i golfisti del codice) amiamo sicuramente sequenze di numeri interi arbitrari. Abbiamo persino un intero sito dedicato a queste sequenze che attualmente ha circa 200.000 voci. In questa sfida, implementeremo ancora un'altra serie di queste sequenze.

Sfida

La tua sfida è quella di scrivere un programma o una funzione che accetta un numero intero N e genera una sequenza di numeri interi di base 10, in cui ogni numero intero successivo viene determinato in questo modo:

  • Inizia da 1.
  • Per ogni cifra D nella rappresentazione di base 10 dell'intero precedente:

    • Se D è 0, aggiungine uno all'intero corrente.
    • Altrimenti, moltiplicare il numero intero corrente D .

Dettagli

  • Puoi presumere che 0 < N <2 31 .
  • È necessario generare ciascun numero intero nella sequenza, iniziando dal numero di input, fino a raggiungere un numero inferiore a 10.
  • L'output può essere un array o una stringa separata da spazi, virgole, newline o una combinazione di questi.
  • È consentito uno spazio finale e / o una nuova riga, ma non una virgola finale.
  • Non dovrebbero mai esserci zero iniziali.

Esempi

Esempio 1: 77

Questo esempio è abbastanza semplice:

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

Pertanto, l'output corretto è 77 49 36 18 8.

Esempio 2: 90

Qui abbiamo:

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

Quindi l'output sarebbe 90 10 2.

Esempio 3: 806

Leggi le equazioni da sinistra a destra:

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

L'output dovrebbe essere 806 54 20 3.

Casi test

Il primo numero in ogni riga è l'input e la riga intera è l'output previsto.

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

Come riferimento, ecco i numeri interi successivi corretti da 10 a 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

Puoi trovare questo elenco esteso a 10000 qui .

punteggio

Questo è , quindi vince il codice valido più breve in byte. Tiebreaker va all'invio che ha raggiunto per primo il numero di byte finale. Il vincitore verrà scelto lunedì prossimo, 19 ottobre. Buona fortuna!

Modifica: Congratulazioni al tuo vincitore, @isaacg , usando ancora Pyth per 14 byte !

Risposte:


10

Pyth, 15 14 byte

.uu|*GHhGjNT1Q

1 byte grazie a Dennis

Test Suite

Questa sfida sembra fatta per le funzioni di riduzione di Pyth. Uno riduce sulle cifre, uno riduce fino a quando il valore non smette di cambiare, e noi siamo a posto.


2
|*GHhGsalva un byte sopra ?H*GHhG.
Dennis,

4

PowerShell, 92 91 90 88 87 byte

($n=$args);while($n-gt9){$x=1;[char[]]"$n"|%{$x=if($y=$_-48){$x*$y}else{$x+1}};($n=$x)}

1
È piuttosto semplice, usando (...)per sfruttare l'output automatico ... Avrò bisogno di ricordarlo in futuro.
AdmBorkBork,

3

Pip , 28 25 23 byte

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

Accetta un numero come argomento della riga di comando e genera la sequenza su righe successive.

Spiegazione:

                         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

Ora sono contento di essere passato Pda una dichiarazione a un operatore diverse revisioni fa. Paè un'espressione che valuta ail valore ma lo emette anche, quindi posso stampare ae testare simultaneamente se sono meno di dieci usando t>Pa.


3

CJam, 26 25 24 22 byte

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

o

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

Provalo online.

Come funziona

Entrambi i programmi essenzialmente fanno lo stesso; il primo è un approccio ricorsivo, il secondo è un approccio iterativo. Spiegherò il primo, che considero più interessante.

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.

2

Minkolang 0.7 , 52 46 byte

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

Anelli nidificati di Woohoo!

Spiegazione

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.

2

Mathematica, 66 byte

Most@FixedPointList[Fold[If[#2<1,#+1,1##]&,1,IntegerDigits@#]&,#]&

2

Python 3, 74, 76 byte

C'era già una risposta Python qui con ridurre, quindi volevo farne una senza. Dovrebbe essere chiamato con un 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)

2

Python, 85 80 byte

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

Questo ora stampa correttamente l'intero elenco, anziché solo il primo valore.


È possibile salvare due byte utilizzando un lambda senza nome, ovvero omettendo g=.
Alex A.

1

K5 , 24 byte

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

Raccogliere un elenco di elementi mentre si scorre su un punto fisso è esattamente ciò che fa l'operatore di scansione \. Ad ogni iterazione ho prima lanciato il numero su una stringa e poi ho valutato ogni carattere ( .:'$:), esplodendo il numero nelle sue cifre. Quindi eseguo una riduzione ( /) a partire da 1 e usando la lambda {(x*y;x+1)@~y}. In questo caso xè il valore riducente ed yè ogni termine successivo della sequenza.

In azione:

  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)

1

Julia, 93 89 88 86 83 77 byte

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

Questo crea una funzione ricorsiva fche stampa gli elementi della sequenza su linee separate.

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

Provalo online

6 byte salvati grazie a Dennis!


Dovrebbe essere n>9conforme al secondo esempio. Inoltre, f(n)=(println(n);if(d=n>9)for i=reverse(digits(n)) i<1?d+=1:d*=i end;f(d)end)è un po 'più corto.
Dennis,

@Dennis Idee eccellenti, grazie!
Alex A.

1

Ruby 83 , 72 byte

Originale dichiarato come funzione:

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

Ho provato a usare Enumerator.newma usa così tanti byte :-(

Migliorato utilizzando la ricorsione:

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

0

C # e LINQ, 165 146 byte

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 (per jarvis) è la funzione ricorsiva. r è l'elenco di int del risultato.

testato 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);}

È possibile salvare alcuni byte rimuovendo gli spazi che circondano gli operatori, ad esempio int n = 1può essere int n=1, ecc.
Alex A.

Buona cattura @AlexA. ridotto a 146.
noisyass2

Puoi anche salvare un po 'facendo + "" invece di a.tostring () :)
Alex Carlsen,

0

Haskell, 71 byte

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

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


0

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

0

Java 8, 148 byte

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;}

formattato

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;
}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.