Explication
Befunge est un programme en deux dimensions qui utilise des piles .
Cela signifie que pour faire 5 + 6, vous écrivez 56+
, ce qui signifie:
56+
5 push 5 into stack
6 push 6 into stack
+ pop the first two items in the stack and add them up, and push the result into stack
(to those of you who do not know stacks, "push" just means add and "pop" just means take off)
Cependant, comme vous l'avez remarqué, vous ne pouvez pas pousser le nombre 56
directement dans la pile.
Pour ce faire, il faut écrire à la 78*
place, qui se multiplie 7
et 8
et pousse le produit dans la pile.
Détails
L'entrée peut être prise dans n'importe quel format, ce qui signifie qu'elle peut être STDIN ou non, à la discrétion du programmeur.
L'entrée sera un entier positif (pas de bonus pour 0
les entiers inclus ou négatifs).
La sortie sera une chaîne composée de seulement ces caractères: 0123456789+-*/
(je ne l' utiliser %
. Modulo)
Le but est de trouver la chaîne la plus courte pouvant représenter l'entrée, en utilisant le format décrit ci-dessus.
Par exemple, si l'entrée est 123
, alors la sortie le serait 67*99*+
. La sortie doit être évaluée de gauche à droite.
S'il y a plus d'une sortie acceptable (par exemple, elle 99*67*+
est également acceptable), n'importe laquelle peut être imprimée (pas de bonus pour toutes les imprimer).
Plus d'explications
Si vous ne comprenez toujours pas comment est 67*99*+
évalué 123
, voici une explication détaillée.
stack |operation|explanation
67*99*+
[6] 6 push 6 to stack
[6,7] 7 push 7 to stack
[42] * pop two from stack and multiply, then put result to stack
[42,9] 9 push 9 to stack
[42,9,9] 9 push 9 to stack
[42,81] * pop two from stack and multiply, then put result to stack
[123] + pop two from stack and add, then put result to stack
TL; DR
Le programme doit trouver la chaîne la plus courte pouvant représenter l'entrée (nombre), en utilisant le format spécifié ci-dessus.
Remarques
C'est un défi de code-golf , donc le code le plus court en octets gagne.
Désambiguïsation
Le -
peut être x-y
soit y-x
, soit à la discrétion du programmeur. Cependant, le choix doit être cohérent au sein de la solution. De même pour le /
.
Exemple de programme
Lua, 1862 octets ( essayez-le en ligne )
Puisque je suis l'auteur, je ne jouerai pas au golf du tout.
Explication:
This uses the depth-first search method.
En savoir plus sur la recherche en profondeur: ici .
Le programme:
local input = (...) or 81
local function div(a,b)
if b == 0 then
return "error"
end
local result = a/b
if result > 0 then
return math.floor(result)
else
return math.ceil(result)
end
end
local function eval(expr)
local stack = {}
for i=1,#expr do
local c = expr:sub(i,i)
if c:match('[0-9]') then
table.insert(stack, tonumber(c))
else
local a = table.remove(stack)
local b = table.remove(stack)
if a and b then
if c == '+' then
table.insert(stack, a+b)
elseif c == '-' then
table.insert(stack, b-a)
elseif c == '*' then
table.insert(stack, a*b)
elseif c == '/' then
local test = div(b,a)
if test == "error" then
return -1
else
table.insert(stack, a+b)
end
end
else
return -1
end
end
end
return table.remove(stack) or -1
end
local samples, temp = {""}, {}
while true do
temp = {}
for i=1,#samples do
local s = samples[i]
table.insert(temp, s..'0')
table.insert(temp, s..'1')
table.insert(temp, s..'2')
table.insert(temp, s..'3')
table.insert(temp, s..'4')
table.insert(temp, s..'5')
table.insert(temp, s..'6')
table.insert(temp, s..'7')
table.insert(temp, s..'8')
table.insert(temp, s..'9')
table.insert(temp, s..'+')
table.insert(temp, s..'-')
table.insert(temp, s..'*')
table.insert(temp, s..'/')
end
for i=1,#temp do
if input == eval(temp[i]) then
print(temp[i])
return
end
end
samples = temp
end
Prime
Un gâteau pour vous si vous utilisez Befunge (ou toute variante de celui-ci) pour écrire le code.
la source
Réponses:
Python 2, 278 octets
Ma meilleure solution, qui à chaque fois donne la réponse la plus courte. (mais très lent)
Python 2, 437 octets
Cette solution est plus longue, mais très rapide (pas de force brute). Et je suis tout à fait sûr, qu'il retourne toujours le résultat le plus court possible.
la source
f(6551)
renvoie25*8*9*7+9*8+
(13 caractères), tandis que9999***52*-
(11 caractères) est meilleur. Vérifié avec ma propreeval
fonction ci-dessus (dans la question).while c:
;
pour séparer les affectations aux variables (ce qui économise des octets dans les blocs en retrait), astuce de ven, se débarrasser des espaces entre un symbole et toute autre chose, ett
peut disparaître.Perl,
134133132128 128 octetsComprend +5 pour
-Xlp
(2 supplémentaires car le code contient'
)Exécutez avec le numéro cible sur STDIN:
befour.pl
:Il n'a pas de limites artificielles et est conceptuellement quelque peu efficace mais a néanmoins des temps d'exécution terribles même si j'ai sacrifié quelques octets pour l'accélérer. La génération d'une solution de longueur 11 (par exemple, le numéro cible 6551) prend environ 5 heures sur mon système.
Sacrifier 7 octets supplémentaires rend la vitesse un peu plus supportable.
17 minutes pour une solution de longueur 11, environ 5 heures pour une solution de longueur 13. Le premier numéro qui a besoin d'une longueur de 15 est 16622, ce qui prend environ 2 jours. Le premier nombre qui a besoin de la longueur 17 est 73319.
Notez qu'il suppose que la division retourne un entier en tronquant vers 0 (selon la spécification befunge 93)
la source
$
accède à la valeur scalaire. Où, dans la plupart des langues, vousa=4
écririez, perl utilisera$a=4
. Mais est également utilisé pour un accès scalaire de variables plus complexes. Par exemple,$a{$b}
récupère du hachage (carte, dictionnaire)%a
la valeur scalaire saisie$b
C,
550545 octets550545 octets après suppression des sauts de ligne inutiles (tous sauf les trois sauts de ligne après les directives de prétraitement).@Kenny Lau - Il peut recevoir en entrée un entier compris entre 1 et 9998, mais je pense que la plage d'entrée pour laquelle une solution optimale est calculée est plus petite que 9998. Par contre, les deux plages peuvent être étendues, si la mémoire le permet.
Le programme ne peut pas pousser sur la pile un nombre supérieur à 9998. (9998 peut être modifié.) J'ai exécuté le programme dans une version différente, en itérant sur la boucle externe (celle avec k) tant qu'il y a une amélioration pour n'importe quel nombre entre 1 et 9998 (comme dans l'algorithme de Dijkstra). Après trois itérations, il n'y a pas d'amélioration. Donc, pour économiser des octets, j'ai codé en dur k = 3.
Pour étendre la plage, deux choses sont nécessaires - modifier les constantes 9999 et 9998, l'exécuter avec un nombre variable d'itérations sur la boucle externe pendant qu'il y a une amélioration, pour voir combien de temps il faut jusqu'à ce qu'aucune amélioration n'ait lieu, puis modifier la constante k = 3 à cette valeur.
la source
i
,j
etk
avantmain()
.Python 2, 284 octets
Avis de non-responsabilité: prend une éternité pour certaines valeurs ... mais doit toujours être garanti pour renvoyer la chaîne la plus courte, et n'a pas de limite de plage imposée artificiellement ... fonctionne même sur des valeurs négatives. :)
Algorithme:
i = 0
i
, et remplacezabcd
par+-*/
respectivement, et supprimez toutef
i
et réessayez.la source
f(i)
partir duquel calculer0 <= i <= 6551
(pour capturer la6551
valeur que vous avez utilisée pour invalider la soumission originale de @pbochniak). En ce moment, cela ne dure que quelques minutes, et voici la dernière sortie du test:91 : 49+7* 3.020 s (total 108.174 s, worst 89: 5.827 s)
Mise à jour - elle vient de se terminer avec la valeur 92:92 : 149+7*+ 258.761 s (total 366.935 s, worst 92: 258.761 s)
113
... voir la sortie complète du test ici (pastebin) si vous êtes intéressé ...Python 2, 182 octets
Si incroyablement lent, je l'ai laissé fonctionner pendant une heure en entrée
221
et il n'est toujours pas terminé. Une grande partie de la lenteur est due au fait que j'utilise une liste comme file d'attente pour une recherche en largeur d'abord, et.pop(0)
estO(n)
pour les listes.L
est juste une file d'attente contenant(stack, code to reach stack)
paires. À chaque étape, des chiffres sont toujours ajoutés et des opérateurs sont exécutés si la pile comporte au moins deux éléments. La division n'est effectuée que si le dernier élément n'est pas 0, bien que je soupçonne fortement que la division n'est jamais nécessaire (même si je n'ai aucun moyen de le prouver, mais j'ai vérifié que c'est le cas jusqu'à 500).Le programme se termine via un
NameError
après l'impression du résultat (éventuellement).la source
;E
à la fin?NameError
terminaison, car elleE
n'est définie nulle part ailleursCJam, 79
Essayez-le en ligne
C'est horriblement inefficace, mais avec suffisamment de mémoire et de temps, cela fonctionne finalement. 123 manque de mémoire avec 16 Go, mais 120 et 125 sont corrects.
la source
Pyth - 35 octets
Force brute. Une chose étrange est que la nouvelle entrée implicite nuit réellement à mon score car elle semble également fonctionner pour
.v
pyth_eval.Essayez-le en ligne ici .
la source
Python 3, 183 octets
La vitesse n'est pas totalement déraisonnable (123, 221, 1237, 6551 terminent de l'ordre des secondes ou des minutes). Changer la
if
déclaration pour l'if j<=i and <k<2*n
accélérer davantage, au prix de 9 octets supplémentaires. J'ai omis division (/
), car je ne vois pas comment cela serait nécessaire.la source