Stackylogic est un langage de programmation basé sur la logique que j'ai composé et qui prend en charge 0
les 1
entrées et les sorties et en sort un seul 0
ou 1
à la fin.
Un programme Stackylogic est composé de lignes qui ne peuvent contenir que les trois caractères 01?
, ainsi qu’un seul <
à la fin de l’une des lignes. Les lignes ne peuvent pas être vide et la ligne avec le <
doivent avoir au moins un 0
, 1
ou ?
devant elle.
Voici un exemple de programme qui (comme je l'expliquerai) calcule la NAND de deux bits:
1
?<
11
?
0
Chaque ligne d'un programme Stackylogic est considérée comme une pile , avec le bas à gauche et le haut à droite. Implicitement, il y a une pile vide (ligne vide) avant la première ligne du programme et après la dernière ligne.
Le <
, que nous appellerons le curseur , marque la pile à démarrer lorsqu'un programme Stackylogic est exécuté. L’exécution d’un programme Stackylogic se déroule comme suit:
Retirez le caractère du haut de la pile sur laquelle le curseur pointe actuellement.
- Si le caractère est
?
, demandez à l'utilisateur un0
ou un1
et agissez comme s'il s'agissait du caractère. - Si le caractère est
0
défini, déplacez le curseur d'une pile vers le haut (sur la ligne située au-dessus de la ligne actuelle). - Si le caractère est
1
défini, déplacez le curseur d'une pile vers le bas (sur la ligne située sous la ligne actuelle).
- Si le caractère est
Si la pile sur laquelle le curseur se déplace est vide, affiche la dernière valeur extraite d'une pile (toujours un
0
ou1
) et termine le programme.Sinon, si la pile sur laquelle le curseur se déplace n'est pas vide, retournez à l'étape 1 et répétez le processus.
Notez que les programmes Stackylogic se terminent toujours car ils doivent éventuellement épuiser leurs piles.
Exemple NAND
Dans le programme NAND, le curseur commence sur un ?
:
1
?<
11
?
0
Nous supposerons que l’utilisateur saisit une 1
fois l’opération ?
, ce qui signifie que le curseur se déplacera vers le bas, donnant au programme l’apparence suivante:
1
11<
?
0
Une plaine se 1
trouve maintenant en haut de la pile de curseurs. Il est dûment sauté et le curseur se déplace à nouveau:
1
1
?<
0
Supposons maintenant que les entrées utilisateur 0
pour le ?
, ce qui signifie que le curseur se déplace vers le haut:
1
1<
0
Encore une fois, a 1
est sur la pile du curseur pour que le curseur apparaisse et descende:
1
<
0
Enfin, la pile de curseurs est vide et la dernière valeur apparue, le 1
, est sortie et le programme se termine.
Ceci est exact pour une porte NON - car 1 NAND 0
est 1
. Ceci fonctionne bien sûr pour les trois autres entrées à deux bits si vous voulez vérifier.
OU Exemple
Ce programme Stackylogic simule une porte OU :
?
?<
Il est facile de voir qu'une entrée initiale de 1
déplacera le curseur sur la pile vide implicite située au-dessous de la dernière ligne, mettant ainsi fin au programme et produisant le résultat 1
qui venait d'être entré.
Par 00
contre, pour une entrée , le curseur se dirigera vers la pile vide implicite située en haut, mettant fin au programme et en sortie la dernière 0
entrée.
Défi
Ecrire un programme ou une fonction qui prend dans un programme Stackylogic comme une chaîne et l' exécute, l' impression ou le retour résultant 0
ou 1
.
Upon ?
, vous pouvez demander à l'utilisateur une entrée 0
ou 1
, ou lire la valeur d'une chaîne prédéfinie de 0
'et de 1
' que vous prenez également comme entrée. (Cela peut être une autre chaîne d'entrée dans votre programme / fonction ou vous pouvez simplement supposer que la première ou la dernière ligne de la chaîne de programme sera le flux d'entrée).
Vous pouvez supposer que le programme et les entrées sont toujours bien formés. Vous pouvez éventuellement supposer que les programmes d'entrée sont fournis avec une nouvelle ligne de fin (bien qu'il y ait toujours une pile implicite vide à la fin).
Le code le plus court en octets gagne.
Plus de programmes exemples
ZERO
0<
ONE
1<
BUFFER
?<
NOT
1
?<
0
AND
?<
?
NAND
1
?<
11
?
0
OR
?
?<
NOR
1
?
00
?<
0
XOR(v1)
?
0
1?<
?
0
XOR(v2)
?
?<
11
?
0
XNOR(v1)
1
?
0?<
1
?
XNOR(v2)
1
?
00
?<
?
MEDIAN(v1)
1
???<
0
MEDIAN(v2)
?
1?<
??
Merci Martin pour les programmes médians .
la source
?\1?<\??
. Sinon, voici une implémentation symétrique à 5 lignes:?\?0\?<\?1\?
1\???<\0
.111\???????<\000
.Réponses:
Retina ,
79787368666563625544 octetsLe nombre d'octets suppose un codage ISO 8859-1.
La saisie s'effectue via STDIN et devrait être la saisie de l'utilisateur séparée par deux sauts de ligne à partir du code source.
Essayez-le en ligne! (Les deux premières lignes permettent une suite de tests, où chaque ligne est un scénario de test séparé avec
/
des sauts de ligne.)Je ne suis pas tout à fait sûr de ce qui s'est passé ici.
Cela ressemble à une solution vraiment maladroite etce n’est vraiment pas le genre de problème que Retina a été créé, mais il bat toutes les réponses actuelles pour une raison quelconque.Explication
La version finale de ceci a finalement été assez simple.
La première étape est simplement une boucle (en raison de l'
+
option) qui interprète réellement la langue. La scène est une substitution de regex unique, mais en réalité, il s’agit de trois substitutions différentes qui s’inscrivent dans une même étape, en exploitant le fait que la capture de groupes à partir de branches inutilisées est simplement considérée comme vide lors de la substitution.Traitement
?
:Cela prend simplement le premier caractère de l'entrée, puis fait correspondre des caractères arbitraires jusqu'à ce qu'il trouve
?<
et place ce premier caractère devant le<
(suppression du?
).Traitement
0
:Ceci correspond à la ligne précédant a
0<
et la met après le<
, en supprimant0
. (Effectivement, cela supprime simplement le0
et déplace la<
ligne vers le haut.)Traitement
1
:À peu près la même chose, sauf que nous déplaçons
<
une ligne tout en supprimant un1
. Un détail important à noter est l'utilisation de à la+
place de*
, c'est-à-dire que nous exigeons que la ligne suivante ne soit pas vide.Ce qui est intéressant, c’est de comprendre pourquoi cela fonctionne et pourquoi nous n’avons pas besoin de garder trace de la dernière valeur apparue pour déterminer la sortie finale. Pour ce faire, nous devons examiner comment la boucle ci-dessus peut se terminer. Étant donné que chaque correspondance possible modifie la chaîne (puisqu'au moins un caractère en est supprimé), il suffit de prendre en compte les cas où la correspondance échoue complètement.
Si le personnage qui se trouve devant
<
est?
le seul moyen d’échouer le match, c’est qu’il n’y a pas de personnage qui ne saute pas de ligne, mais cela ne peut pas arriver car nous avons la garantie que l’entrée est toujours suffisante.Si le caractère précédant
<
est0
, l'expression régulière correspondra toujours, car il y a toujours une autre ligne au-dessus de la ligne actuelle (qui peut être la ligne vide séparant l'entrée du code source).Si le caractère en face de
<
est1
, la regex échouera si nous sommes sur la dernière ligne (puisque la correspondance¶
échoue) ou si la ligne suivante est vide (car la correspondance.+
ne correspond pas). Notez que ces deux cas correspondent à l’arrêt du programme après le popping a1
.Enfin, il y a aussi la possibilité que
<
rien ne soit précédé?01
. Il s'avère que nous ne pouvons atteindre cette situation qu'en sautant une ligne0
et en nous déplaçant jusqu'à une ligne vide, de sorte que la ligne<
est maintenant précédée d'un saut de ligne.Ainsi, lorsque le programme se termine le
1
, le<
sera toujours après1
. Mais si le programme se termine sur un0
, il aura été déplacé sur une ligne vide. Nous pouvons facilement transformer cette information en sortie souhaitée avec une simple étape de correspondance:Ceci compte simplement les correspondances de
1<
dans la chaîne. Selon le raisonnement ci-dessus, ce sera1
si le programme s'est terminé le1
, et0
s'il s'est terminé le0
.la source
Convexe ,
102 à95 octetsEh bien, un langage basé sur une liste de piles empilée s'est révélé assez difficile.
Marquez mes mots: je vais obtenir cela à 100 octets ou moins!EDIT: succès!Essayez-le en ligne!
La saisie du programme s'effectue via les arguments de ligne de commande. Les entrées
0
s et1
s normalement (sur TIO, cela signifie séparé par une nouvelle ligne dans la case "entrée").Explication:
Tout le code peut être divisé en trois parties:
Ce bit prend simplement le programme d'entrée et le convertit en un tableau de lignes, et ajoute également des
" "
lignes au début du tableau. Étant donné que les tableaux de Convex sont bouclés, le fait de ne disposer que d'une pile vide suffit.Cette partie détermine la ligne (ou la pile) avec laquelle commencer l'exécution. Il recherche dans chaque ligne et place le numéro de pile correct dans la
M
variable.C'est la partie amusante! Il boucle continuellement jusqu'à atteindre une ligne contenant uniquement un espace (
" "
) (symbolisant une pile vide). Si la ligne n'est pas vide, il effectue les opérations suivantes:?
, saisissez-le et ajoutez-le à la ligne.0
, déplacez le pointeur de ligne vers le haut.1
, déplacez le pointeur de ligne vers le bas.(espace), imprimez le dernier élément sauté et terminez le programme.
la source
Code machine x86 32 bits, 70 octets
En hex:
L'entrée est une chaîne multiligne à terminaison NULL (séparée par un saut de ligne) transmise via ESI. L'entrée utilisateur est supposée être la première ligne. Renvoie '0' / '1' dans AL.
Démontage:
la source
JavaScript (ES6), 136
138En supposant un retour à la ligne dans le programme
Moins golfé
Tester
la source
05AB1E ,
58565553515046 octets2 octets sauvés grâce à Emigna ! Code:
Utilise le codage CP-1252 . Essayez-le en ligne! .
la source
Python 3,
147146145144 octets1 octet grâce à @Lynn.
la source
Python 3, 318
F étant le programme, z étant entré. Oui, mes noms de variables sont insensés.
la source
ES6, 190 octets
Utiliser comme
f(program, input)
la source
[...o]
au lieu deo.split``
, et utiliserfor
au lieu dewhile
, car cela vous permet de déplacer deux expressions dans lesfor
deux octets de sauvegarde. Quelques conseils spécifiques: Je pense que votreNumber
distribution est inutile, car elle le*2
sera pour vous, et je voudrais juste lire à l'i
aide dej=0
eti[j++]
qui, je pense, économise 11 octets.f=
, les fonctions anonymes sont autorisées.Java,
256255231219215213 octetsDémo sur Ideone.
Prend le programme et l'entrée en tant qu'arguments et renvoie le résultat sous forme d'entier.
la source
for
boucle, mais que signifie votre premier commentaire?int f(String[]I)...
et vous pouvez éviter leString[]p=I.split("\n");
int f(String[]P)
->(String[]I){...
PHP (<7.0),
195192 octetsPrend le programme comme premier argument et chaque valeur comme argument supplémentaire.
Notez que j’ai testé cela avec des espaces asn séparés ("", ..) plutôt que des lignes, mais cela devrait quand même fonctionner.
Donne un avis obsolète si exécuté dans php> 5.3.
Donne également un avertissement si vous sortez du programme. Cependant, cela fonctionne toujours et fonctionne correctement, donc tout va bien.
la source
C
264249244242C ne fait pas si bien avec la manipulation des chaînes, mais c'est assez court.
Cela fonctionne en balayant la chaîne pour le curseur (
<
), en reculant d’une place, en lisant la commande, en la remplaçant par untab
caractère et en se déplaçant d’une ligne en avant ou en arrière. L'entrée se présente sous la forme d'un tableau de caractères C, par exemplechar array[]="1\n?<\n11\n?\n0";result = f(array);
, bien que les retours chariot soient également autorisés.Bien que la chaîne d'entrée soit modifiée, la longueur n'est pas modifiée.
Programme de test
Exécutez ce programme avec chaque cas de test en tant que paramètre distinct, en utilisant une simple barre oblique inverse à la place des nouvelles lignes. Les cas de test seront séparés par une ligne vierge.
la source