Narysuj moje obluzowania


60

Jako programista prawdopodobnie słyszałeś o ukośnikach do przodu i do tyłu. Ale czy słyszałeś o obluzowaniach? Wtedy bierzesz kilka cięć, łączysz ich końce i rysujesz je w dół.

W dzisiejszym wyzwaniu musisz napisać program lub funkcję, która pobiera ciąg składający się wyłącznie z ukośników i wypisuje wszystkie ukośniki narysowane w dół w linii łączącej je. Będzie to o wiele wyraźniejsze, jeśli zobaczysz przykład. Biorąc pod uwagę ciąg \\\//\/\\, powinieneś wypisać:

\
 \
  \
  /
 /
 \
 /
 \
  \

Oto kilka wyjaśnień:

  • Musi być jeden ukośnik na linię.

  • Pierwsza linia będzie miała 0 wiodących spacji.

  • Dla każdej pary ukośników:

    • Jeśli różnią się od siebie, zostaną narysowane w tej samej kolumnie. Na przykład \/da:

      \
      /
      
    • Jeśli są tą samą postacią, dolna jest skierowana w kierunku wskazywanym , czyli przesuwa się w prawo, aby wykonać ukośnik odwrotny, i przesuwa się w lewo, aby wykonać ukośnik. Więc \\//da

      \
       \
       /
      /
      
  • Każda linia może mieć dodatkowe końcowe białe znaki, o ile nie zmienia to wyglądu obrazu wyjściowego. Dopuszczalny jest nawet jeden końcowy i wiodący nowy wiersz. Dodatkowe spacje wiodące są niedozwolone !

Aby uprościć to, możesz założyć, że ciąg nigdy nie będzie zawierał zbyt wielu ukośników. Innymi słowy, żaden prefiks wejścia nie będzie zawierał więcej ukośników niż ukośniki odwrotne, więc dane takie jak \\////lub //nigdy nie zostaną podane. Oznacza to również, że każde wejście zacznie się od ukośnika odwrotnego.

Jeśli twoje dane wejściowe są traktowane jako literał łańcuchowy, możesz uciec od ukośników odwrotnych, jeśli jest to konieczne. Nigdy nie będziesz musiał obsługiwać danych wejściowych, które są puste lub zawierają znaki inne niż ukośnik.

Możesz drukować w dowolnym rozsądnym formacie .

Jak zwykle jest to wyzwanie związane z , więc postaraj się znaleźć możliwie najkrótsze rozwiązanie, nawet jeśli wybierzesz język, w którym jest to dość trudne. Punkty bonusowe za wyjaśnienie wszelkich interesujących technik, których użyłeś do zdjęcia bajtów!

Przykłady

#Input
\\\\\\\\\\\

#Output
\
 \
  \
   \
    \
     \
      \
       \
        \
         \
          \

#Input
\\\//\\/\//\\///

#Output
\
 \
  \
  /
 /
 \
  \
  /
  \
  /
 /
 \
  \
  /
 /
/


#Input
\/\/\/

#Output
\
/
\
/
\
/


Odpowiedzi:


20

GNU Sed, 20

s|\\|&^L|g
s|/|^H/^L^H|g

Zauważ, że ^Li ^Hsą dosłowne znaki formfeed i backspace (0x12 i 0x8).

Ta odpowiedź polega na przesuwaniu kursora za pomocą znaków Backspace i Formfeed. Ukośniki / odwrotne ukośniki nie są wypełnione lewą spacją - Nie jestem pewien, czy to dyskwalifikuje tę odpowiedź. To nie działa w TIO, ale wygląda dobrze pod zwykłymi terminalami, takimi jak xtermi gnome-terminal.

Odtwórz ten skrypt sed w następujący sposób:

base64 -d <<< c3xcXHwmDHxnCnN8L3wILwwIfGc= > downslash.sed

Uruchom w następujący sposób:

$ echo '\\\//\/\\' | sed -f downslash.sed
\ 
 \ 
  \ 
  /
 /
 \ 
 /
 \ 
  \ 

$ 

Wyjaśnienie:

s|\\|&^L|g     # move cursor down after every "\"
s|/|^H/^L^H|g  # move cursor left before every "/", then after, down and left again

14

Węgiel drzewny , 13 12 11 bajtów

FS¿⁼ι/↓¶/↘ι

Wypróbuj online! Link jest do pełnej wersji kodu. Obsługuje dodatkowe //s. Wyjaśnienie:

 S              Input string
F               Loop over each character
  ¿             If
    ι           Current character
   ⁼            Equals
     /          Literal /
      ↓¶        Move left
      ↓ /       Print a / downwards
         ↘ι     Else it's a \ so print that down and right

Myślę, że ↓¶= „Przesuń w lewo” w opisie jest niewłaściwy.
Jonathan Allan

@JonathanAllan Zgadza się (nowa linia wydrukowana w dół = ruch w lewo), chociaż prawdopodobnie łatwiej byłoby powiedzieć „wydrukuj w \n/dół”
tylko ASCII

Nie powiedziałem, print \n/ downponieważ uważałem, że bardziej pomocne byłoby opisanie efektu kodu niż jego dosłowne tłumaczenie.
Neil

1
(Język w policzek: opisywanie efektu = MyCode - Do the spec). Rozumiem teraz, ale efektem jest przesunięcie w lewo; może warto powiedzieć „Przesuń w lewo (drukując nowy wiersz z kierunkiem drukowania w dół)”.
Jonathan Allan

Najbardziej zwięzłe i zrozumiałe ze wszystkich!
j4hangir


10

/// , 119 bajtów

/// nie ma poleceń wejściowych, więc dane wejściowe muszą być osadzone w programie. W tym przypadku łańcuch wejściowy jest po prostu dołączany, bez konieczności zmiany znaczenia.

/=/\/\///M/
|%%=N/%|||=C/BA=\/\\/\/C\\=C\\/CbC=B\A\=CfC=AB=/A/%Mxy=B/|z%N|x|y% %N%x|y%%% |fzN%M%b|zN|M|%
=|/AB\\=%/|=AC

Jak to działa

  • Poniżej, do programu \\/\//zostanie dołączone wejście programu do demonstracji.
  • służy do reprezentowania znaków nowej linii w kodzie wbudowanym.

Skróty

Początek /=/\/\///M/␤|%%=N/%|||=C/BA=programu zawiera zamienniki skrótów golfowych.

  • =rozwija się do //, Mdo ␤|%%, Ndo %|||i Cdo BA.
  • Po tym następuje bieżący program

    /\/\\/\/BA\\//BA\\/BAbBA//B\A\//BAfBA//AB///A/%
    |%%xy//B/|z%%||||x|y% %%|||%x|y%%% |fz%|||%
    |%%%b|z%||||
    |%%|%
    //|/AB\\//%/|//ABA\\/\//
    

Przekodowywanie wejścia

Następny etap przekształca dołączony ciąg wejściowy w bardziej użyteczną formę. Ponieważ składa się wyłącznie z dwóch znaków polecenia ///, należy zachować ostrożność, aby uniknąć zakłócenia programu podstawowego.

  • Pierwsze zasadnicze podstawienie /\/\\/\/BA\\/zastępuje ciąg /\przez /BA\.
    • Program podstawowy nie zawiera /\w tej chwili, więc podstawienie go nie zmienia.
    • Jednak to dzieli dołączony ciąg wejściowy na sekwencje \s, po których następują sekwencje /s, co wraz z ABAkońcem programu podstawowego umożliwia iterację poprzez następujące podstawienia.
    • Uwzględniając ABAprzedrostek, przykładowy ciąg wejściowy staje się teraz ABA\\/BA\//.
  • Następna zamiana /BA\\/BAbBA/, zastępuje się BA\przez BAbBA.
    • Ponieważ podstawienia /// są powtarzane, dopóki nie będą już pasować, iteruje się przez wszystkie \s łańcucha wejściowego, który z prefiksem staje się terazABAbBAbBA/BAbBA//
  • Podobnie /B\A\//BAfBA/zmiany BA/w BAfBA, iterowanie po /s.
    • Ucieczka \w tej substytucji jest potrzebna, ponieważ w przeciwnym razie zostałaby uszkodzona przez poprzednią.
    • Wejście zmieniło się w ABAbBAbBAfBABAbBAfBAfBA.
  • Następnie /AB//usuwa niektóre zbędne części kodowania, zamieniając je w AbBAbBAfBAbBAfBAfBA.
    • Usuwa również ABz /|/AB\\/podstawieniem w dalszej części programu, który był potrzebny, aby chronić je od powyżej /\manipulacji.
    • W tym momencie każdy \pierwotny ciąg wejściowy stał się AbBi każdy /stał się AfB. ( bi fstanąć do tyłu i do przodu.) Na Akońcu jest zbłąkany .
  • Następne dwie substytucje zastępują wszystkie As i Bs fragmentami programu do uruchomienia w końcowym etapie. W ciągach zastępczych %s i |s kodują odpowiednio to, co stanie się /s i \s. Ma to dwie zalety:
    • W przeciwieństwie do /i \, %s i |s nie muszą uciekać, aby zostać skopiowane.
    • Łańcuchy zastępcze unikają zawierania podciągów /\, które w przeciwnym razie zostałyby zniekształcone przez poprzednie manipulacje.
  • Po tym, podstawienie /|/\\/(wcześniej /|/AB\\/) teraz dekoduje |s, po której następuje /%/|//stała się /%/\//i dekoduje %s.

Struktura programu na końcowym etapie

W tym momencie program podstawowy uruchomił wszystkie swoje podstawienia, a pozostaje tylko kodowanie programu ciągu wejściowego.

  • Każdy znak wejściowy stał się podprogramem

    /
    \//xy*\z//\\\\x\y/ //\\\/x\y/// \fz/\\\/
    \///b\z/\\\\
    \//\/
    

    (końcowy znak nowej linii), gdzie *reprezentuje albo foryginał /, albo boryginał \.

  • Na /␤\//xykońcu programu znajduje się również niepełna komenda substytucji , która nie przyniesie żadnego efektu, poza zapewnieniem niezbędnego /zastąpienia poprzedniego podprogramu.

Współużytkowany podciąg

Zanim rozpocznie się końcowa iteracja przez podprogramy, po podprogramie każdej postaci w formularzu znajduje się podciąg \/␤/.

  • Te podciągi są używane jako wspólny stan globalny. Wszystkie pozostałe podstawienia w programie będą nimi manipulować identycznie i równolegle, tak że na końcu podprogramu każdego znaku wejściowego /zostanie uruchomiona jego kopia tego wspólnego podłańcucha (z wyjątkiem końcowego , który zakotwicza podstawienia), aby wydrukować linię dla tego postać.
  • Początkowa wersja podłańcucha reprezentuje wydrukowanie wiersza zawierającego just /, który jest właściwą wyimaginowaną „poprzednią linią”, aby spowodować wydrukowanie pierwszego znaku wejściowego na początku jego linii.
  • Ogólnie podczas etapów drukowania współużytkowany podciąg składa się z pewnej liczby spacji \\lub \/nowej linii i następujących po nim /.

Uruchamianie podprogramu znaków

Kilka poniższych podstawień zawiera dodatkowe \s wewnątrz, aby zapobiec ich wzajemnemu dopasowaniu i zniekształceniu (w tym innym kopiom w innych podprogramach). Osiągnięcie to jest również powód, dlaczego oba xi ysą potrzebne.

  • Pierwsze podstawienie w podprogramie znaków /␤\//xyf\z/lub /␤\//xyb\z/powoduje, że ␤/na końcu współdzielonego podłańcucha staje się xyfzlub xybz, bezpośrednio po \/lub \\.
  • Podstawienie /\\\\x\y/ /zastępuje \\xysię spacją, a podstawienie /\\\/x\y//zastępuje \/xynic.
    • Mają zastosowanie, gdy poprzedni wydrukowany znak wejściowy był odpowiednio a \lub /.
    • Współużytkowany podciąg zawiera teraz odpowiednią liczbę spacji do wydrukowania \następnego, a następnie fzlub bz.
  • Podstawienie / \fz/\\\/␤\//zastępuje ​ fzprzez \/␤/i /b\z/\\\\␤\//zastępuje bzprzez \\␤/.
    • Mają zastosowanie, gdy bieżącym znakiem wejściowym jest odpowiednio /lub \.
    • Pierwszy zjada dodatkową przestrzeń, aby umieścić go /poprawnie.
      • Jeśli brakuje tego miejsca (tj. Dane wejściowe naruszające warunek przedrostka), następujące podstawienia są błędnie interpretowane, drukując dużo śmieci i zwykle uderzając w ///, co jest nieskończoną pętlą.
    • Każde z nich dodaje poprawne polecenie, aby wydrukować własny znak, i przywraca oryginał ␤/na końcu udostępnionego podłańcucha.
  • Podprogram znaków osiągnął teraz swoją kopię współdzielonego podłańcucha, która jest gotowa do wydrukowania swojej linii.

Po uruchomieniu podprogramu ostatniego znaku pozostała część programu /␤\//xy. Ponieważ jest to niepełna zamiana z brakującym końcem /, program pomija ją i zatrzymuje się normalnie.


1
Właściwy język do pracy! Lol
DJMcMayhem

6

Galaretka , 14 bajtów

=”\ðḤ’+\_⁸⁶ẋżY

Pełny program drukujący wynik.

Wypróbuj online!

W jaki sposób?

=”\ðḤ’+\_⁸⁶ẋżY - Link: list of characters, s    e.g. "\\\//\\/"
 ”\            - literal '\'                         '\'
=              - equal? (call this e)                [1, 1, 1, 0, 0, 1, 1, 0]
   ð           - new dyadic chain f(e, s)
    Ḥ          - double                              [2, 2, 2, 0, 0, 2, 2, 0]
     ’         - decrement                           [1, 1, 1,-1,-1, 1, 1,-1]
      +\       - cumulative reduce with addition     [1, 2, 3, 2, 1, 2, 3, 2]
         ⁸     - chain's left argument, e            [1, 1, 1, 0, 0, 1, 1, 0]
        _      - subtract (# of leading spaces)      [0, 1, 2, 2, 1, 1, 2, 2]
          ⁶    - literal ' '                         ''
           ẋ   - repeat                              [""," ","  "," "," "," ","  ","  "]
            ż  - zip with s                          [["",'\'],[" ",'\'],["  ",'\'],["  ",'/'],[" ",'/'],[" ",'\'],["  ",'\'],["  ",'/']]
             Y - join with newlines                  ["",'\','\n'," ",'\','\n',"  ",'\','\n',"  ",'/','\n'," ",'/','\n'," ",'\','\n',"  ",'\','\n',"  ",'/']
               - implicit print - this smashes the lists (shown as "..." above) and the characters (shown as '...' above) together.



5

JavaScript (ES8), 66 59 63 bajtów

7 bajtów zapisanych dzięki Justin Mariner
+ 4 bajty do naprawy /\\/\\/(zauważone przez Neila )

f=([a,...z],b=a<'0')=>a?a.padStart(b+=k=a>'/')+`
`+f(z,b-!k):''

Wypróbuj online!


5

MATL , 23 19 18 bajtów

1 bajt off dzięki @Sanchises

fGqoEq1yd~h*YsGZ?c

Dane wejściowe to ciąg ujęty w pojedyncze cudzysłowy.

Wypróbuj online! Lub sprawdź przypadki testowe: 1 , 2 , 3 .

Wyjaśnienie

Rozważ dane wejściowe '\\\//\/\\'jako przykład.

f      % Implicit input. Array of indices of nonzeros. Since all chars in the input
       % have nonzero code point, this gives [1 2 ... n] where n is input length
       % STACK: [1 2 3 4 5 6 7 8 9]
G      % Push input again
       % STACK: [1 2 3 4 5 6 7 8 9], '\\\//\/\\'
qo     % Subtract 1 from (the code-point) of each char and then compute modulo 2.
       % This transforms '\' into 1 and '/' into 0
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 0 0 1 0 1 1]
Eq     % Double, subtract 1. This transforms 0 into -1
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 -1 -1 1 -1 1 1]
1y     % Push 1 and duplicate from below
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 -1 -1 1 -1 1 1], 1, [1 1 1 -1 -1 1 -1 1 1]
d~     % Consecutive differences, logical negation: gives 1 if consecutive entries
       % are equal, 0 otherwise
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 -1 -1 1 -1 1 1], 1, [1 1 0 1 0 0 0 1]
h      % Horizontally concatenate
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 -1 -1 1 -1 1 1], [1 1 1 0 1 0 0 0 1]
*      % Element-wise multiplication
       % STACK: [1 2 3 4 5 6 7 8 9], [1 1 1 0 -1 0 0 0 1]
Ys     % Cumulative sum
       % STACK: [1 2 3 4 5 6 7 8 9], [1 2 3 3 2 2 2 2 3]
G      % Push input again
       % STACK: [1 2 3 4 5 6 7 8 9], [1 2 3 3 2 2 2 2 3], '\\\//\/\\'
Z?     % Build sparse matrix with those row indices, column indices, and values
       % STACK: [92  0  0;
                  0 92  0;
                  0  0 92;
                  0  0 47;
                  0 47  0;
                  0 92  0;
                  0 47  0;
                  0 92  0;
                  0  0 92]
c      % Convert to char. Char 0 is shown as space. Implicitly display
       % STACK: ['\  ';
                 ' \ ';
                 '  \';
                 '  /';
                 ' / ';
                 ' \ ';
                 ' / ';
                 ' \ ';
                 '  \']

Jeden bajt z nieco innym algorytmem, aby uzyskać swoje indeksy: Wypróbuj online!
Sanchises

@ Sanchises Dziękujemy za bardzo odpowiednie zmiany!
Luis Mendo,

5

C # (.NET Core) , 74 88 82 78 77 76 + 18 bajtów

-1 bajt dzięki Kevin Cruijssen

s=>s.Select((x,i)=>$"{x}".PadLeft((x-s[0])/45-~s.Take(i).Sum(y=>y<92?-1:1)))

Generuje kolekcję ciągów, po jednym dla każdej linii. Liczba bajtów obejmuje również:

using System.Linq;

Wypróbuj online!

Wyjaśnienie 77 bajtowej odpowiedzi:

s =>                              // Take input, a string
    s.Select((x, i) =>            // Replace every character with:
        $"{x}"                    //     The character as string
        .PadLeft(                 //     Pad with this many spaces:
            s.Take(i)             //         Take characters, in the input string, preceding current one
            .Sum(y =>             //         Sum them by:
                y < 92 ? -1 : 1   //             If it's a \ add 1, if / subtract 1
            )
            + (x - s[0]) / 45 + 1 //         If first slash is a / add one more space, if current slash is a \ add one more space (I got this through power of MATHS!)
                                  //         How I arrived at this function:
                                  //         + x / 48        If current slash is a \ add one more space
                                  //         - s[0] / 48 + 1 If the first slash is a / add one more space
        )
    )

3
Nie działa dla /\\/\\/.
Neil

@ Neil dziękuję za zwrócenie na to uwagi! Naprawiony.
Grzegorz Puławski

1
Wiem, że minęło trochę czasu, ale możesz zaoszczędzić bajt, zmieniając s.Take(i).Sum(y=>y<92?-1:1)+(x-s[0])/45+1na(x-s[0])/45-~s.Take(i).Sum(y=>y<92?-1:1)
Kevin Cruijssen

Nice one @KevinCruijssen!
Grzegorz Puławski

4

05AB1E , 14 bajtów

ÇÈx<ηOs-W-ISú»

Wypróbuj online!

Wyjaśnienie

Ç                # convert input string to a list of ascii codes
 È               # check each for evenness
  x              # push a doubled copy
   <             # decrement
    η            # compute prefixes
     O           # sum each prefix
      s          # swap the unaltered copy of evenness to the top
       -         # subtract from the prefix-sum list
        W-       # subtract the minimum value
          IS     # push input split to a list of chars
            ú    # pad each with the number of spaces computed
             »   # join on newline

1
Nie działa dla /\\/\\/.
Neil

Ç¥.¥0<.SηOv¹Nèy<ú, szlochając w systemie binarnym
Magic Octopus Urn

3

R , 122 121 bajtów

-1 bajt dzięki Giuseppe

x=el(strsplit(scan(,""),""));n=seq(x);y=x>"/";for(i in n)cat(rep(" ",diffinv(y[n[-1]-1]+y[n[-1]]-1)[i]),x[i],"\n",sep="")

Wypróbuj online!

Z dodatkową spacją:

x = el(strsplit(scan(,""),""))
n = seq(x)
y = x>"/"
for(i in n) {
  cat(rep(" ", diffinv(y[n[-1]-1]+y[n[-1]]-1)[i]), x[i], "\n", sep="")
}

Objaśnienie: Ta odpowiedź jest oparta na spostrzeżeniu, że liczba wiodących spacji zmienia każdą linię o -1, plus liczba /poprzednich i bieżących linii.

Jeśli mamy N ukośników, zmienna yjest wektorem długości N, z 1 dla każdej pozycji z \, w przeciwnym razie 0. Dlatego, aby uzyskać zmianę liczby wiodących spacji w wierszu, obliczamy y[1:(N-1)] + y[2:N] - 1. Ta funkcja diffinvprzekształca te różnice w sekwencję, zaczynając od 0. Reszta to tylko kwestia złożenia każdej linii jako wymaganej liczby końcowych spacji, a następnie odpowiedniego ukośnika i nowej linii.


1
hę Przyjęłam zupełnie inne podejście do 119 bajtów, co sprawia, że ​​zastanawiam się, czy moglibyśmy połączyć nasze podejścia. (fajne użycie diffinv;) Możesz także ustawić y=x>")"na -1 bajt
Giuseppe

@Giuseppe Powinieneś opublikować to jako osobną odpowiedź, jest to dość odmienne podejście. Twój sposób to dobry sposób na unikanie robienia czegoś strsplit, co zawsze jest zabójcą. Możesz także skorzystać ze słynnego diffinv!
user2390246

1
Myślę również, że jeśli wstawisz library(methods)nagłówek (co powinno być OK bez kary, ponieważ ten pakiet jest częścią podstawy R), możesz użyć el. diffinvOkazało się też, że jest tak długo, jak cumsum! :)
Giuseppe

Tak, właśnie zdałem sobie z tego sprawę, to nie do końca działa w tym kontekście
user2390246

wymyśliłem obejście , ale tak, to *Swszystko psuje.
Giuseppe,

3

Brain-Flak , 175 bajtów (174 znaków + 1 flaga)

Uruchom z -cflagą.

{(({})<(())>){({}[()]<([{}])>)}{}(({}<>{}<><({}<>)((()()()()()){})>)<{({}[()]<((((()()()()){}){}){})>)}>{})<>}<>{}{({}<>)(({})(())){({}[()]<([{}]())>)}{}{<>{}<>(<{}>)}{}<>}<>

Wypróbuj online!

Wyjaśnienie

{ for each char in the input...
  (({})<(())>){({}[()]<([{}])>)}{} push 1/-1 for backslash/slash
  ((
   {}<>{}<> add the 1/-1 to a running total
   <
    ({}<>) move slash/backslash to other stack
    ((()()()()()){}) newline
   >
  )<{({}[()]<((((()()()()){}){}){})>)}>{}) spaces
  <>
}<>{} end for
reverse data order, removing one space before backslash
{({}<>)(({})(())){({}[()]<([{}]())>)}{}{<>{}<>(<{}>)}{}<>}<>

Zawsze głosuję za wybrykiem mózgu. : D
DJMcMayhem

3

Rubinowy , 80 76 bajtów

-4 bajty dzięki manatwork

puts"\\";$*[i=0].chars.each_cons 2{|b,c|puts" "*(b==c ?b==?/?i-=1:i+=1:i)+c}

Wypróbuj online!

Wyjaśnienie:

puts "\\"           # Output the first backslash
$*[i=0].            # Get the first argument and set i to 0
chars.              # Go through every individual character,
each_cons 2 { |b,c| # In pairs to compare easily
                    #
    puts " " *      # Decide how many padding spaces to use based on the value
                    # of i. The expression inside the parenthesis will return
                    # i but before that, it will increment/decrement i based
                    # on what the previous character was.
                        #
    ( b==c ?            # if b == c
        b==?/ ?         #   if b == "/" (Going to the left)
            i-=1        #       return decremented i
            :           #   else        (Going to the right)
            i+=1        #       return incremented i
        :               # else
        i) +            #   return i
                    #
                c   # Finally, write the second of the characters that we're
}                   # iterating through.

1
Która wersja Ruby? 2.3.3 Mam wymaga nawiasów wokół parametru gdy blok kodu w następujący sposób: .each_cons(2){…}. W zamian możesz zapisać, zastępując .each_char.chars.
manatwork

@manatwork Moja wersja ruby ​​to 2.4.1. Dzięki za sugestię dotyczącą znaków, nie wiedziałem o tym.
Pazzaz

Możesz zapisać kolejne dwa bajty, przechodząc i+=na początek zagnieżdżonego wyrażenia trójskładnikowego i kończąc go -1:1:0.
benj2240

3

Java 8, 121 118 110 109 102 bajtów

a->{String r="";int s=0,p=0,i;for(char c:a){for(i=s+=p+(p=c-63)>>5;i-->0;r+=" ");r+=c+"\n";}return r;}

-7 bajtów dzięki nieco magicznej magii @Nevay . :)

Wyjaśnienie:

Wypróbuj tutaj.

a->{                    // Method with char-array parameter and String return-type
  String r="";          //  Return-String
  int s=0,              //  Amount of spaces
      p=0,              //  Previous characters (starting at 0)
      i;                //  Index-integer
  for(char c:a){        //  Loop over the input
    for(i=s+=p+(p=c-63)>>5;
                        //   If the current does not equals the previous character
                        //    Leave `s` the same
                        //   Else-if it's a '\':
                        //    Increase `s` by 1
                        //   Else (it's a '/'):
                        //    Decrease `s` by 1
                        //   And set the previous character to the current in the process
        i-->0;r+=" ");  //   Append `r` with `s` amount of spaces               
    r+=c+"\n";          //   Append the character + a new-line to the result
  }                     //  End of loop
  return r;             //  Return result-String
}                       // End of method

1
102 bajty:a->{String r="";int s=0,p=0,i;for(char c:a){for(i=s+=p+(p=c-63)>>5;i-->0;r+=" ");r+=c+"\n";}return r;}
Nevay

@Nevay Thanks. Wiedziałem, że można go skrócić za pomocą operacji bitowych, ale nie mogłem tego pojąć. Głównie dlatego, że zapomniałem o wypróbowaniu efektów >>/ >>>/ <<... Sprawdziłem tylko niektóre rzeczy w &/ |/ ~/ ^..>.>
Kevin Cruijssen

3

C (GCC), 137 134 97 bajtów

Wypróbuj online!

• 3 bajty dzięki ATaco

• 37 bajtów dzięki Digital Trauma i ThePirateBay

i,d;f(char*s){char c=s[i],n=s[++i];if(c){printf("%*c%c\n",d+1,c);(c-n)?d:(c==47)?--d:++d;f(s);}}

Nic nadzwyczajnego, tylko prosta funkcja rekurencyjna, która pobiera ciąg znaków i wypisuje ukośniki. Zauważ, że wejście musi najpierw uciec przed odwrotnym ukośnikiem.

Stosowanie

f("\\\\\\//\\/\\\\",0,0);

Bez golfa

To jest dla starej odpowiedzi, zobacz link online wypróbuj zaktualizowany!

f(char *s, i, d) {
    char c=s[i], n=s[++i];
    if(!c) return;
    for(int j=0; j<d; j++) printf(" ");
    printf("%c\n",c);
    f(s, i, (c!=n)?d:(c=='/')?d-1:d+1);
}

Wynik

wprowadź opis zdjęcia tutaj


Można wymienić c=='\0'ze !cdla tego samego efektu.
ATaco

Niesamowite dzięki właśnie zaktualizowałem rozwiązanie!
Asleepace

Czy możesz użyć printf("%*s%c", n, "", c)do wydrukowania znaku z n wiodącymi spacjami?
Digital Trauma

Jestem prawie pewien, że można zaoszczędzić kilka bajtów zastępując (c!=n)ze c-ni rozmieszczanie wyrażeń trójskładnikowych. To samo z (c=='/'). Możesz także zastąpić '/'literalną liczbą 47. Myślę, że w sumie jest to 7 bajtów.



3

Siatkówka , 47 bajtów

^|\\
 $&
+m`^( *)( /|\\)(/| \\)
$1$2¶$1$3
m`^ 

Wypróbuj online! Link zawiera przypadki testowe. Wyjaśnienie:

^|\\
 $&

Dodaj spację na początku każdej linii i przed każdą \.

+m`^( *)( /|\\)(/| \\)
$1$2¶$1$3

Rozważ pierwsze dwa znaki ciągu. Jeśli pierwszym jest a, /to tiret musi zostać zmniejszone; osiąga się to poprzez włączenie poprzedniej przestrzeni do przechwytywania (która zawsze istnieje, ponieważ dodano ją w pierwszym etapie); jeśli drugi jest, \\to należy go zwiększyć; osiąga się to poprzez włączenie przestrzeni, którą pierwszy etap dodał do przechwytywania. Po nadaniu drugiemu znakowi poprawnego wcięcia etap powtarza się dla drugiego i trzeciego znaku itp.

m`^ 

Usuń dodatkowe wcięcie.

Napisałem 94-bajtową wersję, która (podobnie jak moja odpowiedź na węgiel drzewny) pozwala na dowolną kombinację ukośników: Wypróbuj online! Wyjaśnienie:

.$
¶$.`$* $&

Spraw, aby piłka potoczyła się, biorąc ostatni cios i wciskając go w to samo miejsce na swojej linii.

/
 /

Prefiks spacji do wszystkich ukośników do przodu, aby można je było uchwycić.

+`^(.*)( /|\\)¶( *)( \\|/)
$1¶$3$2¶$3$4

Kilkakrotnie weź ostatni ukośnik wejścia i wyrównaj go we własnej linii z ukośnikiem w linii poniżej.

+ms`^(?<!^[\\/].*) (?!.*^[\\/])

Usuń wszelkie pozostałe wcięcia.

G`.

Usuń teraz puste wejście.


2

Lua , 96 bajtów

c=0 for s in(...):gmatch(".")do c=c+(p==s and(s=="/"and-1or 1)or 0)p=s print((" "):rep(c)..s)end

Wypróbuj online!

Najkrótszy, jaki mogłem wymyślić w Lua. Dane wejściowe są pobierane z wiersza poleceń.

Wykorzystuje to kilka sztuczek:

  1. (...):gmatch(
    Powinno to być najkrótsza forma wprowadzenia pojedynczego ciągu do programu Lua z wiersza poleceń. ...Wyraz w Lua rejestruje żadnych nadmiarowych parametrów do funkcji, które nie są wymienione w deklaracji funkcji i jest używany do varargs. Ponieważ główna treść programu Lua jest wywoływana jako funkcja z argumentami wiersza poleceń jako parametrami, argumenty wiersza polecenia kończą się na ....
    Nawiasy wokół niego przekształcają ...wyrażenie potencjalnie wielowartościowe w wyrażenie jednowartościowe. Rozważ ten (nieco zaskakujący) przykład:
    function multipleReturnValues()
        return "abc", "def"
    end
    print(  multipleReturnValues()  ) --This prints: abc    def
    print( (multipleReturnValues()) ) --This prints: abc
  2. Parser Lua nie potrzebuje żadnych terminatorów linii, ani nawet spacji między instrukcjami, o ile tokeny obu instrukcji mogą być wyraźnie oddzielone i istnieje tylko jedna interpretacja tekstu, który jest prawidłowym kodem Lua.
  3. Nadużywanie and/ ordla logiki „jeśli x to wartość 1 inaczej wartość 2”. Operator
    Lui andzwraca swój pierwszy argument, jeśli jest fałszem; w przeciwnym razie zwraca drugi argument. orOperator zwraca pierwszego argumentu jeśli jest truthy; w przeciwnym razie drugi argument.
  4. pnie wymaga żadnej inicjalizacji.
    p==szawsze musi być fałszywy w pierwszym uruchomieniu pętli, niezależnie od danych wejściowych. Brak ustawienia pżadnej wartości przed wejściem do pętli (pozostawienie jej nil) spowoduje, że tak się stanie i zaoszczędzi bajty.

Czy ktoś może zagrać w golfa (w Lua)?


Udało mi się zapisać dwa bajty, używając gsub zamiast gmatch. c=0(...):gsub(".",function(s)c=c+(p==s and(s=="/"and-1or 1)or 0)p=s print((" "):rep(c)..s)end)
QuertyKeyboard

Cóż, nie to ma znaczenie. Możesz łatwo zapisać dwa bajty, zmieniając gmatch(".")się gmatch"."tak, jak w następnej odpowiedzi.
QuertyKeyboard

@QuertyKeyboard To dziwne ... Tak naprawdę użyłem gsub w pierwszej wersji tego kodu, ale zamiast tego przełączyłem się na gmatch, ponieważ okazało się, że jest krótszy. Nie wiem jednak, co zrobiłem inaczej, plik jest niestety nadpisany.
Jonathan S.


2

R 119 bajtów

function(s)for(i in 1:nchar(s))cat(rep(" ",cumsum(c(0,!diff(S<-(utf8ToInt(s)>48)*2-1))*S)[i]),substr(s,i,i),"
",sep="")

Wypróbuj online!

Różni się to nieco od odpowiedzi user2390246 . Każdy z nich iteruje ciąg, wypisując określoną liczbę znaków spacji, a następnie odpowiedni /\znak.

Jednak uniknąłem podziału łańcucha, zamiast tego zdecydowałem się zastąpić znaki ich wartością kodowania UTF-8, co pozwala mi wykonywać arytmetykę liczb bezpośrednio, co pozwoliło mi zaoszczędzić tylko kilka bajtów.


Właśnie się nad tym zastanawiam, myślę, że w twoim algorytmie jest błąd: TIO
user2390246

@ user2390246 Naprawiłem to! Miałem trochę źle umieszczonych nawiasów, ale teraz diffinvzdecydowanie nie zadziała tutaj.
Giuseppe,


2

C # (.NET Core) , 60/65 bajtów

Próbowałem krótszej wersji C #

s=>{int i=0;return s.Select(x=>"".PadLeft(x<92?--i:i++)+x);}

jak stwierdzono: „Oznacza to również, że każde wejście będzie zaczynać się odwrotnym ukośnikiem”. Lub nieco dłużej, co rozwiązuje początek „/”

s=>{int i=s[0]&1;return s.Select(x=>"".PadLeft(x<92?--i:i++)+x);}

Wypróbuj online!


Witamy na stronie! :)
DJMcMayhem

2

Lua , 88 84 bajtów

Ulepszona wersja (-4 bajty dzięki QuertyKeyboard)

s=""g=s.gsub g(...,".",function(c)s=g(g(g(s,"\\"," "),"/?$",c)," /","/")print(s)end)

Wypróbuj online!

Wersja oryginalna (88 bajtów)

Kolejna próba w Lua, tym razem z zupełnie innym podejściem, wykorzystująca manipulację ciągiem zamiast zmiennej przeciwnej.

s=""for c in(...):gmatch"."do s=s:gsub("\\"," "):gsub("/?$",c):gsub(" /","/")print(s)end

Nie golfowany:

s = ""
for c in string.gmatch((...), ".") do --for each character in the input
  --s contains the output from the previous iteration
  s = s:gsub("\\", " ") --Replace backslash with space -> indent by 1
  s = s:gsub("/?$", c) --Remove any / at the end of the string and append c to the string
  s = s:gsub(" /", "/") --Remove a single space in front of any / -> un-indent by 1
  print(s)
end

W kodzie jest jedna interesująca rzecz: (...):gmatch"."
wykorzystuje kilka dziwactw w parserze Lua. Kiedy Lua napotka fragment kodu w formularzu func "string", przekształci go na func("string"). Dzieje się tak, aby można było napisać, print "string"aby wydrukować stały ciąg znaków i działa tylko z jednym dosłownym ciągiem znaków po funkcji. Wszystko inne da błąd składniowy. Jednak ten cukier syntaktyczny działa również z wywołaniami funkcji w środku wyrażenia i, co bardziej zaskakujące, działa dobrze w połączeniu z :wywołaniem metody cukru syntaktycznego. W końcu Lua zinterpretuje kod w następujący sposób:

(...):gmatch"."
-> (...):gmatch(".")
-> string.gmatch((...), ".")

Jeśli ktoś wymyśli sposób na usunięcie jednego z trzech połączeń gsub, proszę mi powiedzieć.


1
Byłem rozczarowany, gdy stwierdziłem, że moja sztuczka gsub, którą skomentowałem w twojej drugiej odpowiedzi, nie działała całkiem dobrze. W rzeczywistości dodało jeden bajt. Jednak nie poddałbym się tak łatwo. Najpierw próbowałem zapisać gsub jako zmienną, aby skrócić kod. Ku mojemu zdziwieniu mój kod miał dokładnie taką samą liczbę bajtów - 88. Jednak zdałem sobie sprawę, że po zapisaniu gsub moja sztuczka gsub może teraz działać! Oto mój kod, który zgolił 4 bajty:s=""g=s.gsub g(...,".",function(c)s=g(g(g(s,"\\"," "),"/?$",c)," /","/")print(s)end)
QuertyKeyboard

@QuertyKeyboard Tak, próbowałem również zapisać gsub w zmiennej przed pętlą, a następnie użyć go zamiast pisać gsub trzy razy, i byłem równie zaskoczony, widząc, że nie robi to absolutnie żadnej różnicy. Połączenie sztuczek „gsub zamiast loop” i „store gsub” jest naprawdę fajne, nie pomyślałem o tym! Dzięki! :)
Jonathan S.


1

Perl, 40 + 2 bajty

/\//&&$.--,say($"x$.,$_),/\\/&&$.++for@F

Potrzebujesz -Fflagi.


1

Perl, 34 38 + 1 bajtów

do obsługi dwóch przypadków

s,(/)|.,$"x($1?$c&&--$c:$c++).$&.$/,ge

do uruchomienia z -popcją

s,(/)|.,$"x($1?--$c:$c++).$&.$/,ge

EDYCJA: następujący komentarz nie działa, gdy jest pierwszy znak /

s,(/)|.,$"x($1?$c--:++$c).$&.$/,ge

jednak wynik zostanie przesunięty o jeden znak po prawej stronie, jeśli jest to pierwszy znak \


1
Nie działa dla /\\/\\/.
Neil

Dzięki zaktualizowanemu pytaniu twoje oryginalne 34rozwiązanie jest teraz całkowicie poprawne
Ton Hospel

1

VBA (Excel), 181 bajtów

Sub q()
a = Cells(1, 1)
For x = 1 To Len(a)
c = Mid(a, x, 1)
If c = "\" Then: Debug.Print b & c: b = b + " "
If c = "/" Then: b = Left(b, Len(b) - 1): Debug.Print b & c
Next
End Sub

1
Możesz znacznie pograć w golfa bez zmiany algorytmu, korzystając z autoformatowania programu Excel VBA i [...]notacji: zmniejszyłem go do 128 bajtów Sub q For x=1To[Len(A1)] c=Mid([A1],x,1) If c="\"Then Debug.?b;c:b=b+" " If c="/"Then b=Left(b,Len(b)-1):Debug.?b;c Next End Sub
Taylor Scott

Dziękuję za grę w mój scenariusz. Nauczyłem się czegoś z tego i będę stosować w przyszłości. :) Nie wiedziałem, że mogę tego użyć do pobrania danych bezpośrednio do komórek.
Jeszcze



Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.