Plus et Times, Ones and Nines


18

Implémentez cette relation de récurrence en tant que fonction ou programme qui entre et sort un entier non négatif:

  • F (0) = 0

  • F (N) = le plus petit entier supérieur à F (N-1) tel que la somme et / ou le produit de ses chiffres de base 10 est N

N est l'entrée de votre programme et F (N) sa sortie.

Pour être clair, la somme des chiffres d'un nombre comme 913 est 9 + 1 + 3 = 13. Le produit est 9 × 1 × 3 = 27. Pour les nombres à un chiffre, la somme et le produit sont le même nombre. Les nombres qui contiennent un 0 ont bien sûr le produit 0.

Les résultats par F (70) sont:

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

Le code le plus court en octets gagne. Bravo si vous pouvez montrer que votre code profite d'une certaine efficacité.



1
Pas tout à fait la bonne séquence.
Calvin's Hobbies

Réponses:


4

05AB1E , 20 12 octets

8 octets enregistrés grâce à Osable !

µNSDOsP‚¾>å½

Utilise l' encodage CP-1252 . Essayez-le en ligne!


Le test de longueur est-il requis? Je suis venu avec µNSDOsP‚¾>å½. Il semble fonctionner pour des nombres choisis au hasard.
Osable

@Osable Ahh bien sûr, vous êtes un génie! Je ne sais même pas pourquoi j'ai inclus cela.
Adnan

Incroyable comment vous pouvez réduire soudainement un programme de 20 octets de 40% ...
NikoNyrh

3

Mathematica, 71 octets, 68 caractères

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

Pour seulement 4 octets supplémentaires, voici une version qui stocke les valeurs de ±n:

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

Avec cette dernière version, avant d'évaluer ±n, PlusMinusaura deux valeurs vers le bas:

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

Maintenant, si nous évaluons ±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)}

Cela accélère considérablement les calculs futurs, car Mathematica ne calculera plus les valeurs entre 0et 20récursivement. Le gain de temps est d'autant plus dramatique qu'il naugmente:

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}

Cela commence à F (N - 1) au lieu de F (N - 1) + 1; la récurrence doit être strictement croissante.
LegionMammal978

2

C #, 155 159 135 octets

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 inefficace, prend longtemps pour juste N>=14. Je vais essayer d'obtenir une solution plus efficace mais plus longue.

D'accord, beaucoup mieux maintenant, mais 4 octets de plus. Eh bien, je peux faire N<=50assez rapidement maintenant. Merci @milk d'avoir économisé 24 octets!


-2 octets pour remplacer le for with for(;;)et le foreach with foreach(var c in++i+""). -22 octets pour remplacer int.Parse(c+"")avec c-48.
lait

2

Pyth - 18 17 octets

Un octet sauvé grâce à @Jakube!

Les utilisations réduisent pour faire la chose récursive.

uf}HsM*FBjT;hGSQZ

Suite de tests .


sM*FBjT;génère également la somme des chiffres et le produit et est 1 octet plus court.
Jakube

@Jakube ooh nice trick
Maltysen

1

R, 124 112 octets

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}

Échoue à N = 45 car R insiste pour écrire 10.000 en 1e + 05, ce qui n'est pas apprécié par as.numeric(), cela peut être corrigé en utilisant as.integer()au prix de 12 octets:

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}

En tant que langage de programmation statistique, R a des façons énormément verbeuses de diviser les nombres en un vecteur de chiffres. Surtout parce que tout doit être reconverti des chaînes en valeurs numériques de manière explicite.

12 octets économisés grâce à billywob.


1
Vous pouvez utiliser as.double(el(strsplit(c(x,""),"")))pour diviser un entier en un vecteur de ses chiffres. Cependant, vous rencontrez toujours le problème de formatage, mais cela peut, comme dans votre réponse, être résolu paras.integer()
Billywob

Ooh, façon astucieuse de forcer x dans une chaîne: o
JAD

Vous pouvez également utiliser à la sprintf()place pour formater directement l'entier dans une chaîne sans zéros de fin: as.double(el(strsplit(sprintf("%1.f",x),"")))et ignorer l'utilisation deas.integer()
Billywob

@ LegionMammal978 La première chose qu'il fait dans la boucle while est x=x+1et cela est garanti d'être évalué une fois, car au début, y=F(N-1)ce qui n'est certainement pas égal à N.
JAD

@JarkoDubbeldam Oups, mal lu: P
LegionMammal978

1

JavaScript (ES6) 109 107 105 91 89 Octets

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

Modifier: 2 octets enregistrés thx @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")

Note de test supérieure à 50, il utilisera trop de votre CPU, cliquez sur «Masquer les résultats» pour arrêter avant qu'il ne soit trop tard

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>


Je pense que for(v=n&&f(n-1),p=s=n+1;s&&p-1;)[...++v+''].map(d=>(p/=d,s-=d),p=s=n);vdevrait enregistrer 2 octets. Je soupçonne qu'il peut être raccourci un peu plus, mais je n'ai pas pu le comprendre jusqu'à présent.
Arnauld

@Arnauld J'attends un problème avec la division répétée en virgule flottante
edc65

Notre seule exigence est de p /= dproduire un résultat exact lorsqu'il dest en fait un diviseur de p. À moins que je ne me trompe, cela est vrai pour tous d <= p <= Number.MAX_SAFE_INTEGER. Nous aurons des erreurs d'arrondi en virgule flottante quand p % d != 0, mais cela devrait être sûr.
Arnauld

@darrylyeo ne donne pas de suggestions que vous n'avez pas essayées vous-même (essayez eval`1+1` ) (voici pourquoi codegolf.stackexchange.com/a/52204/21348 : lire le premier commentaire)
edc65

1

Mathematica, 67 octets

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

Fonction, nommée a. Prend un nombre en entrée et renvoie un nombre en sortie. Inspiré de la précédente solution Mathematica, mais utilise un mécanisme de boucle différent.


1

C, 240 octets

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

Essayer d'exploiter certaines propriétés mathématiques de la séquence.


0

PowerShell v3 +, 114 octets

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

Solution itérative, sans moyen facile de transformer un nombre en somme / produit de ses chiffres, c'est donc un peu plus long que les réponses JavaScript.

Prend l'entrée $n, définit $iun tableau avec juste 0(c'est la collection de F(), et définit $légal à 1(c'est la dernière F). Nous bouclons ensuite vers le haut de 1à $n, chaque itération exécutant une forboucle.

Le forconditionnel de la boucle prend le $lnombre atest, dans une chaîne "$l", puis le chartransforme en tableau et stocke ce tableau dans la variable temp $b. Nous avons ensuite -joinces chiffres avec +et rediriger vers iex(abréviation Invoke-Expressionet similaire à eval). De plus, nous faisons de même avec *. Ces deux nombres sont encapsulés entre parenthèses et traités comme l'argument tableau de l' -notinopérateur par rapport au numéro actuel $_de la boucle externe (c'est-à-dire que la forboucle s'exécute tant que l'un +et l' autre *sont différents de $_). Le corps de la forboucle augmente simplement$l++ .

Une fois que nous sommes sortis de cette forboucle interne , nous ajoutons notre $lon comme nouvel élément de $i. Une fois que nous avons complètement terminé la boucle de plage, nous plaçons simplement $i[$n]sur le pipeline et la sortie est implicite.

NB - Obtient assez lentement pour s'exécuter ci-dessus 20, simplement à cause de la structure de la boucle. Par exemple, cela N=40prend environ deux minutes sur ma machine, et je n'ai même pas pris la peine de tester N>50.


0

Pyke, 17 octets

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

Essayez-le ici!

Ou 13 octets non compétitifs

first_nmet désormais le nombre d'objets déjà trouvés plus un is'il est utilisé.

Q.fY'Bs]iR{)e

Essayez-le ici!

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


0

Wonder , 49 octets

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

Motif assorti ftw! Usage:

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

Plus lisible:

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

Il s'agit essentiellement d'une implémentation mot à mot des spécifications.


0

BASH, 107 octets

avec pli + pâte + 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 octets

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

Essayez-le en ligne! Mais notez que ça va devenir très lent une fois que vous aurez atteint la quarantaine. Si vous voulez tester la gamme complète, vous devez vraiment utiliser un compilateur Befunge.

Explication

&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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.