Nous avons tous vu ces "maths hax" en ligne qui ressemblent à ceci:
Think of a number, divide by 2, multiply by 0, add 8.
Et, par magie, tout le monde se retrouve avec le chiffre 8!
La langue
Définissons un langage de programmation qui utilise la syntaxe du texte ci-dessus, appelé "WordMath". Les scripts WordMath suivent ce modèle:
Think of a number, <commandlist>.
Ce qui signifie essentiellement: prenez un nombre (comme entrée de STDIN) comme accumulateur initial, exécutez toutes les commandes dessus et sortez le résultat.
Les commandes sont séparées par le délimiteur ,
(virgule + espace). Les commandes valides sont (notez que cela #
représente un entier non négatif :) :
add #
/subtract #
- Ajouter / soustraire la valeur de l'accumulateur.divide by #
/multiply by #
- floordiv / multiplie l'accumulateur par la valeur donnée.subtract from #
- Similaire àsubtract
, maisacc = # - acc
au lieu deacc = acc - #
repeat
- refait la dernière commande. Cela ne peut pas être la 1ère commande, mais vous devez prendre en charge plusieurs répétitions consécutives.
Le défi
Votre tâche consiste à créer un programme ou une fonction qui prend un script WordMath valide comme entrée et transpile en un programme complet valide - dans la même langue que votre code.
Par exemple, si mon code est en Python 2 et que le script est:
Think of a number, subtract from 10, add 10, multiply by 2.
Le programme généré peut être:
a = input()
a = 10 - a
a += 10
a *= 2
print(a)
Ou bien:
print(((10-input())+10)*2)
Tant qu'il s'agit d'un programme complet qui prend en entrée STDIN
et imprime vers STDOUT
, ou les équivalents les plus proches de la langue.
Règles
- Votre programme d'origine peut supposer que l'entrée est toujours un script WordMath valide.
- Les programmes transpilés ne doivent pas gérer les erreurs mathématiques telles que la division par 0.
- Les programmes transpilés peuvent supposer que l'entrée représente un entier signé valide, dans la plage d'entiers standard de votre langue.
- C'est du code-golf , donc la solution la plus courte (en octets) l'emporte.
- Seul le nombre d'octets de votre programme d'origine est important - le code généré peut être aussi long que vous le souhaitez!
Exemples de scripts
Exemple 1:
Think of a number.
Prenez la saisie, ne faites rien, affichez-la: le programme cat de WordMath.
Exemple 2:
Think of a number, divide by 5, subtract from 9.
N'oubliez pas que «diviser» est la division du plancher, donc pour ce programme 6 -> 8
, et 29 -> 4
.
Exemple 3:
Think of a number, add 5, add 10, multiply by 2, subtract 15, repeat, divide by 2.
Le programme chat étendu!
Exemple 4:
Think of a number, subtract 1, repeat, repeat.
Prend un nombre et soustrait 3.
-5/3
? Arrondissons-nous vers0
ou vers l'infini négatif?Réponses:
05AB1E ,
59565452 octetsEssayez-le en ligne!
Mon cerveau me fait mal comme l'enfer après ça ... Il sort en code 05AB1E comme suit:
Think of a Number
est supprimé, en raison d'une entrée implicite.Subtract From #
caudales à#s-
(échangea
etb
et d' effectuer l' opération).Subtract #
convertit en#-
.Add #
convertit en#+
.Multiply by #
convertit en#*
.Divide by #
convertit en#/
.Repeat
saisit tout ce qui a été stocké en dernier dans le registre et le concatène.Expliqué:
Exemple:
Contribution:
Sortie:
Essayez une solution avec une entrée de 10:
Essayez-le en ligne!
Voir sur google:
Voici un lien vers la même équation saisie dans google.
la source
Préprocesseur C, 362 octets
J'AI PRESQUE fait en sorte que cela fonctionne dans le préprocesseur C, mais la commande de répétition s'avère beaucoup trop difficile à implémenter. Au lieu de cela, j'ai utilisé le préprocesseur pour transformer l'entrée en un tableau qui est ensuite interprété par un code supplémentaire.
L'entrée doit être fournie dans "input.wm" ou simplement vidée dans la source sur cette ligne. J'ai inclus ses octets dans mon décompte car je pense que c'est un peu hacky et légèrement contre les règles du défi, donc ça ne fait que convenir.
Quoi qu'il en soit, une fois que vous avez vidé votre source WordMath dans input.wm où un compilateur peut le trouver, vous devriez être en mesure de le compiler, tel quel, avec des avertissements pour produire un exécutable qui fait ce que dit la source WordMath.
la source
Rétine, 170 octets
Parce que qui ne voudrait pas voir ça?!
J'ai pensé à quel point ce serait génial de voir une solution Retina, et j'ai décidé de la créer rapidement. Cela n'a pris qu'une heure. Comme d'habitude, le nombre d'octets suppose le codage ISO 8859-1.
Essayez-le en ligne
La sortie a un retour à la ligne qui ne doit pas être copié lors du test du programme résultant. Le programme ne prend pas en charge les négatifs, car la plage d'entiers standard de Retina (en unaire) ne le fait pas.
Explication:
Programmes mathématiques:
Ajouter:
Ajoutez le nombre de uns au début. Ajouter 5:
Soustraire:
Supprimez le nombre de ceux du début. Soustrayez 5:
Soustraire de:
Remplacez l'entrée
1
s parx
s. Mettez à côté du nombre fixe. Supprimer à plusieurs reprisesx1
. Soustrayez de 10:Multiplier par:
Remplacez chacun
1
par un certain nombre d'entre eux. Multipliez par 3:Diviser par:
Cela utilise mon programme Retina pour Integer Division . Divisez par 2:
la source
$
correspond à la toute fin de la chaîne ou devant un saut de ligne de fin. Vous en avez besoin\z
si vous ne voulez que le premier.GNU awk, 139 octets
Invocation:
Cas de test:
la source
Haskell,
232231 octetsBien sûr, un programmeur fonctionnel préférerait retourner une fonction plutôt qu'une chaîne représentant un programme, mais c'est parti:
Remarques: Nous commençons toujours par ajouter zéro, sinon la transpilation du programme trivial WordMath ne donnerait pas suffisamment d'informations pour déduire le type auquel il
read
est utilisé.subtract from n
pourrait être mis en œuvre en tant que(n-)
, mais j'utilise((-)n)
pour plus d'uniformité. Dans le cas de lasubtract n
copiesubtract
de l'entrée, je n'ai donc pas à l'écrire, mais je dois compenser l'espace manquant à la fin.repeat
est utilisé comme opération par défaut; avec une opération précédente initiale vide, cela permet d'ignorer facilement les quatre premiers mots.Exemple d'utilisation:
Les autres exemples donnent les résultats suivants:
la source
h
pourrait ressembler à quelque choseh s n r|x<-s.read.init$n=x%r.x
et être appelée avec le premier argument d'une fonction commeh(+)n r
(et il doit y en avoir quelqueflip
part pour obtenir l'ordre d'opérateur correct), le cas de base est_%_=id
. La fonction principale peut éviter tout le passe-partout et être justet l=id%words l
. - Grâce au curry, il pourrait être considéré comme un interprète, et cette idée pourrait conduire à une solution plus facile et / ou plus courte.Python 2,
263258260221 octetsCela pourrait probablement être encore beaucoup plus court.
Essayez-le en ligne
J'utilise à la
//
place de/
, car la dernière instruction aura un.
à la fin, faisant de n'importe quel nombre un flottant. Donc, pour garder la division cohérente, j'utilise la division entière.Sortie des cas de test:
la source
if
s pouro
ce qui suit (ce qui, je pense, devrait fonctionner):,o=[[o+[['+-'['s'in c],'//']['v'in c],'*']['m'in c]+n,n+'-'+o]['f'in c],'input()']['T'in c]
vous pouvez le réduire à 224.Befunge,
342305 octetsEssayez-le en ligne!
Sortie
Le code qu'il génère commence par une commande
&
(valeur d'entrée) et se termine par les commandes.
(valeur de sortie) et@
(sortie). Entre les deux, nous avons les différents calculs sous la forme<number><operation>
, où l' opération peut être+
(ajouter),-
(soustraire),/
(diviser par),*
(multiplier par) et\-
(soustraire de).Le nombre lui-même est un peu compliqué, car Befunge ne prend en charge que les littéraux numériques compris entre 0 et 9, donc tout ce qui est plus grand doit être calculé manuellement. Puisque nous lisons déjà les nombres caractère par caractère, nous construisons simplement le nombre au fur et à mesure que chaque chiffre est lu, donc par exemple, 123 devient
155+*2+55+*3+
, c'est-à-dire(((1 * 10) + 2) * 10) + 3
.Exemples
Explication
Befunge n'a pas la capacité de manipuler les chaînes en tant que telles, donc la plupart de l'analyse est gérée par le comptage des caractères. Nous commençons simplement par sauter les 18 premiers caractères, ce qui nous permet de dépasser le nombre phrase (plus une virgule ou un point). Ensuite, si le caractère suivant est une forme de saut de ligne ou d'EOF, nous allons directement à la routine de sortie, sinon nous continuons à chercher une liste de commandes.
Pour analyser une commande, nous continuons simplement à compter les caractères jusqu'à atteindre un chiffre ou un séparateur. S'il s'agit d'un séparateur, ce doit être la commande de répétition que nous traitons comme un cas spécial. S'il s'agit d'un chiffre, nous l'ajoutons à notre tampon de sortie et continuons à rechercher d'autres chiffres. Chaque fois qu'un chiffre est sorti, nous le préfixons avec
55+*
(pour multiplier le total jusqu'à présent par 10) et le suffixe avec+
(pour l'ajouter au total). Une fois les chiffres terminés, nous ajoutons le caractère de commande.Quant à la façon dont la commande est déterminée, nous prenons le nombre de caractères jusqu'au premier chiffre modulo 7. Pour ajouter ceci est 4 (y compris l'espace suivant), pour soustraire c'est 2, pour diviser par c'est 3, pour multiplier par c'est 5 , et pour soustraire de 0, la soustraire de nécessite un peu de manipulation supplémentaire car elle a besoin du
\-
combo de commandes, mais les autres utilisent simplement leur valeur pour rechercher le caractère de commande approprié dans une table.Ce processus est répété pour chaque commande, créant la sortie dans une chaîne préconstruite à la ligne 8. Chaque fois qu'une commande supplémentaire est ajoutée, nous ajoutons également un guillemet de fermeture à la chaîne pour nous assurer qu'elle est toujours correctement terminée. Ensuite, lorsque nous atteignons finalement la fin de notre entrée, nous «exécutons» simplement cette chaîne pour la pousser sur la pile, puis la suivons avec une séquence de sortie standard pour tout écrire.
la source
JavaScript (ES6), 163 octets
Essayez-le:
la source
Vim
208171168 168 octetsAjout de la possibilité de faire plusieurs répétitions d'affilée selon @ Flp.Tkc, mais de jouer suffisamment d'octets pour que je puisse encore réduire le nombre d'octets.
TryItOnline
Caractères non imprimables:
Sortie des cas de test:
cw^R=^R" ^[
TryItOnlinecw^R=((^R" /5) *-1+9) ^[
TryItOnlinecw^R=((((((^R" +5) +10) *2) -15) -15) /2) ^[
TryItOnlinela source
lex, 246 octets
lex cible C, donc un compilateur C devrait le compiler en quelque chose d'exécutable. La bibliothèque lexer (
ll
) devrait également être liée. Cela peut ajouter une octet-pénalité, mais je ne sais pas combien d'octets si c'est le cas.Le programme génère un programme Lex (par spécification) qui évalue l'expression de mot de passe transpilée. Le code entre
%{
et%}
est pour le "transpilateur" uniquement:Entre les deux
%%
lignes se trouve la partie regex / action. La première règle à mettre en correspondance seraitT
("Pensez ...") qui construit le préambule (les programmes lex doivent commencer à contenir au moins la section de règle, etyytext
est le dernier texte correspondant, donc la règle essentiellement l'accumulateur avec l'entrée de l'utilisateur ).Le programme supprime toutes les entrées à l'exception de celles qui correspondent, et les autres règles (
ad
,fr
jusqu'àre
) gérer les clauses d'expression wordmath avec comme match d'un minimum possible d'être unique. Dans la plupart de ces cas, il définitc
une expression infixe, qui est concaténée entren
et le dernier entier lu lors de l'O
appel (ainsi, par exemple, la lecture de "ajouter 9" définira l'infixe sur+=
, v sur9
et l'appel àO
sortiran+=9;
) . (Un côté intéressant est que "soustraire de 8" entraînera la correspondance entres
lesfr
règles et les règles, mais comme elleO
n'est appelée qu'au numéro, la règle appropriéen=-n+8;
est la seule expression qui obtient la sortie). lere
règle pour "répéter" n'appelle queO
encore une fois, qui génère la dernière expression créée (et puisque les correspondances ultérieures vont s'encombreryytext
, la prise en charge de "répétition" est la raison pour laquelle la conversion entière dans la la fin de programme paire indiquant la fin du programme lex de sortie.[0-9]+
était requise). Enfin, une période entraîne la sortie de la bande-annonce du programme, qui sort simplement l'accumulateur et se ferme avec le%%
Remarque: ni le programme principal de transpiler ni le programme de sortie ne se termineront. L'entrée de tuyauterie fonctionnerait ou fournirait EOF (ctrl-D). Si la terminaison est requise après la première entrée, exit () s peut être ajouté.
Pour construire / exécuter:
Test 1:
Test 2:
Test 3:
Test 4:
la source
Pyth,
6967 octetsUn programme qui prend en entrée un
"quoted string"
et imprime le résultat.Suite de tests
Comment ça marche
Pyth a des opérateurs de préfixe, donc les opérations arithmétiques de base sont effectuées en utilisant
(operator)(operand1)(operand2)
, tandis que la variable pré-initialiséeQ
donne l'entrée. Par conséquent, un programme WordMath transpilé est construit en commençant par la chaîne'Q'
, et à chaque étape, en ajoutant l’opérateur, puis en ajoutant ou en ajoutant l’opérande comme nécessaire.J\Q
DéfinissezJ
, la chaîne de programme transpilée, sur la chaîne'Q'
tcQ\,
Fractionnez l'entrée sur des virgules et jetez le premier élément (qui est 'Think of a number'
)V
CarN
en cela:Iq@N1\r
Si le caractère àN[1]
est'r'
(répétez):=NZ
DéfiniN
surZ
(valeur précédente deN
, définie à la fin de la boucle for)x"asdm"@N1
Trouver l'index deN[1]
dans"asdm"
(additionner, soustraire, diviser, multiplier)@"+-/*"
Indexer avec cela dans"+-/*"
, donnant l'opérateur requis,J-eCN)\.
Produire la liste à deux éléments[J, -eCN)\.]
, où le deuxième élément est le dernier élément deN
fractionnement sur un espace avec tous les'.'
caractères supprimés (opérande)qh@cN)1\f
Si le premier caractère du deuxième élément de laN
division sur un espace est'f'
(soustraire de):.>
Échangez les éléments de la liste à deux éléments+
Fusionner l'opérateur et la liste à deux éléments en une seule liste=Jjd
DéfiniJ
sur celui joint sur les espaces=ZN
RéglezZ
surN
J
ImpressionJ
la source
Pépin , 58 octets
Dommage que je n'ai pas encore implémenté cet opérateur de soustraction inverse.
Le programme prend un script WordMath de stdin et sort le code Pip vers stdout. Le code qui est sorti, de la même manière, prend un nombre de stdin et sort le résultat vers stdout.Essayez-le en ligne!
Stratégie
Pour une entrée comme celle-ci:
nous voulons une sortie comme celle-ci:
qui fonctionne comme suit:
Non golfé + explication
La structure de base du programme est
{...}Mq^k
, qui se diviseq
(une ligne de stdin) surk
(espace virgule) etM
applique une fonction à chaque élément.À l'intérieur de la fonction, nous commençons par traiter le
repeat
cas. Le test le plus court dans Pip semble êtresNa
(y a-t-il un espace dans la commande). Si oui, nous voulons utilisera
; sinon, utilisezp
, qui stocke la commande précédente. Attribuez cette valeur àa
et également àp
(pour la prochaine fois).Pour notre valeur de retour, nous utilisons une liste, ce qui est bien car le format de sortie par défaut pour les listes est de tout concaténer ensemble. Le résultat commence toujours par
Y
. Ensuite, nous avons besoin d'une table de recherche pour les opérations.Notez que les longueurs de
add
(4),subtract
(9),divide by
(10),multiply by
(12) etsubtract from
(14) sont toutes distinctes. Observez en outre qu'ils sont toujours distincts lorsqu'ils sont pris mod 7. Ainsi, nous pouvons les utiliser pour indexer dans une liste de sept éléments (contenant cinq extraits de code et deux espaces réservés) pour mapper chaque commande WordMath au code Pip approprié (conçu de sorte que le nombre peut être simplement enchaîné à la fin):-y+
(subtract from
)y-
(subtract
)y//
(divide by
)y+
(add
)y*
(multiply by
)Pour les indices, nous utilisons regex pour obtenir l'index du premier chiffre de la commande:
a@?`\d`
. Nous avons également récupéré l'expression régulièrey
pour une utilisation future. La table de recherche est générée en fractionnant la chaîne"-y+ y- y// y+ y* "
surs
(espace).Nous devons encore gérer la première entrée, qui devrait se traduire par le code
Yq
. PuisqueThink of a number
ne contient pas de chiffres, l'@?
opérateur retourne nil. L'utilisation de nil comme index dans la table de recherche renvoie également nil. Nil est faux, donc tout ce que nous devons faire est d'ajouter|'q
à utiliserq
au lieu d'une opération dans ce cas.Le dernier élément de la liste renvoyée est le numéro lui-même. Nous l'obtenons via
a@y
(trouver toutes les correspondances dans la commande de l'expression rationnelle numérique que nous avons tirée plus tôt). Cela renvoie une liste de chiffres, mais encore une fois, ce n'est pas un problème car toutes les listes seront concaténées lors de la sortie. Pour la première entrée,a@y
ne correspond à aucun chiffre et donne une liste vide, ce qui n'ajoute rien à la sortie.Par exemple
Avec entrée
l'expression de la carte donne la liste
qui, une fois concaténé, produit
la source
Python 2 ,
154153146 octetsCorrection, et même enregistré plusieurs octets dans le processus. ^ __ ^
Essayez-le en ligne!
Basé sur la même stratégie que ma réponse Pip . Fonctionnalités spécifiques à Python:
Think of
et la fermeture.
sont supprimées de la chaîne avant splitting (input()[9:-1]
). La période était trop embêtante pour être gérée dans la boucle principale. La suppression des neuf premiers caractères aide pour une raison différente (voir ci-dessous).import re
), nous utilisonsrfind(" ")
pour trouver le dernier espace dans la commande. Nous pouvons également l'utiliser pour vérifier lerepeat
cas.a number
, dans laquelle se trouve l'index de l'espace1
. Cet index remplit commodément l'autre trou de la table de recherche. L'autre problème avec le traitement de l'étage d'entrée dans la boucle principale était la+c[s:]
partie qui en résulteraitx=input() number
. Pour résoudre ce problème, nous multiplions les chaînes parc[0]<"a"
:1
pour toutes les commandes régulières, dans lesquellesc
commence par un espace, mais0
pour l'initialea number
.la source
WinDbg,
449388 octets-61 octets en définissant un alias pour le code répété
Inspiré par l' utilisation de LambdaBeta
#define
. Cette approche modifie légèrement la syntaxe WordMath (,
et.
doit être délimitée par un espace comme les autres mots, et,
ne suit pasrepeat
), et crée un alias tel que la syntaxe WordMath modifiée est un code WinDbg valide. La dernière ligne fait ce que la question demande et transpose en convertissant l'entrée dans la syntaxe modifiée.L'entrée est effectuée en définissant une chaîne à une adresse mémoire et en définissant le pseudo-registre
$t0
à cette adresse. Remarque: cela écrasera leint
at0x2000000
, donc si vous commencez votre chaîne là-bas, elle sera partiellement écrasée.$t0
sera également écrasé.Parce qu'il crée des alias, selon que ce code s'est exécuté avant ou après avoir défini la chaîne, le code de sortie sera différent (aliasé ou non). Malheureusement, je n'ai pas trouvé de moyen pour que les alias se développent correctement sans être délimités par des espaces (ce qui signifie que le script WordMath ne pouvait pas simplement être exécuté directement sans être d'abord transformé).
Comment ça marche:
Exemple de sortie, en entrant la chaîne avant d'exécuter une fois ce code (le programme résultant ressemble à WordMath):
Exemple de sortie, en entrant la chaîne après que ce code a été exécuté une fois (les alias sont développés lors de la saisie de la chaîne, de sorte que le programme résultant n'est pas aussi joli):
Quelques exemples de sortie supplémentaires, en utilisant simplement la syntaxe WordMath légèrement modifiée:
la source
Scala, 338 octets
Essayez-le vous-même chez ideone
Explication:
la source