Il s'agit du défi hebdomadaire n ° 2. Thème: Traduction
Écrivez un programme ou une fonction qui prend le code source d'un programme dans Prelude et génère du code pour un programme équivalent dans Befunge-93 . Pour que le programme soit équivalent, il doit, pour toute entrée donnée, produire la même sortie que le programme Prelude, et s'arrêter si et seulement si le programme Prelude s'arrête.
Langue d'entrée: Prélude
Interpréteur Python:
Un programme Prelude se compose d'un certain nombre de "voix" qui exécutent des instructions simultanément. Les instructions pour chaque voix sont sur une ligne distincte. Chaque voix a une pile distincte, qui est initialisée avec une quantité infinie de zéros. L'exécution commence dans la colonne la plus à gauche et avance d'une colonne vers la droite à chaque tick, sauf lorsqu'elle est influencée par )
ou par des (
instructions. Le programme se termine lorsque la dernière colonne est atteinte.
Prélude spec pour ce défi:
Digits 0-9 Push onto the stack a number from 0 to 9. Only single-digit
numeric literals can be used.
^ Push onto the stack the top value of the stack of the above
voice.
v Push onto the stack the top value of the stack of the below
voice.
# Remove the top value from the stack.
+ Pop the top two integers from the stack and push their sum.
- Pop the top two integers from the stack, subtract the topmost
from the second, and push the result.
( If the top of the stack is 0, jump to the column after the
matching `)` after the current column executes.
) If the top of the stack is not 0, jump to the column after
the matching `(` after the current column executes.
? Read an integer from STDIN.
! Pop one value from the stack and print it to STDOUT as an
integer.
<space> No-op
Remarques
v
et^
agissez de manière cyclique, de sorte que lav
voix du bas copiera l'élément de pile de la voix du haut et^
la voix du haut copiera de la voix du bas. Corollaire: les deuxv
et^
dupliquez le haut de la pile dans un programme à une seule voix.- A
(
et sa correspondance)
peuvent être situés sur des lignes différentes. Cependant , un)
regardera toujours la pile de la voix où le correspondant a(
été placé, pas la pile où le)
lui-même est placé. - Les valeurs produites par les instructions
^
etv
opèrent sur les valeurs présentes avant la fin de toute autre opération dans la même colonne. ?
et!
fonctionner différemment de la spécification trouvée sur esolangs.org, alors assurez-vous de tester avec l'interpréteur légèrement modifié fourni dans cet article.
L'entrée est garantie d'avoir:
- Parenthèses correspondantes
- Pas plus d'une parenthèse dans une colonne
- Même nombre de caractères sur chaque ligne
- Au moins une ligne
- Aucune colonne avec plus d'une instruction d' E / S (
!
ou?
) - Un caractère de saut de ligne après les instructions pour chaque voix
- Pas de caractères autres que ceux mentionnés ci-dessus
Langue de sortie: Befunge-93
Befunge est un langage basé sur une pile dont le compteur de programme (PC; un pointeur vers l'instruction en cours) se déplace librement sur une grille à deux dimensions. Il commence dans le coin supérieur gauche, se déplaçant vers la droite. Le champ de jeu est toroïdal, c'est-à-dire que le mouvement du PC s'enroule autour des deux bords. Befunge possède également une pile qui est initialisée à un nombre infini de zéros. Befunge a les opérations suivantes:
Vous pouvez assumer les caractéristiques suivantes du compilateur / interprète Befunge-93:
- Les entiers sont d'une précision illimitée.
- Il permet des grilles de toute taille.
- Les coordonnées de la grille (pour
g
etp
) sont basées sur 0.
Notation
Afin d'éviter les soumissions qui produisent simplement un interpréteur Prelude dans Befunge et codent en dur la source Prelude, l'objectif sera de minimiser la taille du code source Befunge résultant.
Vous trouverez ci-dessous un certain nombre de programmes Prelude. Votre traducteur sera exécuté sur tous ces éléments. Votre score est la somme des tailles des programmes Befunge, à condition que tous soient valides.
Votre traducteur ne doit pas être optimisé spécifiquement vers ces cas de test (par exemple en codant en dur des programmes Befunge manuscrits pour eux). Si je soupçonne une réponse, je me réserve le droit de modifier les entrées ou d'en créer d'autres.
Exemples d'entrées
Imprimer n-1
jusqu'à 0
:
?(1-^!)
ET logique:
? (0)
?(0 )
1 !
OU logique:
? (0)
? (0)
1 1 !
Vérifier la parité d'entrée (ie modulo 2) du nombre non négatif:
?(1-)
^ v
v1-^^-!
Mettre l'entrée au carré:
^
^+ !
?(1-)
Imprimez le n ème numéro de Fibonacci, où n = 0
correspond à 0 et n = 1
correspond à 1:
0 v+v!
1 ^
?(1-)
Signum:
1) v # - !
vv (##^v^+)
?(# ^ ##
Division pour les entrées non négatives:
1 (# 1) v # - 1+)
vv (##^v^+)
? v-(0 # ^ #
?
1+ 1-!
Bien sûr, votre programme doit présenter le même comportement dans tous les cas, même si le comportement de l'exemple de programme pour les nombres négatifs n'est pas spécifié.
Enfin, votre traducteur ne doit pas être excessivement long:
- Il doit être contenu dans une publication Stack Exchange
- Il doit traiter les entrées d'échantillon en moins de 10 minutes sur un ordinateur de bureau typique.
Notez qu'une entrée numérique pour Prelude ou Befunge est donnée sous la forme d'un signe moins facultatif suivi d'un ou plusieurs chiffres décimaux, suivi d'un retour à la ligne. Une autre entrée est un comportement indéfini.
Vous pouvez écrire votre traducteur dans n'importe quelle langue. Le code Befunge traduit le plus court gagne.
Classement
- Sp3000 : 16430 octets
1
trouve dans une boucle, il ne peut donc pas être poussé. Un 0 peut provenir de la quantité infinie de 0 qui commencent sur les piles.Réponses:
Python 3, marquera plus tard
Courez comme
py -3 prefunge.py <input filename> <output filename>
.La semaine a été lente pour moi, donc je me suis finalement assez ennuyé pour aborder cette question vieille de six mois. Je demanderais pourquoi personne d'autre n'a essayé, mais je ressens toujours la douleur du débogage (et il y a probablement encore des bogues pour tout ce que je sais).
La question ne fournit pas d'interprète Befunge-93, j'ai donc utilisé celui-ci , qui est légèrement différent de la spécification. Les deux principales différences sont les suivantes:
Si un caractère n'existe pas dans une ligne donnée du programme, vous ne pouvez pas écrire sur cette ligne. Cela signifie que vous devrez appuyer sur Entrée plusieurs fois pour introduire suffisamment de nouvelles lignes à la fin . Si vous voyez des
NaN
s dans la sortie, c'est la cause la plus probable.Les cellules de la grille ne sont pas préinitialisées à zéro - pour plus de commodité, j'ai inclus une préinitialisation dans les sorties Befunge, mais comme ce n'est pas nécessaire, je pourrais l'enlever lorsque je commence à marquer.
La disposition de base des programmes de sortie est la suivante:
L'espace de la pile est en dehors du programme, d'où le commentaire de nouvelle ligne Enter-spamming précédent.
L'idée centrale est d'attribuer à chaque voix une ligne qui lui sert de pile. Pour conserver ces piles, nous avons également une ligne spéciale de longueur de pile où la longueur de chaque pile est enregistrée dans une cellule le long de la ligne. Le programme est alors beaucoup de
g
ets etp
uts, par exemple pour l'impression du processus est:y = stack_row[stack], x = stack_length[stack]
.91+,
, c'est-à-dire imprimer sous forme d'entier puis imprimer une nouvelle lignestack_length[stack]
Pour effectuer l'évaluation simultanée d'une colonne, toutes les cellules nécessaires sont lues et leurs valeurs sont conservées sur la pile avant l'écriture des cellules (par exemple, pour l'exemple d'impression, il peut y avoir plus d'instructions entre la première et la deuxième étape).
`
, qui est supérieur à, est utilisé pour s'assurer que les longueurs de pile ne deviennent jamais négatives et pour pousser les 0 lorsque la pile est vide. C'est de là que vient la ramification clairement visible, mais j'ai une idée qui supprimera la ramification, ce qui devrait supprimer une grande partie des espaces blancs des première et troisième lignes.Pour les boucles, car les boucles Prelude peuvent sauter dans les deux sens, nous utilisons deux lignes par boucle dans une configuration comme celle-ci:
Ces boucles constituent actuellement la majorité des octets, mais peuvent être facilement analysées en les plaçant dans la boîte à codes avec
p
laquelle je prévois de faire une fois que je suis satisfait que le traducteur fonctionne correctement.Voici un exemple de sortie pour
?(1-^!)
, c.-à-d. Imprimern-1
jusqu'à0
:Place à l'entrée:
Division (de petites entrées sont recommandées):
Il y a aussi un tas d'autres optimisations mineures qui me viennent à l'esprit, comme le remplacement
07p07g
par:07p
, mais je prends cette étape à la fois :)la source
Will score later
2 ans et ça continue! :)