Створити всі дужки-рядки довжиною n


16

Рядок *()[]дужок визначається як рядок, що складається з символів, у яких дужки правильно відповідають:

[brace-string] ::= [unit] || [unit] [brace-string]
[unit]         ::= "" || "*" || "(" [brace-string] ")" || "[" [brace-string] "]"

Це дійсна дужка:

((())***[]**)****[(())*]*

Але це не такі:

)(
**(**[*](**)
**([*)]**

Ваше завдання - написати програму (або функцію), яка за заданим цілим числом nприймає число як вхід і виводить (або повертає) всі дійсні рядки дужки довжини n.

Технічні умови

  • Ви можете виводити рядки в будь-якому порядку.
  • Ви можете виводити у вигляді списку або рядка, розділеного іншим символом.
  • Ваша програма повинна керувати 0 правильно. Існує 1 можлива дужка-рядка довжиною 0, яка є порожньою "".
  • Це , тому найкоротший вірний відповідь - вимірюється в байтах - виграє.

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

0. 
1. *
2. ** () []
3. *** ()* []* (*) [*] *() *[]
4. **** ()** []** (*)* [*]* (**) **() **[] *(*) *[*] (()) ()() ()[] ([]) [**] [()] [[]] []() [][] *()* *[]*

3
Кількість записів у виході - A025235
Габріель Бенамі

@GabrielBenamy Ах. Мені було цікаво, чи це раніше дивилися. Цікаво.
Esolanging Fruit

2
Яка умова виграшу? Я припускаю найкоротшу програму (код гольфу).
Згарб


1
Оскільки всі припускають, що це кодовий гольф, я поставив би відповідний виклик (так як інакше це зробить усі існуючі відповіді дещо безглуздими). Якщо ви задумали інший критерій виграшу, ви можете розглянути можливість подати новий виклик.
Мартін Ендер

Відповіді:


3

Желе, 29 байт

-3 байти завдяки @JonathanAllan

Будь ласка , попередить мене, якщо є якісь проблеми / помилки / помилки чи байти, які я можу зняти!

“[(*)]”ṗµḟ”*œṣ⁾()Fœṣ⁾[]FµÐLÐḟ

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

Попереднє рішення було:

“[(*)]”ṗµḟ”*œṣ⁾()Fœṣ⁾[]FµÐL€Ṇ€Tị
“[(*)]”ṗµ¹ḟ”*œṣ⁾()Fœṣ⁾[]FµÐL€Ṇ€Tị
“[(*)]”ṗµ¹ḟ”*œṣ⁾()Fœṣ⁾[]FµÐL€Ṇ€×Jḟ0ị
“[(*)]”x⁸ṗ⁸Qµ¹ḟ”*œṣ⁾()Fœṣ⁾[]FµÐL€Ṇ€×Jḟ0ị
“[(*)]”x⁸ṗ⁸Qµ¹µḟ”*œṣ⁾()Fœṣ⁾[]FµÐL€Ṇ€×Jḟ0ị
“[(*)]”x⁸ṗ⁸Qµ¹µḟ”*œṣ⁾()Fœṣ⁾[]FµÐLµ€Ṇ€×Jḟ0ị

Пояснення (Моя найкраща спроба опису):

Input n
“[(*)]”ṗ-All strings composed of "[(*)]" of length n
µḟ”*    -Filter out all occurences of "*"
œṣ⁾()   -Split at all occurences of "()"
F       -Flatten
œṣ⁾[]   -Split at all occurences of "[]"
F       -Flatten
µÐL     -Repeat that operation until it gives a duplicate result
Ðḟ      -Filter

Ви можете зберегти три байти за допомогою фільтрування ( “[(*)]”ṗµḟ”*œṣ⁾()Fœṣ⁾[]FµÐLÐḟ)
Джонатан Аллан

15

Пролог, 69 байт

s-->[];e,s.
e-->"*";"(",s,")";"[",s,"]".
b(N,A):-length(A,N),s(A,[]).

Однією з найцікавіших властивостей Prolog є те, що у багатьох випадках він здатний запускати програму назад; наприклад, замість тестування, щоб перевірити, чи щось істинне, ви можете генерувати всі рішення, для яких це правда, і замість перевірки довжини рядка ви можете генерувати всі рядки із заданою довжиною. (Ще однією приємною властивістю Prolog є те, що він вимагає пробілу після закінчення кожного визначення предикатів, і новий рядок можна вставити так само дешево, як пробіл; таким чином, навіть програми для гольфу часто досить читабельні.)

Сказане визначає предикат (еквівалент функції), bякий перевіряє, чи має рядок задану довжину і чи є "рядок дужок", як визначено у питанні. Зокрема, це робиться через підтримку граматики / регексу / шаблону Prolog, яка дає хороший, короткий цукор для визначення такого виразу (мабуть, це є стандартним / переносним, але я про це не знав, спочатку писав відповідь, і таким чином припускаємо, що відповідь буде працювати лише на одній реалізації Prolog, але, здається, вона працює на кожній реалізації, яка відповідає стандартам). Програму можна перекладати англійською мовою досить безпосередньо; перші два рядки кажуть "a s - порожній рядок, або e, а за ним s ; a eє зірочкою, або s у дужках, або s у квадратних дужках ". Третій рядок можна інтерпретувати як" B з N може бути A, якщо A - це список довжиною N, а A - s, а потім нуль " рядок. "

Я подбав про те, щоб написати s(і таким чином b), щоб вони відповідали кожній «дужці рядка» точно одним способом (що є причиною того, що і те, sі інше eповинно існувати, а не групувати їх в один присудок). Це робить їх обох цілком оборотними; таким чином, bможна використовувати для генерації всіх "рядків дужок" заданої довжини, на додаток до тестування, якщо рядок є дужкою рядка заданої довжини (її можна також використовувати третім способом, щоб визначити довжину дужки рядок, але це майже напевно його найменш корисний режим роботи). Реалізація є рекурсивною, наприклад для генерації s , код буде генерувати всі можливі e , які не перевищують необхідну довжину виводу, і додає всі можливі ss, які вміщуються до залишків до них; оскільки я задав довжину аргументу заздалегідь (у межах b ), двигун Prolog знає, що він не може генерувати вихід, який перевищує задану довжину, що дозволяє рекурсії закінчуватися.

Ось приклад роботи програми:

| ?- b(4,A),format("~s ",[A]),fail.
**** **() **[] *()* *(*) *[]* *[*] ()** ()() ()[] (*)* (**) (()) ([]) []** []() [][] [*]* [**] [()] [[]]

відчувається, що синтаксис, який потрібно вказати, чи потрібно запускати програму "вперед" чи "назад", має мати певну вартість. perl платить 1 байт за кожен шматочок
подібної

Ну, ви можете скласти правило, що аргументи в кінці завжди є поверненим значенням, а потім змінити порядок аргументів, щоб вказати, в який бік ви запускаєте програму. Для мов із гольфу досить звичайно зрозуміти, що вони повинні частково робити, дивлячись на те, чи їм дають якісь вклади, і це є порівнянним принципом. В цілому, однак, важко скласти правила, які стосуються кожної можливої ​​мови; як вбудовані вбудовані, так lengthі appendнавпаки, є основоположною частиною мови, а функції користувача часто роблять те саме.

О, хм. Я припускав, що у вашому прикладі є певні вказівки, які викликали питання про поведінку.
Спарр

Так, це цілком пов'язано з тим, які аргументи наводяться. У програмі вище я пишу length(A,N); якщо Nвін заданий, а Aне є (що станеться, якщо предикат використовується таким чином, як запитується в програмі), lengthстворить список, Aщо складається з Nневідомих елементів. Використання lengthдля вимірювання довжини списку, ймовірно , більш широко використовується (хоча використання його «назад» є досить поширеним явищем в програмуванні на Пролозі). Більшість предикатів в кінцевому підсумку працюють майже так само (єдиною причиною цього не є, якщо спроба їх змінити побудує нескінченний цикл, що є досить поширеним явищем).


5

Haskell, 101 94 байт

Збережено 7 байт!

b 0=[""]
b n=[x++y|k<-[1..n],x<-u k,y<-b$n-k]
u 1=["*"]
u n=[a:s++b|s<-b$n-2,a:b<-["()","[]"]]

Майже прямо, слідуючи визначенню, але зі ""справа перенесена.

Використання:

*Main> map b [0..3]
[[""],["*"],["**","()","[]"],["***","*()","*[]","()*","[]*","(*)","[*]"]]
*Main> length $ b 10
21595

(Друге обчислення займає менше секунди на повільній машині.)

Я також хотів би поділитися результатом іншого підходу, який я придумав, думаючи про генерування функцій. Він визначає список b списків рядків таким, який b!!nмістить усі дужки-рядки довжини n. Аналогічно u!!nмістить всі атоми розміру n-1. Одна приємна річ - те, що код не використовує жодних чисел. Це не зовсім golfed: uа iможе бути вбудованими, і це , безумовно , пропускає кілька інших можливостей гри в гольф. На жаль, не схоже, що його можна зробити коротшим, ніж перший варіант, але він обчислює length $ b !! 10навіть швидше.

b=[""]:b%u
u=["*"]:map i b
i=concatMap(\s->['(':s++")",'[':s++"]"])
(b:c)%f=zipWith(++)[[x++y|x<-b,y<-e]|e<-f]([]:c%f)

Збережіть два байти за допомогою b$n-kта b$n-2. Також на фінальній лінії ви можете зробити a:b<-["()","[]"]і повернутися a:s++b.
Згарб

О, я хотів використовувати, ["()","[]"]але не міг зрозуміти, як поліпшити розмір коду за допомогою нього. Спасибі!
Крістіан Сіверс

4

Математика, 116 байт

#<>""&/@Select[Characters@"*([)]"~Tuples~#,(#/."*"->Nothing//.{a___,"(",")",b___}|{a___,"[","]",b___}:>{a,b})=={}&]&

Пояснення

Characters@"*([)]"

Знайдіть символи рядка "*([)]", надаючи знаки List {"*", "(", "[", ")", "]"}.

... ~Tuples~#

Знайдіть кортежі наведеного вище списку за довжиною n.

(#/."*"->Nothing//.{a___,"(",")",b___}|{a___,"[","]",b___}:>{a,b})=={}&

Безназвана булева функція, щоб визначити, чи збалансований кортеж:

#/."*"->Nothing

Видалити всі "*"з вхідних даних.

... //.{a___,"(",")",b___}|{a___,"[","]",b___}:>{a,b}

Неодноразово видаляйте всі послідовні події "("та ")"або "["і "]"до тих пір, поки вхід не зміниться.

... =={}

Перевірте, чи результат порожній List.

Select[ ... , ... ]

Знайдіть кортежі, які видаються Trueпри застосуванні булевої функції.

#<>""&/@

Перетворити кожного Listз символів у Strings.


2
Дещо несподівано, {x=a___,"(",")",y=b___}|{x,"[","]",y}здається, працює.
Мартін Ендер

4

Python 2, 128 байт

n=input()
for i in range(5**n):
 try:s=','.join('  "00([*])00"  '[i/5**j%5::5]for j in range(n));eval(s);print s[1::4]
 except:1

Накрутіть рекурсивні регекси - ми використовуємо парсер Python! Для того, щоб переконатися, що це, наприклад, *(**[])*є дужка-рядок, робимо наступне:

  1. Створіть рядок типу "*", (0,"*","*", [0,0] ,0) ,"*", де кожен другий символ із чотирьох є символом із дужок-рядків, а решта символів - це клей, щоб зробити це потенційним виразом Python.

  2. eval це.

  3. Якщо це не призводить до помилки, роздрукуйте s[1::4](символи дужок).

У клейових символах обрані так , що рядок я роблю це правильне вираження Python , якщо і тільки якщо приймати кожен другий символ з чотирьох виходів дійсної дужки-струнних.


2

PHP, 149 байт

for(;$argv[1]--;$l=$c,$c=[])foreach($l?:['']as$s)for($n=5;$n--;)$c[]=$s.'*()[]'[$n];echo join(' ',preg_grep('/^((\*|\[(?1)]|\((?1)\))(?1)?|)$/',$l));

Використовує старий добрий генератор усіх можливих, а потім метод фільтрації. Використовуйте як:

php -r "for(;$argv[1]--;$l=$c,$c=[])foreach($l?:['']as$s)for($n=5;$n--;)$c[]=$s.'*()[]'[$n];echo join(' ',preg_grep('/^((\*|\[(?1)]|\((?1)\))(?1)?|)$/',$l));" 4

1

Пітон, 134 байти

from itertools import*
lambda n:[x for x in map(''.join,product('*()[]',repeat=n))if''==eval("x"+".replace('%s','')"*3%('*',(),[])*n)]

repl.it

Безіменна функція, яка повертає список дійсних рядків довжини n.
Форми всіх довжини nкортежі персонажів *()[], з'єднують їх в рядки , використовуючи map(''.join,...)і фільтри для тих , які мають збалансовані дужки, видаляючи «пар» "*", "()"і , "[]"в свою чергу , nі перевірте , що результат є символом нового рядка ( nраз це перебір, особливо для "*"але є гравцем).


1

Сітківка , 78 байт

Кількість байтів передбачає кодування ISO 8859-1.

.+
$*
+%1`1
*$'¶$`($'¶$`)$'¶$`[$'¶$`]
%(`^
$';
)+`(\[]|\(\)|\*)(?=.*;)|^;

A`;

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

Пояснення

Я генерую всі можливі рядки довжиною 5, а потім фільтрую недійсні.

.+
$*

Це перетворює вхід в одинаковий, використовуючи 1як цифру.

+%1`1
*$'¶$`($'¶$`)$'¶$`[$'¶$`]

Це неодноразово ( +) замінює перший ( 1) у кожному рядку ( %) таким чином, що він робить п'ять копій рядка, по одному на кожен можливий символ. Це робиться за допомогою заміни префікса та суфікса $`та $'для побудови залишку кожного рядка.

Цей цикл зупиняється, коли немає більше 1-х для заміни. На даний момент у нас є всі можливі рядки довжини N, по одному у кожному рядку.

%(`^
$';
)+`(\[]|\(\)|\*)(?=.*;)|^;

Ці два етапи виконуються для кожного рядка окремо ( %). Перший етап просто дублює рядок з а, ;щоб розділити дві копії.

Другий етап є ще цикл ( +), який видаляє повторно [], ()або *від першої копії рядка, або видаляє точку з коми на початку рядка (що можливо тільки після того, як рядок зникла повністю).

A`;

Дійсні рядки - це ті, у яких більше немає крапки з комою перед ними, тому ми просто відкидаємо всі рядки ( A), які містять крапку з комою.


Я спробував onliny з введенням 5: добре. З введенням 6 я отримав сторінку помилки
edc65

@ edc65 працює для мене, але, звичайно, такий підхід не зовсім ефективний, тому це займає кілька секунд. Яку сторінку помилки ви маєте на увазі?
Мартін Ендер

Введення 5: відповідь за 3 сек. Введення 6: через 7 секунд всередині поля Виведення я отримую html-джерело того, що, ймовірно, є сторінкою помилки з мого проксі. Якщо це час очікування, то це дуже короткий час очікування ... Я намагався отримати правильний тестовий випадок для введення 6, оскільки моя відповідь здається нормальною до введення 5, але неправильною для 6 або більше
edc65

@ edc65 Це, безумовно, займає більше 7 секунд, а час очікування TIO - хвилина. Я ніколи не бачив описаної вами помилки, можливо, варто донести це до чату TIO (або якщо ви віддаєте перевагу в Gitter або GitHub ). Щодо опорного виводу, ось ось що я отримую для введення 6: pastebin.com/WmmPPmrc (Вхід 7 займає більше хвилини.)
Мартін Ендер

1

Python 3,5, 146 байт

import re;from itertools import*;lambda f:{i for i in map(''.join,permutations("[()]*"*f,f))if re.fullmatch("(\**\[\**\]\**|\**\(\**\)\**)*|\**",i)}

Дуже довго в порівнянні з іншими відповідями, але найкоротший, який я міг зараз знайти. Він у формі анонімної лямбда-функції і тому повинен бути викликаний у форматі

print(<Function Name>(<Integer>))

Виводить набір Python з невпорядкованих рядків, що представляють усі можливі дужки-рядки вхідної довжини.

Наприклад, якщо припущено вищевказану функцію G, виклик G(3)призведе до такого результату:

{'[*]', '*()', '*[]', '(*)', '***', '[]*', '()*'}

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


Однак, якщо ви, як і я, ви насправді не любитель спрощення речей за допомогою вбудованих модулів, то ось моя власна оригінальна відповідь, що не використовую жодних зовнішніх бібліотек для пошуку перестановок, і наразі стоїть на величезних 288 237 байтах :

import re;D=lambda f:f and"for %s in range(%d)"%(chr(64+f),5)+D(f-1)or'';lambda g:[i for i in eval('["".join(('+''.join('"[()]*"['+chr(o)+'],'for o in range(65,65+g))+'))'+D(g)+']')if re.fullmatch("(\**\[\**\]\**|\**\(\**\)\**)*|\**",i)]

Знову ж таки, як і конкуруюча відповідь, і ця є у формі лямбда-функції, і тому її також слід викликати у форматі

print(<Function Name>(<Integer>))

І виводить Python список з невпорядкованих рядків , які представляють усі фігурні дужки-рядок довжини входу. Наприклад, якщо лямбду слід викликати якG(3) , цього разу вихід буде таким:

['*()', '(*)', '*[]', '[*]', '()*', '[]*', '***']

Крім того, ця також набагато швидша, ніж моя інша відповідь, знаходячи всі діаграми довжиною брекетів11 приблизно за 115 секунд , довжину 10приблизно за 19 секунд , довжину 9приблизно за 4 секунди і довжину8 в приблизно 0,73 секунди на моїй машині, тоді як моя відповідна відповідь займає набагато більше, ніж 115 секунд для введення6 .

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


0

05AB1E, 23 байти

…[(*.∞sãʒ'*м„()„[]‚õ:õQ

Деякі з цих функцій можуть бути реалізовані після опублікування питання. Будь-які пропозиції вітаються!

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

Як?

…[(* - the string '[(*'
.∞ - intersected mirror, '[(*'=>'[(*)]'
s - swap the top two items, which moves the input to the top
ã - cartesian power
ʒ ...  - filter by this code:
  '*м      - remove all occurrences of '*'
  „()„[]‚  - the array ["()","[]"]
  õ        - the empty string ""
  :        - infinite replacement (this repeatedly removes "()", "[]", and "*" from the string
  õQ       - test equality with the empty string

Я не знаю 05AB1E, але не міг *також бути в масиві видалення? І чи міг õQчек замінити чимось на кшталт НЕ?
Esolanging Fruit

Перша пропозиція не збереже жодного байта: '*м„()„[]‚õ:vs „()„[]‚'*«õ:(не перевірено), оскільки немає команди для об'єднання 3 значень AFAIK. Другий не буде працювати, оскільки немає НЕ, який би працював так на рядку, AFAIK. (Де AFAIK представляє "наскільки я знаю")
Zacharý
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.