Розширення брекета!


36

Ваше завдання полягає в тому, щоб розширити деякі дужки у вході програми, як показано:

  1. Знайдіть рядок s між двома співпадаючими дужками [і ]з однозначною цифрою n після дужки, що закривається.
  2. Зніміть дужки.
  3. Замініть s себе повтореним n разів. (Якщо n дорівнює 0, просто видаліть s .)
  4. Перейдіть до кроку 1, поки у введенні не буде більше відповідних дужок.

Додаткові правила та пояснення:

  • Ви будете брати вклад і давати вихід будь-якими дозволеними засобами.
  • Доступний новий рядок у висновку.
  • Вам потрібно лише обробляти друкований ASCII на вході.
  • Можна вважати , що все дужки збігаються, тобто ви ніколи не будете отримувати вхід []]]]або [[[[].
  • Ви можете припустити, що кожна закриваюча дужка ]має цифру після неї.

Тестові приклади:

Input                -> Output
[Foo[Bar]3]2         -> FooBarBarBarFooBarBarBar
[one]1[two]2[three]3 -> onetwotwothreethreethree
[three[two[one]1]2]3 -> threetwoonetwoonethreetwoonetwoonethreetwoonetwoone
[!@#[$%^[&*(]2]2]2   -> !@#$%^&*(&*($%^&*(&*(!@#$%^&*(&*($%^&*(&*(
[[foo bar baz]1]1    -> foo bar baz
[only once]12        -> only once2
[only twice]23456789 -> only twiceonly twice3456789
[remove me!]0        -> 
before [in ]2after   -> before in in after

Оскільки це , найкоротша відповідь на кожній мові виграє. Удачі!



13
Вам слід поставити черговий виклик, щоб стиснути рядок назад до найкоротшого формату
— Jo King

Чи варто чітко заявляти, що ваша струна sніколи не повинна містити інших дужок? Наприклад, спроба вирішити [Foo[Bar]3]2розширення рядка в Foo[Bar3 рази призведе до недійсного стануFoo[BarFoo[BarFoo[Bar]2
— BradC

@BradC все залежить від того, як ти вирішиш реалізувати завдання.
— MD XF

Чи означає це, що на це є дві вагомі відповіді [a[b]2c[d]2e]2? Ви отримуєте abbcddeabbcddeшляхом розширення bі dспочатку, але ababcdbcdedbabcdbcdedeшляхом розширення a[bі d]2eпершого.
— BradC

Відповіді:


13

Гема , 17 символів

[#]?=@repeat{?;#}

Проба зразка:

bash-4.4$ gema '[#]?=@repeat{?;#}' <<< '[three[two[one]1]2]3'
threetwoonetwoonethreetwoonetwoonethreetwoonetwoone

Нічого, поговоримо про пошук потрібної мови для роботи!
— MD XF

Або правильна робота для мови. Багато проблем довелося пропустити, оскільки рекурсивний аргумент був недостатньо гнучким.
— манатура

Приймаючи це наразі, тому що я не бачу жодного способу, коли його б'ють, але це буде неприйнято в тому малоймовірному випадку.
— MD XF


7

Haskell , 101 96 байт

fst.(""%)
infix 4%
s%']':d:r=(['1'..d]>>s,r)
s%'[':r|(t,q)<-""%r=s++t%q
s%x:r=s++[x]%r
s%e=(s,e)

Спробуйте в Інтернеті! Замість використання регулярного вираження, як більшість інших відповідей, це реалізує рекурсивний аналізатор.

-5 байт завдяки BMO !


4
Декларація про фіксацію (%)економить вам 1 байт і ['1'..d]заощаджує ще 4, див. Це .
— ბიმო

3
@BMO Приємно, я не очікував, що декларація про фіксацію коли-небудь стане корисною для гольфу з кодом. Я думаю, ви повинні додати це до питання щодо підказок.
— Лайконі

7

Perl 5 , 34 33 29 + 1 ( -p) = 30 байт

s/.([^[]*?)](.)/$1x$2/e&&redo

Спробуйте в Інтернеті!

Скоротіть це за допомогою допомоги @Shaggy та @TonHospel.


3
Я не знаю перли, але повтор здається чудовим!
— officialaimm

Я думаю, ви повинні бути в змозі зберегти байт, не уникаючи ].
— Кудлатий

1
Я не знаю Perl, але це, здається, працює на 30 + 1 байт.
— Кудлатий

2
Ці 29 + 1 також працюють: perl -pe 's/.([^[]*?)](.)/$1x$2/e&&redo'іperl -pe 's/.([^][]*)](.)/$1x$2/e&&redo'
— Тон Євангелія

5

Japt v2 , 21 20 19 байт

Збережено 2 байти завдяки @Shaggy

e/.([^[]*?)](./@YpZ

Перевірте це в Інтернеті!

eє рекурсивною заміною, яка робить одну заміну за один раз, поки не буде більше збігів. У цьому випадку відповідність регулярного виразу /\[([^[]*?)](\d)/gзамінюється на <внутрішній текст> повторений <digit> разів, поки не буде більше збігів.

Відповідно до того, що я запланував ( тут ), цей регулярний вираз повинен бути в кінцевому рахунку принаймні на 3 2 байти коротше:

‹[“⁽[»₋”]“.›

2
Як ми « можна вважати , що кожна закриває дужка ]має цифру після » ви повинні бути в змозі замінити (\dз (..
— Кудлатий

Ви також можете замінити \[на.
— Shaggy

@Shaggy Приємно, дякую!
— ETHproductions

4

JavaScript, 71 67 66 байт

У мене було 54-байтне рішення, але воно перекрутилося другим тестом! :(

f=s=>s!=(x=s.replace(/.([^[]*?)](.)/,(_,y,z)=>y.repeat(z)))?f(x):x

Випробування

f=s=>s!=(x=s.replace(/.([^[]*?)](.)/,(_,y,z)=>y.repeat(z)))?f(x):x
o.innerText=`[Foo[Bar]3]2
[one]1[two]2[three]3
[three[two[one]1]2]3
[!@#[$%^[&*(]2]2]2
[[foo bar baz]1]1
[only once]12
[only twice]23456789
[remove me!]0
before [in ]2after`.split`\n`.map(x=>x.padEnd(22)+`:  `+f(x)).join`\n`
<pre id=o></pre>


4

Пітон 3 , 110 93 92 байт

import re
f=lambda s:f(re.sub(r'\[([^][]+)\](.)',lambda m:m[1]*int(m[2]),s))if'['in s else s

Спробуйте в Інтернеті!

-17 байт завдяки pizzapants184 -1 байт завдяки Kevin Cruijssen


1
-17 байт у Python 3 з використанням індексації re.match та перевірки підрядків in.
— pizzapants184

1
-1 байт, змінивши (\d)на (.), тому що ми знаємо, що блок-дужка ]завжди супроводжується цифрою.
— Kevin Cruijssen

4

Scala , 173 байт

l.foreach{x=>def r(c:String):String={val t="""\[([^\[\]]*)\](.)""".r.unanchored;c match{case t(g,h)=>r(c.replaceAllLiterally(s"[$g]$h",g*h.toInt));case _=>c}};println(r(x))}

Спробуйте в Інтернеті!

Розширено:

l.foreach { x =>
  def remove(current: String): String = {
    val test ="""\[([^\[\]]*)\](.)""".r.unanchored
    current match {
      case test(g, h) => remove(current.replaceAllLiterally(s"[$g]$h", g * h.toInt))
      case _ => current
    }
  }

  println(remove(x))
}

Старе рішення

Scala , 219 215 213 212 199 байт

l.foreach{x=>def r(c:String):String={"""\[([^\[\]]*)\](.)""".r.findFirstMatchIn(c).map{x=>val g=x.group(1);val h=x.group(2).toInt;r(c.replaceAllLiterally(s"[$g]$h",g*h))}.getOrElse(c)};println(r(x))}

Спробуйте в Інтернеті!

Розширено:

l.foreach { x =>
  def remove(current: String): String = {
    """\[([^\[\]]*)\](.)""".r.findFirstMatchIn(current).map { x =>
      val g = x.group(1)
      val h = x.group(2).toInt
      remove(current.replaceAllLiterally(s"[$g]$h", g * h))
    }.getOrElse(current)
  }
  println(remove(x))
}

Де l - список рядків, які ми обробимо.

Дякую Кевіну Крейсейну за -1 байт

Пішов з 212 до 199, видаливши невикористаний параметр, не звернув уваги.


4
Ласкаво просимо до PPCG! Спробуйте перекладач Scala tio на сайті tio.run/#scala і подивіться, чи можете ви надіслати посилання для відповіді, щоб інші могли спробувати його в Інтернеті. :)
— officialaimm

2
Дякую! Я відредагував відповідь, щоб включити посилання. Сподіваємось, це нормально, як оголошується заголовок, код і колонтитул, щоб бути правильним поданням.
— Шикко

1
Привіт, Ласкаво просимо до PPCG! Чудова перша відповідь, +1 від мене. Я думаю, що ви можете зберегти 1 байт, змінивши (\d)на (.), тому що ми знаємо, що блок-дужка ]завжди супроводжується цифрою.
— Kevin Cruijssen

3

Складено , 39 38 байт

Збережено 1 байт завдяки Шаггі, погравши в реджекс!

['\[([^[\]]+)](.)'{.y x:x#~y*}recrepl]

Спробуйте в Інтернеті!

Просто рекурсивно замінює регулярний вираз '\[([^[\]]+)](.)'правилом повторення.


Я думаю, ви можете зберегти байт, не уникнувши останнього ].
— Кудлатий


3

JavaScript - 77 75 72 байти

f=a=>a.replace(/(.*)\[([^[]*?)](.)(.*)/,(a,b,c,d,e)=>f(b+c.repeat(d)+e))

Редагувати: оновлений регулярний вираз із рекомендацією Шаггі

Фрагмент:


2
Ласкаво просимо до PPCG! Ви можете звести це до 70 байт , налаштувавши RegEx.
— Кудлатий

Так, 72 байти, очевидно, вибачте; Я забував рахувати f=!
— Кудлатий

2

QuadR з ≡аргументом, 30 28 байт

\[[^[]+?].
∊(⍎⊃⌽⍵M)⍴⊂1↓¯2↓⍵M

Спробуйте в Інтернеті!

\[[^[]+?]. замінити « [не- [речі ]символ» з

¯2↓⍵M скиньте останні два символи M atch (" ]цифра"), укажіть
1↓ перший символ (" ["),
⊂ додайте, щоб його розглядали як ціле
(... )⍴ r Настроїть на довжину:
 ⌽⍵M переверніть M atch,
 ⊃ виберіть першу (цифру)
 ⍎ оцінку
∊ ϵ nlist ( згладити)

≡ повторюйте, поки більше не відбудеться змін


Еквівалентна функція APL Dyalog - 47 байт:

'\[[^[]+?].'⎕R{∊(⍎⊃⌽⍵.Match)⍴⊂1↓¯2↓⍵.Match}⍣≡

Спробуйте в Інтернеті!


2

Java 8, 250 249 241 239 байт

s->{for(;s.contains("[");)for(int i=0,j,k;i<s.length();)if(s.charAt(i++)==93){String t="",r=t;for(j=k=s.charAt(i)-48;j-->0;)t+=s.replaceAll(r="(.*)\\[([^\\]]+)\\]"+k+"(.*)","$2");s=k<1?t:s.replaceFirst(r,"$1$3").replace("",t);}return s;}

-2 байти завдяки @JonathanFrech (код містить два недрукованих символи ASCII, які можна побачити у TIO-посилання нижче).

Зітхніть ... Java з регулярним виразом настільки проклято обмежена. Я просто цитую себе з іншої відповіді тут:

Заміна WWWWз 222Wлегко в Java, але 4Wнемає .. Якщо тільки Java був спосіб використовувати регулярний вираз захоплення-група що - то .. Отримання довжини з "$1".length(), замінивши сам матч з "$1".replace(...), що перетворює матч до цілого числа з new Integer("$1"), або з допомогою щось подібне, як Retina (тобто s.replaceAll("(?=(.)\\1)(\\1)+","$#2$1"))або JavaScript (тобто s.replaceAll("(.)\\1+",m->m.length()+m.charAt(0))) - це моя річ номер 1, яку я хотів би бачити в Java в майбутньому, щоб скористатися codegolfing ..>.> Я думаю, що це 10-й + час, який я ненавиджу Java не можу зробити з матчем групи захоплення ..
Цитата звідси.

Пояснення:

Спробуйте в Інтернеті.

s->{                           // Method with String as both parameter and return-type
  for(;s.contains("[");)       //  Loop as long as the String contains a block-bracket
    for(int i=0,j,k;i<s.length();)
                               //   Inner loop over the characters of the String
      if(s.charAt(i++)==93){   //    If the current character is a closing block-bracket:
        String t="",r=t;       //     Create two temp-Strings, starting empty
        for(j=k=s.charAt(i)-48;//     Take the digit after the closing bracket
            j-->0;)            //     Loop that many times:
          t+=s.replaceAll(r="(.*)\\[([^\\]]+)\\]"+k+"(.*)","$2");
                               //      Append `t` with the word inside the block brackets
        s=k<1?                 //     If the digit was 0:
           t                   //      Replace the input with an empty String as well
          :                    //     Else:
           s.replaceFirst(r,"$1$3").replace("",t);}
                               //      Replace the word between brackets by `t`,
                               //      and remove the digit
  return s;}                   //  Return the modified input-String as result

1
Я думаю, ви можете використовувати справді ASCII, хоча і недрукований символ, щоб зберегти два байти . (Ваше рішення дійсно займає 241 байт, 239 символів.)
— Джонатан Фрех

@JonathanFrech Дякую! Шукав 1-байтний символ за межами діапазону ASCII для друку. Не думав про те, щоб скористатися недрукованим
— файлом


2

С, 407 368 байт

Дякую Джонатану Фреху за збереження байтів.

гольф (файл bracket.c):

i,j,k,l,n;char*f(a,m)char*a;{for(i=0;a[i];++i){a[i]==91&&(j=i+1);if(a[i]==93){k=a[i+1]-48;if(!k){for(l=i+2;l<m;)a[++l-i+j-4]=a[l];a=realloc(a,m-3);return f(a,m-3);}for(l=j;l<i;)a[~-l++]=a[l];for(l=i+2;l<m;)a[++l-4]=a[l];m-=3;n=m+~-k*(i---j--);a=realloc(a,n);for(l=i;l<m;)a[l+++~-k*(i-j)]=a[l];for(m=0;m<k;++m)for(l=j;l<i;)a[l+++m*(i-j)]=a[l];return f(a,n);}}return a;}

невольф з програмою:

#include <stdlib.h>
#include <stdio.h>

// '[' = 133
// ']' = 135
// '0' = 48

i, j, k, l, n;

char* f(a,m) char*a;
{
  for (i=0; a[i]; ++i) {
    a[i]==91&&(j=i+1);

    if (a[i]==93) {
      k=a[i+1]-48;

      if (!k) {
        for (l=i+2; l<m; )
          a[++l-i+j-4] = a[l];

        a = realloc(a,m-3);
        return f(a,m-3);
      }
      for (l=j;l<i;)
        a[~-l++] = a[l];
      for (l=i+2; l<m; )
        a[++l-4] = a[l];
      m -= 3;
      n = m+~-k*(i---j--);
      a = realloc(a,n);

      for (l=i; l<m; )
        a[l+++~-k*(i-j)] = a[l];
      for (m=0; m<k; ++m)
        for (l=j; l<i;)
          a[l+++m*(i-j)] = a[l];

      return f(a,n);
    }
  }
  return a;
}

int main()
{
  char c[]="[Foo[Bar]3]2";
  char *b;

  char cc[]="[remove me!]0";
  char *bb;

  char ccc[]="[only once]12";
  char *bbb;

  b=malloc(13);
  bb=malloc(14);
  bbb=malloc(14);

  for (i=0; i<13; ++i)
    b[i] = c[i];

  for (i=0; i<14; ++i)
    bb[i] = cc[i];

  for (i=0; i<14; ++i)
    bbb[i]=ccc[i];

  printf("%s\n", f(b, 13));
  printf("%s\n", f(bb, 14));
  printf("%s\n", f(bbb, 14));

  return 0;
}

Складено з gcc 5.4.1, gcc bracket.c



387 з необхідними включеннями (для реального часу). Пізніше я проведу чисте оновлення (з версією, що не має волі). Спасибі
— Цатогуа

Якщо ви використовуєте GCC, я думаю, що компілятор спробує відгадати визначення обох mallocі realloc, в тому числі stdlib.h, власних.
— Джонатан Фрех

Я цього не знав. Хороша особливість для коду в гольф. Спасибі.
— Цатогуа

2

Червоний , 147 байт

f: func[t][a: charset[not"[]"]while[parse t[any a some[remove["["copy h any a"]"copy d a](insert/dup v: copy""h to-integer d)insert v | skip]]][]t]

Безголівки:

f: func [t][
    a: charset [not "[]"]                          ; all chars except [ and ]
    while [ parse t [                              ; repeat while parse is returning true
        any a                                      ; 0 or more chars other than [ and ]
        some [                                     ; one or more block:
            remove ["[" copy h any a "]" copy d a] ; remove the entire block, store the
                                                   ; substring between the [] in h,
                                                   ; the digit into d
            (insert/dup v: copy "" h to-integer d) ; makes d copies of h 
            insert v                               ; and inserts them in place 
            | skip ]                               ; skip if no match
        ]                                       
    ][]                                            ; empty block for 'while'
    t                                              ; return the modified string
]

Я почав вивчати діалект Red's Parse лише вчора, тому впевнений, що мій код можна вдосконалити. Синтаксичний розбір незрівнянно більш багатослівний, ніж регулярний вираз, але він дуже чіткий, гнучкий і читабельний і може вільно змішуватися з рештою червоної мови.

Спробуйте в Інтернеті!


1

Желе , 30 байт

œṡ”]µḢUœṡ”[ẋ€1¦Ṫ©Ḣ$FṚ;®
Çċ”]$¡

Спробуйте в Інтернеті!


Пояснення.


œṡ”]µḢUœṡ”[ẋ€1¦Ṫ©Ḣ$FṚ;®    Helper link 1, expand once.
                           Assume input = "ab[cd]2ef".

œṡ      Split at first occurence of
  ”]      character "]".
    µ   Start new monadic chain. Value = "ab[cd","2ef".

Ḣ       Ḣead. "ab[cd"
 U      Upend. "dc[ba"
  œṡ”[  Split at first occurence of "[". | "dc","ba".

ẋ€        Repeat ...
  1¦        the element at index 1...
          by ...
    Ṫ Ḣ$    the Ḣead of the Ṫail of ...
          the input list ("ab[cd","2ef") (that is, 2)

          The command Ḣ also pop the head '2'. The remaining
            part of the tail is "ef".
     ©    Meanwhile, store the tail ("ef") to the register.

          Current value: "dcdc","ba"
FṚ        Flatten and Ṛeverse. | "abcdcd"
  ;®      Concatenate with the value of the register. "abcdcdef"

Çċ”]$¡    Main link.

 ċ”]$     Count number of "]" in the input.
     ¡    Repeatedly apply...
Ç           the last link...
            that many times.

1

C, 381 байт

Компактна версія:

while(1){int t=strlen(i);int a,c=-1;char*w;char*s;char*f;while(c++<t){if(i[c]==']'){int k=c-a;w=calloc((k--),1);memcpy(w,&i[a+1],k);s=calloc((t-c-1),1);memcpy(s,&i[c+2],t-c-2);i[a]=0;int r=i[c+1]-48;if(r==0){f=calloc(t,1);sprintf(f,"%s%s",i,s);}else{f=calloc((t+k),1);sprintf(f,"%s%s[%s]%d%s",i,w,w,r-1,s);}free(i);i=f;break;}else if(i[c]=='[')a=c;}free(w);free(s);if(c>=t)break;}

Повна версія:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void proceed(char* input)
{
  while(1)
  {
    int t=strlen(input);
    int start,cursor=-1;
    char* word;
    char* suffix;
    char* final;
    while(cursor++<t)
    {
      if(input[cursor]==']')
      {
        int wordlength = cursor-start;
        word=calloc((wordlength--),sizeof(char));
        memcpy(word, &input[start+1], wordlength );
        suffix=calloc((t-cursor-1),sizeof(char));
        memcpy( suffix, &input[cursor+2], t-cursor-2 );
        input[start]='\0';
        int rep=input[cursor+1]-'0';
        if(rep==0)
        {
          final=calloc(t,sizeof(char));
          sprintf(final,"%s%s",input,suffix);
        }
        else
        {
          final=calloc((t+wordlength+5),sizeof(char));
          sprintf(final,"%s%s[%s]%d%s",input,word,word,rep-1,suffix);
        }
        free(input);
        input=final;
        break;
      }
      else if(input[cursor]=='[')
        start=cursor;
    }
    free(word);
    free(suffix);

    if(cursor>=t)break;
  }
}

int main()
{
  char* input=calloc(256,sizeof(char));
  sprintf(input,"a[[toto]2b]2[ana]3");
  printf("in : %s\n",input);
  proceed(input);
  printf("out: %s\n",input);
  return 0;
}

3
Ласкаво просимо до PPCG!
— Кудлатий

1
Ласкаво просимо на сайт! Зауважте, що матеріали C повинні бути повноцінними програмами або функціями, а не лише фрагментами.
— MD XF

1

Пітон, 80 байт

import re
b=re.sub
s=lambda x:eval(b(r"\](.)",r"')*\1+'",b(r"\[","'+('","%r"%x)))

Спробуйте в Інтернеті!

s("[Foo[Bar]3]2")Перетворює [Foo[Bar]3]2на''+('Foo'+('Bar')*3+'')*2+'' та оцінює.

Помилка введення з лапками в дужках (наприклад [']3)


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