Interpretuj /// (wyraźne „ukośniki”)

30

Skoro nie mamy dość golfów z ezoterycznym językiem, prawda?

/// - wyraźne ukośniki - to zabawny, mały język oparty na s///funkcji zastępowania wyrażeń regularnych w słowie Perla. Zawiera tylko dwa znaki specjalne, ukośnik /i ukośnik odwrotny \. Pełny artykuł na ten temat można znaleźć na wiki esolangs , ale odtworzę opis języka poniżej, a także kilka przykładów.

Krótko mówiąc, działa poprzez identyfikację /pattern/repl/restw programie i dokonanie podstawienia tyle razy, ile to możliwe. Żadne znaki nie są wyjątkowe, z wyjątkiem /i \: /wyznacza wzory i zamienniki w programie, a jednocześnie \pozwala wstawiać literały /lub \znaki w kodzie. W szczególności nie są to wyrażenia regularne, tylko zwykłe podstawienia ciągów.

Wyzwanie polega na stworzeniu interpretera dla języka ///, jako programu odczytującego STDIN lub funkcji przyjmującej argument ciągu, w jak najmniejszej liczbie znaków.

Możesz używać dowolnego języka oprócz samego ///. Nie wolno używać bibliotek, które interpretują ///; możesz jednak użyć wyrażeń regularnych, bibliotek wyrażeń regularnych lub bibliotek dopasowujących ciągi znaków.


Wykonanie

Istnieją cztery stany: druk , wzór , zamiana i zamiana . W każdym stanie oprócz substytucji :

  • Jeśli program jest pusty, wykonywanie zostaje zatrzymane.
  • W przeciwnym razie, jeśli pierwszym znakiem jest \, zrób coś z następnym znakiem (jeśli jest obecny) i usuń oba z programu.
  • W przeciwnym razie, jeśli pierwszym znakiem jest /, usuń go i przejdź do następnego stanu.
  • W przeciwnym razie zrób coś z pierwszym znakiem i usuń go z programu.
  • Powtarzać.

Stany przechodzą kolejno przez drukowanie , wzór , zastępowanie i zastępowanie w kolejności.

  • W trybie drukowania „zrób coś” oznacza wypisanie znaku.
  • W trybie wzorca „zrób coś” oznacza dodanie znaku do bieżącego wzorca.
  • W trybie zastępczym „zrób coś” oznacza dodać znak do bieżącej zamiany .

W trybie zastępczym przestrzegasz innego zestawu zasad. Wielokrotnie zastępuj pierwsze wystąpienie bieżącego Wzorca bieżącym Zastąpieniem w programie, dopóki nie będzie już możliwe zastąpienie. W tym momencie wyczyść wzór i zamiennik i wróć do trybu drukowania .

W programie /foo/foobar/foo foo foodzieje się:

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

Zapętla się na zawsze i nigdy nie wychodzi z trybu zastępowania . Podobnie, jeśli wzorzec jest pusty, to pierwsze wystąpienie pustego ciągu - na początku programu - zawsze pasuje, więc tryb podstawiania zapętla się na zawsze, nigdy się nie zatrzymując.


Przykłady

no

Wyjście: no.

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

Wyjście: Hello, world!.

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

Wyjście: Hello, world!.

a/ab/bbaa/abb

Wyjście: a. Program się nie zatrzymuje.

//

Wyjście: brak.

///

Wyjście: brak. Program się nie zatrzymuje.

/\\/good/\/

Wyjście: good.

Na wiki znajduje się również quine, którą możesz wypróbować.

algorytmshark
źródło
/-/World//--/Hello//--W/--, w/---!Czego nie kochać? (Spróbuj usunąć myślniki od końca)
patrz
@Loovjo \ Postać ucieka każdej następującej po niej postaci, w tym /, która później może być używana normalnie. Chociaż nie wygląda to zbyt wiele, powoduje to, że /// Turing jest kompletny .
algorytmshark
Myślę, że to lepsze wyjaśnienie języka niż artykuł na temat esolangs wiki. Wykorzystam te informacje w moim ///IDE, które tworzę!
clabe45

Odpowiedzi:

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}

Jest to funkcja, która przyjmuje ///kod za właściwy argument.

Bez golfa, z wyjaśnieniem:

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
źródło
„jeśli nie ma już znaków, zatrzymaj się”. Czy to działa poprawnie na ( ///i //foo/pętle na zawsze)?
algorytmshark
@algorytmshark: tak, w tej sytuacji /nadal pozostałyby w tym momencie.
marinus
11

J - 181 190 170 znaków

To był koszmar. Przepisałem go od zera, dwa razy, bo mnie to ciągle wkurzało. Jest to funkcja pobierająca argument z pojedynczym ciągiem, wysyłająca dane do 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=. ::](^:_)

Aby wyjaśnić, podzielę to na podwyrażenia.

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(skrót od iterate ) to przysłówek. Przyjmuje argument czasownika po lewej stronie i zwraca czasownik (f)i, który po zastosowaniu do argumentu stosuje się fwielokrotnie do argumentu, dopóki nie wydarzy się jedna z dwóch rzeczy: znajdzie on stały punkt ( y = f y) lub zgłasza błąd. Zachowanie stałym punktem jest nieodłącznym ^:_i ::]czyni obsługę błędów.

  • parsetokenizuje dane wejściowe do formy, którą nazywam półparsowaną , a następnie odcina ją w nieokreślonym „/”. Łączy ucieczkowe ukośniki z ich postaciami, ale nie pozbywa się ukośników odwrotnych - więc możemy je cofnąć lub zakończyć w zależności od tego, czego chcemy.

    Większość interesujących prac występuje w ;:. Jest to prymitywny interpreter maszyn sekwencyjnych, zawierający opis maszyny ( (0;(0,:~1 0,.2);'\';&<1 0)) po lewej stronie i coś do analizy po prawej. To powoduje tokenizację. Zwrócę uwagę, że ta konkretna maszyna faktycznie traktuje pierwszy znak jako niespecjalny, nawet jeśli jest to \i powinien się związać. Robię to z kilku powodów: (1) tablica stanu jest prostsza, więc można grać w golfa dalej; (2) możemy z łatwością dodać atrapę z przodu, aby uniknąć problemu; oraz (3) ta postać-manekin zostaje przeanalizowana do połowy bez dodatkowych kosztów, więc mogę użyć jej do przygotowania do fazy cięcia.

    Używamy również <;._1do wycinania tokenizowanego wyniku na nieskalowanym /(który wybrałem jako pierwszy znak). Jest to przydatne do wyciągania wyjścia, wzorca i zamiany ze out/patt/repl/restwszystkich w jednym kroku, ale niestety również tnie resztę programu, gdzie potrzebujemy, /aby pozostały nietknięte. Łączę je z powrotem podczas eval, ponieważ <;._1pozostawienie ich w spokoju kosztuje znacznie więcej.

  • Widelec (eval [ print)wykonuje printwynik z parsejego efektów ubocznych, a następnie uruchamia się eval. printjest prostym czasownikiem, który otwiera pierwsze okno (ten, który na pewno wiemy, jest wyjściem), kończy parsowanie i wysyła je do STDOUT. Korzystamy również z okazji, aby zdefiniować czasownik użytkowy p.

    pjest zdefiniowany jako >@{.@[, więc bierze lewy argument (działa jak tożsamość, jeśli podano tylko jeden argument), bierze pierwszy element tego (tożsamość, gdy podano skalar) i rozpakowuje go (tożsamość, jeśli jest już rozpakowany). Będzie to bardzo przydatne sub.

  • evalocenia pozostałą część przetworzonego programu. Jeśli nie mamy pełnego wzorca lub pełnego zamiennika, evalwyrzuca go i po prostu zwraca pustą listę, która kończy ocenę, popełniając błąd ;:(od parse) przy następnej iteracji. W przeciwnym razie w evalpełni analizuje wzorzec i zamiennik, koryguje pozostałą część źródła, a następnie przekazuje oba do sub. Przez wybuch:

                                                  @}.  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
    
  • subma miejsce jedna (być może nieskończona) runda podstawień. Ze względu na sposób konfiguracji evalźródło jest właściwym argumentem, a wzorzec i zamiennik są zgrupowane po lewej stronie. Ponieważ argumenty są uporządkowane w ten sposób i wiemy, że wzorzec i zamiana nie zmieniają się w ciągu rundy podstawień, możemy użyć innej funkcji i- faktu, że modyfikuje tylko właściwy argument i wciąż przesyła ten sam lewy - do delegowania J trzeba martwić się o śledzenie stanu.

    Istnieją jednak dwa problemy. Po pierwsze, czasowniki J mogą mieć co najwyżej dwa argumenty, więc nie mamy łatwego sposobu na dostęp do tych, które są spakowane razem, takich jak wzorzec i zamiana, tutaj. Dzięki sprytnemu użyciu pzdefiniowanego przez nas narzędzia nie stanowi to większego problemu. W rzeczywistości możemy uzyskać dostęp do wzorca w jednym znaku, po prostu używając p, ze względu na jego >@{.@[definicję: Unbox pierwszego elementu Left arg. Uzyskanie zastępstwa jest szybsze, ale najkrótszą drogą byłoby p&|., 2 znaki krótsze niż ręczne wyciągnięcie go.

    Drugi problem polega na tym, że ikończy się na stałych punktach zamiast zapętlać na zawsze, a jeśli wzorzec i zamiana są równe i dokonujesz podstawienia, wygląda to na stały punkt na J. Zajmujemy się tym, wprowadzając nieskończoną pętlę negacji 1 ponad i skończymy, jeśli wykryjemy, że są równe: to -i@=`p@.~:~/część zastępująca 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
    
  • Cykl ten powtarza się z powodu użycia i, aż do momentu wykrycia czegoś poza subbłędami. O ile mi wiadomo, może się to zdarzyć tylko wtedy, gdy brakuje nam postaci lub wyrzucamy niekompletny zestaw wzorców i zamienników.

Zabawne fakty na temat tego golfa:

  • Po raz pierwszy użycie ;:jest krótsze niż ręczne iterowanie ciągu.
  • 0{powinien mieć szansę na błąd, zanim subprzejdzie do nieskończonej pętli, więc powinno działać dobrze, jeśli wzorzec pasuje do zamiennika, ale nigdy nie pojawia się w pozostałej części źródła. Jednak może to być, ale nie musi, nieokreślone zachowanie, ponieważ nie mogę znaleźć żadnego cytatu w dokumentach. Whoopsie.
  • Przerwania na klawiaturze są przetwarzane jako spontaniczne błędy w uruchomionych funkcjach. Jednak ze względu na charakter ibłędy te również zostają uwięzione. W zależności od tego, kiedy naciśniesz Ctrl + C, możesz:
    • Wyjdź z pętli negacji na zawsze, wyjdź z subpętli, próbując połączyć liczbę z ciągiem, a następnie kontynuuj interpretację ///, jakbyś zakończył podstawianie łańcucha nieskończoną liczbę razy.
    • Wyjdź w subpołowie i kontynuuj interpretację wyrażenia / sub-subbed ///.
    • Wyjdź z interpretera i zwróć nieoceniony program /// do REPL (choć nie STDOUT).

Przykładowe użycie:

   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
algorytmshark
źródło
Łał. Nazwałbym to masochistą. +1
patrz
Kiedy to uruchamiam, otrzymuję pusty ciąg z każdego przypadku testowego. Używam jqt64, czego używasz do uruchomienia tego?
bcsb1001
@ bcsb1001 Korzystam bezpośrednio z (64-bitowego) pliku binarnego jconsole. Sprawdzam jqt teraz, właściwie otrzymuję zamierzone wyniki, z wyjątkiem /\\/good/\/przypadku testowego; debugowanie mówi mi, że problemem jest moje użycie 1!:2&4, ponieważ jqt nie ma standardowego wejścia / wyjścia. Zbada. Jakie są twoje 9!:12''i 9!:14''?
algorytmshark
@al algorytmshark My 9!:12''ma 6 lat i 9!:14''jest 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=''}}

Czyta ///program od standardowego wejścia do EOF.

faubi
źródło
Czy podejście m/^(.*?)(?<!\\)\/(.*?)(?<!\\)\/(.*?)(?<!\\)\/(.*)$/snaraz - takie same wyniki, wzorzec i zamiana - wszystko na raz - stanowiłoby krótszy golf? Sam nie znam żadnego Perla.
algorytmshark
Wierzę, że to się nie udaje z/a/\0/a
Asone Tuhid
3

Pip , 100 102 bajtów

Nigdy nie udowodniłem, że Pip jest kompletny w Turinga (choć jest to całkiem oczywiste), i zamiast iść zwykłą drogą BF, pomyślałem, że /// będzie interesujący. Kiedy już znalazłem rozwiązanie, pomyślałem, że zagram w golfa i opublikuję tutaj.

101 bajtów kodu, +1 dla -rflagi:

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

Oto moja nie golfowa wersja z obfitymi komentarzami:

; 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
}

Wypróbuj online! (Zauważ, że TIO nie daje żadnych danych wyjściowych, gdy program się nie kończy, a także ma limit czasowy. W przypadku większych przykładów i nieskończonych pętli zaleca się uruchomienie Pip z wiersza poleceń.)

DLosc
źródło
Myślę, że powinno to być pip + -r101 bajtów
Asone Tuhid
3

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

To nigdy nie wygra, ale odkąd zdecydowałem, że wszystkie moje przyszłe projekty oprogramowania zostaną napisane w tym niesamowitym języku, potrzebowałem do tego tłumacza i pomyślałem, że równie dobrze mogę podzielić się tym, który zrobiłem ...

Różnica w wynikach polega na tym, że Visual C ++ nie potrzebuje pierwszego dołączenia, ale g ++ tak. Wynik zakłada, że ​​zakończenia linii liczą się jako 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 Jeremiasz
źródło
1
Można przepisać if(!o[i]);jako if(P, aby zapisać znaki, albo ja nieporozumienie jak #define działa?
algorytmshark
@ algorytmshark jak mi tego brakowało ?! jeśli (! P jest idealny. Zmienię to.
Jerry Jeremiah
Każde wystąpienie Pin mainma po nim spację, więc możesz zapisać postać, zastępując je spacjami średnikami i usuwając je #define. Następnie, jeśli możesz użyć #defines wewnątrz innych, możesz zaoszczędzić trochę więcej, przepisując N(x)jako (92==Pzamiast o[i]==92i Opodobnie.
algorytmshark
@ algorytmshark jesteś w tym oczywiście o wiele lepszy niż ja. Dzięki za pomoc.
Jerry Jeremiah
Wiem, że to jest około czterech lat, ale przepisanie N(x)jak P;else if(n<x)(P==92?i zmiana połączeń do Nodpowiednio mógłby zaoszczędzić kilka bajtów.
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

Nazywany jako d(r"""/foo/Hello, world!//B\/\\R/foo/B/\R"""). Potrójne cytaty są potrzebne tylko wtedy, gdy ///program zawiera znaki nowej linii: w przeciwnym razie proste cytaty są w porządku.

EDYCJA: Ten interpreter drukuje teraz rzeczy zgodnie z oczekiwaniami (poprzednio drukowane tylko na samym końcu, patrz komentarze). W przypadku Python 3 usuń pierwszy wiersz (ale nie mam Python 3 na mojej starożytnej instalacji, więc nie mogę się upewnić, że nie ma innych zmian).

Bruno Le Floch
źródło
tłumacz nie drukuje niczego, dopóki problem nie zostanie rozwiązany. napisanie nieskończonej pętli w /// jest możliwe, więc twój interpreter zawiedzie w programach nie kończących się, ale wciąż drukujących coś.
dumny haskeller
@proudhaskeller Naprawiono.
Bruno Le Floch
W rzeczywistości nie jest to naprawione, nie drukuje niczego /a/ab/bbaa/abb.
Beta Decay
@BetaDecay /a/ab/bbaa/abbutknie w nieskończonej pętli bez drukowania czegokolwiek, ponieważ pierwszą substytucją jest a=> ab. Prawidłowe a/ab/bbaa/abbdziała zgodnie z reklamą.
algorytmshark
@BetaDecay: oprócz zmiany sugerowanej przez algorytmshark, może być konieczne włączenie opcji wiersza poleceń, -uaby wymusić buforowanie bufora wyjściowego.
Bruno Le Floch,
2

Kobra - 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)
Obrzydliwe
źródło
2

Rubin , 119 110 bajtów

Kończy się z wyjątkiem

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}

Wypróbuj online!

Kończy się czysto (116 bajtów)

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}

Wypróbuj online!

Asone Tuhid
źródło
1

Python 2/3 (211 bajtów)

Poniższy kod, oparty na odpowiedzi Bruno Le Flocha , jest zgodny z Python 2 i Python 3.

Co więcej, ponieważ jest iteracyjny, a nie rekurencyjny, nie ryzykuje osiągnięcia maksymalnej głębokości rekurencji w Pythonie.

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
źródło
Witam i witam w PPCG. Możesz grać in(0,1,2)w golfa do in 0,1,2i [""]*2+[1]do ["","",1], co daje 211 bajtów .
Jonathan Frech
Połączyłem się z odnośnikiem i dodałem słowo „bajty”. Jeśli nie zgadzasz się z moją edycją, możesz wycofać się.
Jonathan Frech
Dzięki Jonathan, twoje sugestie są bardzo mile widziane!
Carlos Luna
0

BaCon , 391 387 395 bajtów

Z materiałów zamieszczonych na tej stronie mam tylko program Python do pracy. Inne działają dla niektórych próbek /// lub w ogóle nie działają. Dlatego zdecydowałem się dodać moją wersję, która jest implementacją w języku BASIC.

Udział w konkursie CodeGolf z BASICem nie jest łatwy, ponieważ BASIC używa długich słów jako oświadczeń. Jedynym skrótem powszechnie występującym w języku BASIC jest „?” znak, co oznacza DRUKUJ.

Poniższy program może nigdy nie wygrać, ale przynajmniej działa z całym kodem demonstracyjnym na tej stronie Codegolf i na Wiki Esolangs . W tym wszystkie wersje „99 butelek piwa”.

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$
Piotr
źródło
Dodano instrukcję INPUT, aby uzyskać dane wejściowe od użytkownika.
Peter