Dấu ngoặc đơn


79

Xem xét một chuỗi không trống của dấu ngoặc đơn cân bằng chính xác:

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

Chúng ta có thể tưởng tượng rằng mỗi cặp dấu ngoặc đơn đại diện cho một chiếc nhẫn trong một công trình kính thiên văn bị sụp đổ . Vì vậy, hãy mở rộng kính thiên văn:

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

Một cách khác để xem xét nó là các dấu ngoặc đơn ở độ sâu n được chuyển đến dòng n , trong khi vẫn giữ vị trí nằm ngang của chúng.

Nhiệm vụ của bạn là lấy một chuỗi các dấu ngoặc đơn cân bằng như vậy và tạo ra phiên bản mở rộng.

Bạn có thể viết chương trình hoặc hàm, lấy đầu vào qua STDIN (hoặc tương đương gần nhất), tham số dòng lệnh hoặc tham số hàm và tạo đầu ra thông qua STDOUT (hoặc tương đương gần nhất), trả về giá trị hoặc tham số hàm (out).

Bạn có thể giả sử rằng chuỗi đầu vào là hợp lệ, tức là chỉ bao gồm các dấu ngoặc đơn, được cân bằng chính xác.

Bạn có thể in các dấu cách trên mỗi dòng, nhưng không có nhiều khoảng trắng hàng đầu hơn mức cần thiết. Tổng cộng các dòng không được dài hơn hai lần chiều dài của chuỗi đầu vào. Bạn có thể tùy ý in một dòng mới duy nhất.

Ví dụ

Ngoài ví dụ trên, đây là một vài trường hợp thử nghiệm nữa (đầu vào và đầu ra được phân tách bằng một dòng trống).

()

()
(((())))

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

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

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

Những thách thức liên quan:

  • Chuỗi địa hình , yêu cầu bạn sản xuất những gì thực chất là phần bổ sung của đầu ra trong thử thách này.
  • Code Explanation Formatter , một khái quát rộng rãi về các ý tưởng trong thử thách này, được đăng gần đây bởi PhiNotPi. (Trên thực tế, mô tả ban đầu của PhiNotPi về ý tưởng của anh ấy là điều đã truyền cảm hứng cho thử thách này.)

Bảng xếp hạng

Huh, điều này có khá nhiều sự tham gia, vì vậy đây là Stack Snippet để tạo cả bảng xếp hạng thông thường và tổng quan về người chiến thắng theo ngôn ngữ.

Để đảm bảo rằng câu trả lời của bạn hiển thị, vui lòng bắt đầu câu trả lời của bạn bằng một tiêu đề, sử dụng mẫu Markdown sau:

# Language Name, N bytes

nơi Nlà kích thước của trình của bạn. Nếu bạn cải thiện điểm số của mình, bạn có thể giữ điểm số cũ trong tiêu đề, bằng cách đánh bại chúng thông qua. Ví dụ:

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


17
Tiêu đề thay thế: De-Lisp-ify một chuỗi. : P
Alex A.

1
Có bất kỳ hạn chế về màu sắc của đầu ra?
Matteo Italia

1
@ MartinBüttner: nevermind, tôi tìm thấy một cách sạch hơn; hãy nói rằng ý tưởng trước đây của tôi sẽ cạo một byte để lại tất cả các dấu ngoặc đơn đóng màu xanh lam nhấp nháy trên màu lục lam ... :-)
Matteo Italia

8
@MatteoItalia trời ơi, tôi mừng vì điều đó đã không xảy ra. ;)
Martin Ender

12
@MatteoItalia: Đăng phiên bản đó! Thật đáng xem.
user2357112

Câu trả lời:


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=

Trên đây là kết xuất xxd có thể đảo ngược, vì mã nguồn chứa các ký tự không thể in được VT (0x0b) và CSI (0x9b).

Giống như câu trả lời này , nó sử dụng các chuỗi thoát ANSI , nhưng nó cũng sử dụng các tab dọc và nó in trực tiếp các ký tự điều khiển để tránh sử dụng printf .

Điều này đòi hỏi một thiết bị đầu cuối văn bản video hỗ trợ, bao gồm hầu hết các trình giả lập thiết bị đầu cuối không phải của Windows.

Chạy thử nghiệm

Chúng ta phải đặt LANG biến shell và mã hóa của trình mô phỏng đầu cuối thành ISO 8859-1. Cái trước đạt được bằng cách thực hiện

$ LANGsave="$LANG"
$ LANG=en_US

Ngoài ra, trước khi thực thi mã thực tế, chúng tôi sẽ vô hiệu hóa lời nhắc và xóa màn hình.

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

Điều này đảm bảo đầu ra được hiển thị đúng.

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

Để khôi phục LANG và lời nhắc, hãy thực hiện điều này:

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

Làm thế nào nó hoạt động

Chúng tôi chèn một tab dọc sau mỗi ( để di chuyển con trỏ xuống và chuỗi byte 9b 41 ( "\x9bA") trước mỗi ) để di chuyển con trỏ lên.

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.

49

mã máy 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

lắp ráp x86 cho DOS, với một số thủ thuật:

    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

Hạn chế :

  • nó luôn in bắt đầu từ dưới cùng của màn hình, mà không xóa trước; a clstrước khi chạy là gần như bắt buộc;
  • Màu sắc xấu xí; đó là hậu quả của việc tái chế ký tự tiếp theo dưới dạng các thuộc tính màu để lưu hai byte ở đây và ở đó;
  • mã giả định bh=0và cờ chỉ đường rõ ràng khi bắt đầu, cả hai đều không có giấy tờ; OTOH, bxrõ ràng được đặt thành 0 trong tất cả các biến thể DOS mà tôi thấy (DosBox, MS-DOS 2, FreeDOS) và ở mọi nơi tôi đã kiểm tra các cờ đã ổn.

nhập mô tả hình ảnh ở đây


Chỉ cần xác minh điều này. Có nó hoạt động. Bạn có chắc chắn cần phải làm gì cld?
FUZxxl

@FUZx Dù sao đi nữa, đó chỉ là một byte, phần thưởng thực sự sẽ là giết chết ít nhất một trong số đó (= 4 byte mỗi cái) add/ sub.
Matteo Italia

Hừm ... không có ý kiến ​​gì, thật đấy.
FUZxxl

Bạn có thể đổi lopthành loop?
mbomb007

@ mbomb007: có thể? Tôi không chắc chắn nếu nasmphân biệt giữa loopnhãn và loophướng dẫn lắp ráp, vì vậy tôi chỉ viết lopnhư mọi người khác làm.
Matteo Italia

28

J, 32 28 byte

Đây là một niềm vui.

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

Giải trình

Đây là cách giải pháp này hoạt động, bao gồm một lời giải thích về cách nó đã được chơi golf.

   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 ]

1
Rất đẹp! Giải pháp là đầy đủ các phần tuyệt vời!
Randomra

1
(Tôi thường thêm một ví dụ về chức năng gọi để người dùng không có kinh nghiệm cũng có thể dùng thử.)
Randomra

Giải pháp này khiến đầu tôi đau:')
Nic Hartley

@QPaysTaxes Tôi coi đây là một lời khen.
FUZxxl

@FUZxxl Đó là. Đó cũng là một cách chơi chữ dựa trên một chuỗi các ký tự xuất hiện trong câu trả lời của bạn.
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);}

Đây là niềm vui điên rồ đối với golf. Tôi vẫn không bị thuyết phục Tôi đã làm xong với nó.

Chúng tôi xác định một hàm duy nhất, flấy chuỗi này làm đầu vào và đầu ra cho thiết bị xuất chuẩn.

Chúng ta hãy đi qua mã, từng dòng:

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

Tôi sẽ trả lời bất kỳ câu hỏi mà bạn có thể có!

Hãy thử một chương trình thử nghiệm trực tuyến !


Tôi muốn nhớ rằng "char l = strlen (c) +1, o [l * l]" không hợp lệ vì bạn không thể xác định một mảng có kích thước thay đổi như thế, nhưng đã 15 năm kể từ khi tôi thử bất cứ thứ gì sắp xếp trong C.
Sparr

@Sparr Trình biên dịch của tôi thậm chí không đưa ra cảnh báo. Tôi tin rằng đây là tiêu chuẩn "chính thức" trong C99. Tôi sẽ cố gắng tìm một tài liệu tham khảo cho việc này.
BrainSteel

1
@Sparr Đây là một tài liệu tham khảo.
BrainSteel

Cảm ơn. Có vẻ như mọi thứ đã thay đổi khoảng 15 (cho hoặc mất một vài năm) về vấn đề này :)
Sparr

1
@CoolGuy Nó sẽ, nhưng trong các cuộc gọi tiếp theo f, msẽ không được đặt lại về 0. Điều này được tính là "phá vỡ môi trường của bạn", ngoài vòng pháp luật ở đây .
BrainSteel

15

Võng mạc + Bash, 27 byte (14 + 10 + 3 = 27)

Điều này làm cho việc sử dụng ANSI Escapes:

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

Tương đương với sed -e "s/(/(\\\e[B/g;s/)/\\\e[A)/g". Các \e[Bmã thoát có nghĩa là di chuyển con trỏ xuống một hàng, và các \e[Aphương tiện di chuyển con trỏ lên một hàng, vì vậy giải pháp này chỉ đơn giản là chèn những mã sau và trước khi bắt đầu và kết thúc của mỗi cặp lồng nhau của dấu ngoặc đơn. Đầu vào được truyền qua STDIN.

Bạn sẽ phải gọi nó là printf $(Retina ...)để xem đầu ra chính xác.

Đầu ra

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

1
Cũng không tệ! Nếu bạn có thể chỉ đến một thiết bị đầu cuối cụ thể mà không cần printfđiều đó sẽ là tuyệt vời. Mặt khác, tôi nghĩ sẽ chỉ công bằng khi thêm | printfvào số byte.
Martin Ender

@ MartinBüttner Nó nên printf $()hoặc printf $(Retina ).
jimmy23013

1
Cái gì mà Retina điều đó?
FUZxxl

2
@FUZxxl Đó là ngôn ngữ lập trình dựa trên regex của riêng tôi. Xem GitHub .
Martin Ender

2
Tại sao \ecộng printf? Bạn chỉ có thể đặt các ký tự điều khiển trong mẫu thay thế.
Dennis

15

TI-BASIC, 69 60 56 55 byte

Cái này dành cho dòng máy tính TI-83 + / 84 +, mặc dù nó được viết trên Phiên bản Bạc 84+ C.

Chương trình hiển thị dưới dạng lớn hơn do thông tin kích thước VAT + được bao gồm. Ngoài ra, có hơn 56 ký tự ở đây; Lý do là 56 byte là vì tất cả các lệnh có nhiều hơn một ký tự được nén xuống các mã thông báo có kích thước một hoặc hai 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

Cạo đi một byte khác nhờ thomas-kwa ! (cũng từ anh ấy là bước nhảy từ 60 đến 56.)


4
Ahhh, ngôn ngữ lập trình đầu tiên của tôi. Cảm ơn những nỗi nhớ, haha.
Alex Pritchard

1
Vẫn lập trình TI cho lớp toán trung học, rất hữu ích khi có các công thức được xây dựng trong đó sẽ tính toán cho bạn trong các bài kiểm tra và bài tập.
Elias Benevedes

1
Nếu bạn thay đổi mọi thứ xung quanh, bạn có thể sử dụng cos(piAnsthủ thuật để lưu một byte khác.
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)

Gọi như thế f("((()())()(()(())()))"), và đầu ra là STDOUT.

Giải trình

Chúng tôi bắt đầu với n = 0. Đối với mỗi char trong dòng đầu vào:

  • Nếu char là (, chúng ta thêm vào nkhoảng trắng sau đó tăngn
  • Nếu char là ), chúng ta giảm dần nsau đó thêm nkhoảng trắng

Kết quả sau đó được nén và in. Lưu ý rằng các zipkhóa của Python để khớp với độ dài của phần tử ngắn nhất , ví dụ:

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

Thông thường người ta sẽ sử dụng itertools.zip_longest( izip_longest) nếu họ muốn zipđệm theo chiều dài của phần tử dài nhất .

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

Nhưng trong Python 2, hành vi này có thể được mô phỏng bằng cách ánh xạ 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)

Không nén, chỉ cần đệm phù hợp với ljust. Điều này dường như có một số tiềm năng chơi golf.


8

R, 151 127 ký tự

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

Với thụt lề và dòng mới:

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

Sử dụng:

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

Nó đọc chuỗi dưới dạng stdin, chia nó thành một vectơ của các ký tự đơn, tính tổng tích lũy của (), tạo thành chuỗi trước với chuỗi sau (có độ trễ) do đó tính toán "mức" của mỗi dấu ngoặc đơn. Sau đó, nó in ra thiết bị xuất chuẩn, cho mỗi cấp độ, là dấu ngoặc đơn tương ứng hoặc khoảng trắng.

Cảm ơn @MickyT đã giúp tôi rút ngắn đáng kể!


2
+1 Giải pháp đẹp và thanh lịch. Bạn có thể lưu 6 bằng cách thay thế for(i in n)cat(ifelse(D[i]-j," ",S[i]));cat("\n")bằng X=S;X[which(D!=j)]=' ';cat(X,sep='',fill=T). Sau đó nkhông thực sự cần thiết, nhưng bạn sẽ cần thay đổi phần cumsum một chút. D=c(C(S=="("),0)-c(0,C(S==")"));đưa nó xuống 135.
MickyT

@MickyT wow cảm ơn! đã không nghĩ về điều đó. whichkhông thực sự cần thiết ở đây mặc dù ( D!=jđã là một vectơ của booleans cho phép lập chỉ mục). Tôi không biết lý lẽ fillcho cat, đó là một thủ thuật tiện lợi! Cảm ơn vì đã khiến tôi rút ngắn nó bằng 24 ký tự đáng kinh ngạc !!
plannapus

8

C, 58 53 52 51 49 byte

Làm cho việc sử dụng các chuỗi thoát ANSI để di chuyển vị trí con trỏ.

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

Nếu không sử dụng gcc hoặc trình biên dịch khác hỗ trợ \ethì nó có thể được thay thế bằng \x1Btổng cộng 2 byte. \e[Adi chuyển con trỏ lên một hàng và \e[Bdi chuyển con trỏ xuống một hàng. Không cần thiết phải sử dụng \e[Bđể di chuyển xuống một hàng vì nó ngắn hơn hai byte để sử dụng ký tự tab dọc ASCII 0xBhoặc \v.

Chuỗi đầu vào được giả sử, từ câu hỏi, chỉ bao gồm các dấu ngoặc đơn (cân bằng), do đó, kiểm tra tính chẵn lẻ của ký tự, với &1, là đủ để phân biệt giữa ().


7

Pip, 53 byte

Pip là một ngôn ngữ golf-code của phát minh của tôi. Phiên bản đầu tiên được xuất bản vào thứ bảy, vì vậy tôi có thể chính thức mang nó đi quay! Giải pháp dưới đây không cạnh tranh khủng khiếp khi các ngôn ngữ chơi gôn đi, nhưng đó là một phần vì tôi chưa triển khai những thứ như zip và max.

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

Yêu cầu chuỗi dấu ngoặc đơn làm đối số dòng lệnh.

Phiên bản "Ungolfed":

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

Giải trình:

Không giống như hầu hết các ngôn ngữ chơi gôn, Pip là bắt buộc với các toán tử infix, vì vậy cú pháp có phần gần với C và các dẫn xuất của nó. Nó cũng mượn ý tưởng từ lập trình dựa trên chức năng và mảng. Xem kho lưu trữ để có thêm tài liệu.

Chương trình trước tiên tạo một danh sách các độ sâu (lưu trữ nó z) bằng cách ánh xạ một hàm vào chuỗi đầu vào a. Biến toàn cầu vtheo dõi mức hiện tại. (Các biến a-gtrong Pip là các biến cục bộ-hàm, nhưng h-zlà toàn cục. Rất vtiện lợi vì nó được xác định trước thành -1.)

Tiếp theo, chúng tôi sử dụng một Wvòng lặp hile để tạo và in từng dòng, cho đến khi dòng được tạo sẽ bao gồm tất cả các khoảng trắng. vhiện được sử dụng cho các cột và icho các hàng. Các {z@++v=i?as}chức năng, liên tục ánh xạ tới các chuỗi đầu vào ban đầu, kiểm tra xem dòng hiện tại iphù hợp với dòng ngoặc hiện được nghĩa vụ phải được trên (như lưu trong zdanh sách). Nếu vậy, sử dụng dấu ngoặc đơn ( a); nếu không, sử dụng s(preinitialized vào không gian). Kết quả cuối cùng là trên mỗi lần lặp, ođược gán một danh sách các ký tự tương đương với dòng tiếp theo của đầu ra.

Để kiểm tra xem chúng tôi có nên tiếp tục lặp không, chúng tôi kiểm tra xem ovới tất cả các khoảng trắng RMcó trống không. Nếu không, hãy in nó (theo mặc định sẽ ghép mọi thứ lại với nhau như trong CJam), đặt lại số cột thành -1 và tăng số hàng.

(Sự thật thú vị: Lúc đầu tôi có một giải pháp 51 byte ... không hoạt động vì nó đã xuất hiện một lỗi trong trình thông dịch.)


7

Bình thường, 31 byte

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

Hãy thử trực tuyến.

-/<zk\(/<zhk\): Tìm mức phù hợp cho vị trí nhân vật hiện tại.

?YqN-/<zk\(/<zhk\)d: Một khoảng trắng nếu mức phù hợp không phải là mức hiện tại, ký tự hiện tại khác.

Js.e?YqN-/<zk\(/<zhk\)dz: Tạo chuỗi, lưu nó vào J.

I-JdJ: Nếu Jkhông phải là tất cả các khoảng trắng, hãy in nó ra.

Vz: Vòng lặp zthời gian.


6

GNU Bash + coreutils + thụt lề, 135

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

Đầu vào / đầu ra thông qua STDIN / STDOUT:

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

indentthực hiện hầu hết các công việc nặng nhọc, nhưng cần phải làm việc với niềng răng thay vì parens. Phần còn lại là sửa đổi câu trả lời này để hoán chuyển đầu ra của indent.


5

Con trăn 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)

In từng dòng. Đối với một số dòng nhất định i(thực ra là phủ định của nó), đi qua chuỗi đầu vào svà tạo một chuỗi mới zchỉ chứa các ký tự có schiều sâu i. Điều này được thực hiện bằng cách tăng hoặc giảm iđể theo dõi độ sâu hiện tại và thêm các ký tự hiện tại khi iđược 0điều chỉnh cho loại paren và nếu không thì thêm một khoảng trắng.

Sau đó, in và đệ quy tiếp theo itrừ khi dòng hiện tại là tất cả các khoảng trắng. Lưu ý rằng vì các parens được cân bằng, isau vòng lặp giống như lúc bắt đầu.

Python 3 sẽ giống nhau ngoại trừ một ký tự cho print(z).


5

gian lận :( Retina + TeX, N byte gian lận :(

Điều này chỉ hoạt động nếu bạn kết xuất (?) Đầu ra bằng MathJax hoặc một số TeX khác, hiện đang bị vô hiệu hóa cho SE này :(

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

Mỗi dòng nên ở trong một tệp khác nhau, nhưng bạn có thể kiểm tra nó bằng cách sử dụng Retina -e "\(" -e "({" -e "\)" -e "})" -e "\{\(" -e "_{("(hoặc lệnh sed tương đương sed -e "s/(/({/g;s/)/})/g;s/{(/_{(/g"). Đầu vào được truyền qua STDIN.

Điều này hoạt động bằng cách đặt nội dung của từng cặp dấu ngoặc trong dấu ngoặc nhọn, và sau đó đăng ký tất cả các mục bên trong chúng.

Đầu ra

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

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

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

Đầu ra TeX


1
Tôi rất hãnh diện rằng bạn đã sử dụng Retina, và đây là suy nghĩ tuyệt vời bên ngoài hộp nhưng đó không hoàn toàn là những gì đầu ra được cho là trông như thế nào. ;) Đặc biệt, điều này vi phạm công thức thay thế "Một cách khác để xem xét đó là các dấu ngoặc đơn ở độ sâu n được chuyển đến dòng n, trong khi vẫn giữ vị trí nằm ngang của chúng." Tôi rất ấn tượng với một giải pháp Retina thuần túy, tuân thủ quy tắc và có thể đưa ra một khoản tiền thưởng cho nó. ;)
Martin Ender

In total the lines must not be longer than twice the length of the input string. Thay đổi dòng 2 thành (\,{dòng 4 thành }\,)có nghĩa là đầu ra phù hợp với điều này (mặc dù độ sâu dọc vẫn sai: ()
user22723

Chà, tôi đã xoay sở để đưa ra giải pháp tuân thủ quy tắc :)
user22723

1
Công việc tốt. Tôi đoán điều đó có nghĩa là bạn có thể xóa câu trả lời gian lận ngay bây giờ. ;)
Martin Ender

5

Java, 232 226 224 222 byte

Phiên bản chơi gôn:

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

Phiên bản dài:

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

Chuỗi đầu vào được phân tích trước tiên, tìm kiếm "(" và ")" để thêm / bớt một bộ đếm và lưu trữ giá trị của nó để xác định khoảng cách các dấu ngoặc sẽ đi sâu trong một mảng trong khi cũng theo dõi mức độ sâu nhất của nó. Sau đó, mảng được phân tích; các dấu ngoặc đơn có giá trị nhỏ hơn được in trước và sẽ tiếp tục in từng dòng cho đến khi đạt được mức tối đa.

Có lẽ tôi sẽ tìm cách để chơi golf này sau này.


5

Javascript / ES6, 97 ký tự

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

Sử dụng

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

Giải trình

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

Thay vì n<m?console.log(o):0, bạn có thể sử dụng n<m&&console.log(o)để tiết kiệm 1 byte.
Ismael Miguel

4

CJam, 43 41 36 byte

Không quá chơi gôn (tôi nghĩ vậy), nhưng đây là nỗ lực đầu tiên của tôi:

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

Làm thế nào nó hoạt động

Tôi đang sử dụng một thực tế rất tiện dụng rằng )(trong CJam có nghĩa là tăng và giảm tương ứng. Vì vậy, tôi chỉ đơn giản là đánh giá các dấu ngoặc để có được độ sâu.

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

Dùng thử trực tuyến tại đây


4

Octave, 85 ký tự

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

Đó là một sự tối ưu hóa của cách tiếp cận ngây thơ, điều thực sự khá tự nhiên đối với Matlab và 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;

Bảng t thậm chí có thể chưa tồn tại và chúng tôi có thể gán cho bất kỳ phần tử nào ngay lập tức và nó định hình lại kích thước nhỏ nhất được yêu cầu để phần tử này tồn tại khá thuận tiện.


4

Perl, 91 89 88 84 80 79 byte

$t=<>;{$_=$t;s/\((?{$l++})|.(?{--$l})/$^R==$c?$&:$"/ge;print,++$c,redo if/\S/}
  • $ t là chuỗi đầu vào.
  • $ c là độ sâu mà chúng tôi muốn in trên dòng hiện tại.
  • $ l là độ sâu chúng ta đang có sau khi gặp paren.
  • $ l được cập nhật trong các khối mã nhúng regex .
  • $ ^ R là kết quả của khối mã gần đây nhất.

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

cùng ý tưởng với giải pháp Haskell khác, nhưng có phần ngắn hơn. - Sử dụng:

echo  '(((())())(()))' | runghc Golf.hs

3

J, 46

Không tuyệt vời như các 'ngôn ngữ chơi gôn' khác, nhưng trong phòng thủ của tôi: J rất tệ với dây.

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

Lấy chuỗi làm đầu vào cho một hàm. Có lẽ cũng có một cách tốt hơn để làm điều đó trong J.

Sử dụng:

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

Xem câu trả lời của tôi cho một cách khác để làm điều này trong J.
FUZxxl

3
Cá nhân, tôi nghĩ rằng J hoàn toàn phù hợp với chuỗi. Bạn chỉ cần suy nghĩ với mảng.
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]}}

Giải trình:

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

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

Thụt lề:

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

Tôi đoán vòng lặp cuối cùng có thể được rút ngắn, nhưng tôi sẽ để nó như một bài tập cho người đọc. ;-)


Cũ, 233 byte trả lời:

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

Thụt lề:

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

Tôi biết đã hơn một năm, nhưng "Tôi đoán vòng lặp cuối cùng có thể được rút ngắn, nhưng tôi sẽ để nó như một bài tập cho người đọc. ;-)"; bạn thực sự đúng Nó có thể được thay đổi từ for(x=0;x<l*l;x++)System.out.print((x%l==0?"\n":"")+m[x]);thành for(x=0;x<l*l;)System.out.print((x%l==0?"\n":"")+m[x++]);cho byte byte. Ngoài ra, bạn có thể lưu thêm 2 byte bằng cách loại bỏ p=x=0và chỉ sử dụng int p=0,x=0,khi khởi tạo các trường thay thế. Tổng cộng nó trở thành 211 byte .
Kevin Cruijssen

3

C #, 195 byte

Lần đầu tiên thử chơi golf - hét lên nếu tôi làm sai.

Phiên bản C # thay thế bằng cách sử dụng SetCthonP vị trí và làm việc từ trái sang phải lấy đầu vào làm dòng lệnh arg.

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

Tôi nghĩ sẽ rất vui khi điều chỉnh vị trí ghi dựa trên paren mở / đóng và không đầy đủ dòng. Đóng paren di chuyển vị trí lên trước khi viết; mở paren di chuyển nó xuống sau khi viết. Hành động SetCthonP vị trí lưu năm byte. Di chuyển con trỏ đến dòng tiếp theo sau khi đầu ra sẽ mất thêm một chút.

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

3

Batch, 356 335 byte

Tôi biết rằng đã có một giải pháp Batch cho thử thách này, nhưng giải pháp này được đánh gôn nhiều hơn đáng kể và dường như có một cách tiếp cận khác. Quan trọng nhất, giải pháp lô khác chứa ít nhất một lệnh powershell; Giải pháp này không.

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

Có một ký tự backspace ( U+0008) trên dòng thứ hai đến dòng cuối cùng sau dấu chấm (dòng 12, cột 57). Điều này không thể nhìn thấy trong mã được đăng ở đây nhưng được bao gồm trong số byte.


Ai đó khác thực sự gửi câu trả lời trong Batch - Nice one +1.
khai mạc

3

Hàng loạt, 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!

Chưa chơi gôn:

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

Thí dụ:

h:\>par.bat (((())())(()))
 (            )
  (      )(  )
   (  )()  ()
    ()

3

C, 118 117 byte

Một câu trả lời khác trong C, nhưng của tôi ngắn hơn.

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

Phiên bản bị đánh cắp:

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

Và nó hoạt động!

% ./telescope '()(())((()))(())()'
()(  )(    )(  )()
   ()  (  )  ()
        ()
% ./telescope '((()())()(()(())()))'
(                  )
 (    )()(        )
  ()()    ()(  )()
             ()

1
Khá là một giải pháp tao nhã, tuy nhiên putchar(c-d?32:*p)ngắn hơn một ký tự 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

1
Bạn có thể lưu một vài khoảng trắng với các toán tử: ví dụ n#[]thay vì m n [].
Franky

2

Perl, 76 byte

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

Không có use strictở đây :)


2

Lex, 94 byte

Phụ thuộc vào mã bảng điều khiển Linux. Với gcc, bạn có thể cắt ra bốn byte bằng cách thay thế cả hai trường hợp \33bằng một ký tự thoát thực tế.

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

Để biên dịch và chạy:

$ flex -o telescopic.c telescopic.l
$ gcc -o telecopic telescopic.c -lfl
$ ./telescopic
(()(()())()((())))(())
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
--- type ctrl-D ---
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.