Prindeal (prononcé prin-dee-al ) est un nouveau langage de programmation ésotérique qui n'a que quatre commandes: pr int , in crement , de crement et al ias . Malgré son minimalisme, des opérations mathématiques complexes peuvent être effectuées dans Prindeal en combinant intelligemment les quatre commandes.
Votre tâche dans ce défi de golf de code est d'écrire le programme le plus court qui peut exécuter le code Prindeal.
La spécification est longue mais j'ai essayé de la rendre aussi claire que possible et je crois que si vous faites l'effort d'apprendre Prindeal, vous la trouverez assez élégante!
Intrépide Prindeal
Prétraitement
Avant qu'un programme Prindeal puisse être interprété, ces éléments doivent être supprimés dans cet ordre:
- Tout ce qui se trouve après un
#
signe à la fin de la ligne est allumé, plus le#
lui - même. (Ce sont des commentaires.) - Espace de fin sur n'importe quelle ligne.
- Lignes complètement vides.
Par exemple, le programme Prindeal
p cat #The next line has 7 trailing spaces.
p dog
#p mouse
serait prétraité en
p cat
p dog
À partir de là, nous supposerons que cette étape de prétraitement a été effectuée.
Variables
Nous devons rapidement définir des variables avant de montrer comment elles sont utilisées.
Les variables (et les références aux variables) sont ce qui est passé dans les arguments des commandes Prindeal. Les variables étant toujours globales , les modifications apportées à une variable, peu importe où elles se produisent, se reflètent partout.
Chaque variable contient un entier de précision arbitraire non négatif (0, 1, 2, 3, ...). Les variables n'ont pas besoin d'être pré-initialisées - elles commencent toujours par la valeur 0 la première fois qu'elles sont utilisées ou appelées.
Un nom de variable peut être une chaîne alphanumérique non vide et des traits de soulignement qui ne commencent pas par un chiffre - [a-zA-Z_][0-9a-zA-Z_]*
dans l' expression régulière . Ils sont sensibles à la casse spiny_lumpsuck3r
et Spiny_lumpsuck3r
sont donc des variables différentes.
Exécution
Prindeal est un langage de programmation impératif . Lorsqu'un programme Prindeal est exécuté, ses instructions sont exécutées de haut en bas dans l'ordre, puis le programme se termine.
Chaque ligne non en retrait dans un programme Prindeal est une instruction qui implique l'exécution d'une seule commande qui peut ou non prendre des arguments.
Les lignes en retrait n'apparaissent qu'après les commandes d' alias . Plus précisément, exactement trois lignes en retrait avec des espaces simples apparaissent après chaque commande d' alias et sont considérées comme faisant partie de celle-ci. Les instructions d' alias comportent donc en réalité quatre lignes. (Ils pourraient être une ligne, quatre est simplement plus lisible.)
Non alias Déclarations
À l'exception de l' alias , chaque instruction d'un programme Prindeal a la forme:
[command name] [argument 1] [argument 2] [argument 3] ...
Il peut y avoir un nombre arbitraire d'arguments (y compris aucun). Chaque argument est toujours une variable ou (comme nous le verrons lors de la discussion sur l' alias ) une référence à une variable .
Une fois l'exécution terminée, chaque instruction est signalée comme un échec ou un succès selon que des erreurs ont été rencontrées ou non. (Cela n'a d'importance que lorsque nous utilisons l' alias .)
L' impression , l' incrémentation et la décrémentation intégrées sont des instructions de la forme ci-dessus. Voici ce qu'ils font:
print a un nom de commande
p
et prend un argument. Il affiche le nom de la variable passée et sa valeur (en décimal) séparés par "=", puis un retour à la ligne. Il est toujours signalé comme un succès .Par exemple, le programme Prindeal
p _MyVariable_321 p screaming_hairy_armadillo
sortirait
_MyVariable_321 = 0 screaming_hairy_armadillo = 0
car toutes les variables commencent à 0. (Les espaces avant et après le signe égal sont obligatoires.)
increment a un nom de commande
i
et prend un argument. Il incrémente la valeur de la variable passée de 1. Il est toujours signalé comme un succès .Par exemple, le programme
i alpaca p alpaca i alpaca p alpaca
sortirait
alpaca = 1 alpaca = 2
Notez comment a
alpaca
été incrémenté de 0 à 1 même s'il n'y avait jamais eu accès auparavant.décrémenter a un nom de commande
d
et prend un argument. Si la variable transmise n'est pas nulle, sa valeur est décrémentée de 1 et l'instruction est signalée comme réussie . Si la variable transmise est 0, rien n'est fait et l'instruction est signalée comme un échec .Par exemple, le programme
i malamute p malamute d malamute #success p malamute d malamute #failure p malamute d akita #failure p akita
sortirait
malamute = 1 malamute = 0 malamute = 0 akita = 0
Notez que la décrémentation d'une variable avec la valeur 0 est le seul moyen de produire un échec .
L' instruction alias et les commandes aliasées
La commande alias a une syntaxe spéciale et est la plus puissante car elle peut être utilisée pour définir de nouvelles commandes. Le nom de la commande d' alias est a
et une instruction d' alias a la forme:
a [name of new command]
[statement A]
[statement B]
[statement C]
Où chacun [statement X]
représente une instruction non- alias , c'est-à-dire quelque chose avec le formulaire [command name] [argument 1] [argument 2] [argument 3] ...
.
Le nom de la commande aliasée [name of new command]
peut être n'importe quelle chaîne non vide de caractères alphanumériques et de soulignements qui ne commence pas par un chiffre - [a-zA-Z_][0-9a-zA-Z_]*
dans l'expression régulière.
(Il s'agit du même ensemble de noms que de variables, mais les commandes et variables aliasées sont différentes choses utilisées à différents endroits . Une variable peut être nommée de la même manière qu'une commande sans conséquences néfastes.)
Lorsqu'une instruction d' alias est exécutée, une nouvelle commande est ajoutée aux côtés des quatre p
i
d
a
commandes d'origine. La nouvelle commande peut être utilisée comme [command name]
instruction in et appelée avec des arguments comme toute autre commande non alias .
Lorsqu'une instruction avec un nom de commande aliasé est exécutée, exactement deux autres instructions de son instruction d' alias d' origine sont exécutées:
[statement A]
est toujours exécuté[statement B]
est exécuté si[statement A]
était un succès[statement C]
est exécuté si[statement A]
était un échec
Les instructions A, B et C sont toujours exécutées paresseusement , c'est-à-dire qu'elles sont évaluées à la volée au moment de leur exécution.
Une fois l'exécution terminée, la commande aliasée est signalée avec le même indicateur de réussite ou d' échec que l'instruction B ou C, selon celle qui a été exécutée . (Les déclarations d' alias elles-mêmes n'ont pas besoin d'être marquées car elles ne peuvent pas se produire en elles-mêmes.)
Exemple d'alias 1
Disons que nous voulons une nouvelle commande qui incrémente la variable
frog
deux fois. Cette déclaration d'alias y parvient:a increment_frog_twice i frog i frog d frog
L'instruction A (
i frog
) est toujours exécutée et toujours signalée comme un succès, de sorte que l'instruction B (i frog
) est également toujours exécutée et la variablefrog
est ainsi incrémentée de 2. Laincrement_frog_twice
commande est toujours signalée comme un succès car l'instruction B est toujours exécutée et B est toujours un succès . L'instruction C (d frog
) n'est jamais exécutée.Ainsi, la sortie vers
a increment_frog_twice i frog i frog d frog p frog increment_frog_twice p frog
serait
frog = 0 frog = 2
Nous pouvons généraliser cet exemple afin que toute variable puisse être incrémentée deux fois en donnant un argument à la commande aliasée.
Dans une instruction d' alias , les entiers positifs 1, 2, 3, etc. représentent les 1er, 2e, 3e, etc. arguments passés dans la commande alias. (Ces arguments peuvent être des variables simples ou des références aux variables elles-mêmes.) Ces nombres ne peuvent apparaître que dans les arguments des instructions A, B et C dans une instruction d' alias . Cela n'a aucun sens pour eux d'apparaître ailleurs.
Exemple d'alias 2
Cela généralise le dernier exemple - toute variable passée dans
increment_twice
sera incrémentée de 2 car1
c'est une référence au premier argument passé dans:a increment_twice i 1 i 1 d 1 #never reached p toad increment_twice toad p toad
Le résultat de ce programme serait
toad = 0 toad = 2
Nous pourrions alors alias une autre commande qui prend deux arguments et les appelle
increment_twice
tous les deux:a increment_twice i 1 i 1 d 1 #never reached a increment_both_twice increment_twice 1 increment_twice 2 d 1 #never reached increment_both_twice platypus duck p platypus p duck
La sortie ici serait
platypus = 2 duck = 2
Il est important de réaliser que les commandes aliasées peuvent être récursives, car c'est là que réside leur véritable pouvoir. Par exemple, nous pouvons créer une commande qui définit toute variable transmise à 0:
Exemple d'alias 3
La
set_to_zero
commande prend un argument et définit sa variable à 0 et est signalée comme un succès lorsqu'elle est terminée:a set_to_zero d 1 set_to_zero 1 i _dummy_ i oryx i oryx i oryx p oryx set_to_zero oryx p oryx
Le résultat de ce programme serait
oryx = 3 oryx = 0
Ce qui se passe, c'est que lorsque
set_to_zero oryx
est exécuté,d 1
décrémente avec succèsoryx
de 3 à 2, puisset_to_zero 1
est appelé, ce qui revient à rappelerset_to_zero oryx
. Ainsi, le processus se répète jusqu'à ce qued 1
soit un échec , arrêtant la récursivité et incrémentant la_dummy_
variable pour qu'un succès soit produit.
Défi
Écrivez un programme qui peut exécuter le code Prindeal exactement comme décrit ci-dessus. Prenez le code Prindeal via stdin, la ligne de commande ou sous forme de fichier texte. Imprimez la sortie du programme Prindeal sur stdout ou l'alternative la plus proche de votre langue.
Alternativement, vous pouvez écrire une fonction qui prend le code sous forme de chaîne et imprime ou renvoie la chaîne de sortie.
De plus, vous pouvez supposer que:
- Le code Prindeal saisi ne contiendra que des sauts de ligne et des caractères ASCII imprimables et (éventuellement) qu'il se terminera par une ligne vide.
- Le code d'entrée sera Prindeal valide - bien formé et syntaxiquement correct.
- L'exécution du code ne produira aucune boucle infinie ni aucune référence invalide à des commandes qui n'ont pas été définies ou à des arguments qui n'ont pas été donnés.
- Les noms de commandes
p
,i
,d
eta
ne seront jamais plus aliasées. (Vous ne pouvez pas supposer que les variables n'auront pas ces noms.)
En outre, peu importe si vos valeurs de variable ne sont pas vraiment des entiers de précision arbitraire, car seuls les nombres inférieurs à environ 1000 seront testés. C'est aussi bien si votre langue a des limites de récursivité (comme Python ) que les programmes Prindeal plus complexes peuvent rencontrer tant que le programme de test ci-dessous fonctionne.
Programme de test
Voici un grand programme Prindeal qui construit les opérations d'addition, de multiplication et d'exponentiation grâce à l'utilisation de variables factices (à commencer _
par convention) et de nombreux alias d'assistance:
#Command Definitions:
a s #flag as a success
i _
d _
d _
a f #flag as a failure
d _
d _
d _
a z #1 = zero
d 1
z 1
s
a n #1 = one
z 1
i 1
s
a move #2 += 1, 1 = zero
moveH 1 2
move 1 2
s
a moveH #move helper
d 1
i 2
f
a dupe #2 += 1, 3 += 1, 1 = zero
dupeH1 1 2 3
dupe 1 2 3
s
a dupeH1 #dupe helper
d 1
dupeH2 2 3
f
a dupeH2 #dupe helper
i 1
i 2
s
a copy #2 = 1
z 2
copyH 1 2
s
a copyH #copy helper
dupe 1 2 _copy
move _copy 1
s
a addTo #1 += 2
copy 2 _add
#testing comments #
move _add 1#in weird places # just because #
s
#it's a g##d idea
###
a add #1 = 2 + 3
#its a good idea
z 1
addH 1 2 3
s
##
#
a addH #add helper
#this is a comment
addTo 1 2 #as is this
addTo 1 3
s
a mul #1 = 2 * 3
mulH1 1 2
mulH2 1 3
s
a mulH1 #mul helper
z 1
copy 2 _mul
s
a mulH2 #mul helper
mulH3 1 2
mulH2 1 2
s
a mulH3 #mul helper
d _mul
addTo 1 2
f
a mulBy #1 *= 2
mul _mulBy 1 2
copy _mulBy 1
s
a pow #1 = 2^3
powH1 1 3
powH2 1 2
s
a powH1 #pow helper
n 1
copy 2 _pow
s
a powH2 #pow helper
powH3 1 2
powH2 1 2
s
a powH3 #pow helper
d _pow
mulBy 1 2
f
#Running Tests:
p A
p B
p C
n A #A = 1
n B #B = 1
add C A B #C = A + B = 1 + 1 = 2
p ____
p A
p B
p C
add B A C #B = A + C = 1 + 2 = 3
p ____
p A
p B
p C
mul d B C #d = B * C = 3 * 2 = 6
p ____
p d
mulBy d B #d = d * B = 6 * 3 = 18
p ____
p d
d A #A = A - 1 = 1 - 1 = 0
mulBy d A #d = d * A = 18 * 0 = 0
p ____
p d
pow A C B #A = C ^ B = 2 ^ 3 = 8
p ____
p A
p B
p C
pow A B C #A = B ^ C = 3 ^ 2 = 9
p ____
p A
p B
p C
pow C A B #C = A ^ B = 9 ^ 3 = 729
p ____
p A
p B
p C
(Si vous jouez avec ce code, sachez que de nombreuses commandes échoueront si la même variable est donnée plusieurs fois comme argument. Cela peut facilement être corrigé mais le code résultant est plus long.)
Votre interprète Prindeal devrait être capable de produire la sortie exacte:
A = 0
B = 0
C = 0
____ = 0
A = 1
B = 1
C = 2
____ = 0
A = 1
B = 3
C = 2
____ = 0
d = 6
____ = 0
d = 18
____ = 0
d = 0
____ = 0
A = 8
B = 3
C = 2
____ = 0
A = 9
B = 3
C = 2
____ = 0
A = 9
B = 3
C = 729
Notation
Le code le plus court en octets gagne. Tiebreaker revient à une soumission antérieure.
Brownie Bonus: Écrivez un programme sympa dans Prindeal. J'ai implémenté l'addition et la multiplication, pouvez-vous faire de la soustraction ou de la division?
la source
p
, et ensuitep p
, qui afficherait 1, non?Réponses:
Pyth,
162136 octetsManifestation.
Golfed à 26 caractères par inline les variables et le changement de
I
et leE
flux de commande sur la base de?
et le.x
flux de commande sur la base.Pour la première fois, j'ai manqué de variables en Pyth. Chaque variable unique en Pyth (
bdkGHNTY
etJK
) était en cours d'utilisation, et je voulais l'utiliserb
comme une nouvelle ligne. Heureusement, j'ai pu utiliserN
pour signifier deux choses complètement différentes dans différentes parties du programme, et donc cela fonctionne toujours.Non golfé (exécuté avec -m):
la source
Python 2,
600584397373 octetsCeci est ma propre solution de référence pour le golf. Tout le monde est invité à l'améliorer ou à suivre sa logique dans sa propre réponse tant que l'attribution est donnée.
La partie intéressante à ce sujet est qu'aucune récursivité n'est effectuée, donc elle n'aura jamais de problèmes avec la limite de récursivité de Python. Par exemple, le programme Countup Prindeal de Sp peut s'exécuter indéfiniment.
C'est un programme qui prend la chaîne de programme citée avec des sauts de ligne, par exemple
'p _MyVariable_321\np screaming_hairy_armadillo'
.J'ai pris divers indices de golf à partir des réponses de Sp et Pietu . Merci les gars :)
la source
Python 3,
345336335328 octets(-6 octets grâce à @orlp)
Toujours au golf. Suppose que le programme est stocké dans un fichier nommé
P
.Mettre les appels à l'
f
intérieur du lambdad
économiserait quelques octets, mais cela ferait que le dernier cas de test atteindrait la profondeur de récursivité maximale.Quelques programmes Prindeal
Le programme de soustraction inutile
Voici un programme de soustraction inutile . C'est inutile parce que, même s'il soustrait correctement, il ne renvoie pas le succès / l'échec en conséquence.
La sortie doit être:
Compter jusqu'à
Compte vers le haut et imprime
n
pour toujours. Pourrait éventuellement fonctionner comme un test pour la vitesse de l'interpréteur (méfiez-vous des longs retraits sur interruption du clavier).la source
l[:(l+"#").find("#")]
et toutes ses variantes peuvent être remplacées par un simplel.split('#')[0]
.find
que j'ai oublié que vous pourriez le fairesplit
même si#
vous n'y étiez pas. Merci :)JavaScript (ES6), 273
258Modifier les bugs corrigés et ajouté une vraie suite de tests.
Sans compter les grands espaces et les nouvelles lignes.
Peut certainement être un peu plus joué au golf.
Trop fatigué pour écrire une explication maintenant, je pense que c'est un bon exemple d'utilisation de fermetures pour maintenir en vie des valeurs temporaires (paramètres).
Testez l'exécution de l'extrait sur n'importe quel navigateur compatible EcmaScript 6 (notamment pas Chrome ni MSIE. J'ai testé sur Firefox, Safari 9 pourrait aller)
la source
C # 6, 653 octets
Voici mon entrée, au milieu d'une mer de Python ...
Développé et commenté:
Pour l'utiliser, il suffit d'instancier la classe et d'appeler la
R()
méthode, par exemple:la source
Lisp commun,
758646619Mettez ceci
file.lisp
et appelez par exemplesbcl --script file.lisp
; l'entrée est lue à partir du flux d'entrée standard.Cette version analyse un sur - ensemble de Prindeal: sans trop de difficultés, vous pouvez accéder à tous les Common Lisp à partir d'une source Prindeal. Je considère cela comme une caractéristique de l'interprète.
Version commentée
Exemple
Si nous remplaçons
eval
parprint
dans la boucle de lecture / évaluation, nous pouvons voir ce qui est évalué:Macroexpansion
Si nous choisissons la définition d'alias suivante:
... nous pouvons voir des références à une variable nommée
g
qui ne se trouve nulle part dans la portée lexicale. Mais après macroexpansion, voici le code en cours d'évaluation:Désormais,
g
fait référence à la liste d'arguments de la fonction en cours de définition.la source
Python 2, 486 octets
C'est la solution de référence sur laquelle j'ai le plus joué (actuellement -98 octets).
Changements (dont je me souviens):
[l,l[:l.find('#')]]['#'in l]
).V[k]=-~V[k]if k in V else 1
)k=s[1]
)print
ajout automatique d'espaces (print k,'=',V.get(k,0)
)'0'<t[0]<':'
)r
around pour enregistrerreturn
smap(str.split,c[:3]))
)la source
Python 3, 1322 octets
Golfé:
Non golfé:
Usage:
Où
c
est le contenu du texte.Exemples:
Les chaînes unifilaires sont acceptées:
P("p cat")
P("p dog\ni dog\np dog")
Les cordes à lignes multiples sont également acceptées:
Ou:
Etc.
Remarques:
Cela fonctionne correctement pour tous les cas de test, mais atteint la limite de récursivité sur:
D'où le
sys.setrecursionlimit(2000)
.la source
Python -
695688 octets<TAB>
est un caractère de tabulation littéral.la source
C ++, 1111 octets
Celui-ci est C ++ - aussi idiomatique que je pourrais le faire.
Cela signifie le rendre plus C ++ - ish et moins C-ish.
Cela signifie également qu'il est plus grand que le programme C équivalent.
Je pense que C ++ rivalise avec Java pour la bibliothèque standard verbeuse.
Il se compile avec VS2013 et g ++ 4.9.2 (avec -std = c ++ 11)
Voici l'original. Si quelqu'un peut penser à un moyen de le rendre plus idiomatique et plus court en même temps, faites-le moi savoir.
la source
Haskell, 1009
J'ai fait de mon mieux pour jouer au golf; mon code non golfé comprenait plus de 3 000 caractères. À ce stade, je ne me souviens pas de toutes les fonctions, donc jouer au golf signifie plus deviner ce qui le cassera et ce qui ne le fera pas.
la source