Nawiasy teleskopowe

79

Rozważ niepusty ciąg poprawnie zrównoważonych nawiasów:

(()(()())()((())))(())

Możemy sobie wyobrazić, że każda para nawiasów reprezentuje pierścień w zwiniętej konstrukcji teleskopowej . Rozszerzmy więc teleskop:

(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()

Innym sposobem na to jest to, że nawiasy na głębokości n są przenoszone do linii n , przy jednoczesnym zachowaniu ich pozycji poziomej.

Twoim zadaniem jest wziąć taki ciąg zrównoważonych nawiasów i stworzyć rozszerzoną wersję.

Możesz napisać program lub funkcję, pobierając dane wejściowe przez STDIN (lub najbliższy odpowiednik), argument wiersza poleceń lub parametr funkcji i generując dane wyjściowe przez STDOUT (lub najbliższy odpowiednik), wartość zwracaną lub parametr funkcji (wyjściowej).

Możesz założyć, że łańcuch wejściowy jest prawidłowy, tzn. Składa się tylko z nawiasów, które są odpowiednio zrównoważone.

Możesz drukować końcowe spacje w każdej linii, ale nie więcej spacji wiodących niż to konieczne. Łącznie wiersze nie mogą być dłuższe niż dwukrotność długości ciągu wejściowego. Możesz opcjonalnie wydrukować jedną końcową linię nowego wiersza.

Przykłady

Oprócz powyższego przykładu, oto jeszcze kilka przypadków testowych (wejście i wyjście są oddzielone pustą linią).

()

()
(((())))

(      )
 (    )
  (  )
   ()
()(())((()))(())()

()(  )(    )(  )()
   ()  (  )  ()
        ()
((()())()(()(())()))

(                  )
 (    )()(        )
  ()()    ()(  )()
             ()

Powiązane wyzwania:

  • Ciągi topograficzne , które proszą cię o stworzenie tego, co jest zasadniczo uzupełnieniem wyników w tym wyzwaniu.
  • Code Explanation Formatter , szerokie uogólnienie pomysłów w tym wyzwaniu, opublikowane niedawno przez PhiNotPi. (W rzeczywistości oryginalny opis PhiNotPi jego pomysłu był tym, co zainspirowało to wyzwanie).

Liderów

Huh, to miało dość duży udział, więc oto fragment kodu, który generuje zarówno zwykłą tabelę wyników, jak i przegląd zwycięzców według języka.

Aby upewnić się, że twoja odpowiedź się pojawi, zacznij od nagłówka, korzystając z następującego szablonu Markdown:

# Language Name, N bytes

gdzie Njest rozmiar twojego zgłoszenia. Jeśli poprawić swój wynik, to może zachować stare porachunki w nagłówku, uderzając je przez. Na przykład:

# Ruby, <s>104</s> <s>101</s> 96 bytes

Martin Ender
źródło
17
Alternatywny tytuł: De-Lisp-ify string. : P
Alex A.
1
Czy są jakieś ograniczenia dotyczące koloru wydruku?
Matteo Italia
1
@ MartinBüttner: nieważne, znalazłem czystszy sposób; powiedzmy, że mój poprzedni pomysł wygoliłby bajt, pozostawiając wszystkie zamknięte nawiasy migające na niebiesko nad błękitem ... :-)
Matteo Italia
8
@MatteoItalia o Boże, cieszę się, że tak się nie stało. ;)
Martin Ender
12
@MatteoItalia: Opublikuj tę wersję! To jest warte zobaczenia.
user2357112,

Odpowiedzi:

8

CJam, 17 16 15 bajtów

0000000: 72 3a 69 22 28 0b 20 9b 41 29 22 53 2f 66 3d     r:i"(. .A)"S/f=

Powyższe jest odwracalnym zrzutem xxd, ponieważ kod źródłowy zawiera niedrukowalne znaki VT (0x0b) i CSI (0x9b).

Podobnie jak ta odpowiedź , wykorzystuje sekwencje specjalne ANSI , ale używa także pionowych tabulatorów i drukuje znaki sterujące bezpośrednio, aby uniknąć używania printf .

Wymaga to obsługi terminalu tekstowego wideo, który obejmuje większość emulatorów terminali innych niż Windows.

Testowe uruchomienie

Musimy ustawić zmienną powłoki LANG i kodowanie emulatora terminala na ISO 8859-1. Ten pierwszy osiąga się przez wykonanie

$ LANGsave="$LANG"
$ LANG=en_US

Ponadto przed wykonaniem rzeczywistego kodu wyłączymy monit i wyczyścimy ekran.

$ PS1save="$PS1"
$ unset PS1
$ clear

Dzięki temu dane wyjściowe są wyświetlane poprawnie.

echo -n '()(())((()))(())()' | cjam <(base64 -d <<< cjppIigLIJtBKSJTL2Y9)
()(  )(    )(  )()
   ()  (  )  ()
        ()

Aby przywrócić LANG i monit, wykonaj następujące czynności:

$ LANG="$LANGsave"
$ PS1="$PS1save"

Jak to działa

Po każdym wstawiamy pionową zakładkę ( aby przesunąć kursor w dół i sekwencję bajtów 9b 41 ( "\x9bA") przed każdą ), aby przesunąć kursor w górę.

r         e# Read a whitespace-separated token from STDIN.
:i        e# Replace each character by its code point.
          e#   '(' -> 40, ')' -> 41
"(. .A)"  e# Push the string "(\v \x9bA)".
S/        e# Split at spaces into ["(\v" "\x9bA)"].
f=        e# Select the corresponding chunks.
          e# Since arrays wrap around in CJam, ["(\v" "\x9bA)"]40= and 
          e# ["(\v" "\x9bA)"]41= select the first and second chunk, respectively.
Dennis
źródło
49

kod maszynowy x86, 39 34 33 30 29 bajtów

00000000  68 c3 b8 07 31 ff be 82  00 b3 a0 ad 4e 3c 28 7c  |h...1.......N<(||
00000010  f0 77 05 ab 01 df eb f3  29 df ab eb ee           |.w......)....|
0000001d

Montaż x86 dla DOS, z kilkoma sztuczkami:

    org 100h

section .text

start:
    ; point the segment ES to video memory
    ; (c3 is chosen so that it doubles as a "ret")
    push 0b8c3h
    pop es
    ; di: output pointer to video memory
    xor di,di
    ; si: input pointer from the command line
    mov si,82h
    ; one row=160 bytes (assume bh=0, as should be)
    mov bl,160
lop:
    ; read & increment si (assume direction flag clean)
    ; we read a whole word, so that later we have something nonzero to
    ; put into character attributes
    lodsw
    ; we read 2 bytes, go back 1
    dec si
    ; check what we read
    cmp al,'('
    ; less than `(`: we got the final `\n` - quit
    ; (we jump mid-instruction to get a c3 i.e. a ret)
    jl start+1
    ; more than `(`: assume we got a `)`
    ja closed
    ; write a whole word (char+attrs), so we end
    ; one position on the right
    stosw
    ; move down
    add di,bx
    ; rinse & repeat
    jmp lop
closed:
    ; move up
    sub di,bx
    ; as above
    stosw
    jmp lop

Ograniczenia :

  • zawsze drukuje, zaczynając od dolnej części ekranu, bez uprzedniego kasowania; clsprzed uruchomieniem jest niemal obowiązkowe;
  • kolory są brzydkie; jest to konsekwencja recyklingu następnego znaku jako atrybutów kolorów, aby zaoszczędzić dwa bajty tu i tam;
  • kod zakłada, bh=0a flaga kierunku wyczyść na początku, oba nieudokumentowane; OTOH, bxjest wyraźnie ustawiony na zero we wszystkich wariantach DOS, które widziałem (DosBox, MS-DOS 2, FreeDOS) i wszędzie, gdzie testowałem, flagi były już OK.

wprowadź opis zdjęcia tutaj

Matteo Italia
źródło
Właśnie to zweryfikowałem. Tak to działa. Czy na pewno musisz to zrobić cld?
FUZxxl
@FUZxxl: na DosBox działa dobrze nawet bez niego, ale patrząc na jego źródła mówi, że flagi są zachowane od tego, co zdarzyło się wcześniej w DOS i TRS, więc prawdopodobnie trzeba będzie grać bezpiecznie. W każdym razie byłby to tylko jeden bajt, prawdziwą wypłatą byłoby zabicie co najmniej jednego z tych dużych (= 4 bajty każdy) add/ sub.
Matteo Italia
Hm ... naprawdę nie mam pojęcia.
FUZxxl
Czy możesz się zmienić lopna loop?
mbomb007
@ mbomb007: może? Nie jestem pewien, czy nasmrozróżnia między loopetykietą a loopinstrukcją montażu, więc piszę tak, lopjak wszyscy inni.
Matteo Italia
28

J, 32 28 bajtów

To było zabawne.

0|:')(('&(i.-<:@+/\@i:){."0]

Wyjaśnienie

Oto jak działa to rozwiązanie, w tym wyjaśnienie, w jaki sposób zostało ono zagrane w golfa.

   NB. Let a be a test case
   a =. '((()())()(()(())()))'

   NB. level alterations
   _1 + ').(' i. a
1 1 1 _1 1 _1 _1 1 _1 1 1 _1 1 1 _1 _1 1 _1 _1 _1

   NB. absolute levels
   +/\ _1 + ').(' i. a
1 2 3 2 3 2 1 2 1 2 3 2 3 4 3 2 3 2 1 0

   NB. adjusted levels
   (+/\ _1 + ').(' i. a) - ')(' i. a
0 1 2 2 2 2 1 1 1 1 2 2 2 3 3 2 2 2 1 0

   NB. take level from end of each item of a and transpose
   |: a {."0~ _1 - (+/\ _1 + ').(' i. a) - ')(' i. a
(                  )
 (    )()(        ) 
  ()()    ()(  )()  
             ()     

   NB. code as a tacit verb
   [: |: ] {."0~ _1 - ([: +/\ _1 + ').(' i. ]) - ')(' i. ]

   NB. subtractions pulled into the prefix insert
   [: |: ] {."0~ (')(' i. ]) - [: <:@+/\ ').(' i. ]

   NB. i: instead of i. so we can use the same string constant
   [: |: ] {."0~ (')((' i. ]) - [: <:@+/\ ')((' i: ]

   NB. get rid of the caps
   0 |: ] {."0~ (')((' i. ]) - ')((' <:@+/\@i: ]

   NB. join the two usages of ')((' into a single dyadic phrase
   0 |: ] {."0~ ')((' (i. - <:@+/\@i:) ]

   NB. bond ')((' and flip arguments to {."0
   0 |: ')(('&(i. - <:@+/\@i:) {."0 ]
FUZxxl
źródło
1
Bardzo dobrze! Rozwiązanie jest pełne świetnych części!
randomra
1
(Zazwyczaj dodaję przykładowe wywołanie funkcji, aby niedoświadczeni użytkownicy również mogli ją wypróbować.)
randomra
To rozwiązanie powoduje ból głowy:')
Nic Hartley,
@QPaysTaxes Traktuję to jako komplement.
FUZxxl,
@FUZxxl To jest. Jest to także gra słów oparta na sekwencji znaków pojawiających się w odpowiedzi.
Nic Hartley,
15

C, 150 bajtów

t;f(char*c){char l=strlen(c)+1,o[l*l],*A=o,m=0;for(t=1;t<l*l;t++)o[t-1]=t%l?32:10;for(t=-1;*c;c++)A++[l*(*c-41?++t>m?m=t:t:t--)]=*c;A[m*l]=0;puts(o);}

To była szalona zabawa w golfa. Nadal nie jestem przekonany, że z tym skończyłem.

Definiujemy pojedynczą funkcję, fktóra pobiera ciąg jako dane wejściowe i wyjściowe na standardowe wyjście.

Przejdźmy przez kod, linia po linii:

/* t will represent the current depth of a parentheses. It must be an int. */
t;
f(char*c){
    //Our variables:
    char l=strlen(c)+1,    //The length of each row of output, including newlines
         o[l*l],           //The output string. It's way larger than it needs to be.
         *A=o,             //We need another pointer to keep track of things.
         m=0;              //The maximum depth recorded thus far.

    for(t=1;t<l*l;t++)     //For each character in our output...
        o[t-1]=t%l?32:10;  //If it's at the end of a line, make it '\n'. Else, ' '.
    for(t=-1;*c;c++)       //While we have an input string...
        //Perhaps a personal record for ugliest warning-less line...
        A++[l*(*c-41?++t>m?m=t:t:t--)]=*c;
    /* 
        A breakdown:
        A++        --> Go to the next *column* of output, after writing. 
                   --> There will only ever be one parentheses per output column.
        [l*(...)]  --> A[l*X] is the character in the current column at depth X.
        (*c-41?    --> If the character is a '('...    
        ++t>m?     --> Increment t *before* we write it. If this is a new highest depth
        m=t:       --> Set m to t, and set the whole expression to t.
        t:         --> If it's not a new highest depth, don't set m.
        t--)       --> If the character was a ')', decrement t *after* we write it.
        =*c        --> Write our output character to whatever the input read.
    */    

    A[m*l]=0; //The last character of the maximum-depth line should be null terminated.
    puts(o);  //Output!
}

Odpowiem na wszelkie pytania!

Wypróbuj program testowy online !

BrainSteel
źródło
Chcę pamiętać, że „char l = strlen (c) +1, o [l * l]” nie jest poprawny, ponieważ nie można zdefiniować tablicy o zmiennej wielkości, ale minęło 15 lat, odkąd próbowałem czegoś tego rodzaju w C.
Sparr
@Sparr Mój kompilator nawet nie rzuca ostrzeżenia. Uważam, że był to „oficjalnie” standard w C99. Spróbuję znaleźć odniesienie do tego.
BrainSteel
1
@Sparr Oto odniesienie.
BrainSteel,
Dzięki. Wygląda na to, że zmieniło się to około 15 lat (daj lub weź kilka lat temu) pod tym względem :)
Sparr
1
@CoolGuy To, ale przy kolejnych wywołaniach f, mnie zresetuje się do 0. To liczy się jako „niszczenie środowiska”, tutaj zakazane .
BrainSteel
15

Retina + Bash, 27 bajtów (14 + 10 + 3 = 27)

Wykorzystuje to ucieczkę ANSI:

\(
(\e[B
\)
\e[A)

Odpowiednik sed -e "s/(/(\\\e[B/g;s/)/\\\e[A)/g". \e[BKod Escape powoduje przesunięcie kursora na dół jeden rząd, i \e[Aśrodki przesunąć kursor o jeden wiersz, więc roztwór ten po prostu wkłada te kody przed i po początku i na końcu każdego pod-nawiasach. Dane wejściowe są przekazywane przez STDIN.

Będziesz musiał to nazwać, printf $(Retina ...)aby poprawnie wyświetlić dane wyjściowe.

Wynik

(((())))
(\e[B(\e[B(\e[B(\e[B\e[A)\e[A)\e[A)\e[A)
^C
amans:~ a$ printf "(\e[B(\e[B(\e[B(\e[B\e[A)\e[A)\e[A)\e[A)"
(      )amans:~ a$ 
 (    )
  (  )
   ()

((()())()(()(())()))
(\e[B(\e[B(\e[B\e[A)(\e[B\e[A)\e[A)(\e[B\e[A)(\e[B(\e[B\e[A)(\e[B(\e[B\e[A)\e[A)(\e[B\e[A)\e[A)\e[A)
^C
amans:~ a$ printf "(\e[B(\e[B(\e[B\e[A)(\e[B\e[A)\e[A)(\e[B\e[A)(\e[B(\e[B\e[A)(\e[B(\e[B\e[A)\e[A)(\e[B\e[A)\e[A)\e[A)"
(                  )amans:~ a$ 
 (    )()(        )
  ()()    ()(  )()
             ()
użytkownik22723
źródło
1
Cóż, nieźle! Gdybyś mógł wskazać konkretny terminal, który nie potrzebuje printf, byłoby świetnie. W przeciwnym razie myślę, że dodanie | printfdo liczby bajtów byłoby sprawiedliwe .
Martin Ender
@ MartinBüttner Powinno to być printf $()lub printf $(Retina ).
jimmy23013
1
Co to za Retina?
FUZxxl
2
@FUZxxl To mój własny język programowania oparty na wyrażeniach regularnych. Zobacz GitHub .
Martin Ender
2
Dlaczego \eplus printf? Możesz po prostu umieścić znaki kontrolne we wzorze zastępczym.
Dennis
15

TI-BASIC, 69 60 56 55 bajtów

Dotyczy to rodziny kalkulatorów TI-83 + / 84 +, chociaż zostało napisane w 84+ C Silver Edition.

Program wyświetla się jako większy na podstawie obliczeń VAT + informacje o rozmiarze. Ponadto jest tu ponad 56 znaków; powodem jest 56 bajtów, ponieważ wszystkie polecenia zawierające więcej niż jeden znak są skompresowane do tokenów o rozmiarze jednego lub dwóch bajtów.

Input Str1
1→B
For(A,1,length(Str1
sub(Str1,A,1→Str2
Ans="(
Output(B+Ans,A,Str2
B-1+2Ans→B
End

Ogolono kolejny bajt dzięki Thomas-kwa ! (także od niego był skok z 60 na 56.)

MI Wright
źródło
4
Ahhh, mój pierwszy język programowania. Dzięki za tęsknotę, haha.
Alex Pritchard
1
Nadal programuję TI dla licealnej klasy matematycznej, bardzo przydatne, aby mieć wbudowane formuły, które obliczą dla ciebie testy i zadania.
Elias Benevedes,
1
Jeśli zmienisz sytuację, możesz użyć tej cos(piAnssztuczki, aby zapisać kolejny bajt.
lirtosiast
9

Python 2, 115 bajtów

def f(L,n=0,O=()):
 for c in L:n-=c>"(";O+=" "*n+c,;n+=c<")"
 for r in map(None,*O):print"".join(c or" "for c in r)

Wywołaj jak f("((()())()(()(())()))"), a wyjście jest do STDOUT.

Wyjaśnienie

Zaczynamy od n = 0. Dla każdego znaku w linii wejściowej:

  • Jeśli char jest (, dodamy nspacje, a następnie zwiększamyn
  • Jeśli char jest ), zmniejszamy, na następnie dodajemy nspacje

Wynik jest następnie spakowany i wydrukowany. Zauważ, że zipzamki błyskawiczne Pythona pasują do długości najkrótszego elementu, np

>>> zip([1, 2], [3, 4], [5, 6, 7])
[(1, 3, 5), (2, 4, 6)]

Zwykle używa się itertools.zip_longest( izip_longest), jeśli chcemy zipuzupełnić długość najdłuższego elementu.

>>> import itertools
>>> list(itertools.izip_longest([1, 2], [3, 4], [5, 6, 7]))
[(1, 3, 5), (2, 4, 6), (None, None, 7)]

Ale w Pythonie 2 to zachowanie można symulować, odwzorowując None:

>>> map(None, [1, 2], [3, 4], [5, 6, 7])
[(1, 3, 5), (2, 4, 6), (None, None, 7)]

Python 3, 115 bajtów

L,d,*O=input(),0
for i,c in enumerate(L):b=c>"(";O+="",;O[d-b]=O[d-b].ljust(i)+c;d-=b*2-1
for l in O:l and print(l)

Bez zamka błyskawicznego, wystarczy odpowiednie wypełnienie ljust. Ten wydaje się mieć pewien potencjał golfowy.

Sp3000
źródło
8

R, 151 127 znaków

S=strsplit(scan(,""),"")[[1]];C=cumsum;D=c(C(S=="("),0)-c(0,C(S==")"));for(j in 1:max(D)){X=S;X[D!=j]=' ';cat(X,sep='',fill=T)}

Z wcięciami i znakami nowej linii:

S=strsplit(scan(,""),"")[[1]]
C=cumsum
D=c(C(S=="("),0)-c(0,C(S==")"))
for(j in 1:max(D)){
    X=S
    X[D!=j]=' '
    cat(X,sep='',fill=T)
    }

Stosowanie:

> S=strsplit(scan(,""),"")[[1]];C=cumsum;D=c(C(S=="("),0)-c(0,C(S==")"));for(j in 1:max(D)){X=S;X[D!=j]=' ';cat(X,sep='',fill=T)}
1: ()(())((()))(())()
2: 
Read 1 item
()(  )(    )(  )()
   ()  (  )  ()   
        ()        
> S=strsplit(scan(,""),"")[[1]];C=cumsum;D=c(C(S=="("),0)-c(0,C(S==")"));for(j in 1:max(D)){X=S;X[D!=j]=' ';cat(X,sep='',fill=T)}
1: ((()())()(()(())()))
2: 
Read 1 item
(                  )
 (    )()(        ) 
  ()()    ()(  )()  
             ()     

Odczytuje ciąg jako stdin, dzieli go jako wektor pojedynczych znaków, oblicza skumulowaną sumę (i )odejmuje pierwsze z drugim (z opóźnieniem), obliczając w ten sposób „poziom” każdego nawiasu. Następnie drukuje na standardowe wyjście, dla każdego poziomu, albo w nawiasach, albo spacją.

Dzięki @MickyT za pomoc w znacznym skróceniu!

plannapus
źródło
2
+1 Ładne i eleganckie rozwiązanie. Można zapisać 6 zastępując for(i in n)cat(ifelse(D[i]-j," ",S[i]));cat("\n")z X=S;X[which(D!=j)]=' ';cat(X,sep='',fill=T). To nnie jest tak naprawdę wymagane, ale trzeba by trochę zmienić część sumy. D=c(C(S=="("),0)-c(0,C(S==")"));obniżając go do 135.
MickyT
@MickyT wow dzięki! nie myślałem o tym. whichnie jest tu tak naprawdę konieczne ( D!=jponieważ jest już wektorem wartości logicznych umożliwiających indeksowanie). Nie wiedziałem, że argumenty fillza cat, to sprytne sztuczki! Dzięki, że skróciłem go o zdumiewające 24 znaki !!
plannapus
8

C, 58 53 52 51 49 bajtów

Wykorzystuje sekwencje specjalne ANSI do przesunięcia pozycji kursora.

f(char*s){while(*s)printf(*s++&1?"\e[A)":"(\v");}

Jeśli nie używasz gcc lub innego kompilatora, który obsługuje \e, możesz go zastąpić \x1Bw sumie 2 dodatkowymi bajtami. \e[Aprzesuwa kursor o jeden wiersz w górę i \e[Bprzesuwa kursor o jeden wiersz w dół. Nie trzeba używać, \e[Baby przejść w dół o jeden wiersz, ponieważ jest o dwa bajty krótszy, aby użyć znaku tabulacji pionowej ASCII 0xBlub \v.

Zakłada się, że łańcuch wejściowy składa się tylko z (zrównoważonych) nawiasów, więc sprawdzenie parzystości znaku za pomocą &1, wystarcza do rozróżnienia między (i ).

CL-
źródło
7

Pip, 53 bajty

Pip jest językiem golfa mojego wynalazku. Pierwsza wersja została opublikowana w sobotę, więc mogę ją oficjalnie wypróbować! Poniższe rozwiązanie nie jest zbyt konkurencyjne ze względu na języki gry w golfa, ale częściowo dlatego, że nie wdrożyłem jeszcze takich rzeczy jak zip i max.

z:{aEQ'(?++v--v+1}MaW(o:{z@++v=i?as}Ma)RMs{Pov:-1++i}

Oczekuje ciąg nawiasów jako argument wiersza polecenia.

Wersja „bez golfa”:

z:{
   a EQ '( ?
    ++v
    --v+1
  } M a
W (o:{
      z @ ++v = i ?
       a
       s
     } M a
  ) RM s
{
 P o
 v:-1
 ++i
}

Wyjaśnienie:

W przeciwieństwie do większości języków golfowych, Pip jest niezbędny dla operatorów infix, więc składnia jest nieco bliższa C i jej pochodnym. Pożycza również pomysły z programowania funkcjonalnego i tablicowego. Zobacz repozytorium w celu uzyskania dalszej dokumentacji.

Najpierw program generuje listę głębokości (zapisując ją z) poprzez mapowanie funkcji na łańcuch wejściowy a. Zmienna globalnav śledzi bieżący poziom. (Zmienne a-gw Pip są zmiennymi lokalnymi dla funkcji, ale h-zsą globalne. vJest przydatne, ponieważ jest wstępnie zainicjalizowane na -1.)

Następnie używamy Wpętli kreskowej do generowania i drukowania każdej linii, aż wygenerowana linia będzie się składać ze wszystkich spacji. vjest teraz używany do kolumn i iwierszy. {z@++v=i?as}Funkcja, wielokrotnie mapowane do oryginalnego wejściowego łańcucha, testy czy bieżąca linia ipasuje do linii prądu nawias ma być włączony (zapisane na zliście). Jeśli tak, użyj nawiasu (a ); jeśli nie, użyj s(zainicjalizowany do spacji). Rezultatem końcowym jest to, że do każdej iteracji ozostaje przypisana lista znaków równoważna do następnego wiersza wyniku.

Aby sprawdzić, czy powinniśmy kontynuować zapętlanie, sprawdzamy, czy o ze wszystkimi spacjami RMd jest puste. Jeśli nie, wydrukuj go (który domyślnie konkatenuje wszystko razem jak w CJam), zresetuj numer kolumny na -1 i zwiększ numer wiersza.

(Ciekawostka: na początku miałem 51-bajtowe rozwiązanie ... które nie działało, ponieważ wykryło błąd w tłumaczu.)

DLosc
źródło
7

Pyth, 31 bajtów

VzJs.e?YqN-/<zk\(/<zhk\)dzI-JdJ

Wypróbuj online.

-/<zk\(/<zhk\): Znajduje odpowiedni poziom dla aktualnej pozycji postaci.

?YqN-/<zk\(/<zhk\)d: Spacja, jeśli odpowiedni poziom nie jest bieżącym poziomem, w przeciwnym razie obecny znak.

Js.e?YqN-/<zk\(/<zhk\)dz: Wygeneruj ciąg, zapisz go w J.

I-JdJ: Jeśli Jto nie wszystkie spacje, wydrukuj je.

Vz: zCzasy pętli .

isaacg
źródło
6

GNU Bash + coreutils + tiret, 135

eval paste "`tr '()' {}|indent -nut -i1 -nbap|sed 's/.*/<(fold -1<<<"&")/'|tr '
' \ `"|expand -t2|sed 'y/{}/()/;s/\(.\) /\1/g;s/ \+$//'

Wejście / wyjście przez STDIN / STDOUT:

$ ./telescopic.sh <<< "(()(()())()((())))(())"
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
$ 

indentwykonuje większość ciężkiego podnoszenia, ale musi pracować z aparatami ortodontycznymi zamiast parens. Reszta to modyfikacja tej odpowiedzi w celu transponowania wyniku indent.

Cyfrowa trauma
źródło
5

Python 2, 92

def f(s,i=0,z=''):
 for x in s:b=x>'(';z+=[' ',x][i==b];i-=2*b-1
 if'('in z:print z;f(s,i-1)

Drukuje linia po linii. Dla danego numeru wiersza i(a właściwie jego negacji) przechodzi przez ciąg wejściowy si tworzy nowy ciąg, zktóry zawiera tylko znaki sgłębokości i. Odbywa się to poprzez zwiększanie lub zmniejszanie w icelu śledzenia bieżącej głębokości oraz dodawanie bieżących znaków, gdy ijest 0dostosowany do typu paren, lub w inny sposób dodawanie spacji.

Następnie drukuje i przechodzi do następnego, ichyba że bieżąca linia zawiera wszystkie spacje. Zauważ, że ponieważ pareny są zrównoważone, ipętla po jest taka sama jak na początku.

Python 3 byłby taki sam, gdyby nie znak dla print(z).

xnor
źródło
5

oszukiwanie :( Retina + TeX, N bajtów oszukiwanie :(

Działa to tylko wtedy, gdy renderujesz (?) Dane wyjściowe za pomocą MathJax lub innego TeXa, który jest obecnie wyłączony dla tego SE :(

\(
({
\)
})
\{\(
_{(

Każda linia powinna znajdować się w innym pliku, ale możesz to przetestować za pomocą Retina -e "\(" -e "({" -e "\)" -e "})" -e "\{\(" -e "_{("(lub równoważnego polecenia sed sed -e "s/(/({/g;s/)/})/g;s/{(/_{(/g"). Dane wejściowe są przekazywane przez STDIN.

Działa to poprzez umieszczenie zawartości każdej pary nawiasów w nawiasach klamrowych, a następnie indeksowanie wszystkich elementów w nich zawartych.

Wynik

(((())))
(_{(_{(_{({})})})})

()(())((()))(())()
({})(_{({})})(_{(_{({})})})(_{({})})({})

((()())()(()(())()))
(_{(_{({})({})})({})(_{({})(_{({})})({})})})

Wyjście TeX

użytkownik22723
źródło
1
Pochlebia mi to, że użyłeś Retiny, i to jest fajne myślenie nieszablonowe, ale nie do końca tak powinno wyglądać wyjście. ;) W szczególności narusza to alternatywne sformułowanie „Innym sposobem spojrzenia na to jest to, że nawiasy na głębokości n są przesuwane do linii n, przy jednoczesnym zachowaniu ich pozycji poziomej”. Byłbym pod wielkim wrażeniem czystego, zgodnego z regułami rozwiązania Retina i mógłbym za to wynagrodzić. ;)
Martin Ender
In total the lines must not be longer than twice the length of the input string. Zmiana linii 2 na (\,{i linii 4 na }\,)oznacza, że ​​dane wyjściowe pasują do tego (chociaż głębokość pionowa jest nadal nieprawidłowa: ()
user22723,
Udało mi się stworzyć rozwiązanie zgodne z
regułami:)
1
Dobra robota. To chyba oznacza, że ​​możesz teraz usunąć tę podstępną odpowiedź. ;)
Martin Ender
5

Java, 232 226 224 222 bajtów

Wersja golfowa:

int i,j,k,l,m,a[];void f(String s){a=new int[s.length()];j=a.length;for(k=0;k<j;){a[k]=s.charAt(k++)<41?i++:--i;m=m<i?i:m;}for(k=0;k<m;k++)for(l=0;l<j;)System.out.print(k==a[l++]?i++%2<1?'(':l==j?")\n":')':l==j?'\n':' ');}

Długa wersja:

int i, j, k, l, m, a[];
void f(String s) {
    a = new int[s.length()];
    j = a.length;
    for (k = 0; k < j;) {
        a[k] = s.charAt(k++) < 41 ? i++ : --i;
        m = m < i ? i : m;
    }
    for (k = 0; k < m; k++)
        for (l = 0; l < j;)
            System.out.print(k == a[l++] ? (i++ % 2 < 1 ? '(' : (l == j ? ")\n" : ')')) : (l == j ? '\n':' '));
}

Łańcuch wejściowy jest najpierw analizowany, szukając „(” i „)”, aby dodać / odjąć licznik i zapisać jego wartość, określając, jak daleko nawiasy powinny się znaleźć w tablicy, a także śledzić, jak głęboko schodzi. Następnie tablica jest analizowana; nawiasy z mniejszymi wartościami są drukowane jako pierwsze i będą kontynuować drukowanie linia po linii, aż do osiągnięcia maksimum.

Prawdopodobnie później znajdę sposoby na grę w golfa.

TNT
źródło
5

Javascript / ES6, 97 znaków

f=s=>{for(n in s){m=o=d='';for(c of s)o+=n==(c<')'?d++:--d)?c:' ',m=m<d?d:m;n<m&&console.log(o)}}

Stosowanie

f("(()(()())()((())))(())")

Wyjaśnienie

fn=str=>{                          // accepts string of parenthesis
  for(line in str){                // repeat process n times where n = str.length
    max=output=depth='';           // max: max depth, output: what to print, depth: current depth
    for(char of str)               // iterate over chars of str
      output+=
        line==(char<')'?depth++:--depth)? // update depth, if line is equal to current depth
        char:' ',                  // append either '(', ')', or ' '
        max=max<depth?depth:max;   // update max depth
    line<max&&console.log(output)  // print if current line is less than max depth
  }
}
Dendrobium
źródło
Zamiast tego n<m?console.log(o):0możesz użyć, n<m&&console.log(o)który oszczędza 1 bajt.
Ismael Miguel
4

CJam, 43 41 36 bajtów

Nie za bardzo w golfa (tak myślę), ale oto moja pierwsza próba:

l:L,{)L<)_')=@~zS*\+}%_$0=,f{Se]}zN*

Jak to działa

Używam bardzo poręczny, że )i (w CJam znaczy zwiększania i zmniejszania odpowiednio. Dlatego po prostu oceniam nawiasy, aby uzyskać głębokość.

l:L,{)L<)_')=@~zS*\+}%_$0=,f{Se]}zN*
l:L,{                    }%                "Store input line in L and iterate over [0,L)";
     )L<                                   "substr(L, 0, iterator + 1)";
        )                                  "Slice off the last character to stack";
         _')=                              "Put 0 on stack if the sliced character is (,
                                            else 1 if sliced character is )";
             @~                            "bring forth the remaining
                                            brackets after slicing and evaluate them";
               zS*                         "Stack has negative depth number, take absolute
                                            value and get that many spaces";
                  \+                       "Prepend to the sliced character";
                      _$0=,                "Get the maximum depth of brackets";
                           f{Se]}          "Pad enough spaces after each string to match
                                            the length of each part";
                                 zN*       "Transpose and join with new lines";

Wypróbuj online tutaj

Optymalizator
źródło
4

Oktawa, 85 znaków

function r=p(s)i=j=0;for b=s k=b==40;k&&++j;t(j,++i)=9-k;k||--j;r=char(t+32);end;end

Jest to optymalizacja naiwnego podejścia, co w rzeczywistości jest całkiem naturalne dla Matlaba i Octave:

function r=p(s)
i=j=1;
for b=s
 if b=='(' t(++j,i++)='(' else t(j--,i++)=')' end; end; t(~t)=' '; r=char(t);
end;

Tabela t może nawet jeszcze nie istnieć, a my możemy od razu przypisać dowolny element, i przekształca się w najmniejszy wymiar wymagany do istnienia tego elementu, co jest dość wygodne.

pawel.boczarski
źródło
4

Perl, 91 89 88 84 80 79 bajtów

$t=<>;{$_=$t;s/\((?{$l++})|.(?{--$l})/$^R==$c?$&:$"/ge;print,++$c,redo if/\S/}
  • $ t to ciąg wejściowy.
  • $ c to głębokość, którą chcemy wydrukować w bieżącym wierszu.
  • $ l to głębokość, na jakiej jesteśmy po spotkaniu z paren.
  • $ l jest aktualizowany w blokach kodu osadzonego w wyrażeniach regularnych .
  • $ ^ R jest wynikiem najnowszego bloku kodu.
Helios
źródło
4

Haskell, 154 bajty

f h('(':s)=h:f(h+1)s;f h(')':s)=(h-1):f(h-1)s;f _ _=[]
main=interact$ \s->unlines[[if i==h then c else ' '|(c,i)<-zip s l]|let l=f 0 s,h<-[0..maximum l]]

ten sam pomysł jak inne rozwiązanie Haskell, ale nieco krótszy. - Stosowanie:

echo  '(((())())(()))' | runghc Golf.hs
d8d0d65b3f7cf42
źródło
3

J, 46

Nie tak świetne jak inne „języki gry w golfa”, ale w mojej obronie: J jest okropny ze strunami.

[:|:(((,~(' '#~]))"0)(0,2%~[:+/\2+/\1-'(('i.]))~

Pobiera ciąg jako dane wejściowe dla funkcji. Jest też prawdopodobnie lepszy sposób na zrobienie tego w J.

Stosowanie:

   f=:[:|:(((,~(' '#~]))"0)(0,2%~[:+/\2+/\1-'(('i.]))~
   f '(()(()())()((())))(())'
(                )(  )
 ()(    )()(    )  () 
    ()()    (  )      
             ()       
.ıʇǝɥʇuʎs
źródło
Zobacz moją odpowiedź na inny sposób robienia tego w J.
FUZxxl,
3
Osobiście uważam, że J doskonale nadaje się do łańcuchów. Musisz tylko myśleć z tablicami.
FUZxxl,
3

Ruby, 119 115 114

->s{r=[""]*s.size
d=0
s.chars.map{|l|r.map!{|s|s+" "}
b=l>"("?1:0
d-=b
r[d][-1]=l
d+=1-b}.max.times{|i|puts r[i]}}

Wyjaśnienie:

->s{r=[""]*s.size  # Take an array of strings big enough
d=0                # This will contain the current depth
s.chars.map{|l|r.map!{|s|s+" "}  # Add a new space to every array
b=l>"("?1:0       # Inc/Dec value of the depth
d-=b               # Decrement depth if we are at a closing paren
r[d][-1]=l         # Set the corresponding space to the actual open/close paren
d+=1-b             # Increment the depth if we are at a opening paren
}.max.times{|i|puts r[i]}}  # Print only the lines up to the max depth
rorlork
źródło
3

Java, 233 214 bajtów

void f(String s){int p,x,d,l=s.length();char c,m[]=new char[l*l];java.util.Arrays.fill(m,' ');p=x=0;while(x<l){d=(c=s.charAt(x))==40?p++:--p;m[d*l+x++]=c;}for(x=0;x<l*l;x++)System.out.print((x%l==0?"\n":"")+m[x]);}

Zębaty:

void f(String s){
    int p, x, d, l = s.length();
    char c, m[] = new char[l * l];
    java.util.Arrays.fill(m, ' ');
    p = x = 0;
    while (x < l){
        d = (c = s.charAt(x)) == 40
                ? p++
                : --p;
        m[d * l + x++] = c;
    }
    for (x = 0; x < l * l; x++)
        System.out.print((x % l == 0 ? "\n" : "") + m[x]);
}

Wydaje mi się, że ostatnią pętlę można skrócić, ale pozostawię to jako ćwiczenie dla czytelnika. ;-)


Stara, 233 bajty odpowiedź:

void f(String s){int y=s.length(),x=0;char[][]m=new char[y][y];for(char[]q:m)java.util.Arrays.fill(q,' ');y=0;for(char c:s.toCharArray())if(c=='(')m[y++][x++]=c;else m[--y][x++]=c;for(char[]q:m)System.out.println(String.valueOf(q));}

Zębaty:

static void f(String s) {
    int y = s.length(), x = 0;
    char[][] m = new char[y][y];
    for(char[] q : m)
        java.util.Arrays.fill(q, ' ');
    y = 0;
    for(char c : s.toCharArray())
        if(c == '(')
            m[y++][x++] = c;
        else
            m[--y][x++] = c;
    for(char[] q : m)
        System.out.println(String.valueOf(q));
}
ArturoTena
źródło
Wiem, że minął już ponad rok, ale „Wydaje mi się, że ostatnią pętlę można skrócić, ale zostawię to jako ćwiczenie dla czytelnika. ;-)”; naprawdę masz rację. To może być zmieniony z for(x=0;x<l*l;x++)System.out.print((x%l==0?"\n":"")+m[x]);do for(x=0;x<l*l;)System.out.print((x%l==0?"\n":"")+m[x++]);do -1 bajt. Możesz także zaoszczędzić 2 bajty, usuwając je p=x=0i po prostu używaj int p=0,x=0,przy inicjalizacji pól. W sumie staje się 211 bajtów .
Kevin Cruijssen
3

C #, 195 bajtów

Najpierw spróbuj golfa - krzycz, jeśli zrobiłem coś złego.

Alternatywna wersja C # wykorzystująca SetCursorPosition i pracująca od lewej do prawej, przyjmująca dane wejściowe jako argument linii poleceń.

using System;class P{static void Main(string[] a){Action<int,int>p=Console.SetCursorPosition;int r=0,c=0;foreach(var x in a[0]){r+=x==')'?-1:0;p(c,r);Console.Write(x);r+=x=='('?1:0;p(c,r);c++;}}}

Pomyślałem, że fajnie byłoby dopasować pozycję zapisu na podstawie otwartych / zamkniętych paren, a nie pełnych linii. Zamknij paren przesuwa pozycję w górę przed napisaniem; open paren przesuwa go w dół po napisaniu. Działanie SetCursorPosition oszczędza pięć bajtów. Przeniesienie kursora do następnego wiersza po wyjściu zająłoby trochę więcej.

using System;
class P
{
    static void Main(string[] a)
    {
        Action<int, int> p = Console.SetCursorPosition;
        int r = 0, c = 0;
        foreach (var x in a[0])
        {            
            r += x == ')' ? -1 : 0;
            p(c, r);
            Console.Write(x);
            r += x == '(' ? 1 : 0;
            p(c, r);
            c++;
        }
    }
}
Jeremy Murray
źródło
3

Partia, 356 335 bajtów

Wiem, że istnieje już rozwiązanie Batch dla tego wyzwania, ale jest ono znacznie bardziej rozbudowane i wydaje się, że przyjmuje inne podejście. Co najważniejsze, drugie rozwiązanie wsadowe zawiera co najmniej jedno polecenie programu PowerShell; to rozwiązanie nie.

@echo off
setlocal enabledelayedexpansion
set p=%1
set p=%p:(="(",%
set p=%p:)=")",%
set c=0
for %%a in (%p%)do (if ")"==%%a set/ac-=1
set d=!d!,!c!%%~a
if "("==%%a set/ac+=1&if !c! GTR !m! set m=!c!)
set/am-=1
for /l %%a in (0,1,!m!)do (for %%b in (!d!)do (set t=%%b
if "%%a"=="!t:~0,-1!" (cd|set/p=!t:~-1!)else (cd|set/p=. ))
echo.)

Znak U+0008kropki () jest umieszczony w przedostatniej linii po kropce (linia 12, kolumna 57). Nie jest to widoczne w zamieszczonym tutaj kodzie, ale jest uwzględnione w liczbie bajtów.

ankh-morpork
źródło
Ktoś inny faktycznie wysyła odpowiedź w partii - ładna +1.
niepomyślnie
3

Partia, 424 bajty

@echo off
setLocal enableDelayedExpansion
set s=%1
set a=1
:c
if defined s (set/ac+=1
set "z="
if "%s:~0,1%"=="(" (set "1=(")else (set/aa-=1
set "1=)")
for %%a in (!a!)do for /f usebackq %%b in (`powershell "'!l%%a!'".Length`)do (set/ay=!c!-%%b
for /l %%a in (1,1,!y!)do set z= !z!
set "l%%a=!l%%a!!z!!1!")
if "%s:~0,1%"=="(" set/aa+=1
if !a! GTR !l! set/al=!a!-1
set "s=%s:~1%"
goto c)
for /l %%a in (1,1,!l!)do echo !l%%a!

Bez golfa:

@echo off
setLocal enableDelayedExpansion

set s=%1
set a=1
set c=0
set l=0

:c
if defined s (
    set /a c+=1
    set "z="
    if "%s:~0,1%"=="(" (
        set "1=("
    ) else (
        set /a a-=1
        set "1=)"
    )
    for %%a in (!a!) do for /f usebackq %%b in (`powershell "'!l%%a!'".Length`) do (
        set /a y=!c!-%%b
        for /l %%a in (1,1,!y!) do set z= !z!
        set "l%%a=!l%%a!!z!!1!"
    )
    if "%s:~0,1%"=="(" set /a a+=1
    if !a! GTR !l! set /a l=!a!-1
    set "s=%s:~1%"
    goto c
)

for /l %%a in (1,1,!l!) do echo !l%%a!

Przykład:

h:\>par.bat (((())())(()))
 (            )
  (      )(  )
   (  )()  ()
    ()
nieprzyzwoity
źródło
3

C 118 117 bajtów

Kolejna odpowiedź w C, ale moja jest krótsza.

c;d;main(m,v)int**v;{while(d++<m){char*p=v[1];while(*p)c+=*p==40,putchar(c-d?*p:32),m=c>m?c:m,c-=*p++==41;puts("");}}

Wersja bez golfa:

c; /* current depth */
d; /* depth to print in current row */
main(m,v)int**v;{
    while(d++<m) {
        char*p=v[1];
        while(*p){
            c+=*p==40;           /* 40 = '(' */
            putchar(c-d?*p:32); /* 32 = ' ' (space) */
            m=c>m?c:m;           /* search maximum depth */
            c-=*p++==41;         /* 41 = ')' */
        }
        puts("");
    }
}

I to działa!

% ./telescope '()(())((()))(())()'
()(  )(    )(  )()
   ()  (  )  ()
        ()
% ./telescope '((()())()(()(())()))'
(                  )
 (    )()(        )
  ()()    ()(  )()
             ()
MarcDefiant
źródło
1
Dość eleganckie rozwiązanie, jednak putchar(c-d?32:*p)jest o jedną postać krótsze niż putchar(c==d?*p:32).
pawel.boczarski
2

Haskell, 227 bajtów

n _ []=[]
n h ('(':r)=('(',h):n(h+1)r
n d (')':r)=let h=d-1 in(')',h):n h r
m n []=n
m n ((_,h):r)=m(max h n)r
p s=let v=n 0 s;h=m 0 v;in map(\d->map(\(b,l)->if l==d then b else ' ')v)[0..h]
main=fmap p getLine>>=mapM_ putStrLn
Lista Jeremy
źródło
1
Możesz zaoszczędzić kilka miejsc za pomocą operatorów: np. n#[]Zamiast m n [].
Franky
2

Perl, 76 bajtów

$a[/\(/?$l++:--$l][$i++]=$_ for split//,<>;print map{$_||' '}@$_,"\n"for@a

Nie use stricttutaj :)

Alexander-Brett
źródło
2

Lex, 94 bajty

Zależy od kodów konsoli Linux. Za pomocą gcc możesz wyciąć cztery bajty, zastępując oba wystąpienia \33rzeczywistym znakiem ucieczki.

%%
 int p[2]={0};
\( printf("(\33D");++p[!*p];
\) printf("\33M)");--*p;
\n while(p[1]--)ECHO;

Aby skompilować i uruchomić:

$ flex -o telescopic.c telescopic.l
$ gcc -o telecopic telescopic.c -lfl
$ ./telescopic
(()(()())()((())))(())
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
--- type ctrl-D ---
rici
źródło