Interpretar /// (pronunciado 'barras')

30

Porque no podemos tener suficiente golf esotérico, ¿verdad?

/// - barras pronunciadas: es un lenguaje pequeño y divertido basado en la s///función de reemplazo de expresiones regulares de la fama de Perl. Contiene solo dos caracteres especiales, barra /diagonal y barra diagonal inversa \. Puede encontrar un artículo completo en el wiki de esolangs , pero reproduciré una descripción del lenguaje a continuación, así como algunos ejemplos.

En resumen, funciona identificando /pattern/repl/resten el programa y haciendo la sustitución tantas veces como sea posible. Ningún carácter es especial excepto /y \: /delimita patrones y reemplazos en el programa, mientras le \permite insertar caracteres literales /o \caracteres en su código. Notablemente, estas no son expresiones regulares, solo sustituciones simples de cadenas.

Su desafío es producir un intérprete para el lenguaje ///, ya sea como un programa que lee STDIN o como una función que toma un argumento de cadena, en la menor cantidad de caracteres posible.

Puede usar cualquier idioma excepto /// en sí mismo. No puede usar ninguna biblioteca que interprete ///; sin embargo, puede usar expresiones regulares, bibliotecas de expresiones regulares o bibliotecas de coincidencia de cadenas.


Ejecución

Hay cuatro estados, impresión , patrón , reemplazo y sustitución . En todos los estados excepto la sustitución :

  • Si el programa está vacío, la ejecución se detiene.
  • De lo contrario, si el primer carácter es \, haga algo con el siguiente carácter (si está presente) y elimine ambos del programa.
  • De lo contrario, si el primer carácter es /, elimínelo y cambie al siguiente estado.
  • De lo contrario, haz algo con el primer personaje y quítalo del programa.
  • Repetir.

Los estados se desplazan por la impresión , el patrón , el reemplazo y la sustitución en orden.

  • En el modo de impresión , 'hacer algo' significa dar salida al personaje.
  • En el modo de patrón , "hacer algo" significa agregar el carácter al patrón actual.
  • En el modo de reemplazo , 'hacer algo' significa agregar el personaje al Reemplazo actual.

En el modo de sustitución , sigue un conjunto diferente de reglas. Sustituya repetidamente la primera aparición del Patrón actual con el Reemplazo actual en el programa, hasta que no sean posibles más sustituciones. En ese punto, borre el Patrón y Reemplazo y regrese al modo de impresión .

En el programa /foo/foobar/foo foo foo, sucede lo siguiente:

/foo/foobar/foo foo foo
foo foo foo
foobar foo foo
foobarbar foo foo
foobarbarbar foo foo
...

Esto se repite para siempre y nunca sale del modo de sustitución . Del mismo modo, si el Patrón está vacío, la primera aparición de la cadena vacía, al comienzo del programa, siempre coincide, por lo que el modo de sustitución se repite para siempre, sin detenerse nunca.


Ejemplos

no

Salida: no.

/ world! world!/Hello,/ world! world! world!

Salida: Hello, world!.

/foo/Hello, world!//B\/\\R/foo/B/\R

Salida: Hello, world!.

a/ab/bbaa/abb

Salida: a. El programa no se detiene.

//

Salida: ninguna.

///

Salida: ninguna. El programa no se detiene.

/\\/good/\/

Salida: good.

También hay una cita en la wiki que puedes probar.

Algoritmo de tiburón
fuente
/-/World//--/Hello//--W/--, w/---!¿Qué no se podría amar? (Intente eliminar guiones desde el final)
vea el
@Loovjo El \ personaje escapa a cualquier personaje que lo siga, incluido /, que luego se puede usar normalmente. Si bien esto no parece mucho, esto hace que /// Turing-complete .
algorithmshark
Creo que esta es una mejor explicación del lenguaje que el artículo wiki de esolangs. ¡Usaré esta información en mi ///IDE que estoy haciendo!
clabe45

Respuestas:

7

APL (133)

{T←''∘{(0=≢⍵)∨'/'=⊃⍵:(⊂⍺),⊂⍵⋄(⍺,N⌷⍵)∇⍵↓⍨N←1+'\'=⊃⍵}⋄⍞N←T⍵⋄p N←T 1↓N⋄r N←T 1↓N⋄''≡N:→⋄∇{⍵≡p:∇r⋄∨/Z←p⍷⍵:∇(r,⍵↓⍨N+≢p),⍨⍵↑⍨N←1-⍨Z⍳1⋄⍵}1↓N}

Esta es una función que toma el ///código como argumento correcto.

Sin golfos, con explicación:

slashes←{
   ⍝ a function to split the input string into 'current' and 'next' parts,
   ⍝ and unescape the 'current' bit
   split←''∘{
       ⍝ if the string is empty, or '/' is reached,
       ⍝ return both strings (⍺=accumulator ⍵=unprocessed)
       (0=≢⍵)∨'/'=⊃⍵:(⊂⍺),⊂⍵
       ⍝ otherwise, add current character to accumulator,
       ⍝ skipping over '\'s. (so if '\/' is reached, it skips '\',
       ⍝ adds '/' and then processes the character *after* that.)
       idx←1+'\'=⊃⍵
       (⍺,idx⌷⍵)∇idx↓⍵
   }

   ⍞   next ← split ⍵      ⍝ output stage
   pat next ← split 1↓next ⍝ pattern stage, and eat the '/'
   rpl next ← split 1↓next ⍝ replacement stage, and eat the '/'

   ⍝ if there are no characters left, halt.
   ''≡next:⍬

   ⍝ otherwise, replace and continue.
   ∇{  ⍝ if the input string equals the pattern, return the replacement and loop
       ⍵≡pat:∇rpl

       ⍝ otherwise, find occurences, if there are, replace the first and loop
       ∨/occ←pat⍷⍵:∇(rpl, (idx+≢pat)↓⍵),⍨ (idx←(occ⍳1)-1)↑⍵

       ⍝ if no occurences, return string
       ⍵

   }1↓next
}
marinus
fuente
"si no quedan caracteres, deténgase". ¿Funciona correctamente en ///y //foo/(es decir, bucles para siempre)?
algormshark
@algorithmshark: sí, en esa situación /aún se quedaría en ese punto.
marinus
11

J - 181 190 170 char

Esto fue una pesadilla. Lo reescribí desde cero, dos veces, porque me seguía molestando. Esta es una función que toma un único argumento de cadena y lo envía a STDOUT.

(0&$`((2{.{:@>&.>)((j{.]),-i@=`p@.~:~/@[,]}.~#@p+j=.0{p I.@E.])i 5;@}.&,'/';"0;&.>)@.(2<#)@}.[4:1!:2~{:@>@p=.>@{.@[)@((0;(0,:~1 0,.2);'\';&<1 0)<;._1@;:'/'&,)i=. ::](^:_)

Para explicarlo, lo dividiré en subexpresiones.

i =. ::](^:_))
parse =: ((0;(0,:~1 0,.2);'\';&<1 0)<;._1@;:'/'&,)
print =: 4:1!:2~{:@>@p=.>@{.@[
eval  =: 0&$`((2{.{:@>&.>)sub 5;@}.&,'/';"0;&.>)@.(2<#)@}.
sub   =: ((j{.]),-i@=`p@.~:~/@[,]}.~#@p+j=.0{p I.@E.])i

interp =: (eval [ print) @ parse i
  • i(abreviatura de iterar ) es un adverbio. Toma un argumento verbal a la izquierda y devuelve un verbo (f)i, que cuando se aplica a un argumento, se aplica frepetidamente al argumento hasta que ocurra una de dos cosas: encuentra un punto fijo ( y = f y) o arroja un error. El comportamiento de punto fijo es inherente ^:_y ::]maneja los errores.

  • parsetokeniza la entrada en lo que yo llamo forma medio analizada , y luego la corta en el '/' sin escape. Vincula las barras diagonales que se escapan a sus personajes, pero no elimina las barras diagonales inversas, por lo que podemos revertirlo o terminarlo según lo que queramos.

    La mayor parte del trabajo interesante ocurre en ;:. Este es un primitivo intérprete de máquina secuencial, que toma una descripción de la máquina ( (0;(0,:~1 0,.2);'\';&<1 0)) a la izquierda y algo para analizar a la derecha. Esto hace la tokenización. Notaré que esta máquina específica en realidad trata el primer carácter no especial, incluso si es un \y debería unirse. Hago esto por varias razones: (1) la tabla de estado es más simple, por lo que puede jugarse más; (2) podemos simplemente agregar un personaje ficticio al frente para esquivar el problema; y (3) ese personaje ficticio se analiza a medias sin costo adicional, por lo que puedo usarlo para configurar la fase de corte, a continuación.

    También usamos <;._1para cortar el resultado tokenizado en no escapado /(que es lo que elijo ser el primer personaje). Esto es útil para extraer la salida, el patrón y el reemplazo de out/patt/repl/resttodo en un solo paso, pero desafortunadamente también corta el resto del programa, donde necesitamos /que permanezcan intactos. Los vuelvo a unir durante eval, porque <;._1dejarlos en paz termina costando mucho más.

  • La bifurcación se (eval [ print)ejecuta printen el resultado de parsesus efectos secundarios y luego se ejecuta eval. printes un verbo simple que abre el primer cuadro (el que sabemos con certeza es salida), termina de analizarlo y lo envía a STDOUT. Sin embargo, también aprovechamos la oportunidad para definir un verbo de utilidad p.

    pse define como >@{.@[, por lo que toma su argumento izquierdo (actúa como la identidad si se le da un solo argumento), toma el primer elemento de ese (identidad cuando se le da un escalar) y lo desempaqueta (identidad si ya no se encuentra en un recuadro). Esto será muy útil sub.

  • evalevalúa el resto del programa procesado. Si no tenemos un patrón completo o un reemplazo completo, evallo descarta y solo devuelve una lista vacía, que finaliza la evaluación al hacer un error ;:(desde parse) en la próxima iteración. De lo contrario, evalanaliza completamente el patrón y el reemplazo, corrige el resto de la fuente y luego pasa ambos a sub. Por explosión:

                                                  @}.  NB. throw out printed part
                                           @.(2<#)     NB. if we have a pattern and repl:
          2{.                                          NB.  take the first two cuts:
                 &.>                                   NB.   in each cut:
             {:@>                                      NB.    drop escaping \ from chars
         (          )                                  NB.  (these are pattern and repl)
                                       &.>             NB.  in each cut:
                                      ;                NB.   revert to source form
                                '/';"0                 NB.  attach a / to each cut
                              &,                       NB.  linearize (/ before each cut)
                         5  }.                         NB.  drop '/pattern/repl/'
                          ;@                           NB.  splice together
        (            sub                  )            NB.  feed these into sub
       `                                               NB. else:
    0&$                                                NB.  truncate to an empty list
    
  • subes donde ocurre una ronda (posiblemente infinita) de sustituciones. Debido a la forma en que configuramos eval, la fuente es el argumento correcto, y el patrón y el reemplazo se agrupan a la izquierda. Dado que los argumentos están ordenados de esta manera y sabemos que el patrón y el reemplazo no cambian dentro de una ronda de sustituciones, podemos usar otra característica de i—el hecho de que solo modifica el argumento derecho y sigue pasando en la misma izquierda— para delegar a J la necesidad de preocuparse por hacer un seguimiento del estado.

    Sin embargo, hay dos puntos de problemas. El primero es que los verbos J pueden tener como máximo dos argumentos, por lo que no tenemos una manera fácil de acceder a ninguno de los que están agrupados, como el patrón y el reemplazo, aquí. Mediante el uso inteligente de la putilidad que definimos, este no es un gran problema. De hecho, podemos acceder al patrón en un carácter, simplemente usando p, debido a su >@{.@[definición: el Unbox del primer elemento del argumento izquierdo. Obtener el reemplazo es un truco, pero la forma más corta sería p&|., 2 caracteres más cortos que sacarlo manualmente.

    El segundo problema es que isale en puntos fijos en lugar de hacer un bucle para siempre, y si el patrón y el reemplazo son iguales y haces una sustitución, eso parece un punto fijo para J. Manejamos esto ingresando un bucle infinito de negación de 1 sobre y si detectamos que son iguales, esta es la -i@=`p@.~:~/porción que reemplaza p&|..

                                        p    E.]    NB. string search, patt in src
                                          I.@       NB. indices of matches
                                      0{            NB. take the first (error if none)
                                   j=.              NB. assign to j for later use
                               #@p+                 NB. add length of pattern
                           ]}.~                     NB. drop that many chars from src
                       /@[                          NB. between patt and repl:
                      ~                             NB.  patt as right arg, repl as left
                  @.~:                              NB.  if equal:
            -i@=                                    NB.   loop forever
                `p                                  NB.  else: return repl
     (j{.])                                         NB. first j chars of src
           ,              ,                         NB. append all together
    (                                           )i  NB. iterate
    
  • Este ciclo se repite debido al uso de i, hasta que subsalga algo fuera de los errores. Hasta donde yo sé, esto solo puede suceder cuando nos quedamos sin personajes, o cuando desechamos un conjunto incompleto de patrones y reemplazos.

Datos curiosos sobre este golf:

  • Por una vez, usar ;:es más corto que iterar manualmente a través de la cadena.
  • 0{debería tener la posibilidad de error antes de subentrar en un bucle infinito, por lo que debería funcionar bien si el patrón coincide con el reemplazo pero nunca aparece en el resto de la fuente. Sin embargo, esto puede o no ser un comportamiento no especificado, ya que no puedo encontrar una cita de ninguna manera en los documentos. Whoopsie
  • Las interrupciones del teclado se procesan como errores espontáneos dentro de las funciones en ejecución. Sin embargo, debido a la naturaleza de i, esos errores quedan atrapados también. Dependiendo de cuándo presione Ctrl + C, podría:
    • Salga del ciclo negate-forever, error fuera del subciclo tratando de concatenar un número a una cadena, y luego continúe interpretando /// como si hubiera terminado de sustituir una cadena consigo mismo un número infinito de veces.
    • Salga a la submitad y continúe interpretando una expresión /// semicubierta.
    • Salga del intérprete y devuelva un programa /// no evaluado al REPL (aunque no STDOUT).

Ejemplo de uso:

   f=:(0&$`((2{.{:@>&.>)((j{.]),-i@=`p@.~:~/@[,]}.~#@p+j=.0{p I.@E.])i 5;@}.&,'/';"0;&.>)@.(2<#)@}.[4:1!:2~{:@>@p=.>@{.@[)@((0;(0,:~1 0,.2);'\';&<1 0)<;._1@;:'/'&,)i=. ::](^:_)
   f 'no'
no
   f '/ world! world!/Hello,/ world! world! world!'
Hello, world!
   f '/foo/Hello, world!//B\/\\R/foo/B/\R'
Hello, world!
   f '//'  NB. empty string

   f '/\\/good/\/'
good
Algoritmo de tiburón
fuente
Guau. Yo llamaría a esto masoquista. +1
verqu
Cuando ejecuto esto, obtengo la cadena vacía de cada caso de prueba. Estoy usando jqt64, ¿qué estás usando para ejecutar esto?
bcsb1001
@ bcsb1001 He estado usando el binario jconsole (64 bits) directamente. Comprobando jqt ahora, realmente estoy obteniendo los resultados previstos, excepto para el /\\/good/\/caso de prueba; la depuración me dice que el problema es mi uso 1!:2&4, ya que jqt no tiene stdin / out. Investigaré. ¿Cuáles son tus 9!:12''y 9!:14''?
algorithmshark
@algorithmshark My 9!:12''tiene 6 años y 9!:14''es j701 / 2011-01-10 / 11: 25.
bcsb1001
4

Perl - 190

$|=1;$/=undef;$_=<>;while($_){($d,$_)=/(.)(.*)/;eval(!$e&&({'/','$a++','\\','$e=1'}->{$d})||('print$d','$b.=$d','$c.=$d')[$a].';$e=0');if($a==3){while($b?s/\Q$b/$c/:s/^/$c/){}$a=0;$b=$c=''}}

Lee el ///programa desde stdin hasta EOF.

faubi
fuente
¿Un enfoque a lo largo de las líneas de m/^(.*?)(?<!\\)\/(.*?)(?<!\\)\/(.*?)(?<!\\)\/(.*)$/s, es decir, salida de partido, patrón y reemplazo al mismo tiempo, haría un golf más corto? Yo no conozco a ningún Perl.
algorithmshark
Creo que esto falla con/a/\0/a
Asone Tuhid
3

Pip , 100 102 bytes

Nunca había probado que Pip estuviera completo en Turing (aunque obviamente es así), y en lugar de seguir la ruta habitual de BF, pensé que /// sería interesante. Una vez que tuve la solución, pensé en jugarlo y publicarlo aquí.

101 bytes de código, +1 para -rbandera:

i:gJnf:{a:xW#i&'/NE YPOia.:yQ'\?POiya}W#iI'\Q YPOiOPOiEIyQ'/{p:VfY0s:VfIyQ'/WpNi&YviR:Xp{++y?ps}}E Oy

Aquí está mi versión sin golf con abundantes comentarios:

; Use the -r flag to read the /// program from stdin
; Stdin is read into g as a list of lines; join them on newline and assign to c for code
c : gJn

; Loop while c is nonempty
W #c {
 ; Pop the first character of c and yank into y
 Y POc
 ; If y equals "\"
 I yQ'\
  ; Pop c again and output
  O POc
 ; Else if y equals "/"
 EI yQ'/ {
  ; Build up pattern p from empty string
  p : ""
  ; Pop c, yank into y, loop while that is not equal to "/" and c is nonempty
  W #c & '/ NE Y POc {
   ; If y equals "\"
   I yQ'\
    ; Pop c again and add that character to p
    p .: POc
   ; Else, add y to p
   E p .: y
  }

  ; Yank 0 so we can reliably tell whether the /// construct was completed or not
  Y0
  ; Build up substitution s from empty string
  s : ""
  ; Pop c, yank into y, loop while that is not equal to "/" and c is nonempty
  W #c & '/ NE Y POc {
   ; If y equals "\"
   I yQ'\
    ; Pop c again and add that character to s
    s .: POc
   ; Else, add y to s
   E s .: y
  }

  ; If the last value yanked was "/", then we have a complete substitution
  ; If not, the code must have run out; skip this branch, and then the outer loop
  ; will terminate
  I yQ'/ {
   ; While pattern is found in code:
   W pNc {
    ; Set flag so only one replacement gets done
    i : 0
    ; Convert p to a regex; replace it using a callback function: if ++i is 1,
    ; replace with s; otherwise, leave unchanged
    c R: Xp {++i=1 ? s p}
   }
  }
 }
 ; Else, output y
 E Oy
}

Pruébalo en línea! (Tenga en cuenta que TIO no da ningún resultado cuando el programa no termina, y también tiene un límite de tiempo. Para ejemplos más grandes y bucles infinitos, se recomienda ejecutar Pip desde la línea de comandos).

DLosc
fuente
Creo que esto debería ser pip + -r, 101 bytes
Asone Tuhid
3

C ++: Visual C ++ 2013 = 423, g ++ 4.9.0 = 442

Esto nunca ganará, pero como he decidido que todos mis futuros proyectos de software se escribirán en este increíble lenguaje, necesitaba un intérprete para él y pensé que también podría compartir el que hice ...

La diferencia en la puntuación es que Visual C ++ no necesita la primera inclusión, pero g ++ sí. La puntuación supone que los finales de línea cuentan como 1.

#include<string.h>
#include<string>
#define M(x)memset(x,0,99);
#define P o[i])
#define N(x)P;else if(n<x)(P==92?
#define O (o[++i]):(P==47?n++:
#define S std::string
int main(int n,char**m){S o=m[1];char p[99],*q=p,r[99],*s=r;M(p)M(r)for(int i=0,t;i<=o.size();++i){if(!N(3)putchar O putchar(N(4)*q++=O(*q++=N(5)*s++=O(*s++=P;if(n>4){for(;;){if((t=o.find(p,i+1))==S::npos)break;o=o.substr(0,t)+r+o.substr(t+strlen(p));}M(p)M(r)n=2;q=p;s=r;}}}
Jerry Jeremiah
fuente
1
Se puede reescribir if(!o[i]);como if(Ppara guardar caracteres, o estoy malentendido cómo funciona #define?
Algoritmoshark
@algorithmshark, ¿cómo me perdí eso? si (! P es perfecto. Lo cambiaré.
Jerry Jeremiah
Cada instancia de Pin maintiene un espacio después, por lo que puede guardar un personaje reemplazando esos espacios con punto y coma y eliminándolo #define. Luego, si puede usar #defines dentro de otros, puede guardar algo más reescribiendo N(x)como en (92==Plugar de o[i]==92e Oigualmente.
algormshark
@algorithmshark obviamente eres mucho mejor en esto que yo. Gracias por la ayuda.
Jerry Jeremiah
Sé que esto es alrededor de cuatro años, pero volver a escribir N(x)como P;else if(n<x)(P==92?y el cambio de las llamadas a Npodría ahorrar unos pocos bytes en consecuencia.
Zacharý
2

Python 2 (236), Python 3 (198?)

from __future__ import print_function
def d(i):
 t=0;p=['']*3+[1]
 while i:
  if'/'==i[0]:t+=1
  else:
   if'\\'==i[0]:i=i[1:]
   p[t]+=i[0]
  i=i[1:]
  print(end=p[0]);p[0]=''
  if t>2:
   while p[1]in i:i=i.replace(*p[1:])
   d(i);i=0

Llamado como d(r"""/foo/Hello, world!//B\/\\R/foo/B/\R"""). Las comillas triples solo son necesarias si el ///programa contiene nuevas líneas; de lo contrario, las comillas simples están bien.

EDITAR: Este intérprete ahora imprime las cosas como se esperaba (anteriormente solo se imprimía al final, ver comentarios). Para Python 3, elimine la primera línea (pero no tengo Python 3 en mi instalación antigua, así que no puedo estar seguro de que no haya otro cambio).

Bruno Le Floch
fuente
el intérprete no imprime nada hasta que la terminación es problemática. es posible escribir un bucle infinito en ///, por lo que su intérprete falla en los programas que no terminan pero aún imprimen algo.
orgulloso Haskeller
@proudhaskeller Fijo.
Bruno Le Floch
En realidad, esto no está arreglado, no imprime nada /a/ab/bbaa/abb.
Beta Decay
@BetaDecay se /a/ab/bbaa/abbquedará atascado en un bucle sin fin sin imprimir nada, porque la primera sustitución es a=> ab. El correcto a/ab/bbaa/abbfunciona como se anuncia.
algormshark
@BetaDecay: además del cambio sugerido por algoritmshark, es posible que deba incluir la opción de línea de comando -upara forzar que el búfer de salida no esté protegido.
Bruno Le Floch
2

Cobra - 226

sig Z as String
def f(l='')
    m=Z(do=[l[:1],l=l[1:]][0])
    n as Z=do
        if'/'<>(a=m())>'',return if(a=='\\',m(),a)+n()
        else,return''
    print n()stop
    p,s=n(),n()
    if''<l
        while p in l,l=l[:l.indexOf(p)+1]+s+l[p.length:]
        .f(l)
Οurous
fuente
2

Ruby , 119 110 bytes

Termina con excepción

r=->s,o=$>{s[k=s[0]]='';k==?/?o==$>?s.gsub!([r[s,''],e=r[s,'']][0]){e}:t=o:o<<(k==?\\?s[0]+s[0]='':k);t||redo}

Pruébalo en línea!

Termina limpiamente (116 bytes)

r=->s,o=$>{s[k=s[0]||exit]='';k==?/?o==$>?s.gsub!([r[s,''],e=r[s,'']][0]){e}:t=o:o<<(k==?\\?s[0]+s[0]='':k);t||redo}

Pruébalo en línea!

Asone Tuhid
fuente
1

Python 2/3 (211 bytes)

El siguiente código, basado en la respuesta de Bruno Le Floch , es compatible con Python 2 y Python 3.

Además, al ser iterativo en lugar de recursivo, no corre el riesgo de alcanzar la máxima profundidad de recursión de Python.

def S(c):
 while c:
  B=["","",1]
  for m in 0,1,2:
   while c:
    if"/"==c[0]:c=c[1:];break
    if"\\"==c[0]:c=c[1:]
    if m:B[m-1]+=c[0]
    else:yield c[0]
    c=c[1:]
  while c and B[0]in c:c=c.replace(*B)
Carlos luna
fuente
Hola y bienvenidos a PPCG. Puede jugar al golf in(0,1,2)a in 0,1,2y [""]*2+[1]a ["","",1], lo que resulta en 211 bytes .
Jonathan Frech
He vinculado a la respuesta mencionada y agregué la palabra "bytes". Si no está de acuerdo con mi edición, no dude en retroceder.
Jonathan Frech
Gracias Jonathan, tus sugerencias son bienvenidas.
Carlos Luna
0

Tocino , 391 387 395 bytes

De las contribuciones en esta página solo conseguí que el programa Python funcionara. Los otros trabajan para algunas muestras ///, o no funcionan en absoluto. Por lo tanto, decidí agregar mi versión, que es una implementación en BASIC.

Competir en un concurso de CodeGolf con BASIC no es fácil, ya que BASIC usa palabras largas como declaraciones. La única abreviatura que se encuentra comúnmente en BASIC es el '?' signo, que significa IMPRIMIR.

Por lo tanto, el programa a continuación puede que nunca gane, pero al menos funciona con todos los códigos de demostración en esta página de Codegolf y en Wiki Wiki de Esolangs . Incluidas todas las versiones de las "99 botellas de cerveza".

p$=""
r$=""
INPUT i$
WHILE LEN(i$)
t$=LEFT$(i$,1)
i$=MID$(i$,2)
IF NOT(e) THEN
IF t$="\\" THEN
e=1
CONTINUE
ELIF t$="/" THEN
o=IIF(o<2,o+1,0)
IF o>0 THEN CONTINUE
FI
FI
IF o=1 THEN
p$=p$&t$
ELIF o=2 THEN
r$=r$&t$
ELIF o=0 THEN
IF LEN(p$) THEN i$=REPLACE$(i$,p$,r$)
IF NOT(INSTR(t$&i$,"/")) THEN
?t$;
BREAK
ELSE
?LEFT$(i$,INSTR(i$,"/")-1);
i$=MID$(i$,INSTR(i$,"/"))
FI
p$=""
r$=""
FI
e=0
WEND
?i$
Peter
fuente
Se agregó la instrucción INPUT para obtener información del usuario.
Peter