Введіть рядок за допомогою заданих дужок


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 Adams

@Joey, я б припустив, що ні, хоча це буде ще більш вражаючим.
Ніл

joey: вхідні символи 1. відкриті дужки 2.закрити символи дужок 3. рядок до відступу. Хуан: ми можемо припустити, що, хоча код не потребує покладання на це, я маю на увазі, якщо delim є частиною відкриття символів дужок, збільшення відступу, інакше, якщо частина закритих дужок дужок зменшує відступ.
Prashant Bhate

1
@Phrasant Bhate: А у виході?
Lowjacker

Відповіді:


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
Ви можете зберегти 4 символи, використовуючи ~-j+=1замість (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

Математика (без коду гольф)

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]

EDIT (код без гольфу) Оновлено з дрібним детальним контролем за способом надання нових рядків

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. Чи є ваша мета максимально коротким кодом чи читабельністю? Існує кілька способів скоротити цей код, якщо це справді ваша мета. Також: "Ви можете не жорстко кодувати список символів" в дужках "." все-таки це не саме те, що ви тут зробили? У всякому разі, шкода, що звучить так негативно; це просто вражає мене дивною відповіддю на твій власний виклик.
Mr.Wizard

1
@ Mr.Wizard не гольф з кодом, я додав його для власної довідки [оновлено, щоб було зрозуміло]. Я часто використовую його для розуміння неформатованого математичного коду, який охоплює більше сторінки
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: Я ... я думав, що ніколи цього не робив. Д: Мені так шкода. (Ви полювали?)
Ри-

@Doorknob: і дякую, що нагадали про це; скорочено :)
Ри-

Ні, я не полював, просто натрапив на це питання, але я вирішив, і я виявив це : O: P
Дверна ручка

2

Пітон - 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

@ Джої зауважив, я з часом вирішуся, щоб виправити це. Спасибі
Хуан

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висловлювань?
Zacharý

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 ( 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 зайвих символів просто, щоб виправити помилку з порожніми рядками :( Чесно кажучи, мені потрібен новий підхід, але я зараз зателефоную це.

#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

Скала (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 байт

Версія відповіді Ходжунга Юна, яка приймає символи блоку за допомогою двох аргументів.

#!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. Хоча це трохи крихко. Наприклад, поміняйте місцями] і} в аргументі близько-батьків, і] закриває клас символів, що призводить до незрівнянної помилки батьків. Аналогічно, припустимо, відкритий набір починається з ^, можливо, щоб відповідати v у близькому множині; ви отримаєте додаток до призначеного класу [$ a]. Ось чому я використав \ Q ... \ E у своїй відповіді. \ W + для не батьківських символів працює для прикладу, а як щодо введення типу "x (foo-bar) y '' ('')"? Звичайно, не ясно, що з кодом потрібно обробляти щось подібне.
DCharness

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 запропонував зберегти двох символів, змінивши другий рядок на_,p,q,t=sys.argv
Пітер Тейлор

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}]}}" "{[(" ") ]} "


Я спробував довгий час, коли я побачив вашу відповідь, я застосував подібний підхід, але мій набагато довший, ніж ваш, тому я навіть не буду турбуватися. :)
Fels

1

Пітон - 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

Java

Номери codegolf version! Якщо припустити, що у нас є версія 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

@joey виправлено, дякую за відгук!
esneider

Він все ще жорстко кодує дужки, хоча вони повинні бути частиною вводу. В даний час всі відповіді не відповідають специфікації.
Joey
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.