使用给定的括号缩进字符串


16

给程序以下输入:

  1. 块开始字符列表
  2. 块结束字符列表
  3. 要格式化的字符串

使用以缩进的两个字符集分隔的块来格式化字符串。

格式化是在每个级别上用两个空格完成的,并且括号的放置如下例所示。您可以假定开头和结尾字符集是不相交的。

例如{[(<}])>作为和作为开始和结束字符集以及以下字符串:

abc{xyz{text[note{comment(t{ex}t)abc}]}}

预期以下输出:

abc
{
  xyz
  {
    text
    [
      note
      {
        comment
        (
          t
          {
            ex
          }
          t
        )
        abc
      }
    ]
  }
}

您可能没有对“括号”字符列表进行硬编码。但是,没有指定输入方式。您可以根据需要使用命令行参数或通过标准输入。


5
我们是否可以假设每个括号都有一个闭合括号,并且顺序相同?
胡安

程序是否必须支持作为参数给出的任何括号字符?例如,./program 'p' 'q' <<< '1p23p45q67q8' 还是只需要支持{[(<}])>
乔伊·亚当斯

@Joey,我认为没有,尽管那会更加令人印象深刻。
尼尔

joey:输入为1.打开括号字符2.close括号字符3.要缩进的字符串。胡安:我们可以假设,尽管代码不必依赖于此,但我的意思是,如果delim是左括号的一部分,则增加缩进,否则,如果右括号的一部分则减少缩进。
Prashant Bhate

1
@Phrasant Bhate:在输出中?
Lowjacker

Answers:


6

红宝石,106 101 96 95

s,e,i=$*
i.scan(/[#{z=Regexp.quote s+e}]|[^#{z}]*/){|l|puts'  '*(s[l]?~-$.+=1:e[l]?$.-=1:$.)+l}

输入是通过命令行提供的。


1
您可以使用~-j+=1代替来保存4个字符(j+=1;j-1)。此外,在所有位置使用$.代替j可以删除j=0,从而节省了另一个字符。
Ventero'7

6

Perl- 131 96 94字符

$i="";for$_(split/([\Q$ARGV[0]$ARGV[1]\E])/,$ARGV[2]){$i=~s/..// if/[\Q$ARGV[1]\E]/;print "$i$_\n"if$_;$i.='  'if/[\Q$ARGV[0]\E]/;}

似乎至少应该有消除通用表达式的空间,但这是处理示例以及乔伊·亚当斯(Joey Adams)关于任意括号的假设的快速入门。


实际上,还有很多改进的空间:

$_=pop;($s,$e)=map"[\Q$_\E]",@ARGV;for(split/($s|$e)/){print"  "x($i-=/$e/),"$_\n"if$_;$i+=/$s/}

...还有更多:

$_=pop;($s,$e)=map"[\Q$_\E]",@ARGV;map{print"  "x($i-=/$e/),"$_\n"if$_;$i+=/$s/}split/($s|$e)/

3

Mathematica(非代码高尔夫)

indent[str_String]:=Module[{ind,indent,f},
ind=0;
indent[i_]:="\n"<>Nest["    "<>ToString[#]&,"",i];
f[c_] :=  (indent[ind] <> c <> indent[++ind]) /; StringMatchQ["[({",___~~c~~___];
f[c_] := ( indent[--ind] <> c <>indent[ind])  /; StringMatchQ["])}",___~~c~~___];
f[c_] := (c <>indent[ind])       /; StringMatchQ[";,",___~~c~~___];
f[c_] := c  ;
f /@ Characters@ str//StringJoin
]

测试

indent["abc{xyz{text[note{comment(t{ex}t)abc}]}}"]
abc
{
    xyz
    {
        text
        [
            note
            {
                comment
                (
                    t
                    {
                        ex
                    }
                    t
                )
                abc
            }

        ]

    }

}

另外,可以使用以下函数来格式化mathematica表达式

format[expr_] := indent[expr // FullForm // ToString]

编辑(非代码高尔夫) ,通过对换行符的呈现方式进行细粒度控制进行更新

indent[str_String, ob_String, cb_String, delim_String] := 
  Module[{ind, indent, f, tab}, ind = 0; tab = "    ";
   indent[i_, tab_, nl_] := nl <> Nest[tab <> ToString[#] &, "", i];
   f[c_] := (indent[ind, "", " "] <> c <> indent[++ind, tab, "\n"]) /;StringMatchQ[ob, ___ ~~ c ~~ ___];
   f[c_] := (indent[--ind, "", " "] <> c <> indent[ind, tab, "\n"]) /;StringMatchQ[cb, ___ ~~ c ~~ ___];
   f[c_] := (c <> indent[ind, tab, "\n"]) /;StringMatchQ[delim, ___ ~~ c ~~ ___];
   f[c_] := c;
   f /@ Characters@str // StringJoin];
format[expr_] := indent[expr // InputForm // ToString, "[({", "])}", ";"];

format[Hold@Module[{ind, indent, f, tab}, ind = 0; tab = "    ";
 indent[i_, tab_, nl_] := nl <> Nest[tab <> ToString[#] &, "", i];
 f[c_] := (indent[ind, "", " "] <> c <> indent[++ind, tab, "\n"]) /;StringMatchQ[ob, ___ ~~ c ~~ ___];
 f[c_] := (indent[--ind, "", " "] <> c <> indent[ind, tab, "\n"]) /;StringMatchQ[cb, ___ ~~ c ~~ ___];
 f[c_] := (c <> indent[ind, tab, "\n"]) /;StringMatchQ[delim, ___ ~~ c ~~ ___];
 f[c_] := c;
 f /@ Characters@str // StringJoin]]

输出量

Hold [
    Module [
         {
            ind, indent, f, tab }
        , ind = 0;
         tab = "    ";
         indent [
            i_, tab_, nl_ ]
         := StringJoin [
            nl, Nest [
                StringJoin [
                    tab, ToString [
                        #1 ]
                     ]
                 & , "", i ]
             ]
        ;
         f [
            c_ ]
         := StringJoin [
            indent [
                ind, "", " " ]
            , c, indent [
                ++ind, tab, "\n" ]
             ]
         /;
         StringMatchQ [
            ob, ___~~c~~___ ]
        ;
         f [
            c_ ]
         := StringJoin [
            indent [
                --ind, "", " " ]
            , c, indent [
                ind, tab, "\n" ]
             ]
         /;
         StringMatchQ [
            cb, ___~~c~~___ ]
        ;
         f [
            c_ ]
         := StringJoin [
            c, indent [
                ind, tab, "\n" ]
             ]
         /;
         StringMatchQ [
            delim, ___~~c~~___ ]
        ;
         f [
            c_ ]
         := c;
         StringJoin [
            f / @
                 Characters [
                    str ]
                 ]
             ]
         ]

那几乎不是代码高尔夫球,它具有多个字符的名称indent。您的目标是最大程度的简洁代码还是可读性?如果确实是您的目标,则有多种方法可以缩短该代码。另外:“您可能不对“括号”字符列表进行硬编码。” 难道这不是您在这里所做的吗?无论如何,很遗憾听起来如此消极。这对我来说是对您自己挑战的奇怪回答。
Wizard先生

1
@ Mr.Wizard的代码不是golf,我已经添加了它作为我自己的参考(已更新,以使其更清楚)。我经常使用它来理解跨越一个页面的无格式数学代码
Prashant Bhate

3

JavaScript,255 227 205个字符

嘿,它的长度非常适合一个字节!:D

function(s,e,t){R=eval.bind(0,"Array(n).join(' ')");for(i=n=0,b=r='';c=t[i++];)~s.indexOf(c)?(r+=b,b='\n'+R(++n)+c+'\n '+R(++n)):~e.indexOf(c)?b+='\n'+((n-=2)?R()+' ':'')+c+'\n'+(n?R()+' ':''):b+=c;return r+b}

这是一个函数,将开始字符,结束字符和文本传递给它。


您自己的编辑评论已被您使用。:D
门把手

@Doorknob:我……我以为我从未做到过。D:对不起。(您在狩猎吗?)
Ry-

@Doorknob:感谢您提醒我有关此事;缩短了:)
Ry-

不,我不是在打猎,只是偶然发现了这个问题,但是我决定这么做:O:P
Doorknob

2

Python – 162个字符

i=f=0
s=""
l,r,z=[raw_input()for c in'   ']
o=lambda:s+("\n"+"  "*i)*f+c
for c in z:
 if c in l:f=1;s=o();i+=1
 elif c in r:i-=1;f=1;s=o()
 else:s=o();f=0
print s

请注意,该任务要求将两组括号作为输入的一部分,而不是硬编码。
乔伊(Joey)

@Joey指出,我会在一段时间内解决这个问题。谢谢
胡安

2

Python 2.7.X-136个字符

import sys
a,c=sys.argv,0
for i in a[3]:
 if not(i in a[2]):print ' '*c+i
 else:print ' '*(c-4)+i
 if i in a[1]:c+=4
 if i in a[2]:c-=4

用法:$ ./foo.py'('')''(ab(cd(ef)gh)ij)'

结果输出:

(
    a
    b
    (
        c
        d
        (
            e
            f
        )
        g
        h
    )
    i
    j
)

print报表后是否需要空格?
扎卡里

2

Ç - 213 209

我讨厌愚蠢的错误...>。<

#include<stdio.h>
#include<string.h>
int main(int i,char**s){for(char q,r,c,t,a=0;~(c=getchar());t=q|r){q=!!strchr(s[1],c);a-=r=!!strchr(s[2],c);for(i=0;t|q|r&&i<2*a+1;putchar(i++?' ':'\n'));a+=q;putchar(c);}}

从第一个命令行参数读取左括号,从第二个参数读取右括号,并在stdin上输入缩进。

精美印刷并评论:

int main(int i, char **s) {
  for (char q, r, /* is left-paren? is right-paren? */
            c,    /* character read from input */
            t,    /* last char was a paren-char */
            a=0;  /* indentation */
       ~(c = getchar());
       t = q|r) {
         q = !!strchr(s[1],c);
    a -= r = !!strchr(s[2],c);
    for (i=0; t|q|r && i<2*a+1; putchar(i++? ' ' : '\n'));
    a += q;
    putchar(c);
  }
}

1

C(159225个字符)

#define q(s,c)strchr(s,c)
#define p(i,j,k)printf("\n%*s%c%c%*s",i,"",*s,k,j,"")
g(char*b,char*e,char*s){int i;for(i=0;*s;s++)q(b,*s)?p(i-2,i+=2,'\n'):q(e,*s)?q(b,*(s+1))||q(e,*(s+1))?p(i-=2,i-2,0):p(i-=2,i-2,'\n'):putchar(*s);}

仅仅为了用空行来修复错误,我花了66个额外的字符:

#define p(i,j)printf("\n%*s%c\n%*s",i,"",*s,j,"")
f(char*b,char*e,char*s){int i;for(i=0;*s;s++){strchr(b,*s)?p(i-2,i+=2):strchr(e,*s)?p(i-=2,i-2):putchar(*s);}}

一种相当快捷和肮脏的方法。它有一个在连续的右括号之间产生空行的错误,但否则它可以完成工作(或者我认为)。我将在本周的某个时候重新访问它,以寻求更好,更清洁的解决方案。

char * b是开头括号集,char * e是结尾括号集,而char * s是输入字符串。


1

Perl-69字节

TMTOWTDI使代码简单

#!perl -p
s/([[{(<])|([]})>])|\w+/"  "x($1?$t++:$2?--$t:$t)."$&
"/ge

3
您应该将括号作为输入,而不是对其进行硬编码。
加雷斯

1

Scala(2.9),211个字符

object P extends App{def x(j:Int)={"\n"+"  "*j}
var(i,n)=(0,"")
for(c<-args(2)){if(args(0).exists(_==c)){print(x(i)+c)
i+=1
n=x(i)}else{if(args(1).exists(_==c)){i-=1
print(x(i)+c)
n=x(i)}else{print(n+c)
n=""}}}}

1

Perl- 89 85字节

Hojung Youn答案的一种版本,它通过两个参数接受块字符。

#!perl -p
BEGIN{$b=pop;$a=pop}s/([$a])|([$b])|\w+/"  "x($1?$t++:$2?--$t:$t)."$&
"/ge

像这样称呼:

perl golf.pl<<<'abc{xyz{text[note{comment(t{ex}t)abc}]}}' '[{(<' ']})>'

非常好的概念,@ Hojung和Sorpigal。但是,它有点脆弱。例如,在close-paren参数中交换[]和},然后[]关闭字符类,从而导致不匹配的paren错误。同样,假设开放集以^开头,可能与封闭集中的v匹配;您将获得预期的[$ a]类的补充。这就是为什么我在答案中使用\ Q ... \ E的原因。非零字符的\ w +适用于该示例,但是像'x(foo-bar)y''('')'这样的输入呢?当然,尚不清楚代码是否需要处理类似的事情。
DCharness

1

Python3,184182 字符

import sys
_,p,q,t=sys.argv
i,f,x=0,1,print
for e in t:
 if e in p:f or x();x(' '*i+e);i+=2;f=1
 elif e in q:f or x();i-=2;f=1;x(' '*i+e)
 else:not f or x(' '*i,end='');f=x(e,end='')

例:

$ python3 ./a.py '{[(<' '}])>' 'abc{xyz{text[note{comment(t{ex}t)abc}]}}'
abc
{
  xyz
  {
    text
    [
      note
      {
        comment
        (
          t
          {
            ex
          }
          t
        )
        abc
      }
    ]
  }
}

heinrich5991建议通过将第二行更改为_,p,q,t=sys.argv
Peter Taylor

1

Groovy,125岁

p=args;i=0;s={a,b->"\n"+"\t"*(b?i++:--i)+a+"\n"+"\t"*i};p[0].each{c->print p[1].contains(c)?s(c,1):p[2].contains(c)?s(c,0):c}

您可以将脚本保存在文件indent.groovy中,并尝试使用:
groovy indent.groovy“ abc {xyz {text [note {comment(t {ex} t)abc}]}}}”“” {[(“ ]}“


在看到您的答案之前,我尝试了一个小时的常规操作,我使用了类似的方法,但是我的方法比您的方法长得多,所以我什至不愿意发布。:)
Fels

1

Python-407

from sys import*;o=argv[1];c=argv[2];t=argv[3];p=0;n=False;a=lambda:h not in e;b=lambda s:print(s+(" "*p)+h);r="";e=o+c
for h in t:
 for k in o:
  if h==k:
   if(r in e)and(r!=""):b("")
   else:b("\n")
   p+=2;n=True;break
 for k in c:
  if h==k:
   p-=2
   if(r in e)and(r!=""):b("")
   else:b("\n")
   n=True;break
 if a()and n:print((" "*p)+h,end="");n=False
 elif a():print(h,end="")
 r=h

该程序的未发布版本:

import sys

open_set = sys.argv[1]
close_set = sys.argv[2]
text = sys.argv[3]
spaces = 0
newline = False
a = lambda : char not in b_set
b = lambda s: print(s + (" " * spaces) + char)
prev = ""
b_set = open_set + close_set

for char in text:
    for bracket in open_set:
        if char == bracket:
            if (prev in b_set) and (prev != ""):
                b("")
            else:
            b("\n")
        spaces += 2
        newline = True
        break
    for bracket in close_set:
        if char == bracket:
            spaces -= 2
            if (prev in b_set) and (prev != ""):
                b("")
            else:
                b("\n")
            newline = True
            break
    if a() and newline:
        print((" " * spaces) + char, end="")
        newline = False
    elif a():
        print(char, end="")
    prev = char

程序的参数是(按顺序):左括号,右括号和要缩进的文本。

示例($是命令行提示符):

$ python indent.py "{[(<" "}])>" "abc{xyz{text[note{comment(t{ex}t)abc}]}}"
abc
{
  xyz
  {
    text
    [
      note
      {
        comment
        (
          t
          {
            ex
          }
          t
        )
        abc
      }
    ]
  }
}

0

D(300)

C[] i(C,S)(ref S s,C p){if(!*s)return[];static C[] w;w~=" ";C[] r;C c=s[0];while(c!=p){s=s[1..$];r~=(c=='{'||c=='['||c=='<'?"\n"~w~c~"\n"~i(s,cast(char)(c+2)):c=='('?"\n"~w~c~"\n"~i(s,')'):[c]);c=*s;}w=w[1..$];if(*s)s=s[1..$];c=*s;return" "~w~r~"\n"~w~(c=='}'||c==']'||c=='>'||c==')'?[p]:p~"\n"~w);}

需要以空值终止的字符串进行边界检查(否则,if(*s)需要更改为if(s.length)


请注意,该任务要求将两组括号作为输入的一部分,而不是硬编码。
乔伊(Joey)

0

爪哇

codegolf version!假设我们有包含delims 的split()这个版本,

public static String indent(String input, String openPars,
        String closingPars) {
    String re = "["
            + (openPars + closingPars).replace("[", "\\[").replace("]",
                    "\\]") + "]";
    String[] split = inclusiveSplit(input, re, 0);
    int indent = 0;
    StringBuilder sb = new StringBuilder();
    for (String string : split) {
        if (StringUtils.isEmpty(string))
            continue;
        if (closingPars.indexOf(string) != -1) {
            indent--;
        }
        sb.append(StringUtils.repeat(" ", indent * 2));
                    sb.append(string);
                    sb.append("\n");
        if (openPars.indexOf(string) != -1) {
            indent++;
        }
    }
    String string = sb.toString();
    return string;
}

2
StringUtils不属于标准JDK。
st0le 2011年

0

C 284非空格字符

我不喜欢混淆,但是...

#include<cstdio>
#include<cstring>
#define g printf
#define j char
int main(int a,j**b){int c=0;for(j*f=b[3];*f!='\0';++f){if(strchr(b[1],*f)!=0){g("\n%*c\n%*c",c,*f,c+2,'\0');c+=2;}else if(strchr(b[2],*(f))!=0){c-=2;g("\n%*c",c,*f);if(strchr(b[2],*(f+1))==0)g("\n%*c",c,'\0');}else putchar(*f);}}

用法:./program start_brackets end_brackets string_to_parse


0

PHP (187)(153)

function a($s,$o,$e){while(''!=$c=$s[$i++]){$a=strpbrk($c,$o)?2:0;$b=strpbrk($c,$e)?2:0;echo ($a+$b||$r)?"\n".str_pad('',$t-=$b):'',$c;$t+=$a;$r=$a+$b;}}

函数将字符串,打开定界符,结束定界符作为参数。


0

C,256

参数:

  • e是结尾字符,
  • n是缩进,
  • b打开括号,
  • d右括号。

我将代码分解以避免水平滚动条。

#define r char
#define P(c) putchar(c);
#define N P(x)
#define W printf("%*s",n,"");
r*s,x='\n';i(r e,int n,r*b,r*d){r*t=s,*p;int l=0;W while(*s!=e)    
{if(p=strchr(b,*s)){if(s!=t){N W}P(*s++)N i(d[p-b],n+2,b,d); N W 
P(*s++);l=1;}else{if(l){N W l=0;}P(*s++)}}}

完整程序为363个字符。

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define r char
#define P(c) putchar(c);
#define N P(x)
#define W printf("%*s",n,"");
r*s,x='\n';i(r e,int n,r*b,r*d)
{r*t=s,*p;int l=0;W while(*s!=e)
{if(p=strchr(b,*s)){if(s!=t){N W}
P(*s++)N i(d[p-b],n+2,b,d); N W
P(*s++);l=1;}else{if(l){N W l=0;}
P(*s++)}}}main(int c,r*v[]){s =
v[3];i('\0',0,v[1],v[2]);}

0

VB.net(?c)

语言不适合打高尔夫球,因此我使用了一种不常见的方法。使用跟踪侦听器输出到控制台。

Imports System.Diagnostics.Debug
Module Module1
  Sub Main(args() As String)
    IndentText(args(0), args(1), args(2)) 'openings, closings, text)
  End Sub
  Sub IndentText(o As String, e As String, t As String)
    Dim x = 0
    Listeners.Add(New Diagnostics.ConsoleTraceListener)
    IndentSize = 2
    For Each c In t
      If o.Contains(c) Then
        WriteLine("")
        WriteLine(c)
        Indent()
        x = 1
      ElseIf e.Contains(c) Then
        If x = 0 Then WriteLine("")
        Unindent()
        WriteLine(c)
        x = 1
      Else
        Write(c)
        x = 0
      End If
    Next
  End Sub
End Module

使用命令行参数作为输入

args(0) is the indenting chars
args(1) is the undenting chars
args(2) is the text to be indented.

0

Powershell,146字节

param([char[]]$s,[char[]]$e,[char[]]$f)$f|%{}{if($_-in$s){$o;'  '*$i+$_;$o='  '*++$i;}elseif($_-in$e){$o;'  '*--$i+$_;$o='  '*$i}else{$o+=$_}}{$o}

空洞的解释

param([char[]]$start,             # Cast as array of Chars
      [char[]]$end,
      [char[]]$string)
$string | foreach-object { } {    # For every char in string. Empty Begin block
    if ( $_ -in $start ) {        # If char is in start
        $o                        # Print stack ($o)
        '  ' * $i + $_            # Newline, indent, insert start char
        $o = '  ' * ++$i          # Set stack to ident (incremented)
    } elseif ( $_ -in $end ) {    # If char is in end
        $o                        # Print stack
        '  ' * --$i + $_          # Newline, decrement indent, insert end char
        $o = '  ' * $i            # Set stack to indent
    } else {
        $o+ = $_                  # Otherwise add character to stack
    }
} { $o }                          # Print remaining stack (if any)

0

C,181个字符

#define d(m,f)if(strchr(v[m],*s)){puts("");for(j=f;j--;)printf("  ");}
i;main(j,v,s)char**v,*s;{for(s=v[3];*s;s++){d(1,i++)d(2,--i)putchar(*s);d(1,i)if(!strchr(v[2],*(s+1)))d(2,i)}}

几乎是可以想到的最直接的方法。遍历字符串(v [3]),如果它是左括号(如v [1]中定义),则增加缩进级别,如果它是右括号(如v [2]中定义),则减小缩进级别。


-1

C,114 121

main(i,x,s,c){while(~(c=getchar()))(s=x)|(x=2*!!strchr("(){}[]<>",c))?s=c-1&x,i-=x-2*s,printf("\n%*c",i-s,c):putchar(c);}

不是很好,但是解决方案..根据输入是否以括号开头/结尾,可能在一行之前/之后出现一个空行。

有了新的限制,这种方法几乎对高尔夫球没有用。


缩进的圆括号没有足够的缩进,并且在连续的圆括号之间输出空行。
乔伊(Joey)

@joey已修复,谢谢您的反馈!
esneider

当括号应该作为输入的一部分时,它仍然对括号进行硬编码。当前,所有答案均不符合规范。
乔伊,
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.