Parce que nous ne pouvons pas en avoir assez des golfs en langue ésotérique, n'est-ce pas?
/// - prononcé des barres obliques -est un langage peu amusant basé sur la s///
fonction regex-remplacement de la renommée Perl. Il ne contient que deux caractères spéciaux, barre oblique /
et barre oblique inverse \
. Vous pouvez trouver un article complet à ce sujet sur le wiki esolangs , mais je vais reproduire une description du langage ci-dessous, ainsi que quelques exemples.
En bref, cela fonctionne en s'identifiant /pattern/repl/rest
dans le programme et en effectuant la substitution autant de fois que possible. Aucun caractère n'est spécial sauf /
et \
: /
délimite les modèles et les remplacements dans le programme, tandis que \
vous permet d'insérer des littéraux /
ou des \
caractères dans votre code. Notamment, ce ne sont pas des expressions régulières, juste des substitutions de chaînes simples.
Votre défi est de produire un interpréteur pour le langage ///, soit un programme lisant STDIN soit une fonction prenant un argument chaîne, en le moins de caractères possible.
Vous pouvez utiliser n'importe quelle langue à l'exception de /// lui-même. Vous ne pouvez utiliser aucune bibliothèque interprétant ///; vous pouvez cependant utiliser des expressions régulières, des bibliothèques d'expressions régulières ou des bibliothèques de correspondance de chaînes.
Exécution
Il existe quatre états: impression , motif , remplacement et substitution . Dans tous les états sauf substitution :
- Si le programme est vide, l'exécution s'arrête.
- Sinon, si le premier caractère est
\
, faites quelque chose avec le caractère suivant (s'il est présent) et supprimez les deux du programme. - Sinon, si le premier caractère est
/
, supprimez-le et passez à l'état suivant. - Sinon, faites quelque chose avec le premier caractère et supprimez-le du programme.
- Répéter.
Les états font défiler l' impression , le motif , le remplacement et la substitution dans l'ordre.
- En mode d' impression , «faire quelque chose» signifie sortir le caractère.
- En mode modèle , «faire quelque chose» signifie ajouter le caractère au modèle actuel.
- En mode de remplacement , «faire quelque chose» signifie ajouter le personnage au remplacement actuel.
En mode substitution , vous suivez un ensemble de règles différent. Remplacez à plusieurs reprises la première occurrence du modèle actuel par le remplacement actuel dans le programme, jusqu'à ce qu'aucune substitution ne soit possible. À ce stade, effacez le motif et le remplacement et revenez en mode d' impression .
Dans le programme /foo/foobar/foo foo foo
, les événements suivants se produisent:
/foo/foobar/foo foo foo
foo foo foo
foobar foo foo
foobarbar foo foo
foobarbarbar foo foo
...
Cela boucle pour toujours et ne quitte jamais le mode de substitution . De même, si le Pattern est vide, la première occurrence de la chaîne vide - au début du programme - correspond toujours, donc le mode de substitution boucle pour toujours, sans jamais s'arrêter.
Exemples
no
Sortie: no
.
/ world! world!/Hello,/ world! world! world!
Sortie: Hello, world!
.
/foo/Hello, world!//B\/\\R/foo/B/\R
Sortie: Hello, world!
.
a/ab/bbaa/abb
Sortie: a
. Le programme ne s'arrête pas.
//
Sortie: aucune.
///
Sortie: aucune. Le programme ne s'arrête pas.
/\\/good/\/
Sortie: good
.
Il y a aussi une quine sur le wiki que vous pouvez essayer.
la source
/-/World//--/Hello//--W/--, w/---!
Qu'est-ce qu'il n'y a pas à aimer? (Essayez de supprimer les tirets de la fin)\
personnage échappe à tout personnage qui le suit, y compris/
, qui peut ensuite être utilisé normalement. Bien que cela ne ressemble pas beaucoup, cela rend /// Turing-complet .///
IDE que je fais!Réponses:
APL (133)
Il s'agit d'une fonction qui prend le
///
code comme argument de droite.Non golfé, avec explication:
la source
///
et//foo/
(c'est-à-dire en boucle pour toujours)?/
serait toujours laissé à ce point.J -
181190170 charCe fut un cauchemar. Je l'ai réécrit à partir de zéro, deux fois, car il n'arrêtait pas de me déranger. Il s'agit d'une fonction prenant un seul argument de chaîne, sortie vers STDOUT.
Pour l'expliquer, je vais le décomposer en sous-expressions.
i
(court pour itérer ) est un adverbe. Il prend un argument de verbe sur la gauche et renvoie un verbe(f)i
qui, lorsqu'il est appliqué à un argument, s'applique àf
plusieurs reprises à l'argument jusqu'à ce qu'une des deux choses se produise: il trouve un point fixe (y = f y
), ou il renvoie une erreur. Le comportement en virgule fixe est inhérent à^:_
, et::]
effectue la gestion des erreurs.parse
tokenise l'entrée dans ce que j'appelle une forme semi-analysée , puis la coupe au «/» non échappé. Il lie les contre-obliques qui s'échappent à leurs personnages, mais ne supprime pas les contre-obliques — nous pouvons donc soit le rétablir soit le terminer selon ce que nous voulons.La majeure partie du travail intéressant se produit en
;:
. Il s'agit d'une primitive d'interpréteur de machine séquentielle, prenant une description de la machine ((0;(0,:~1 0,.2);'\';&<1 0)
) à gauche et quelque chose à analyser à droite. Cela fait la tokenisation. Je noterai que cette machine spécifique traite en fait le premier caractère non spécial, même si c'est un\
et devrait se lier. Je le fais pour plusieurs raisons: (1) la table d'état est plus simple, donc elle peut être jouée plus loin; (2) nous pouvons facilement ajouter simplement un caractère factice à l'avant pour esquiver le problème; et (3) ce personnage factice est à moitié analysé sans frais supplémentaires, donc je peux l'utiliser pour configurer la phase de découpe, ensuite.Nous utilisons également
<;._1
pour couper le résultat symbolisé sur non échappé/
(qui est ce que je choisis d'être le premier caractère). Ceci est pratique pour retirer la sortie, le modèle et le remplacement deout/patt/repl/rest
tout en une seule étape, mais malheureusement, coupe également le reste du programme, où nous avons besoin de ceux-ci/
pour rester intacts. Je les épissure de nouveau pendanteval
, car les<;._1
laisser seuls finit par coûter beaucoup plus cher.Le fork
(eval [ print)
s'exécuteprint
sur le résultat deparse
pour ses effets secondaires, puis s'exécuteeval
.print
est un simple verbe qui ouvre la première boîte (celle dont nous savons à coup sûr qu'elle est sortie), termine l'analyse et l'envoie à STDOUT. Cependant, nous profitons également de l'occasion pour définir un verbe utilitairep
.p
est défini comme>@{.@[
, donc il prend son arg gauche (agit comme l'identité si on lui donne seulement un arg), prend le premier élément de cela (identité quand on lui donne un scalaire), et le déballe (identité s'il est déjà non boxé). Cela vous sera très utilesub
.eval
évalue le reste du programme traité. Si nous n'avons pas de modèle complet ou de remplacement complet, leeval
jette et renvoie simplement une liste vide, qui termine l'évaluation en faisant une erreur;:
(deparse
) à la prochaine itération. Sinon,eval
analyse entièrement le motif et le remplacement, corrige le reste de la source, puis passe les deux àsub
. Par explosion:sub
est l'endroit où un cycle (éventuellement infini) de substitutions se produit. En raison de notre configurationeval
, la source est l'argument de droite et le modèle et le remplacement sont regroupés à gauche. Étant donné que les arguments sont ordonnés comme ceci et que nous savons que le modèle et le remplacement ne changent pas au sein d'un cycle de substitutions, nous pouvons utiliser une autre caractéristique dei
-le fait qu'il modifie uniquement l'argument de droite et continue de passer dans la même gauche - pour déléguer à J la nécessité de s'inquiéter de garder une trace de l'état.Il y a cependant deux problèmes. Le premier est que les verbes J peuvent avoir au maximum deux arguments, nous n'avons donc pas de moyen facile d'accéder à ceux qui sont regroupés, comme le modèle et le remplacement, ici. Grâce à une utilisation intelligente de l'
p
utilitaire que nous avons défini, ce n'est pas un gros problème. En fait, nous pouvons accéder au motif en un seul caractère, simplement en utilisantp
, en raison de sa>@{.@[
définition: la Unbox du premier élément de l'argument Left. Obtenir le remplacement est plus délicat, mais le moyen le plus court serait dep&|.
2 caractères plus court que de le retirer manuellement.Le deuxième problème est que les
i
sorties sur des points fixes au lieu de boucler pour toujours, et si le modèle et le remplacement sont égaux et que vous effectuez une substitution, cela ressemble à un point fixe pour J. Nous gérons cela en entrant une boucle infinie de négation de 1 sur et plus si nous détectons qu'ils sont égaux: c'est la-i@=`p@.~:~/
partie, remplaçantp&|.
.Ce cycle se répète en raison de l'utilisation de
i
, jusqu'à ce que quelque chose en dehors dessub
erreurs sorte. Pour autant que je sache, cela ne peut se produire que lorsque nous sommes à court de personnages, lorsque nous jetons un ensemble incomplet de modèle et de remplacement.Faits amusants sur ce golf:
;:
est plus courte que l'itération manuelle de la chaîne.0{
devrait avoir une chance de sortir avant d'sub
entrer dans une boucle infinie, donc cela devrait fonctionner correctement si le motif correspond au remplacement mais n'apparaît jamais dans le reste de la source. Cependant, cela peut ou non être un comportement non spécifié, car je ne peux pas trouver de citation dans les documents. Whoopsie.i
, ces erreurs sont également bloquées. Selon le moment où vous appuyez sur Ctrl + C, vous pouvez:sub
boucle en essayant de concaténer un nombre dans une chaîne, puis continuez à interpréter /// comme si vous aviez fini de remplacer une chaîne par elle-même un nombre infini de fois.sub
mi-chemin et continuer d'interpréter une expression /// semi-subbed.Exemple d'utilisation:
la source
/\\/good/\/
cas de test; le débogage me dit que le problème est mon utilisation1!:2&4
, car jqt n'a pas stdin / out. Va enquêter. Quels sont vos9!:12''
et9!:14''
?9!:12''
6 ans et9!:14''
est j701 / 2011-01-10 / 11: 25.Perl - 190
Lit le
///
programme de stdin jusqu'à EOF.la source
m/^(.*?)(?<!\\)\/(.*?)(?<!\\)\/(.*?)(?<!\\)\/(.*)$/s
sortie, du modèle et du remplacement des matchs à la fois ferait un golf plus court? Je ne connais aucun Perl, moi-même./a/\0/a
Pip ,
100102 octetsJe n'avais jamais prouvé que Pip était complet de Turing (bien que ce soit évidemment le cas), et au lieu de suivre la voie habituelle de BF, je pensais que /// serait intéressant. Une fois que j'ai eu la solution, j'ai pensé que je jouerais au golf et la posterais ici.
101 octets de code, +1 pour l'
-r
indicateur:Voici ma version non golfée avec de nombreux commentaires:
Essayez-le en ligne! (Notez que TIO ne donne aucune sortie lorsque le programme ne se termine pas, et il a également une limite de temps. Pour des exemples plus grands et des boucles infinies, il est recommandé d'exécuter Pip à partir de la ligne de commande.)
la source
pip + -r
, 101 octetsC ++: Visual C ++ 2013 = 423, g ++ 4.9.0 = 442
Cela ne gagnera jamais mais comme j'ai décidé que tous mes futurs projets logiciels seront écrits dans ce langage génial, j'avais besoin d'un interprète pour cela et je me suis dit que je pourrais aussi bien partager celui que j'ai fait ...
La différence de score est que Visual C ++ n'a pas besoin du premier include mais g ++ en a besoin. Le score suppose que les fins de ligne comptent pour 1.
la source
if(!o[i]);
commeif(P
pour sauver les caractères, ou je comprends mal comment fonctionne #define?P
inmain
a un espace après, vous pouvez donc enregistrer un caractère en remplaçant ces espaces par des points-virgules et en les supprimant#define
. Ensuite, si vous pouvez utiliser des#define
s à l'intérieur d'autres, vous pouvez en économiser davantage en réécrivantN(x)
as(92==P
au lieu deo[i]==92
et deO
même.N(x)
furP;else if(n<x)(P==92?
et à mesure que les appels changent enN
conséquence pourrait économiser quelques octets.Python 2 (236), Python 3 (198?)
Appelé comme
d(r"""/foo/Hello, world!//B\/\\R/foo/B/\R""")
. Les guillemets triples ne sont nécessaires que si le///
programme contient des retours à la ligne: sinon les guillemets simples sont corrects.EDIT: Cet interpréteur imprime maintenant les choses comme prévu (auparavant, il ne s'imprimait qu'à la toute fin, cf. commentaires). Pour Python 3, supprimez la première ligne (mais je n'ai pas Python 3 sur mon ancienne installation, donc je ne peux pas être sûr qu'il n'y a pas d'autre changement).
la source
/a/ab/bbaa/abb
./a/ab/bbaa/abb
restera coincé dans une boucle sans fin sans rien imprimer, car la première substitution esta
=>ab
. Le bona/ab/bbaa/abb
fonctionne comme annoncé.-u
pour forcer le tampon de sortie à ne pas être tamponné.Cobra - 226
la source
Rubis ,
119110octetsSe termine avec exception
Essayez-le en ligne!
Se termine proprement (116 octets)
Essayez-le en ligne!
la source
Python 2/3 (211 octets)
Le code suivant, basé sur la réponse de Bruno Le Floch , est compatible Python 2 et Python 3.
De plus, étant itératif plutôt que récursif, il ne risque pas d'atteindre la profondeur de récursivité maximale de Python.
la source
in(0,1,2)
au golf versin 0,1,2
et[""]*2+[1]
vers["","",1]
, ce qui donne 211 octets .BaCon ,
391387395 octetsÀ partir des contributions sur cette page, je n'ai obtenu que le programme Python. Les autres fonctionnent pour certains /// échantillons, ou ne fonctionnent pas du tout. J'ai donc décidé d'ajouter ma version, qui est une implémentation en BASIC.
Participer à un concours CodeGolf avec BASIC n'est pas facile, car BASIC utilise des mots longs comme déclarations. La seule abréviation couramment trouvée dans BASIC est le «?» signe, ce qui signifie IMPRIMER.
Ainsi, le programme ci-dessous peut ne jamais gagner, mais au moins il fonctionne avec tout le code de démonstration sur cette page Codegolf et sur le Wiki Esolangs . Y compris toutes les versions des "99 bouteilles de bière".
la source