Trouvez le nombre de ceux pour obtenir un nombre en utilisant + et *

28

introduction

Votre objectif est de trouver le moins de nombres dont vous avez besoin d'ajouter ou de multiplier ensemble pour obtenir la valeur d'entrée, c'est A005245 .

Contribution

Un nombre entier positif N .

Sortie

Le plus petit nombre de ceux qui doivent être ajoutés / multiplié pour obtenir N .

Exemple d'entrée

7

Exemple de sortie

6

Explication

( 1+ 1+ 1) * ( 1+ 1) + 1= 7

Parce que cela en nécessite 6, la sortie est6

Cas de test

 1  1
 2  2
 3  3
 5  5
10  7
20  9
50 12

Comme il s'agit d'un défi de , le plus petit nombre d'octets gagne.

Spyrali Chyuu
la source
4
OEIS A005245
betseg
9
Bienvenue dans Programmation d'énigmes et Code Golf! En tant que premier défi, c'est OK, mais la prochaine fois, veuillez utiliser le bac à sable avant de publier des défis afin que vous puissiez obtenir des commentaires!
betseg
4
Je suggère de modifier cela pour indiquer explicitement que vous recherchez le nombre minimum requis. Sinon, simplement émettre le numéro d'origine et prétendre que c'est le nombre de ceux que vous devez additionner serait une solution valide.
Shaggy
2
Y a-t-il des exemples où f(x) != x.primeFactorisation().sum()sauf 1?
jrtapsell
1
@jrtapsell: oui. L'exemple donné de $ f (7) = 6 $ en est un. Pour tout $ p $ (assez grand) premier, vous pouvez factoriser $ p-1 $ et en ajouter un. Vous pourrez peut-être faire encore mieux.
Ross Millikan

Réponses:

17

Python 2 , 74 70 octets

f=lambda n:min([n]+[f(j)+min(n%j*n+f(n/j),f(n-j))for j in range(2,n)])

Essayez-le en ligne!

Version alternative, 59 octets (non vérifié)

f=lambda n:min([n]+[f(j)+f(n/j)+f(n%j)for j in range(2,n)])

Cela fonctionne au moins jusqu'à n = 1 000 000 , mais je dois encore prouver que cela fonctionne pour tous les n positifs .

Essayez-le en ligne!

Dennis
la source
Désolé si je manque quelque chose de simple, mais il n'est pas évident que cela essaie tous les arbres d'expression viables. En particulier, nous avons une couche extérieure n=a*j+bavec b<j, mais pourrions-nous avoir besoin b>=j?
2018
Hm, il échouerait seulement si les deux b>=jet b>=a. Mais vous avez raison, il n'est pas évident que cela ne se produira pas.
Dennis
Intéressant qu'il n'y ait pas de contre-exemples jusqu'à 1000000, je me demande si cela fonctionne vraiment toujours. Ma meilleure pensée pour un contre-exemple serait quelque chose de forme a*b+c*davec a,b,c,dtoutes les expressions de sommation et est très efficace.
xnor
10

Gelée , 16 14 octets

Merci Dennis d'avoir économisé 2 octets!

ÆḌḊ,Ṗ߀€+U$FṂo

Essayez-le en ligne!


Explication logique

Étant donné un nombre n :

  • Si c'est le cas 1, la réponse est 1. Autrement:

La représentation est soit a + bou a × b, où aet bsont des expressions.

Tenez compte de toutes les valeurs possibles de aet b:

  • Si la représentation est a + b, alors aet bsont dans la plage [1 .. n-1].
  • Si la représentation est a × b, aet bsont des diviseurs propres nsupérieurs à 1.

Dans les deux cas, la liste [[<proper divisors of n larger than 1>], [1, 2, ..., n-1]]est calculée ( ÆḌḊ,Ṗ), mappez le lien actuel sur chaque nombre ߀€, ajoutez les paires correctes ensemble ( +U$) et obtenez la valeur minimale ( FṂo).

Explication du code

ÆḌḊ,Ṗ߀€+U$FṂo   Main link. Assume n = 10.
ÆḌ       Proper divisors. [1,2,5]equeue, remove the first element. [2,5]
   ,Ṗ    Pair with op. Auto convert n = 10 to range 
         [1,2,3,4,5,6,7,8,9,10] and remove the last element
         10, get [1,2,3,4,5,6,7,8,9].

߀€      Apply this link over each element.
   +U$   Add with the Upend of itself.

FṂ       Flatten and get the inimum element.
  o      Logical or with n.
         If the list is empty, minimum returns 0 (falsy), so logical or
         convert it to n.
user202729
la source
5

JavaScript (ES6), 108 96 octets

f=n=>n<6?n:Math.min(...[...Array(n-2)].map((_,i)=>Math.min(f(++i)+f(n-i),n%++i/0||f(i)+f(n/i))))

Très inefficace; Array(n>>1)l'accélère légèrement au prix d'un octet. Explication: n%++iest non nul si in'est pas un facteur, il en n%++i/0est de même Infinity(et donc véridique, et certainement pas minimal) si in'est pas un facteur, mais NaN(et donc falsifié) si iest un facteur. Edit: 12 octets enregistrés avec l'inspiration de @ edc65.

Neil
la source
J'ai essayé de l'exécuter en arrière-plan pour voir s'il était en fait capable de calculer, f(50)mais malheureusement, Windows Update a redémarré mon PC avant qu'il ne puisse terminer.
Neil
Avez-vous essayé une seule marche sur un tableau?
edc65
@ edc65 Désolé, mais je ne sais pas trop ce que vous proposez et pourquoi.
Neil
Je vois 2 cartes, chacune scannant le atableau. Vous ne pouvez pas fusionner les évaluations dans les 2 lambdas et prendre le min?
edc65
@ edc65 Ah oui, pour une raison quelconque, je pensais que l'emboîtement du min ne serait pas moins cher mais je peux le remplacer (i+=2)par un autre, ++idonc j'économise 12 octets au total, merci!
Neil
5

Pari / GP , 66 octets

Un port de la réponse Python de Dennis :

f(n)=vecmin(concat(n,[f(j)+min(n%j*j+f(n\j),f(n-j))|j<-[2..n-1]]))

Essayez-le en ligne!


Pari / GP , 72 octets

Plus long, mais plus efficace:

f(n)=if(n<6,n,vecmin([if(d>1,f(d)+f(n/d),1+f(n-1))|d<-divisors(n),d<n]))

Essayez-le en ligne!

alephalpha
la source
1
Dennis a amélioré sa méthode et l' utilisation qui peut vous faire économiser 11 octets: f(n)=vecmin(concat(n,[f(j)+f(n\j)+f(n%j)|j<-[2..n-1]])).
Jonathan Allan
4

Pari / GP , 213 octets

Edit: j'ai été sévèrement battu .

f(n)={d;n<6&return(n);if(n<=#a,a[n]&return(a[n]),a=vector(n));for(i=1,n-1,a[i]||a[i]=f(i));a[n]=min(vecmin(vector(n\2,k,a[k]+a[n-k])),if(isprime(n),n,vecmin(vector((-1+#d=divisors(n))\2,i,a[d[i+1]]+a[d[#d-i]]))))}

Essayez-le en ligne!

MD XF
la source
3

Python 2 , 181 octets

def F(N,n,s="",r=""):
 try:
	if n<1:return(eval(s)==N)*0**(`11`in s or"**"in s)*s
	for c in"()+*1":r=F(N,~-n,s+c)or r
 except:r
 return r
f=lambda N,n=1:F(N,n).count(`1`)or f(N,-~n)

Essayez-le en ligne!

Jonathan Frech
la source
@ pizzapants184 La fonction principale ne fdoit pas être anonyme, car elle s'appelle récursivement.
Jonathan Frech
Ah, désolé, je n'ai pas vu ça.
pizzapants184
1

Perl 5 , -p 78 octets

79 octets en comptage à l'ancienne ( +1pour -p)

Le fait que perl doive utiliser un extra $pour tous les accès scalaires nuit vraiment à la longueur des golfs qui font beaucoup d'arithmétique ...

Cette méthode est principalement similaire aux autres déjà publiées (essayez la multiplication et l'ajout pour construire un nombre cible, prenez le moins cher). Cependant, il ne recuit pas de manière répétée, il peut donc être utilisé pour des entrées relativement importantes.

Il n'essaie pas non plus de minimiser le coût de construction d'un nombre par addition ou par multiplication, car perl 5 n'a pas de tri intégré minet numérique est looooooong (comme le montre le tri toujours dans le code). Au lieu de cela, je suppose simplement que si un nombre est un facteur de la cible, j'utiliserai la multiplication. C'est sûr car si par exemple 3est un facteur de 12(donc il résume le coût de 3et 12/3) plus tard dans la boucle, il considérera 9=12-3ce qui ne sera pas un facteur, donc 9+3avec le même coût que celui qui 3+9sera essayé de toute façon. Cependant, cela peut échouer pour les cibles <= 4(cela ne fonctionne que pour 1et 2). Ajout $_à la liste pour minimiser les correctifs. Ce qui est regrettable car je n'ai pas vraiment besoin de cela pour les cas de base car j'ai déjà initialisé@; avec les valeurs de départ appropriées, donc cela coûte 3 octets.

#!/usr/bin/perl -p
($_)=sort{$a-$b}$_,map{$;[$_]+$;[$'%$_?$'-$_:$'/$_]}//..$_ for@;=0..$_;$_=pop@

Essayez-le en ligne!

Ton Hospel
la source