伸缩括号


79

考虑正确平衡的括号的非空字符串:

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

我们可以想象每对括号代表一个折叠的伸缩式结构中的圆环。因此,让我们扩展望远镜:

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

另一种看待它的方法是将深度为n的括号移到第n行,同时保持其水平位置。

您的任务是采用这样的平衡括号字符串,并生成扩展版本。

您可以编写程序或函数,通过STDIN(或最接近的等效项),命令行参数或函数参数获取输入,并通过STDOUT(或最接近的等效项),返回值或函数(out)参数生成输出。

您可以假定输入字符串有效,即仅包含正确平衡的括号。

您可以在每行上打印尾随空格,但不要在多余的空格前打印多余的空格。总的来说,这些行的长度不能超过输入字符串长度的两倍。您可以选择打印单个尾随换行符。

例子

除了上面的示例,这里还有更多的测试用例(输入和输出用空行分隔)。

()

()
(((())))

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

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

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

相关挑战:

  • 地形字符串,要求您提供此挑战中输出的本质补充。
  • PhiNotPi最近发布了 “代码解释格式化程序”,它是对这一挑战中思想的广泛概括。(实际上,PhiNotPi对他的想法的最初描述是激发这一挑战的原因。)

排行榜

呵呵,这次活动吸引了很多人,因此这里有一个Stack Snippet,可用来生成常规排行榜和获胜者语言概览。

为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

# Language Name, N bytes

N您提交的文件大小在哪里。如果您提高了分数,则可以通过打败旧分数保持标题。例如:

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


17
备用标题:对字符串进行去Lisp化处理。:P
Alex A.

1
输出的颜色是否有限制?
Matteo Italia 2015年

1
@MartinBüttner:没关系,我找到了一种更清洁的方法。让我们只说我以前的想法会削掉一个字节,使所有封闭的括号在青色上闪烁蓝色... :-)
Matteo Italia 2015年

8
@MatteoItalia哦,天哪,我很高兴没有发生。;)
Martin Ender 2015年

12
@MatteoItalia:发布该版本!值得一看。
user2357112

Answers:


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运行前几乎是强制性的;
  • 颜色丑陋;这是将下一个字符作为颜色属性回收以在此处和此处保存两个字节的结果;
  • 代码假定bh=0且启动时方向标记清除,均未记录;OTOH bx在我看到的所有DOS变体(DosBox,MS-DOS 2,FreeDOS)中都显式设置为零,并且在我测试过的所有位置,标志都已确定。

在此处输入图片说明


刚刚验证了这一点。是的,它有效。您确定需要这样做cld吗?
FUZxxl 2015年

@FUZxxl:即使没有它,在DosBox上它也可以正常工作,但是从其来源看,它表明标志是从DOS和TRS之前发生的任何事件中保留下来的,因此可能需要对其进行安全保护。无论如何,那只是一个字节,真正的收获是杀死那些大的(至少= 4个字节)add/ 中的至少一个sub
Matteo Italia

嗯...不知道,真的。
FUZxxl 2015年

您可以更改loploop
mbomb007

@ mbomb007:也许吗?我不确定标签和汇编指令nasm之间是否存在歧义,所以我只是像其他人一样编写。looplooplop
Matteo Italia 2015年

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

1
(我通常会添加该函数的示例调用,以便没有经验的用户也可以尝试一下。)
randomra 2015年

这种解决方案使我的头部受伤:')
Nic Hartley

@QPaysTaxes我认为这是一种赞美。
FUZxxl

@FUZxxl是。这也是根据您的答案中出现的一系列字符的双关语。
Nic Hartley

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。

让我们逐行浏览代码:

/* 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]”是无效的,因为您无法定义像这样的可变大小的数组,但是距我尝试了15年以来,那种在C.
SPARR

@Sparr我的编译器甚至没有发出警告。我相信这是C99中的“官方”标准。我将尝试为此找到参考。
BrainSteel

1
@Sparr 是参考。
BrainSteel 2015年

谢谢。在这方面,事情似乎确实发生了变化,大约在15年之前
送出

1
@CoolGuy它将,但是在随后的调用时fm将不会重置为0。这被视为“破坏环境”,在这里是非法的。
BrainSteel

15

视网膜+重击,27个字节(14 + 10 + 3 = 27)

这利用了ANSI Escapes:

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

等同于sed -e "s/(/(\\\e[B/g;s/)/\\\e[A)/g"。该\e[B逃逸代码装置移动光标下移一行,并且\e[A装置向上移动光标一行,所以该解决方案简单地后和每个嵌套对括号的开始和结束之前插入这些代码。输入通过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字节数将是公平的。
Martin Ender

@MartinBüttner应该是printf $()printf $(Retina )
jimmy23013 2015年

1
视网膜那是什么东西?
FUZxxl 2015年

2
@FUZxxl这是我自己的基于正则表达式的编程语言。见GitHub
马丁·恩德

2
为什么\eprintf?您可以简单地将控制字符放在替换模式中。
丹尼斯

15

TI-BASIC,69 60 56 55字节

尽管它是在84+ C Silver Edition上编写的,但它适用于TI-83 + / 84 +系列计算器。

由于包含了VAT +尺寸信息,该程序显示为较大的按计算器。另外,这里有超过56个字符;之所以是56字节,是因为所有超过一个字符的命令都被压缩为大小为一或两个字节的令牌。

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削减了另一个字节!(同样是他从60跳到56。)


4
啊,我的第一门编程语言。感谢您的怀旧,哈哈。
亚历克斯·普里查德

1
仍在为高中数学课程编程TI,这对于构建内置的公式非常有用,该公式将为您计算测试和作业。
Elias Benevedes 2015年

1
如果您四处移动,可以使用cos(piAns技巧来保存另一个字节。
lirtosiast,2015年

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)

调用like f("((()())()(()(())()))"),输出到STDOUT。

说明

我们从开始n = 0。对于输入行中的每个字符:

  • 如果char为(,则我们先加n空格,然后递增n
  • 如果char为),则我们递减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)

没有拉链,只需用适当填充ljust。这个似乎有打高尔夫球的潜力。


8

R,151127个字符

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

它以stdin读取字符串,将其拆分为单个字符的向量,计算(and 的累加和),将前者与后者相减(带有滞后),从而计算每个括号的“级别”。然后针对每个级别,将相应的括号或空格打印到标准输出。

感谢@MickyT帮助我大大缩短了它!


2
+1不错而优雅的解决方案。您可以通过替换for(i in n)cat(ifelse(D[i]-j," ",S[i]));cat("\n")为保存6 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已经是允许索引的布尔向量)。我不知道争论fillcat,这是一个漂亮的把戏!感谢您让我将其缩短为惊人的24个字符!!
plannapus 2015年

8

C,58 53 52 51 49字节

利用ANSI转义序列移动光标位置。

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

如果不使用gcc或其他支持的编译器,\e则可以将其替换\x1B为总共2个额外的字节。\e[A将光标向上\e[B移动一行,然后将光标向下移动一行。不必\e[B向下移动一行,因为使用ASCII垂直制表符0xB或时要短两个字节\v

从问题出发,假设输入字符串仅包含(平衡)括号,因此使用来检查字符的奇偶性&1足以区分()


7

点子,53个字节

点子是我发明的一种代码高尔夫语言。第一版于周六发布,因此我可以正式试用一下!随着高尔夫语言的发展,下面的解决方案并不具有很强的竞争力,但这部分是因为我尚未实现zip和max之类的东西。

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

期望将括号字符串作为命令行参数。

“非高尔夫”版本:

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必须使用infix运算符,因此语法在某种程度上更接近C及其派生词。它还借鉴了基于函数和基于数组的编程的思想。请参阅存储库以获取更多文档。

该程序首先z通过将函数映射到输入字符串来生成深度列表(将其存储在其中)a。全局变量v跟踪当前级别。(a-gPip中的变量是函数局部变量,但是h-z全局变量。v由于它已预先初始化为-1,因此非常方便。)

接下来,我们使用While循环生成并打印每一行,直到生成的行将包含所有空格为止。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-JdJ:如果J不是所有空格,请打印出来。

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,并提出了新的字符串z,只包含的字符s的深度i。这是通过增加或减少进行i跟踪当前深度,并且当当前的字符添加i0调整括号的类型,以及以其他方式增加的空间。

然后,打印并递归到下一个,i除非当前行是所有空格。注意,由于parens是平衡的,因此iafter循环与开始时相同。

Python 3除了的字符外,其余相同print(z)


5

作弊:( Retina + TeX,N个字节作弊:(

仅当您使用MathJax或某些其他TeX渲染(?)输出时才有效(当前已对此SE禁用::(

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

每行应该在不同的文件中,但是您可以使用Retina -e "\(" -e "({" -e "\)" -e "})" -e "\{\(" -e "_{("(或等效的sed命令sed -e "s/(/({/g;s/)/})/g;s/{(/_{(/g")对其进行测试。输入通过STDIN传递。

通过将每对括号的内容括在括号中,然后在其中的所有项下标,可以起作用。

输出量

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

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

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

TeX输出


1
对于您使用了Retina,我感到很受宠若惊,这是一种很好的即席即用的想法,但这并不是输出应该看起来的样子。;)特别是违反了另一种说法:“另一种看待方式是将深度n的括号移到第n行,同时保持其水平位置。” 纯粹的,符合规则的Retina解决方案会让我印象深刻,并且可能会为此提供奖励。;)
Martin Ender

In total the lines must not be longer than twice the length of the input string。将行2更改为(\,{行4 }\,),将输出更改为4 (尽管垂直深度仍然错误:()
user22723 2015年

好吧,我设法制定了符合规则的解决方案
:)

1
不错的工作。我想这意味着您可以立即删除作弊的答案。;)
Martin Ender 2015年

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):0,您可以使用n<m&&console.log(o)节省1个字节。
Ismael Miguel

4

CJam,43 41 36字节

我不太喜欢打高尔夫球,但是这是我的第一次尝试:

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

这个怎么运作

我使用一个非常方便的事实,即CJam )(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/}
  • $ t是输入字符串。
  • $ c是我们要在当前行上打印的深度。
  • $ l是遇到括号后的深度。
  • $ l在正则表达式嵌入式代码块中更新。
  • $ ^ R是最新代码块的结果。

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.这样做的另一种方式
FUZxxl

3
就个人而言,我认为J非常适合于字符串。您只需要考虑数组。
FUZxxl 2015年

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

我知道已经有一年多了,但是“我想最后的循环可能会缩短,但我会将其留给读者练习。;-)” 你确实是对的。它可以被改变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再保存2个字节,而仅int p=0,x=0,在字段初始化时使用。总共变成211个字节
凯文·克鲁伊森

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

我认为基于打开/关闭括号而不是全行来调整写入位置会很有趣。在写之前,关闭括号将位置上移;写完后,打开paren将其向下移动。操作SetCursorPosition可节省五个字节。将光标移动到输出之后的下一行会花费很多时间。

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

批次,356335字节

我知道已经存在一个针对该挑战的批处理解决方案,但是这一解决方案的使用率要高得多,并且似乎采取了不同的方法。最重要的是,另一个批处理解决方案至少包含一个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点后(倒数第12行,第57列)的倒数第二行上有一个退格字符()。这在此处发布的代码中不可见,但包含在字节数中。


实际有人以批处理的方式提交答案-不错的+1。
2015年

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)比短一个字符putchar(c==d?*p:32)
pawel.boczarski 2015年

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 []
弗兰基(Franky)2015年

2

Perl,76个字节

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

use strict这里没有:)


2

Lex,94个字节

取决于Linux控制台代码。使用gcc,您可以通过将两个实例替换\33为实际的转义字符来减少四个字节。

%%
 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 ---
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.