伸縮式括弧


79

正しくバランスの取れた括弧の空でない文字列を考えてみましょう:

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

括弧の各ペアは、折り畳まれた伸縮構造のリングを表すと想像できます。それでは、望遠鏡を拡張しましょう。

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

別の見方をすると、深さnの括弧は、水平位置を維持したまま行nに移動します。

あなたの仕事は、バランスの取れた括弧のような文字列を取り、拡張バージョンを作成することです。

プログラムまたは関数を記述し、STDIN(またはそれに最も近いもの)、コマンドライン引数または関数パラメーターを介して入力を取得し、STDOUT(または最も近いもの)、戻り値または関数(出力)パラメーターを介して出力を生成できます。

入力文字列が有効である、つまり、括弧のみで構成されており、それらが正しくバランスしていると想定できます。

各行に末尾のスペースを印刷できますが、必要以上の先行スペースは印刷できません。合計で、行は入力文字列の長さの2倍を超えてはなりません。オプションで、単一の末尾の改行を印刷できます。

上記の例に加えて、さらにいくつかのテストケースがあります(入力と出力は空の行で区切られています)。

()

()
(((())))

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

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

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

関連する課題:

  • Topographic Strings。このチャレンジの出力を本質的に補完するものを生成するように求められます。
  • PhiNotPiによって最近投稿された、この課題のアイデアを広く一般化したコード説明フォーマッター。(実際、PhiNotPiの彼のアイデアの元の説明が、この課題のきっかけとなりました。)

リーダーボード

フー、これはかなり多くの参加を得たので、ここでは、定期的なリーダーボードと言語ごとの勝者の概要の両方を生成するスタックスニペットがあります。

回答が表示されるようにするには、次のマークダウンテンプレートを使用して、見出しから回答を開始してください。

# Language Name, N bytes

N提出物のサイズはどこですか。スコアを改善する場合、古いスコアを打つことで見出しに残すことができます。例えば:

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


17
代替タイトル:文字列のDe-Lisp-ify。:P
アレックスA.

1
出力の色に制限はありますか?
マッテオイタリア

1
@MartinBüttner:気にせず、もっときれいな方法を見つけました。私の以前のアイデアは、すべての閉じた括弧をシアン上で青く点滅させたままバイトを削っただろうと言ってみましょう... :
Matteo Italia

8
@MatteoItaliaなんてこった、それが起こらなかったことがうれしい。;)
マーティン・エンダー

12
@MatteoItalia:そのバージョンを投稿してください!見る価値がある。
user2357112

回答:


8

CJam、17 16 15バイト

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

上記はリバーシブルxxdダンプです。これは、ソースコードにVT(0x0b)およびCSI(0x9b)の印刷不能文字が含まれているためです。

同じように、この答えは、それが使用するANSIエスケープシーケンスを、それはまた、垂直方向のタブを使用していますし、それは使用しないように直接制御文字を出力printf関数を

これには、Windows以外のほとんどのターミナルエミュレーターを含むサポートビデオテキストターミナルが必要です。

テスト走行

シェル変数LANGと端末エミュレーターのエンコードをISO 8859-1 に設定する必要があります。前者は、実行することにより達成されます

$ LANGsave="$LANG"
$ LANG=en_US

また、実際のコードを実行する前に、プロンプトを無効にして画面をクリアします。

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

これにより、出力が適切に表示されます。

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

LANGとプロンプトを復元するには、次を実行します。

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

使い方

それぞれの後に垂直タブを挿入しカーソルを下に移動し、各バイトの前にバイトシーケンス9b 41を移動して、カーソルを上に移動します。"\x9bA"

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

x86マシンコード、 39 34 33 30 29バイト

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

DOS用のx86アセンブリ、いくつかのトリック:

    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

制限事項

  • 常に最初に消去せずに、画面の一番下から印刷されます。cls実行する前には、ほぼ必須です。
  • 色がugいです。これは、次の文字を色属性としてリサイクルして、あちこちで2バイトを節約した結果です。
  • コードはbh=0、ドキュメント化されていない状態で、開始時に方向フラグがクリアされると仮定します。OTOHは、bx私が見たすべてのDOSバリアント(DosBox、MS-DOS 2、FreeDOS)で明示的にゼロに設定されており、フラグをテストしたすべての場所で既にOKでした。

ここに画像の説明を入力してください


これを確認しました。はい、動作します。本当にする必要がありcldますか?
-FUZxxl

@FUZxxl:DosBoxでは、それがなくても正常に動作しますが、そのソースを見ると、DOSおよびTRSで以前に発生したものはすべてフラグが保存されるため、おそらく安全にプレイする必要があります。とにかく、それはたった1バイトで、本当の見返りはそれらの大きな(少なくとも4バイト)add/の少なくとも1つを殺すことsubです。
マッテオイタリア

うーん...全くわからない。
FUZxxl

あなたは変更することができますloploop
mbomb007

@ mbomb007:たぶん?ラベルとしてとアセンブリ命令のnasm間で曖昧さを解消するかどうかはわかりませんので、私は他のみんなと同じように書きます。looplooplop
マッテオイタリア

28

J、32 28バイト

これは楽しいものでした。

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

説明

これは、このソリューションがどのように機能するかを示しています。

   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
非常に素晴らしい!ソリューションには素晴らしい部分がいっぱいです!
randomra

1
(通常、関数の呼び出し例を追加して、経験のないユーザーも試してみられるようにします。)
randomra

この解決策により頭が痛くなる:')
ニックハートリー

@QPaysTaxesこれはお世辞になります。
FUZxxl

@FUZxxlです。また、回答に表示される一連の文字に基づいたしゃれです。
ニックハートリー

15

C、150バイト

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

これはゴルフに夢中になりました。私はまだそれをやったと確信していません。

f入力として文字列を受け取り、stdoutに出力する単一の関数を定義します。

コードを1行ずつ見ていきましょう。

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

質問がある場合はお答えします!

オンラインでテストプログラムを試してみてください!


「char l = strlen(c)+1、o [l * l]」は、そのような可変サイズの配列を定義できないため有効ではないことを覚えておく必要がありますが、 C.でその種
SPARR

@Sparr私のコンパイラーは警告さえ投げません。これはC99の「公式に」標準だったと思います。このためのリファレンスを見つけようとします。
BrainSteel

1
@Sparr ここで参照です。
BrainSteel

ありがとう。この点に関しては、15年前後(数回または数回)に物事が変化したように見えます:)
Sparr

1
@CoolGuyそれは、しかし、の後続の呼び出しになりfmこれは非合法化「ご使用の環境を壊す」としてカウント0にリセットされませんここに
BrainSteel

15

Retina + Bash、27バイト(14 + 10 + 3 = 27)

これは、ANSIエスケープを使用します。

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

と同等sed -e "s/(/(\\\e[B/g;s/)/\\\e[A)/g"です。\e[Bエスケープ・コードは、1つの行にカーソルを下に移動手段、及び\e[A手段は、1つの行にカーソルを移動するので、この解決策は、単に後の括弧のネストされた各対の開始と終了の前にこれらのコードを挿入します。入力はSTDINを介して渡されます。

printf $(Retina ...)出力を正しく表示するために呼び出す必要があります。

出力

(((())))
(\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
まあ、悪くない!必要のない特定の端末を指すことができれば、printfそれは素晴らしいことです。そうでなければ、| printfバイトカウントに追加するだけでいいと思います。
マーティンエンダー

@MartinBüttner printf $()またはである必要がありますprintf $(Retina )
jimmy23013

1
あのRetinaって何?
FUZxxl

2
@FUZxxlそれは私自身の正規表現ベースのプログラミング言語です。GitHubを参照してください
マーティンエンダー

2
なぜ\eプラスprintf?単純に制御文字を置換パターンに入れることができます。
デニス

15

TI-BASIC、69 60 56 55バイト

これはTI-83 + / 84 +ファミリーの計算機用ですが、84 + C Silver Editionで書かれています。

VAT +サイズ情報が含まれているため、プログラムはより大きなオンカルとして表示されます。また、ここには56文字以上があります。56バイトである理由は、2文字以上のコマンドはすべて、サイズが1バイトまたは2バイトのトークンに圧縮されるためです。

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

thomas-kwaのおかげでもう1バイト削りました!(彼からも60から56へのジャンプがありました。)


4
ああ、私の最初のプログラミング言語。懐かしさ、ありがとう。
アレックスプリチャード

1
高校の数学のクラスのためにTIをまだプログラミングしています。テストや割り当てを計算する数式を組み込むのに非常に便利です。
エリアスベネベデス

1
物事をシフトする場合は、cos(piAnsトリックを使用して別のバイトを保存できます。
リスト管理者

9

Python 2、115バイト

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)

のようf("((()())()(()(())()))")に呼び出し、出力はSTDOUTになります。

説明

で始まりn = 0ます。入力行の各文字に対して:

  • 文字がの場合、スペース(を追加してnからインクリメントしますn
  • 文字がの場合、スペース)をデクリメントしてnから追加しnます

その後、結果が圧縮されて印刷されます。Pythonのzipzipは最短要素の長さに一致することに注意してください。例えば

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

通常、最も長い要素の長さまでパディングしたい場合はitertools.zip_longestizip_longest)を使用します。zip

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

しかし、Python 2では、この動作はマッピングによってシミュレートできますNone

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

Python 3、115バイト

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)

zipではなく、で適切にパディングするだけljustです。これにはゴルフの可能性があるようです。


8

R、151 127文字

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

これは、単一の文字のベクトルとして、それを分割し、標準入力として文字列を読み取るの累積和を計算(及び)、従って各括弧の「レベル」を計算する(遅れで)後者は前者をsubstracts。次に、レベルごとに、対応する括弧またはスペースを標準出力に出力します。

@MickyTを大幅に短縮してくれてありがとう!


2
+1素敵でエレガントなソリューション。を6に置き換えるfor(i in n)cat(ifelse(D[i]-j," ",S[i]));cat("\n")と、保存できますX=S;X[which(D!=j)]=' ';cat(X,sep='',fill=T)。そのn場合、実際には必要ありませんが、cumsum部分を少し変更する必要があります。D=c(C(S=="("),0)-c(0,C(S==")"));135にそれをダウンさせ
MickyT

@MickyTすごいありがとう!それを考えていませんでした。whichただし、ここでは実際に必要ではありません(D!=j既にインデックス付けを許可するブール値のベクトルです)。の議論fillを知りませんでしたcat、それは気の利いたトリックです!驚異的な24文字で短縮してくれてありがとう!!
プランナパス

8

C、58 53 52 51 49バイト

ANSIエスケープシーケンスを使用して、カーソル位置を移動します。

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

gccまたはサポートする別のコンパイラを使用していない場合は、合計2バイト余分に\e置き換えることができ\x1Bます。\e[Aカーソルを1行上に\e[B移動し、カーソルを1行下に移動します。\e[BASCIIの垂直タブ文字0xBまたはを使用するには2バイト短いため、1行下に移動するために使用する必要はありません\v

入力文字列は、質問から(バランスのとれた)括弧のみで構成されると想定さ&1れているため、(とを区別するには、で文字のパリティを確認するだけで十分)です。


7

ピップ、53バイト

ピップは私の発明のコードゴルフ言語です。最初のバージョンは土曜日に公開されたので、公式に試してみることができます!以下のソリューションは、ゴルフの言語としてはそれほど競争力がありませんが、それは、zipやmaxのようなものをまだ実装していないからです。

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

コマンドライン引数として括弧の文字列を期待します。

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

説明:

ほとんどのゴルフ言語とは異なり、Pipは中置演算子を使用する必要があります。そのため、構文はCおよびその派生物に多少似ています。また、関数型および配列ベースのプログラミングからアイデアを借りています。詳細なドキュメントについては、リポジトリを参照してください。

プログラムはz、関数を入力文字列にマッピングすることにより、最初に深さのリストを生成します(格納します)a。グローバル変数vは現在のレベルを追跡します。(変数a-g Pipのは関数ローカル変数ですがh-z、グローバルです。v-1に事前初期化されているため便利です。)

次に、W生成された行がすべてスペースになるまで、ヒルループを使用して各行を生成および印刷します。v列とi行に使用されるようになりました。この{z@++v=i?as}関数は、元の入力文字列に繰り返しマッピングされ、現在iの行が現在の括弧が(zリストに保存されている)ある行と一致するかどうかをテストします。その場合は、括弧(a)を使用します。そうでない場合は、使用しますs(事前にスペースに初期化)。最終結果は、各反復oで、出力の次の行に相当する文字のリストが割り当てられることです。

ループを続行するかどうかをテストするにはo、すべてのスペースでRM 'dが空ます。そうでない場合は、それを印刷し(デフォルトではすべてをCJamのように連結します)、列番号を-1にリセットし、行番号をインクリメントします。

(面白い事実:最初は51バイトの解決策がありました...インタープリターのバグが判明したため、うまくいきませんでした。)


7

Pyth、31バイト

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

オンラインでお試しください。

-/<zk\(/<zhk\):現在の文字位置に適切なレベルを見つけます。

?YqN-/<zk\(/<zhk\)d:適切なレベルが現在のレベルでない場合はスペース、それ以外の場合は現在の文字。

Js.e?YqN-/<zk\(/<zhk\)dz:文字列を生成し、保存しJます。

I-JdJJすべてのスペースではない場合は、印刷してください。

Vz:ループz時間。


6

GNU Bash + coreutils +インデント、135

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

STDIN / STDOUTを介した入出力:

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

indentほとんどの重荷を持ち上げますが、括弧ではなくブレースを使用する必要があります。残りはの出力を転置するためのこの回答の修正ですindent


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)

行ごとに印刷します。指定された行番号i(実際にはその否定)について、入力文字列を調べs、depthのz文字のみを含む新しい文字列を作成します。これは、現在の深さを追跡するためにインクリメントまたはデクリメントし、かっこ型に調整されている場合は現在の文字を追加し、それ以外の場合はスペースを追加することによって行われます。siii0

次に、i現在の行がすべてスペースでない限り、印刷して次の行に再帰します。括弧は均衡しているため、iループの後は開始時と同じであることに注意してください。

Python 3は、の文字​​を除いて同じですprint(z)


5

不正行為:( Retina + TeX、Nバイト不正行為:(

これはMathJaxまたは他のTeXを使用して出力をレンダリング(?)した場合にのみ機能します。

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

各行は異なるファイルにある必要がありますが、Retina -e "\(" -e "({" -e "\)" -e "})" -e "\{\(" -e "_{("(または同等のsedコマンドsed -e "s/(/({/g;s/)/})/g;s/{(/_{(/g")を使用してテストできます。入力はSTDINを介して渡されます。

これは、括弧の各ペアの内容を中括弧で囲み、その中のすべての項目に添え字を付けることにより機能します。

出力

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

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

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

TeX出力


1
私はあなたがRet​​inaを使用したことを誇りに思っています。これは箱の外で考えるのは素晴らしいことですが、それは出力がどのように見えるかということではありません。;)特に、これは代替の定式化に違反しています。「別の見方は、深さnの括弧が水平位置を維持しながら行nに移動することです。」しかし、純粋でルールに準拠したRetinaソリューションには非常に感銘を受け、そのための恩恵を与えるかもしれません。;)
マーティン・エンダー

In total the lines must not be longer than twice the length of the input string。行2から(\,{行4への変更}\,)は、出力がこれに適合することを意味します(ただし、垂直方向の深さはまだ間違っています:()
user22723

さて、私はルールに準拠したソリューションを作成することができました:)
user22723

1
良くやった。これは、あなたがチートな答えを今すぐ削除できることを意味すると思います。;)
マーティンエンダー

5

Java(登録商標)、232の 226 224 222バイト

ゴルフバージョン:

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

ロングバージョン:

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

入力文字列が最初に分析され、「(」および「)」を探してカウンターを加算/減算し、その値を格納して、配列内の括弧の深さを決定すると同時に、最深の深さを追跡します。次に、配列が分析されます。小さい値の括弧が最初に印刷され、最大値に達するまで行ごとに印刷が続けられます。

あとでゴルフをする方法を見つけるでしょう。


5

Javascript / ES6、97文字

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

使用法

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

説明

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

の代わりにn<m?console.log(o):0n<m&&console.log(o)1バイトを節約するを使用できます。
イスマエルミゲル

4

CJam、43 41 36バイト

あまりゴルフはしていませんが(私は思う)、ここに私の最初の試みがあります:

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

使い方

私はそれを非常に便利な事実使用しています)し、(それぞれインクリメントとデクリメントを意味CJamにします。したがって、単に深さを取得するために括弧を評価します。

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

こちらからオンラインでお試しください


4

オクターブ、85文字

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

これはナイーブアプローチの最適化であり、Matlabおよび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;

テーブルt はまだ存在しない場合もあり、すぐに任意の要素に割り当てることができ、この要素が存在するために必要な最小の寸法に再形成され、非常に便利です。


4

Perl、91 89 88 84 80 79バイト

$t=<>;{$_=$t;s/\((?{$l++})|.(?{--$l})/$^R==$c?$&:$"/ge;print,++$c,redo if/\S/}

4

Haskell、154バイト

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

他のHaskellソリューションと同じアイデアですが、多少短くなります。- 使用法:

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

3

J、46

他の「ゴルフ言語」ほど素晴らしいものではありませんが、私の弁護では、Jは文字列がひどいです。

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

文字列を関数の入力として受け取ります。Jでそれを行うより良い方法もおそらくあります。

使用法:

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

Jでこれを行う別の方法についての私の答えを参照しください。
FUZxxl15年

3
個人的には、Jは文字列に完全に適していると思います。配列について考える必要があります。
FUZxxl

3

ルビー、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]}}

説明:

->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バイト

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

インデント:

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

最終ループは短縮できると思いますが、読者への演習として残しておきます。;-)


古い、233バイトの回答:

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

インデント:

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

1年以上経っていることは知っていますが、「最後のループは短縮できると思いますが、読者に演習として残しておきます。;-)」; あなたは本当に正しいです。それはから変更することができるfor(x=0;x<l*l;x++)System.out.print((x%l==0?"\n":"")+m[x]);for(x=0;x<l*l;)System.out.print((x%l==0?"\n":"")+m[x++]);は-1バイト。また、代わりにフィールドの初期化時に削除p=x=0して使用するだけint p=0,x=0,で、さらに2バイト節約できます。合計で211バイトになります
ケビンCruijssen

3

C#、195バイト

最初にゴルフを試してください-私が何か間違ったことをしたなら大声で叫んでください。

SetCursorPositionを使用し、入力をコマンドライン引数として左から右に処理する代替C#バージョン。

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

フルラインではなく、オープン/クローズの括弧に基づいて書き込み位置を調整するのは楽しいと思いました。括弧を閉じると、書き込み前に位置が上に移動します。開いた括弧は、書き込み後にそれを下に移動します。SetCursorPositionを実行すると、5バイト節約されます。出力後にカーソルを次の行に移動すると、かなり余分に時間がかかります。

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

バッチ、356 335バイト

この課題に対するバッチソリューションが既に存在することは知っていますが、これはかなり多くのゴ​​ルフに使用されており、異なるアプローチを採用しているようです。最も重要なことは、他のバッチソリューションに少なくとも1つのpowershellコマンドが含まれていることです。この解決策はそうではありません。

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

バックスペース文字(U+0008ドットに続く2番目から最後の行(行12、列57)に)ます。これは、ここに投稿されたコードには表示されませんが、バイトカウントに含まれています。


他の誰かが実際にバッチで回答を送信します-Nice one +1
unclemeat

3

バッチ、424バイト

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

ゴルフをしていない:

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

例:

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

3

C、 118 117バイト

Cの別の答えですが、私のほうが短いです。

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

ゴルフされていないバージョン:

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

そしてそれは動作します!

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

1
かなりエレガントなソリューションですが、putchar(c-d?32:*p)1文字よりも短いですputchar(c==d?*p:32)
pawel.boczarski

2

Haskell、227バイト

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
演算子を使用していくつかのスペースを保存できます。たとえば、のn#[]代わりにm n []
フランキー


2

Lex、94バイト

Linuxコンソールコードに依存します。gccでは、の両方のインスタンスを\33実際のエスケープ文字で置き換えることにより、4バイトを切り取ることができます。

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

コンパイルして実行するには:

$ flex -o telescopic.c telescopic.l
$ gcc -o telecopic telescopic.c -lfl
$ ./telescopic
(()(()())()((())))(())
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
--- type ctrl-D ---
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.