Más y tiempos, unos y nueve

18

Implemente esta relación de recurrencia como una función o programa que ingresa y emite un entero no negativo:

  • F (0) = 0

  • F (N) = el entero más pequeño mayor que F (N-1) de modo que la suma y / o el producto de sus dígitos de base 10 es N

N es la entrada de su programa y F (N) su salida.

Para ser claros, la suma de los dígitos en un número como 913 es 9 + 1 + 3 = 13. El producto es 9 × 1 × 3 = 27. Para números de un solo dígito, la suma y el producto son el mismo número. Los números que contienen un 0, por supuesto, tienen el producto 0.

Los resultados a través de F (70) son:

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

El código más corto en bytes gana. Felicitaciones si puede demostrar que su código aprovecha cierta eficiencia.

Pasatiempos de Calvin
fuente
1
Secuencia OEIS
MildlyMilquetoast
1
No es la secuencia correcta.
Aficiones de Calvin

Respuestas:

4

05AB1E , 20 12 bytes

¡Guardado 8 bytes gracias a Osable !

µNSDOsP‚¾>å½

Utiliza la codificación CP-1252 . Pruébalo en línea!

Adnan
fuente
¿Se requiere la prueba de longitud? Se me ocurrió µNSDOsP‚¾>å½. Parece funcionar para números elegidos al azar.
Osable
@Osable Ahh, por supuesto, eres un genio! Ni siquiera sé por qué incluí eso.
Adnan
Increíble cómo puedes reducir de repente un programa de 20 bytes en un 40% ...
NikoNyrh
3

Mathematica, 71 bytes, 68 caracteres

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

Por solo 4 bytes más, aquí hay una versión que almacena los valores de ±n:

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

Con la última versión, antes de evaluar ±n, PlusMinustendrá dos valores bajos:

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

Ahora si evaluamos ±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)}

Esto acelera drásticamente los cálculos futuros, ya que Mathematica ya no calculará los valores entre 0y 20recursivamente. El tiempo ahorrado es más dramático a medida que naumenta:

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}
ngenisis
fuente
Esto comienza en F (N - 1) en lugar de F (N - 1) + 1; La recurrencia debe ser estrictamente creciente.
LegionMammal978
2

C #, 155 159 135 bytes

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

Súper ineficiente, lleva mucho tiempo solo N>=14. Voy a tratar de obtener una solución más eficiente pero más larga.

Bien, mucho mejor ahora, pero 4 bytes más. Oh, bueno, ahora puedo hacerlo N<=50bastante rápido. ¡Gracias @milk por guardar 24 bytes!

Yodle
fuente
-2 bytes para reemplazar el con for(;;)y el foreach con foreach(var c in++i+""). -22 bytes para reemplazar int.Parse(c+"")con c-48.
leche
2

Pyth - 18 17 bytes

¡Un byte guardado gracias a @Jakube!

Los usos se reducen para hacer lo recursivo.

uf}HsM*FBjT;hGSQZ

Test Suite .

Maltysen
fuente
sM*FBjT;también genera la suma de dígitos y el producto y es 1 byte más corto.
Jakube
@Jakube ooh buen truco
Maltysen
1

R, 124 112 bytes

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}

Falla en N = 45 porque R insiste en escribir 10.000 como 1e + 05, lo cual no es apreciado por as.numeric()esto, esto se puede solucionar usando as.integer()al costo de 12 bytes:

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}

Como lenguaje de programación estadística, R tiene formas molestas de dividir números en un vector de dígitos. Especialmente porque todo tiene que volver a convertirse de cadenas en valores numéricos explícitamente.

12 bytes guardados gracias a billywob.

JAD
fuente
1
Puede usar as.double(el(strsplit(c(x,""),"")))para dividir un número entero en un vector de sus dígitos. Sin embargo, todavía se encuentra con el problema de formato, pero eso puede resolverse como en su respuestaas.integer()
Billywob
Ooh, forma inteligente de forzar x en una cadena: o
JAD
También puede usar sprintf()en su lugar para formatear el entero en una cadena sin ceros finales directamente: as.double(el(strsplit(sprintf("%1.f",x),"")))y omitir el uso deas.integer()
Billywob
@ LegionMammal978 Lo primero que hace en el ciclo while es x=x+1y está garantizado que se evaluará una vez, porque al principio y=F(N-1)definitivamente no es igual a N.
JAD
@JarkoDubbeldam Whoops, leí mal: P
LegionMammal978
1

JavaScript (ES6) 109 107 105 91 89 Bytes

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

Lmis
fuente
1

JavaScript (ES6), 84 86

Editar: 2 bytes guardados gracias @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 de prueba superior a 50, usará demasiada CPU, haga clic en 'Ocultar resultados' para detener antes de que sea demasiado tarde

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>

edc65
fuente
Creo que for(v=n&&f(n-1),p=s=n+1;s&&p-1;)[...++v+''].map(d=>(p/=d,s-=d),p=s=n);vdebería guardar 2 bytes. Sospecho que se puede acortar un poco más, pero no pude resolverlo hasta ahora.
Arnauld
@Arnauld Espero algún problema con la división repetida de coma flotante
edc65
Nuestro único requisito es que p /= dproduzca un resultado exacto cuando en drealidad es un divisor de p. A menos que me equivoque, esto es cierto para cualquiera d <= p <= Number.MAX_SAFE_INTEGER. Obtendremos errores de redondeo de coma flotante cuando p % d != 0, pero eso debería ser seguro.
Arnauld
@darrylyeo no dé sugerencias que no haya probado (intente eval`1+1` ) ( he aquí por qué codegolf.stackexchange.com/a/52204/21348 : lea el primer comentario)
edc65
1

Mathematica, 67 bytes

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

Función, nombrada a. Toma un número como entrada y devuelve un número como salida. Inspirado en la solución anterior de Mathematica, pero utiliza un mecanismo de bucle diferente.

LegionMammal978
fuente
1

C, 240 bytes

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

Tratando de explotar algunas propiedades matemáticas de la secuencia.

bernaf
fuente
0

PowerShell v3 +, 114 bytes

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

Solución iterativa, sin una forma fácil de convertir un número en la suma / producto de sus dígitos, por lo que es bastante más largo que el JavaScript responde.

Toma la entrada $n, los conjuntos $ia un array con sólo 0(esto es la colección de F(), y se pone $ligual a 1(esta es la última F). A continuación, bucle hacia arriba desde 1a $n, cada iteración la ejecución de un forbucle.

El forcondicional del bucle toma el $lnúmero de prueba, en una cadena "$l", luego lo charconvierte como una matriz y almacena esa matriz en la variable temporal $b. Luego -joinjuntamos esos dígitos +y los canalizamos a iex(abreviatura Invoke-Expressiony similar a eval). Además, también hacemos lo mismo con *. Esos dos números se encapsulan en pares y se tratan como el argumento de matriz para el -notinoperador contra el número actual $_del bucle externo (es decir, el forbucle se ejecuta tanto como sea +y *son diferentes a $_). El cuerpo del forbucle solo se incrementa $l++.

Una vez que estamos fuera de ese forciclo interno , agregamos nuestro $lencendido como un nuevo elemento de $i. Una vez que hemos completado completamente el bucle de rango, simplemente lo colocamos $i[$n]en la tubería y la salida es implícita.

NB: es bastante lento para ejecutar arriba 20, simplemente debido a la estructura del bucle. Por ejemplo, N=40toma alrededor de dos minutos en mi máquina, y ni siquiera me he molestado en probar N>50.

AdmBorkBork
fuente
0

Pyke, 17 bytes

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

Pruébalo aquí!

O 13 bytes no competitivos

first_nahora pone la cantidad de elementos ya encontrados más uno isi se usa

Q.fY'Bs]iR{)e

Pruébalo aquí!

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

Maravilla , 49 bytes

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

¡Patrón a juego ftw! Uso:

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

Más legible:

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

Esto es básicamente una implementación palabra por palabra de las especificaciones.

Mama Fun Roll
fuente
0

BASH, 107 bytes

con pliegue + pegar + bc

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

Befunge, 101 bytes

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

Pruébalo en línea! Pero tenga en cuenta que se volverá muy lento una vez que llegue a los cuarenta años. Si desea probar el rango completo, realmente necesita usar un compilador Befunge.

Explicación

&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.
James Holderness
fuente
0

PHP , 110 bytes

for(;$c<=$a=$argn;$c=count($r))array_product($s=str_split($n++))!=$c&&array_sum($s)!=$c?:$r[]=~-$n;echo$r[$a];

Pruébalo en línea!

Jörg Hülsermann
fuente