introduction
Forte est un langage ésotérique très particulier basé sur le concept de modification des valeurs des nombres. Dans Forte, les nombres ne sont pas des constantes mais des variables, vous pouvez utiliser l' LET
instruction pour leur attribuer de nouvelles valeurs.
Par exemple, après avoir exécuté à LET 2=4-1
partir de maintenant, il 2
prend la valeur de 3
, ce qui signifie que chaque fois que la valeur 2
apparaît dans une expression, elle est plutôt "remplacée" par 3
. L'expression (1+1)*2
serait désormais évaluée à 9
.
Cette instruction dans Forte est utilisée à la fois pour stocker des informations et pour contrôler le flux (les lignes sont numérotées et en modifiant la valeur de leurs nombres, vous pouvez déterminer l'ordre de leur exécution). Dans ce défi, nous ne traiterons pas de ce deuxième aspect.
Le défi
Vous devez écrire un interpréteur pour un sous-ensemble simplifié d' LET
expressions de Forte .
Vous recevrez en entrée une série de lignes suivant cette grammaire:
<line>::= <number>=<expression>
<expression>::= <number>|<expression>+<number>
Remarque: cette grammaire n'est pas valide en Forte car elle manque de numéros de ligne, de LET et de parenthèses (qui sont toujours obligatoires)
Autrement dit, vous n'aurez qu'à gérer le calcul des sommations et l'attribution de valeurs aux nombres. Les parenthèses ne seront pas présentes dans l'entrée, et chaque expression devra être évaluée de gauche à droite: attention aux résultats partiels affectés par les redéfinitions!
Les nombres seront toujours des entiers non négatifs, jusqu'à la limite du type d'entier natif de votre langue (ou 2 ^ 32, selon le plus élevé des deux).
Pour chaque ligne, vous devez sortir le résultat de l'expression et affecter ce résultat à la valeur (éventuellement réaffectée) du premier nombre, ce qui affectera la façon dont les lignes suivantes seront interprétées.
C'est le code-golf , le code le plus court (en octets) gagne!
Autres règles
- Le format d'entrée est flexible, vous pouvez par exemple prendre une seule chaîne avec des sauts de ligne, une liste de chaînes, une liste de listes de nombres ... Il en va de même pour la sortie, tant qu'il est clair quel est le résultat de chaque expression dans l'entrée.
- Vous pouvez soumettre une fonction, un programme complet ou une solution à exécuter dans un environnement REPL en l'appelant une fois pour chaque ligne.
- Les failles standard sont interdites, en particulier vous ne pouvez pas appeler un interprète Forte externe dans votre code.
Exemples
Ils font tous partie de la même entrée. Après chaque ligne, la sortie attendue par rapport à cette ligne est affichée, parfois avec un commentaire indiquant les réaffectations pertinentes (ne faisant pas partie de la sortie requise).
5=4
4
6=5
4 # 5 -> 4
7=1+2+5
7
7=5+2+1
4 # Order of operations matters! 5+2 -> 4+2 -> 6 -> 4
18=5+6+7
12
5=3
3 # Remember: 5 -> 4
10=6+4
3 # 6 -> 4 -> 3, 3+3 = 6 -> 3
0
un numéro valide?0
est valide ("Les nombres seront toujours des entiers non négatifs")Réponses:
Gelée , 28 octets
Essayez-le en ligne!
C'est l'un des rares programmes Jelly où il semble plus difficile de prendre des entrées à partir des entrées standard. C'est un programme complet (l'écriture d'une fonction aurait été plus courte mais est interdite par les règles PPCG, car elle ne s'exécuterait pas correctement la deuxième fois). Le format d'entrée ressemble à ceci:
Explication
Fonction d'assistance
1Ŀ
(traduire un entier en sa valeur)Assez commodément, cette fonction d'assistance fonctionnera correctement soit sur une seule valeur, soit sur une liste de valeurs, en raison de la façon dont
y
est définie. Si plusieurs mappages sont donnés pour une seule valeur, nous prenons le premier mappage de la table. La table de mappage est stockée dans le registre (qui n'est fondamentalement qu'une variable; Jelly n'a qu'une seule variable).Fonction d'aide
2Ŀ
(évaluer une instruction LET)Nous ne voulons pas vraiment de valeur de retour ici; nous exécutons simplement cela pour ses effets secondaires (mise à jour du registre et sortie de la valeur assignée). Les fonctions Jelly retournent toujours une valeur, cependant, nous laissons simplement la table de mappage être renvoyée, car c'est le plus tersest.
Programme principal
Normalement,
⁸
cela nous donnerait le premier argument de ligne de commande lorsqu'il est exécuté dans ce contexte, mais il n'y en a pas (nous prenons l'entrée à partir de l'entrée standard), donc il s'exécute dans un mode alternatif qui nous donne la chaîne nulle. La nécessité d'initialiser le registre (à partir de sa valeur par défaut de0
, qui se bloquey
) signifie que nous ne pouvons pas mentionner implicitement l'entrée de l'utilisateur, ce qui signifie qu'il est aussi bon marché de le prendre à partir de l'entrée standard (Ɠ
) que de le prendre à partir d'un argument de ligne de commande (³
ou⁸
), et être en mesure d'accéder à l'utilisation alternative des⁸
moyens que la forme inhabituelle (pour Jelly) d'entrée est en fait un octet plus court.Il est possible que cela puisse être amélioré. Je n'ai toujours pas compris pourquoi la deuxième ligne doit dire
⁸Ǥ;
plutôt que juste;@Ç
- les deux devraient être équivalentes, pour autant que je comprends Jelly, étant donné le manque d'utilisation deµ
/ð
/ø
- mais ce dernier se bloque pour une raison quelconque. De même, il existe plusieurs autres façons de réorganiser le programme sans perdre d'octets, il est donc possible que j'ai manqué un moyen de raccourcir les choses.Soit dit en passant, la modification
ḷ
de la dernière ligne;
vous donne un aperçu intéressant du fonctionnement interne du programme, car il affichera alors l '"historique du registre" qui est implicitement émis par les valeurs de retour de2Ḷ
.la source
Perl 5 , 92 octets
90 octets de code +
-pl
drapeaux.Essayez-le en ligne!
J'utilise la table
%h
de hachage pour stocker le mappage entre les nombres.La fonction (
sub
)f
renvoie le numéro auquel son mappage d'entrée (ou son entrée si elle n'est mappée à aucun numéro):$h{$a=pop}
récupère le numéro vers lequel le mappage d' entrée. Si ce n'est pas le cas, grâce à//$a
, la valeur de($b=$h{$a=pop}//$a)
est l'entrée ($a
). Nous nous assurons que cette valeur n'est pas l'entrée elle-même pour ne pas boucler indéfiniment (!=$a
). Ensuite, nous appelons récursivementf
ou renvoyons l'entrée.Le programme principal se compose de deux étapes:
-
s%(\d+)\+(\d+)%f($1)+f$2%e&&redo
évalue le premier ajout sur le côté droit, alors qu'il y a encore un ajout: il remplace permet d'accéder au côté gauche avec et au côté droit avec , puisx+y
par le résultat de l'évaluation def(x)+f(y)
.-
/=/;$_=$h{f$`}=f$'
la mission:/=/
$`
$'
$h{f$`}=f$'
fait l'affectation. Et nous l'affectons également à ce$_
qui est implicitement imprimé après chaque ligne.la source
JavaScript (Node.js) , 81 octets
Essayez-le en ligne!
Reçoit l'entrée en appelant f avec la valeur à affecter, puis en appelant le résultat de cela avec un tableau de valeurs à additionner. (ie
f(5)([4])
) Répétez pour plusieurs lignes.v
est utilisé comme une fonction pour calculer la valeur actuelle réelle d'un nombre, et également comme un objet pour stocker les valeurs réelles.v[x]=v[x]||x
S'assure d' abord quev[x]
c'est défini.v[x]-x
effectue une comparaison pour déterminer s'il s'agit du nombre réel ou non. Si le nombre ne correspond pas à lui-même,v(v[x])
réessayez récursivement, sinon retournezx
.f
effectue le calcul et l'affectation, curry pour enregistrer un octet, où le deuxième appel renvoie la valeur calculée.la source
Haskell ,
116113108106octetsEssayez-le en ligne! Chaque équation
4=3+1+5
est notée comme tuple(4,[3,1,5])
. La fonction anonyme(id?)
prend une liste de ces tuples et renvoie une liste de tous les résultats intermédiaires.#
est une fonction permettant de trouver un point fixe d'une fonction donnéee
et une valeur de départx
.La fonction
?
prend une fonction d'évaluatione
et résout récursivement chaque équation.foldl1(\a b->e#(e#a+e#b))s
évalue le côté droit d'une équation et enregistre le résultatm
, par exemple pour4=3+1+5
le calculeval(eval(eval 3 + eval 1) + eval 5)
, où chacuneval
est une application de point fixe dee
. Ensuite, la fonction eval est modifiée pour prendre en compte la nouvelle affectation den
:(\x->last$m:[e#x|x/=e#n])
qui est la même que\x -> if x == eval n then m else eval x
.La fonction d'évaluation initiale consiste à
id
mapper chaque entier sur lui-même.Merci à Ørjan Johansen pour une fonction de point fixe plus courte, économisant 2 octets!
la source
last.
(#)e=until((==)=<<e)e
ou(#)=until=<<((==)=<<)
est plus courte.oK, 48 octets
Usage:
f[5;1 2 3] / 5=1+2+3
Essayez-le en ligne!
Si vous ne me dérange pas d' avoir une limite supérieure aux chiffres que vous pouvez utiliser, comme en utilisant uniquement des nombres à
0
travers998
, puis les suivantes suffixes ( 41 octets ± quelques en fonction du maximum):Explication:
;
sépare trois définitions.a
est un dictionnaire / carte de nombres. Dans le premier cas, c'est un véritable dictionnaire vide[]
, dans le second cas, c'est une liste des numéros0
à998
.s
est une fonction qui trouve le nombre "résultant" lorsqu'il reçoit un nombre. La/
fin de la fonction signifie qu'elle s'appliquera à sa propre sortie jusqu'à ce que la sortie cesse de changer.Le dernier bit,,
f
signifie que:la source
Python 3,
146132130 130 octets14 octets enregistrés grâce à @Dada
2 octets enregistrés grâce à @ mbomb007
Essayez-le en ligne!
Reçoit l'entrée sous forme de tuples d'équations [
x = y + z + w
as(x, (y, z, w))
], les sorties via le générateur.la source
g
pourrait probablement être écritg=lambda x:d.get(x)and d[x]!=x and g(d[x])or x
. Et je pense que vous pouvez utiliser 1 espace pour mettre en retrait au lieu de 2. Cela devrait vous amener à [132 octets] ( Essayez-le en ligne! ).