与えられた括弧を使用して文字列をインデントします


16

プログラムへの次の入力がある場合:

  1. ブロック開始文字のリスト
  2. ブロック終了文字のリスト
  3. フォーマットする文字列

インデントされた2つの文字セットで区切られたブロックで文字列をフォーマットします。

フォーマットはレベルごとに2つのスペースを使用して行われ、下の例に示すように括弧が配置されます。開始文字と終了文字のセットがばらばらであると仮定することができます。

用など{[(<}])>開口部と文字セットを閉じると、次の文字列として:

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.括弧文字を閉じます3.インデントする文字列。Juan:コードはそれに依存する必要はありませんが、delimが開き括弧文字の一部である場合、インデントを増やす場合、閉じ括弧文字の一部がインデントを減らす場合、ということです。
のPrashant Bhate

1
@Phrasant Bhate:そして出力には?
ロージャッカー

回答:


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、を削除して別のキャラクターを保存できます。
ヴェンテロ

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

少なくとも一般的な表現を排除する余地があるように思われますが、例を扱い、ジョーイ・アダムスが任意の括弧について仮説を立てるのは簡単です。


実際、多くの改善の余地がありました。

$_=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
            }

        ]

    }

}

ボーナスとして、次の関数を使用して数学表現をフォーマットできます。

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。あなたの目標は最大限に簡潔なコードですか、それとも可読性ですか?それが本当にあなたの目標であるならば、そのコードを短くする多くの方法があります。また、「「括弧」文字のリストをハードコーディングすることはできません。」まだあなたがここでやったことではありませんか?とにかく、とても否定的に聞こえて申し訳ありません。それはあなた自身の挑戦に対する奇妙な答えとして私を襲っただけです。
ミスターウィザード

1
@ Mr.Wizardはコードゴルフではなく、自分の参照用に追加しました[明確にするために更新]。私は頻繁にページを超えるまたがる未フォーマットMathematicaコードを理解するためにそれを使用
のPrashant Bhate

3

JavaScript、255 227 205文字

ちょっと、その長さは1バイトに完全に収まります!: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-

ありません私はこの質問につまずいたが、私はすることを決めた、と私が見つけた、狩猟されませんでした。この P:O:
ドアノブ

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

タスクは、ハードコードではなく、入力の一部になるように2組の括弧を呼び出すことに注意してください。
ジョーイ

@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ステートメントの後にスペースが必要ですか?
ザカリー16

2

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

最初のコマンドライン引数から左括弧を読み取り、2番目の引数から右括弧を読み取り、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(159 225文字)

#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文字余分にコストがかかりました:(率直に言って、私は新鮮なアプローチが必要ですが、今のところ1日と呼びます。

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

2つの引数を介してブロック文字を受け入れる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引数の]と}を交換すると、]が文字クラスを閉じ、一致しない括弧エラーが発生します。同様に、オープンセットが^で始まり、おそらくクローズセットのvに一致するとします。目的の[$ a]クラスの補完を取得します。だからこそ、答えに\ Q ... \ Eを使用しました。非括弧文字の\ w +はこの例では機能しますが、 'x(foo-bar)y' '(' ')'のような入力はどうでしょうか?もちろん、コードがそのようなものを処理する必要があるかどうかは明らかではありません。
-Dチャーネス

1

python3、184の 182文字

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は、2行目を次のように変更して2人のキャラクターを保存することを提案しました_,p,q,t=sys.argv
Peter Taylor

1

グルーヴィー、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}]}}" "{[(" ") ]}」


私はあなたの答えを見る前に1時間グルーヴィーで試しました、私は同様のアプローチを使用しましたが、私のものはあなたのものよりもはるかに長いので、投稿することさえしません。:)
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);}

境界チェックのためにnullで終了する文字列がif(*s)必要です(そうでない場合はに変更する必要がありますif(s.length)


タスクは、ハードコードではなく、入力の一部になるように2組の括弧を呼び出すことに注意してください。
ジョーイ

0

Java

ノンcodegolf version!delimを含む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

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が修正され、フィードバックをありがとう!
esneider

括弧は入力の一部である必要がありますが、それでも括弧をハードコーディングします。現在、すべての回答は仕様に準拠していません。
ジョーイ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.