Plus and Times, Ones and Nines


18

Implementare questa relazione di ricorrenza come una funzione o un programma che input e output un numero intero non negativo:

  • F (0) = 0

  • F (N) = il numero intero più piccolo maggiore di F (N-1) in modo tale che la somma e / o il prodotto delle sue cifre di base 10 sia N

N è l'input del tuo programma e F (N) il suo output.

Per essere chiari, la somma delle cifre in un numero come 913 è 9 + 1 + 3 = 13. Il prodotto è 9 × 1 × 3 = 27. Per i numeri a una cifra, la somma e il prodotto sono lo stesso numero. I numeri che contengono uno 0 ovviamente hanno prodotto 0.

I risultati attraverso F (70) sono:

N F(N)
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 19
11 29
12 34
13 49
14 59
15 69
16 79
17 89
18 92
19 199
20 225
21 317
22 499
23 599
24 614
25 799
26 899
27 913
28 1147
29 2999
30 3125
31 4999
32 5999
33 6999
34 7999
35 8999
36 9114
37 19999
38 29999
39 39999
40 41125
41 59999
42 61117
43 79999
44 89999
45 91115
46 199999
47 299999
48 311128
49 499999
50 511125
51 699999
52 799999
53 899999
54 911116
55 1999999
56 2111147
57 3999999
58 4999999
59 5999999
60 6111125
61 7999999
62 8999999
63 9111117
64 11111188
65 29999999
66 39999999
67 49999999
68 59999999
69 69999999
70 71111125

Vince il codice più breve in byte. Complimenti se riesci a dimostrare che il tuo codice sfrutta una certa efficienza.



1
Sequenza non del tutto corretta.
Calvin's Hobbies,

Risposte:


4

05AB1E , 20 12 byte

Risparmiato 8 byte grazie a Osable !

µNSDOsP‚¾>å½

Utilizza la codifica CP-1252 . Provalo online!


È richiesto il test di lunghezza? Mi è venuta in mente µNSDOsP‚¾>å½. Sembra funzionare per numeri scelti a caso.
Osable,

@Osable Ahh certo, sei un genio! Non so nemmeno perché l'ho incluso.
Adnan,

Incredibile come è possibile ridurre improvvisamente un programma di 20 byte del 40% ...
NikoNyrh,

3

Mathematica, 71 byte, 68 caratteri

±0=0;±n_:=(For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];x)

Per solo altri 4 byte, ecco una versione che memorizza i valori di ±n:

±0=0;±n_:=(For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)

Con quest'ultima versione, prima di valutare ±n, PlusMinusavrai due valori negativi:

In[2]:= DownValues@PlusMinus
Out[2]= {HoldPattern[±0] :> 0, HoldPattern[±n_] :> (For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)}

Ora se valutiamo ±20:

In[3]:= ±20
In[3]:= 225

In[4]:= DownValues@PlusMinus
Out[4]= {HoldPattern[±0] :> 0, HoldPattern[±1] :> 1, HoldPattern[±2] :> 2, HoldPattern[±3] :> 3, HoldPattern[±4] :> 4, HoldPattern[±5] :> 5, HoldPattern[±6] :> 6, HoldPattern[±7] :> 7, HoldPattern[±8] :> 8, HoldPattern[±9] :> 9, HoldPattern[±10] :> 19, HoldPattern[±11] :> 29, HoldPattern[±12] :> 34, HoldPattern[±13] :> 49, HoldPattern[±14] :> 59, HoldPattern[±15] :> 69, HoldPattern[±16] :> 79, HoldPattern[±17] :> 89, HoldPattern[±18] :> 92, HoldPattern[±19] :> 199, HoldPattern[±20] :> 225, HoldPattern[±n_] :> (For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)}

Questo accelera notevolmente i calcoli futuri poiché Mathematica non calcolerà più i valori tra 0e 20ricorsivamente. Il tempo risparmiato è più drammatico nall'aumentare:

In[5]:= Quit[]

In[1]:= ±0=0;±n_:=(For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)

In[2]:= AbsoluteTiming[±60]
Out[2]= {23.0563, 6111125}

In[3]:= AbsoluteTiming[±60]
Out[3]= {9.89694*10^-6, 6111125}

Questo inizia da F (N - 1) invece di F (N - 1) + 1; la ricorrenza deve essere strettamente crescente.
LegionMammal978,

2

C #, 155 159 135 byte

a=n=>{if(n<1)return 0;int i=n,s=0,p=1,N=a(n-1);for(;;){s=0;p=1;foreach(var c in++i+""){s+=c-48;p*=c-48;}if(i>N&(s==n|p==n))return i;}};

Super inefficiente, richiede molto tempo solo N>=14. Cercherò di ottenere una soluzione più efficiente, ma più lunga.

Bene, ora molto meglio, ma 4 byte in più. Oh bene, ora posso fare N<=50abbastanza velocemente. Grazie @ latte per aver salvato 24 byte!


-2 byte per sostituire for con for(;;)e foreach con foreach(var c in++i+""). -22 byte da sostituire int.Parse(c+"")con c-48.
latte,

2

Pyth - 18 17 byte

Un byte salvato grazie a @Jakube!

Gli usi si riducono per fare la cosa ricorsiva.

uf}HsM*FBjT;hGSQZ

Test Suite .


sM*FBjT;genera anche la somma delle cifre e il prodotto ed è più breve di 1 byte.
Jakube,

@Jakube ooh bel trucco
Maltysen il

1

R, 124 112 byte

f=function(N){y=x=`if`(N-1,f(N-1),0);while(N!=prod(y)&N!=sum(y)){x=x+1;y=as.double(el(strsplit(c(x,""),"")))};x}

Non riesce a N = 45 perché R insiste nel scrivere 10.000 come 1e + 05, che non è apprezzato da as.numeric(), questo è risolvibile usando as.integer()al costo di 12 byte:

f=function(N){y=x=`if`(N-1,f(N-1),0);while(N!=prod(y)&N!=sum(y)){x=x+1;y=as.double(el(strsplit(c(as.integer(x),""),"")))};x}

Come linguaggio di programmazione statistica, R ha modi fastidiosamente prolissi di dividere i numeri in un vettore di cifre. Soprattutto perché tutto deve essere riconvertito esplicitamente da stringhe a valori numerici.

12 byte salvati grazie a billywob.


1
Puoi usare as.double(el(strsplit(c(x,""),"")))per dividere un numero intero in un vettore delle sue cifre. Tuttavia, si as.integer()
riscontra

Ooh, un modo intelligente di forzare x in una stringa: o
JAD,

Puoi anche usare sprintf()invece per formattare l'intero in una stringa senza zero finali direttamente: as.double(el(strsplit(sprintf("%1.f",x),"")))e saltare l'uso dias.integer()
Billywob il

@ LegionMammal978 La prima cosa che fa nel ciclo while è x=x+1e questo è garantito per essere valutato una volta, perché all'inizio y=F(N-1)che non è assolutamente uguale N.
JAD,

@JarkoDubbeldam Whoops, frainteso: P
LegionMammal978

1

JavaScript (ES6) 109 107 105 91 89 byte

f=n=>n&&eval(`for(i=f(n-1);++i,${x="[...i+''].reduce((r,v)=>"}+r+ +v)-n&&${x}r*v)-n;);i`)



console.log(f.toString().length + 2); 
console.log(f(25));
console.log(f(13));
console.log(f(8));                                  


1

JavaScript (ES6), 84 86

Modifica: 2 byte salvati grazie a @Arnauld

f=n=>eval("for(v=n&&f(n-1),p=s=n+1;s&&p-1;)[...++v+''].map(d=>(p/=d,s-=d),p=s=n);v")

Nota di prova sopra 50 utilizzerà troppa CPU, fai clic su "Nascondi risultati" per interrompere prima che sia troppo tardi

f=n=>eval("for(v=n&&f(n-1),p=s=n+1;s&&p-1;)[...++v+''].map(d=>(p/=d,s-=d),p=s=n);v")

out=x=>O.textContent=x+'\n'+O.textContent

i=0
step=_=>out(i+' '+f(i),++i,setTimeout(step,i*10))

step()
<pre id=O></pre>


Penso che for(v=n&&f(n-1),p=s=n+1;s&&p-1;)[...++v+''].map(d=>(p/=d,s-=d),p=s=n);vdovrebbe salvare 2 byte. Sospetto che possa essere abbreviato un po 'di più, ma non sono riuscito a capirlo finora.
Arnauld,

@Arnauld Mi aspetto un problema con ripetute divisioni in virgola mobile
edc65

Il nostro unico requisito è quello di p /= dprodurre un risultato esatto quando in drealtà è un divisore di p. A meno che non mi sbagli, questo è vero per qualsiasi d <= p <= Number.MAX_SAFE_INTEGER. Quando si verificheranno errori di arrotondamento in virgola mobile p % d != 0, questo dovrebbe essere sicuro.
Arnauld,

@darrylyeo non dare suggerimenti che non hai provato (prova eval`1+1` ) (ecco perché codegolf.stackexchange.com/a/52204/21348 : leggi il primo commento)
edc65

1

Mathematica, 67 byte

a@0=0;a@b_:=NestWhile[#+1&,a[b-1]+1,+##!=b&&1##!=b&@*IntegerDigits]

Funzione, denominata a. Prende un numero come input e restituisce un numero come output. Ispirato alla precedente soluzione Mathematica, ma utilizza un meccanismo di loop diverso.


1

C, 240 byte

int f(char n){int q[19],i=19,r=n%9,j=9,*p=q,c=n/9;while(i)q[--i]=0;if(c){if(!r){r=9;c--;}q[9]=c;if(!(n%r)){n/=r;while((j-1)*(n-1)*c){if(n%j)j--;else{c--;q[9+j]++;n/=j;}}q[10]=c;if(1==n)p+=9;}while(++i<10){while(p[i]--)r=r*10+i;}}return(r);}

Prova di sfruttare alcune proprietà matematiche della sequenza.


0

PowerShell v3 +, 114 byte

param($n)$i=,0;$l=1;1..$n|%{for(;$_-notin((($b=[char[]]"$l")-join'+'|iex)),(($b-join'*'|iex))){$l++}$i+=$l};$i[$n]

Soluzione iterativa, senza un modo semplice per trasformare un numero nella somma / prodotto delle sue cifre, quindi è un po 'più lungo delle risposte JavaScript.

Prende input $n, imposta $isu un array con just 0(questa è la raccolta di F()e imposta $luguale a 1(questa è l'ultima F). Quindi eseguiamo il ciclo verso l'alto da 1a $n, ogni iterazione che esegue un forciclo.

Il forcondizionale del ciclo prende il $lnumero minimo, in una stringa "$l", quindi lo lancia come un chararray e memorizza tale array in una variabile temp $b. Abbiamo quindi -joinquelle cifre insieme +e reindirizziamo a iex(abbreviazione Invoke-Expressione simile a eval). Inoltre, facciamo altrettanto con *. Questi due numeri sono incapsulati in parentesi e trattati come argomento di matrice per l' -notinoperatore rispetto al numero corrente $_del ciclo esterno (ovvero, il forciclo funziona fino a quando entrambi +e *sono diversi da $_). Il corpo del forciclo aumenta solo $l++.

Una volta usciti da quel forcircuito interno , aggiungiamo il nostro $lcome nuovo elemento di $i. Dopo aver completato completamente il loop di intervallo, ci limitiamo a posizionarci $i[$n]sulla pipeline e l'output è implicito.

NB: diventa abbastanza lento da eseguire sopra 20, semplicemente a causa della struttura del loop. Ad esempio, N=40impiega circa due minuti sulla mia macchina e non ho nemmeno disturbato i test N>50.


0

Pyke, 17 byte

t.fY'Bs]~ohR{Io(e

Provalo qui!

O 13 byte non competitivi

first_nora inserisce la quantità di oggetti già trovati più uno ise usato.

Q.fY'Bs]iR{)e

Provalo qui!

Q.f        )  -  first_n(input, start=1)
   Y          -   digits(^)
    'Bs]      -   [sum(^), product(^)]
         R}   -   V in ^
        i     -    len(results)+1
            e - ^[-1]


0

Meraviglia , 49 byte

f\.{0\0@(:>@(| =#1sum#0)=#1prod#0)(dp +1f -#0 1)N

Pattern matching ftw! Uso:

f\.{0\0@(:>@(| =#1sum#0)=#1prod#0)(dp +1f -#0 1)N}; f 10

Più leggibile:

f\.{
  0\0
  @(
    find @(or = #1 sum #0) = #1 prod #0
  ) (dp + 1 (f -#0 1)) N
}

Questa è fondamentalmente solo un'implementazione parola per parola delle specifiche.


0

BASH, 107 byte

con piega + incolla + bc

for ((;n<=$1;z++)){
p(){ fold -1<<<$z|paste -sd$1|bc;}
[ `p +` = $n -o `p \*` = $n ]&&((z-->n++))
}
echo $z

0

Befunge, 101 byte

&20p>:000pv
>\1+^vp011<
| >.@>:55+%:00g+00p10g*v>10g-*
::\$_^#!:/+55p01*!`"~":<^\-g00
< |!-g02
+1< v\

Provalo online! Ma nota che diventerà molto lento una volta entrati negli anni Quaranta. Se vuoi testare l'intera gamma, devi davvero usare un compilatore Befunge.

Spiegazione

&20p           Read N and save for later.

>              Start of main loop; current target and test number on stack, initially 0.
:              Duplicate the test number so we can manipulate it.
000p           Initialise the sum to 0.
110p           Initialise the product to 1.

>              Start of inner loop.
:55+%:         Modulo 10 of the test number to get the first digit.
00g+00p        Add to the sum.
10g*           Multiply by the product.
:"~"`!*        If greater than 126, set to 0 to prevent overflows - it'll never match.
10p            Update the product variable.
55+/           Divide the test number by 10 to get the next digit.
:!_            If not zero, repeat the inner loop

$              Drop the zero left over from the loop.
\::00g-\10g-   Compare the sum and product with the current target.
*|             Multiply the two diffs and branch; up if no match, down if either match.
\1+^           On no match, we increment the test number and repeat the main loop.
:>20g-!|       With a match, we compare the current target with the saved N.
1+\v           If that doesn't match, increment the current target and restart main loop.
\>.@           If it does match, we've got our result; output it and exit.

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.