Kurung Teleskopik

79

Pertimbangkan string kurung yang tidak kosong dengan benar:

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

Kita dapat membayangkan bahwa setiap pasangan kurung mewakili cincin dalam konstruksi teleskopik yang runtuh . Jadi mari kita memperluas teleskop:

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

Cara lain untuk melihatnya adalah bahwa tanda kurung di kedalaman n dipindahkan ke garis n , sambil menjaga posisi horizontal mereka.

Tugas Anda adalah mengambil string kurung yang seimbang dan menghasilkan versi yang diperluas.

Anda dapat menulis suatu program atau fungsi, mengambil input melalui STDIN (atau yang setara terdekat), argumen baris perintah atau parameter fungsi, dan menghasilkan output melalui STDOUT (atau yang terdekat terdekat), mengembalikan nilai atau parameter fungsi (keluar).

Anda dapat mengasumsikan bahwa string input valid, yaitu hanya terdiri tanda kurung, yang seimbang dengan benar.

Anda dapat mencetak spasi tambahan di setiap baris, tetapi tidak lebih banyak spasi dari yang diperlukan. Total garis harus tidak lebih dari dua kali panjang string input. Anda dapat secara opsional mencetak satu baris baru.

Contohnya

Selain contoh di atas, berikut adalah beberapa kasus uji lagi (input dan output dipisahkan oleh garis kosong).

()

()
(((())))

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

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

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

Tantangan Terkait:

  • String Topografi , yang meminta Anda untuk menghasilkan apa yang pada dasarnya adalah pelengkap dari output dalam tantangan ini.
  • Code Explanation Formatter , generalisasi luas gagasan dalam tantangan ini, baru-baru ini diposting oleh PhiNotPi. (Sebenarnya, deskripsi asli PhiNotPi tentang idenya adalah yang menginspirasi tantangan ini.)

Papan peringkat

Huh, ini mendapat cukup banyak partisipasi, jadi di sini ada Stack Snippet untuk menghasilkan leaderboard biasa dan gambaran umum pemenang berdasarkan bahasa.

Untuk memastikan bahwa jawaban Anda muncul, silakan mulai jawaban Anda dengan tajuk utama, menggunakan templat Penurunan harga berikut:

# Language Name, N bytes

di mana Nukuran kiriman Anda. Jika Anda meningkatkan skor Anda, Anda bisa menyimpan skor lama di headline, dengan mencoretnya. Misalnya:

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

Martin Ender
sumber
17
Judul alternatif: De-Lisp-ify a string. : P
Alex A.
1
Apakah ada batasan pada warna output?
Matteo Italia
1
@ MartinBüttner: Nevermind, saya menemukan cara yang lebih bersih; anggap saja ide saya sebelumnya akan mencukur satu byte meninggalkan semua tanda kurung tertutup berkedip biru di atas cyan ... :-)
Matteo Italia
8
@MatteoItalia oh tuhan, aku senang itu tidak terjadi. ;)
Martin Ender
12
@MatteoItalia: Posting versi itu! Layak dilihat.
user2357112

Jawaban:

8

CJam, 17 16 15 byte

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

Di atas adalah dump xxd reversibel, karena kode sumber berisi karakter VT yang tidak dapat dicetak (0x0b) dan CSI (0x9b).

Seperti jawaban ini , ia menggunakan urutan pelarian ANSI , tetapi juga menggunakan tab vertikal dan mencetak karakter kontrol secara langsung untuk menghindari penggunaan printf .

Ini memerlukan terminal teks video pendukung, yang mencakup sebagian besar emulator terminal non-Windows.

Uji coba

Kita harus mengatur variabel shell LANG dan pengkodean terminal emulator ke ISO 8859-1. Yang pertama dicapai dengan mengeksekusi

$ LANGsave="$LANG"
$ LANG=en_US

Juga, sebelum mengeksekusi kode aktual, kami akan menonaktifkan prompt dan menghapus layar.

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

Ini memastikan output ditampilkan dengan benar.

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

Untuk mengembalikan LANG dan prompt, jalankan ini:

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

Bagaimana itu bekerja

Kami menyisipkan tab vertikal setelah masing-masing ( untuk memindahkan kursor ke bawah dan urutan byte 9b 41 ( "\x9bA") sebelum masing-masing ) untuk memindahkan kursor ke atas.

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
sumber
49

kode mesin x86, 39 34 33 30 29 byte

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

rakitan x86 untuk DOS, dengan beberapa trik:

    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

Keterbatasan :

  • selalu dicetak mulai dari bagian bawah layar, tanpa menghapus terlebih dahulu; a clssebelum menjalankan hampir wajib;
  • warnanya jelek; itulah konsekuensi mendaur ulang karakter berikutnya sebagai atribut warna untuk menghemat dua byte di sana-sini;
  • kode mengasumsikan bh=0dan tanda arah jelas saat start, keduanya tidak berdokumen; OTOH, bxsecara eksplisit diatur ke nol di semua varian DOS yang saya lihat (DosBox, MS-DOS 2, FreeDOS), dan di mana-mana saya menguji flag-flag yang sudah OK.

masukkan deskripsi gambar di sini

Matteo Italia
sumber
Baru saja memverifikasi ini. Ya itu berhasil. Apakah Anda yakin perlu melakukannya cld?
FUZxxl
@ FuZxxl: pada DosBox berfungsi dengan baik bahkan tanpa itu, tetapi melihat sumbernya mengatakan bahwa bendera disimpan dari apa pun yang terjadi di DOS dan di TRS sebelumnya, jadi mungkin itu akan diperlukan untuk bermain aman. Bagaimanapun, itu hanya satu byte, hasil sebenarnya adalah membunuh setidaknya satu dari yang besar (= masing-masing 4 byte) add/ sub.
Matteo Italia
Hm ... tidak tahu, sungguh.
FUZxxl
Anda dapat mengubah lopke loop?
mbomb007
@ mbomb007: mungkin? Saya tidak yakin apakah nasmmemisahkan antara loopsebagai label dan loopinstruksi perakitan, jadi saya hanya menulis lopseperti yang dilakukan orang lain.
Matteo Italia
28

J, 32 28 byte

Ini menyenangkan.

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

Penjelasan

Ini adalah cara kerja solusi ini, termasuk penjelasan tentang cara golfnya.

   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
sumber
1
Sangat bagus! Solusinya penuh dengan bagian-bagian hebat!
randomra
1
(Saya biasanya menambahkan contoh doa fungsi sehingga pengguna yang tidak berpengalaman bisa mencobanya juga.)
randomra
Solusi ini membuat kepala saya sakit:')
Nic Hartley
@QPaysTaxes Saya menganggap ini sebagai pujian.
FUZxxl
@ FuZxxl Ini. Itu juga pelesetan berdasarkan urutan karakter yang muncul dalam jawaban Anda.
Nic Hartley
15

C, 150 byte

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

Ini adalah gila menyenangkan untuk golf. Saya masih tidak yakin saya selesai dengan itu.

Kami mendefinisikan satu fungsi,, fyang mengambil string sebagai input dan output ke stdout.

Mari kita membaca kode, baris demi baris:

/* 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!
}

Saya akan menjawab pertanyaan apa pun yang Anda miliki!

Coba program pengujian online !

BrainSteel
sumber
Saya ingin mengingat bahwa "char l = strlen (c) +1, o [l * l]" tidak valid karena Anda tidak dapat mendefinisikan array berukuran variabel seperti itu, tetapi sudah 15 tahun sejak saya mencoba sesuatu dari semacam itu di C.
Sparr
@Parr Kompiler saya bahkan tidak memberikan peringatan. Saya percaya ini adalah standar "resmi" di C99. Saya akan mencoba mencari referensi untuk ini.
BrainSteel
1
@Parr Ini adalah referensi.
BrainSteel
Terima kasih. Tampaknya hal-hal berubah sekitar 15 (memberi atau mengambil pasangan) tahun yang lalu dalam hal ini :)
Sparr
1
@ CoolGuy Itu akan, tetapi pada panggilan berikutnya f, mtidak akan mengatur ulang ke 0. Ini dianggap sebagai "melanggar lingkungan Anda," dilarang di sini .
BrainSteel
15

Retina + Bash, 27 byte (14 + 10 + 3 = 27)

Ini menggunakan Escapes ANSI:

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

Setara dengan sed -e "s/(/(\\\e[B/g;s/)/\\\e[A)/g". The \e[Bkode escape berarti memindahkan kursor ke bawah satu baris, dan \e[Acara menggerakkan kursor ke atas satu baris, sehingga solusi ini hanya menyisipkan kode-kode setelah dan sebelum awal dan akhir dari masing-masing pasangan bersarang kurung. Input dilewatkan melalui STDIN.

Anda harus menyebutnya printf $(Retina ...)untuk melihat output dengan benar.

Keluaran

(((())))
(\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$ 
 (    )()(        )
  ()()    ()(  )()
             ()
pengguna22723
sumber
1
Yah, tidak buruk! Jika Anda bisa menunjuk ke terminal tertentu yang tidak perlu, printfitu akan bagus. Kalau tidak, saya pikir itu hanya adil untuk menambah | printfjumlah byte.
Martin Ender
@ MartinBüttner Seharusnya printf $()atau printf $(Retina ).
jimmy23013
1
Apa itu Retina?
FUZxxl
2
@ FuZxxl Ini adalah bahasa pemrograman berbasis regex saya sendiri. Lihat GitHub .
Martin Ender
2
Mengapa \editambah printf? Anda cukup menempatkan karakter kontrol dalam pola penggantian.
Dennis
15

TI-BASIC, 69 60 56 55 byte

Ini untuk keluarga kalkulator TI-83+ / 84+, meskipun ditulis pada Edisi Perak 84+ C.

Program ini muncul sebagai on-calc lebih besar karena info ukuran + PPN dimasukkan. Juga, ada lebih dari 56 karakter di sini; alasannya adalah 56 byte adalah karena semua perintah yang lebih dari satu karakter dikompresi ke token yang berukuran satu atau dua byte.

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

Dicukur byte lain berkat thomas-kwa ! (juga darinya adalah lompatan dari 60 ke 56.)

MI Wright
sumber
4
Ahhh, bahasa pemrograman pertamaku. Terima kasih atas nostalgianya, haha.
Alex Pritchard
1
Masih memprogram TI untuk kelas matematika sekolah menengah, sangat berguna untuk memiliki formula yang akan menghitung untuk Anda pada tes dan tugas.
Elias Benevedes
1
Jika Anda menggeser hal-hal di sekitar Anda dapat menggunakan cos(piAnstrik untuk menyimpan byte lain.
lirtosiast
9

Python 2, 115 byte

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)

Sebut seperti f("((()())()(()(())()))"), dan output ke STDOUT.

Penjelasan

Kita mulai dengan n = 0. Untuk setiap karakter di baris input:

  • Jika char adalah (, kami menambahkan nspasi kemudian menambahn
  • Jika karakternya adalah ), kita mengurangi nlalu menambahkan nspasi

Hasilnya kemudian di-zip dan dicetak. Perhatikan bahwa zipritsleting Python sesuai dengan panjang elemen terpendek , misalnya

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

Biasanya orang akan menggunakan itertools.zip_longest( izip_longest) jika mereka ingin zippad dengan panjang elemen terpanjang .

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

Namun dalam Python 2, perilaku ini dapat disimulasikan dengan memetakan None:

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

Python 3, 115 byte

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)

Tanpa zip, cukup padding dengan ljust. Yang ini tampaknya memiliki potensi golf.

Sp3000
sumber
8

R, 151 127 karakter

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

Dengan indentasi dan baris baru:

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

Pemakaian:

> 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
(                  )
 (    )()(        ) 
  ()()    ()(  )()  
             ()     

Bunyinya string sebagai stdin, membaginya sebagai vektor karakter tunggal, menghitung jumlah kumulatif (dan ), mengurangkan yang sebelumnya dengan yang terakhir (dengan lag) sehingga menghitung "level" dari masing-masing tanda kurung. Ia kemudian mencetak ke stdout, untuk setiap level, baik kurung yang sesuai atau spasi.

Terima kasih kepada @MickyT karena telah membantu saya memperpendeknya!

plannapus
sumber
2
+1 Solusi bagus dan elegan. Anda dapat menyimpan 6 dengan mengganti for(i in n)cat(ifelse(D[i]-j," ",S[i]));cat("\n")dengan X=S;X[which(D!=j)]=' ';cat(X,sep='',fill=T). Maka ntidak benar-benar diperlukan, tetapi Anda perlu sedikit mengubah bagian cumsum. D=c(C(S=="("),0)-c(0,C(S==")"));membawanya ke 135.
MickyT
@MickyT wow terima kasih! tidak memikirkan itu. whichtidak benar-benar diperlukan di sini ( D!=jsudah menjadi vektor boolean yang memungkinkan pengindeksan). Saya tidak tahu argumen filluntuk cat, itu trik bagus! Terima kasih telah membuat saya mempersingkatnya dengan 24 karakter yang mengejutkan !!
plannapus
8

C, 58 53 52 51 49 byte

Memanfaatkan urutan pelarian ANSI untuk memindahkan posisi kursor.

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

Jika tidak menggunakan gcc atau kompiler lain yang mendukung, \emaka dapat diganti dengan \x1Btotal 2 byte tambahan. \e[Amemindahkan kursor ke atas satu baris dan \e[Bmemindahkan kursor ke bawah satu baris. Tidak perlu menggunakan \e[Buntuk bergerak ke bawah satu baris karena dua byte lebih pendek untuk menggunakan karakter tab vertikal ASCII 0xBatau \v.

Input string diasumsikan, dari pertanyaan, hanya terdiri dari tanda kurung (seimbang), jadi memeriksa paritas karakter, dengan &1 , cukup untuk membedakan antara (dan ).

CL-
sumber
7

Pip, 53 byte

Pip adalah bahasa kode-golf dari penemuan saya. Versi pertama diterbitkan pada hari Sabtu, jadi saya dapat mengambilnya secara resmi! Solusi di bawah ini tidak terlalu kompetitif ketika bahasa golf digunakan, tetapi itu sebagian karena saya belum menerapkan hal-hal seperti zip dan max.

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

Mengharapkan string tanda kurung sebagai argumen baris perintah.

Versi "Tidak Dicampur":

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

Penjelasan:

Tidak seperti kebanyakan bahasa golf, Pip sangat penting dengan operator infiks, jadi sintaksisnya agak lebih dekat dengan C dan turunannya. Ini juga meminjam ide dari pemrograman berbasis fungsional dan array. Lihat repositori untuk dokumentasi lebih lanjut.

Program pertama-tama menghasilkan daftar kedalaman (menyimpannya z) dengan memetakan fungsi ke string input a. Variabel global vmelacak level saat ini. (Variabel a-gdalam Pip adalah variabel fungsi-lokal, tetapi h-zbersifat global.v Berguna karena diinisialisasi ke -1.)

Selanjutnya, kami menggunakan While loop untuk menghasilkan dan mencetak setiap baris, hingga baris yang dihasilkan terdiri dari semua spasi. vsekarang digunakan untuk kolom, dan iuntuk baris. The {z@++v=i?as}fungsi, berulang kali dipetakan ke input string asli, tes apakah baris saat ipertandingan garis kurung saat ini seharusnya pada (yang disimpan dalam zdaftar). Jika demikian, gunakan tanda kurung ( a); jika tidak, gunakan s(diinisialisasi ke spasi). Hasil akhirnya adalah bahwa pada setiap iterasi, oakan diberikan daftar karakter yang setara dengan baris berikutnya dari output.

Untuk menguji apakah kita harus melanjutkan perulangan, kita periksa apakah osemua spasi RMkosong. Jika tidak, cetaklah (yang secara default menggabungkan semuanya seperti dalam CJam), mengatur ulang nomor kolom menjadi -1, dan menambah nomor baris.

(Fakta menyenangkan: Saya punya solusi 51-byte pada awalnya ... yang tidak berfungsi karena muncul bug pada juru bahasa.)

DLosc
sumber
7

Pyth, 31 byte

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

Cobalah online.

-/<zk\(/<zhk\): Menemukan level yang sesuai untuk posisi karakter saat ini.

?YqN-/<zk\(/<zhk\)d: Ruang jika level yang sesuai bukan level saat ini, karakter saat ini sebaliknya.

Js.e?YqN-/<zk\(/<zhk\)dz: Hasilkan string, simpan ke J.

I-JdJ: Jika Jtidak semua spasi, cetaklah.

Vz: zWaktu putaran .

isaacg
sumber
6

GNU Bash + coreutils + indent, 135

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

Input / output melalui STDIN / STDOUT:

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

indentmelakukan sebagian besar pengangkatan berat, tetapi perlu bekerja dengan kawat gigi, bukan paren. Sisanya adalah modifikasi dari jawaban ini untuk mengubah output dari indent.

Trauma Digital
sumber
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)

Mencetak baris demi baris. Untuk nomor baris yang diberikan i(sebenarnya, negasinya), melewati string input s, dan membuat string baru zyang hanya berisi karakter spada kedalaman i. Ini dilakukan dengan menambah atau mengurangi iuntuk melacak kedalaman saat ini, dan menambahkan karakter saat iini ketika 0disesuaikan dengan tipe paren, dan jika tidak menambahkan spasi.

Kemudian, cetak dan berulang ke yang berikutnya ikecuali garis saat ini adalah semua spasi. Perhatikan bahwa karena parensnya seimbang, iloop setelahnya sama dengan di awal.

Python 3 akan sama kecuali untuk karakter untuk print(z).

Tidak
sumber
5

kecurangan :( Retina + TeX, N byte kecurangan :(

Ini hanya berfungsi jika Anda me-render (?) Output menggunakan MathJax atau TeX lainnya, yang saat ini dinonaktifkan untuk SE ini :(

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

Setiap baris harus dalam file yang berbeda, tetapi Anda dapat mengujinya dengan menggunakan Retina -e "\(" -e "({" -e "\)" -e "})" -e "\{\(" -e "_{("(atau perintah sed yang setara sed -e "s/(/({/g;s/)/})/g;s/{(/_{(/g"). Input dilewatkan melalui STDIN.

Ini berfungsi dengan melampirkan konten dari setiap pasang tanda kurung di dalam kurung kurawal, dan kemudian mensubkripsikan semua item di dalamnya.

Keluaran

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

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

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

Output TeX

pengguna22723
sumber
1
Saya tersanjung bahwa Anda telah menggunakan Retina, dan ini adalah pemikiran yang bagus di luar kotak tapi itu tidak seperti apa yang seharusnya terlihat seperti apa. ;) Khususnya ini melanggar formulasi alternatif "Cara lain untuk melihatnya adalah bahwa tanda kurung di kedalaman n dipindahkan ke garis n, sambil menjaga posisi horizontal mereka." Saya akan sangat terkesan dengan solusi Retina yang murni dan patuh pada aturan dan mungkin membagikan hadiah untuk itu. ;)
Martin Ender
In total the lines must not be longer than twice the length of the input string. Mengubah baris 2 ke (\,{dan baris 4 }\,)berarti output sesuai dengan ini (meskipun kedalaman vertikal masih salah: ()
user22723
Yah, saya berhasil membuat solusi yang sesuai dengan aturan
:)
1
Pekerjaan yang baik. Saya kira itu berarti Anda dapat menghapus jawaban cheaty sekarang. ;)
Martin Ender
5

Java, 232 226 224 222 byte

Versi golf:

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':' ');}

Versi panjang:

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':' '));
}

String input dianalisis terlebih dahulu, mencari "(" dan ")" untuk menambah / mengurangi penghitung dan menyimpan nilainya menentukan seberapa jauh kurung harus berjalan dalam array sambil juga melacak seberapa dalam yang terdalam berjalan. Kemudian array dianalisis; tanda kurung dengan nilai yang lebih rendah dicetak terlebih dahulu, dan akan melanjutkan pencetakan baris demi baris hingga maksimum tercapai.

Saya mungkin akan menemukan cara untuk bermain golf ini lebih jauh nanti.

TNT
sumber
5

Javascript / ES6, 97 karakter

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

Pemakaian

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

Penjelasan

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
sumber
Alih-alih n<m?console.log(o):0, Anda dapat menggunakan n<m&&console.log(o)yang menghemat 1 byte.
Ismael Miguel
4

CJam, 43 41 36 bytes

Tidak terlalu bermain golf (saya pikir), tetapi inilah upaya pertama saya:

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

Bagaimana itu bekerja

Saya menggunakan fakta yang sangat berguna itu )dan (di CJam berarti kenaikan dan penurunan masing-masing. Jadi, saya hanya mengevaluasi tanda kurung untuk mendapatkan kedalaman.

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

Cobalah online di sini

Pengoptimal
sumber
4

Oktaf, 85 karakter

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

Ini merupakan optimasi dari pendekatan naif, yang sebenarnya cukup alami untuk Matlab dan Oktaf:

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;

Tabel t mungkin bahkan belum ada, dan kami dapat menetapkan untuk setiap elemen segera, dan itu membentuk kembali ke dimensi terkecil yang diperlukan agar elemen ini ada yang cukup nyaman.

pawel.boczarski
sumber
4

Perl, 91 89 88 84 80 79 byte

$t=<>;{$_=$t;s/\((?{$l++})|.(?{--$l})/$^R==$c?$&:$"/ge;print,++$c,redo if/\S/}
  • $ t adalah string input.
  • $ c adalah kedalaman yang ingin kita cetak pada baris saat ini.
  • $ l adalah kedalaman yang kita hadapi setelah bertemu paren.
  • $ l diperbarui dalam blok kode tertanam regex .
  • $ ^ R adalah hasil dari blok kode terbaru.
Helios
sumber
4

Haskell, 154 byte

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]]

ide yang sama dengan solusi Haskell lainnya, tetapi agak lebih pendek. - Penggunaan:

echo  '(((())())(()))' | runghc Golf.hs
d8d0d65b3f7cf42
sumber
3

J, 46

Tidak sehebat 'bahasa golf' lainnya, tetapi dalam pembelaan saya: J mengerikan dengan string.

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

Mengambil string sebagai input untuk suatu fungsi. Mungkin juga ada cara yang lebih baik untuk melakukannya di J.

Pemakaian:

   f=:[:|:(((,~(' '#~]))"0)(0,2%~[:+/\2+/\1-'(('i.]))~
   f '(()(()())()((())))(())'
(                )(  )
 ()(    )()(    )  () 
    ()()    (  )      
             ()       
ɐɔıʇǝɥʇu
sumber
Lihat jawaban saya untuk cara lain dalam melakukan ini di J.
FUZxxl
3
Secara pribadi, saya pikir J sangat cocok untuk string. Anda hanya perlu berpikir dengan array.
FUZxxl
3

Ruby, 119 115 114 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]}}

Penjelasan:

->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
sumber
3

Java, 233 214 byte

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

Bertakuk:

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

Saya kira putaran terakhir bisa diperpendek, tetapi saya akan membiarkannya sebagai latihan bagi pembaca. ;-)


Lama, 233 byte menjawab:

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

Bertakuk:

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
sumber
Saya tahu ini sudah lebih dari setahun, tetapi "Saya kira putaran terakhir bisa dipersingkat, tapi saya akan menyerahkannya sebagai latihan untuk pembaca. ;-)"; Anda memang benar. Itu dapat diubah dari for(x=0;x<l*l;x++)System.out.print((x%l==0?"\n":"")+m[x]);ke for(x=0;x<l*l;)System.out.print((x%l==0?"\n":"")+m[x++]);untuk -1 byte. Selain itu, Anda dapat menyimpan 2 byte lebih banyak dengan menghapus p=x=0dan hanya menggunakan int p=0,x=0,inisialisasi bidang sebagai gantinya. Totalnya menjadi 211 byte .
Kevin Cruijssen
3

C #, 195 byte

Pertama-tama coba golf - berteriak jika saya melakukan kesalahan.

Versi C # alternatif menggunakan SetCursorPosition dan bekerja dari kiri ke kanan mengambil input sebagai arg baris perintah.

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

Saya pikir akan menyenangkan untuk menyesuaikan posisi penulisan berdasarkan pada buka / tutup paren dan bukan garis penuh. Tutup paren menggerakkan posisi ke atas sebelum menulis; buka paren memindahkannya ke bawah setelah menulis. Actioning SetCursorPosition menghemat lima byte. Memindahkan kursor ke baris berikutnya setelah output akan mengambil sedikit tambahan.

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
sumber
3

Batch, 356 335 byte

Saya tahu bahwa sudah ada solusi Batch untuk tantangan ini, tetapi yang satu ini lebih banyak bermain golf dan sepertinya mengambil pendekatan yang berbeda. Yang paling penting, solusi batch lainnya mengandung setidaknya satu perintah PowerShell; solusi ini tidak.

@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.)

Ada karakter backspace ( U+0008) pada baris kedua hingga terakhir setelah titik (baris 12, kolom 57). Ini tidak terlihat dalam kode yang diposting di sini tetapi termasuk dalam jumlah byte.

ankh-morpork
sumber
Orang lain benar-benar mengirimkan jawaban dalam Batch - Bagus satu +1.
hapus tanda
3

Batch, 424 byte

@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!

Tidak golf:

@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!

Contoh:

h:\>par.bat (((())())(()))
 (            )
  (      )(  )
   (  )()  ()
    ()
hapus clemeat
sumber
3

C, 118 117 Bytes

Jawaban lain dalam C, tetapi jawaban saya lebih pendek.

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("");}}

Versi tidak disatukan:

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("");
    }
}

Dan itu berhasil!

% ./telescope '()(())((()))(())()'
()(  )(    )(  )()
   ()  (  )  ()
        ()
% ./telescope '((()())()(()(())()))'
(                  )
 (    )()(        )
  ()()    ()(  )()
             ()
MarcDefiant
sumber
1
Solusi yang cukup elegan, namun putchar(c-d?32:*p)satu karakter lebih pendek dari putchar(c==d?*p:32).
pawel.boczarski
2

Haskell, 227 byte

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
Daftar Jeremy
sumber
1
Anda dapat menghemat beberapa ruang dengan operator: mis. n#[]Alih-alih m n [].
Franky
2

Perl, 76 byte

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

Tidak use strictdisini :)

alexander-brett
sumber
2

Lex, 94 byte

Tergantung pada kode konsol Linux. Dengan gcc, Anda dapat memotong empat byte dengan mengganti kedua instance \33dengan karakter escape yang sebenarnya.

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

Untuk mengkompilasi dan menjalankan:

$ flex -o telescopic.c telescopic.l
$ gcc -o telecopic telescopic.c -lfl
$ ./telescopic
(()(()())()((())))(())
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
--- type ctrl-D ---
rici
sumber