Зняття батьківства з рядка


25

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

Ви можете припустити, що вхід містить лише малі літери ASCII та круглі дужки.

Вашою відповіддю повинна бути функція, яка при введенні рядка повертає список рядків.

Приклади:

                   'a(b)c(d)e' -> ['ace', 'b', 'd']
                   'a(b(c)d)e' -> ['ae', 'bd', 'c']
                  'a((((b))))' -> ['a', 'b']
                        'a()b' -> ['ab']
                            '' -> []
                           'a' -> ['a']
          '(((a(b)c(d)e)f)g)h' -> ['h', 'g', 'f', 'ace', 'b', 'd']
'ab(c(((d)ef()g)h()(i)j)kl)()' -> ['ab', 'ckl', 'hj', 'efg', 'i', 'd']

Виграє найменше байт.


Є 'i'і 'd'в правильному порядку , в останньому тесті?
PurkkaKoodari

@ Pietu1998 iменш глибоко вкладений, ніж d.
feersum

@feersum О, правильно.
PurkkaKoodari

1
Чи можете ви проти дозволити також і інші стандартні типи подання, зокрема повні програми? Не всі мови мають поняття функцій. Для консенсусу за замовчуванням див. Meta.codegolf.stackexchange.com/a/2422/8478 та meta.codegolf.stackexchange.com/questions/2447/… .
Мартін Ендер

2
@redstonerodent Формулювання, яке я, як правило, використовую: "Ви можете написати програму або функцію, взявши введення через STDIN (або найближчу альтернативу), аргумент командного рядка або аргумент функції та вивівши результат за допомогою STDOUT (або найближчої альтернативи), повернення значення функції або параметр функції (вихід). " і у вашому випадку "Вихід може бути у будь-якому зручному, однозначному форматі плоского списку".
Мартін Ендер

Відповіді:


11

JavaScript ES6, 91 93 104 133 148

Edit2 2 байти збережено thx користувача81655

Редагувати Використовуючи більше рядків і менше масивів

Випробуйте запуск фрагмента нижче у веб-переглядачі, сумісному з EcmaScript 6

f=s=>[...s].map(c=>l+=c<')'||-(o[l]=(o[l]||'')+c,c<'a'),o=[],l=0)&&(o+'').match(/\w+/g)||[]

// Less golfed

u=s=>{
  o=[]; l=0;
  [...s].map(c=>{
    if (c>'(') // letters or close bracket
      o[l]=(o[l]||'')+c, // add letter or close bracket to current level string
      l-=c<'a' // if close bracket, decrement level
    else
      ++l // open bracket, increment level
  })
  o = o+'' // collapse array to comma separated string
  return o.match(/\w+/g)||[] // fetch non empty strings into an array
}

// TEST
console.log=x=>O.innerHTML+=x+'\n'

;[ 'a(b)c(d)e'                    // ['ace', 'b', 'd']
 , 'a(b(c)d)e'                    // ['ae', 'bd', 'c']
 , 'a((((b))))'                   // ['a', 'b']
 , 'a()b'                         // ['ab']
 , ''                             // []
 , 'a'                            // ['a']
 , '(((a(b)c(d)e)f)g)h'           // ['h', 'g', 'f', 'ace', 'b', 'd']
 , 'ab(c(((d)ef()g)h()(i)j)kl)()' // ['ab', 'ckl', 'hj', 'efg', 'i', 'd']
].forEach(t=>console.log(t +" -> " + f(t)))
<pre id=O></pre>


Збережіть 2 байти за допомогою c=>l+=c<')'||-(o[l]=(o[l]||'')+c,c<'a'),.
користувач81655

@ user81655 приємно, дякую
edc65

8

Юлія, 117 86 83 байт

v->(while v!=(v=replace(v,r"(\(((?>\w|(?1))*)\))(.*)",s"\g<3> \g<2>"))end;split(v))

Це рішення для регулярних викидів.

Безголівки:

function f(v)
  w=""
  while v!=w
    w=v
    v=replace(v,r"(\(((?>\w|(?1))*)\))(.*)",s"\g<3> \g<2>"))
  end
  split(v)
end

r"(\(((?>\w|(?1))*)\))(.*)"- це рекурсивний ( (?1)повторювана група 1) регулярний вираз, який буде відповідати першим зовнішнім врівноваженим дужкам (які не містять незбалансованих / зворотних дужок), при цьому друга група містить усе, що знаходиться в круглих дужках (не включаючи самі дужки), а третя група містить все після дужок (до кінця рядка).

replace(v,r"...",s"\g<3> \g<2>")потім перемістить другу групу до кінця рядка (після пробілу, щоб діяти як роздільник), при цьому відповідні дужки будуть видалені. Ітерацією до v == w гарантується, що заміна повторюється, поки не залишиться дужок. Оскільки сірники переміщуються до кінця, а потім наступний збіг йде для перших круглих дужок, результатом буде рядка, розбита в порядку глибини.

Потім splitповертає всі непробільні компоненти рядка у вигляді масиву рядків (у яких немає пробілу).

Зверніть увагу, що w=""він використовується в коді, який не використовується для перегляду, щоб переконатися, що цикл while працює принаймні один раз (за винятком випадків, якщо вхідний рядок порожній, звичайно), і він не потрібен у формі для гольфу.

Дякую Мартіну Бюттнеру за допомогу в збереженні 3-х байт.


Акуратно, я дійшов до того ж рішення самостійно в Сітківці. Це 44 байти там, але, як воно стоїть, повнопрограмні рішення заборонені. : /
Мартін Ендер

Ви можете зберегти три байти, використовуючи \wзамість [^()].
Мартін Ендер

@ MartinBüttner - дякую. Я насправді вважав це, але я переживав, що щось пропустив і що це не вдасться в якійсь крайовій справі. Якщо ви скажете, що це добре, тоді це добре.
Глен О

6

Пітон, 147 байт

def f(s):
 d=0;r=[['']for c in s]
 for c in s:
  if c=='(':d+=1;r[d]+=['']
  elif c==')':d-=1
  else:r[d][-1]+=c
 return[i for i in sum(r,[])if i]

Тестові одиниці:

assert f('a(b)c(d)e') == ['ace', 'b', 'd']
assert f('a(b(c)d)e') == ['ae', 'bd', 'c']
assert f('a((((b))))') == ['a', 'b']
assert f('a()b') == ['ab']
assert f('') == []
assert f('a') == ['a']
assert f('(((a(b)c(d)e)f)g)h') == ['h', 'g', 'f', 'ace', 'b', 'd']
assert f('ab(c(((d)ef()g)h()(i)j)kl)()') == ['ab', 'ckl', 'hj', 'efg', 'i', 'd']

Мені подобається ця головоломка; це дуже мило!


4

Pyth, 32 байти

fTscR)uX0.<GJ-FqLH`()@[Hdk)Jzmkz

Тестовий набір

Мало базується на підході @ Quuxplusone. На кожній глибині створює розділені між собою простіри списки символів, потім розбиває їх і фільтрує порожні групи. Робочий список повертається, щоб підтримувати поточний список глибин попереду весь час.


4

Сітківка , 44 41 байт

+`\(((\w|(\()|(?<-3>.))*).(.*)
$4 $1
S_` 

Біжи з -sпрапором. Помітьте пробіл в кінці останнього рядка.

Я придумав це рішення незалежно від Глена О, але воно виявилося ідентичним. Ідея полягає у тому, щоб зіставити першу пару дужок, видалити її та вставити її вміст у кінці виводу (повторно). Через відсутність рекурсії у .NET, мені довелося використовувати балансуючі групи, що на чотири байти довше.

Якщо ви не розумієте перший регекс, дозвольте мені віднести вас до моєї відповіді "SO" про балансуючі групи . Оскільки введення гарантовано правильно в дужках, ми можемо зберегти два байти, зіставивши )їх .замість \). Тоді ми просто співставляємо решту рядка з (.*). $4 $1спочатку записує згаданий решта рядка (опускаючи як круглі дужки, так і їх зміст), а потім зміст дужок після пробілу. +`Каже Retina повторити цей крок , поки рядок не перестає змінюватися (що трапляється тільки один раз все дужки були видалені).

Порожні дужки призведуть до двох послідовних пробілів, тому, нарешті, ми розділимо весь рядок на пробіли ( S`активується режим розділення, а регулярний вираз - це єдиний пробіл). Цей _параметр повідомляє Retina опускати порожні частини розбиття, тому ми не включаємо порожні результати у висновок.


3

Лист звичайний, 160

(lambda(x)(labels((g(l)(cons(#1=format()"~(~{~A~}~)"(#2=remove-if'listp l))(mapcan #'g(#2#'atom l)))))(remove""(g(read-from-string(#1#()"(~A)"x))):test'equal))))

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


2

Haskell, 114 112 111 байт

')'%(h:i:t)=("":i):t++[h]
'('%l=last l:init l
c%((h:i):t)=((c:h):i):t
g x=[a|a<-id=<<foldr(%)(x>>[[""]])x,a>""]

Приклад використання: g "ab(c(((d)ef()g)h()(i)j)kl)()"-> ["ab","ckl","hj","efg","i","d"].

Я йду назад через рядок введення. Проміжна структура даних - це список списку рядків. Зовнішній список складається за рівнем, а внутрішній - за групою в межах рівня, наприклад [["ab"],["ckl"],["hj"],["efg","i"],["d"]](примітка: реальний список має багато порожніх рядків між ними). Все починається з кількості порожніх рядків, рівних довжині введення - більш ніж достатньо, але порожні списки все одно відфільтровані. Зовнішні списки або повертаються на (/, )або додають символу до переднього елемента. )також починає нову групу.

Редагувати: @Zgarb знайшов байт для збереження.


1

Сід, 90 байт

:
s/^(\w*)\((.*)\n?(.*)/\1\n\3_\2/M
s/(\n\w*_)(\w*)\)(.*)/\3\1\2/M
t
s/[_\n]+/,/g
s/,$//

Використовуються розширені регулярні вирази ( -rпрапор), що враховуються +1 байтом. Також для цього використовується розширення GNU ( Mпрапор sкоманди).

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

$ echo 'ab(c(((d)ef()g)h()(i)j)kl)()' | sed -r -f deparenthesize.sed
ab,ckl,hj,efg,i,d

Пояснення: Оскільки sed не підтримує такі речі, як рекурсивні регулярні виразки, необхідна ручна робота. Вираз розбито на кілька рядків, кожен з яких представляє рівень глибини вкладення. Окремі вирази на одній глибині (а значить, на одній і тій же лінії) відокремлюються знаком an _. Сценарій працює через вхідний рядок по одній дужці одночасно. Решта вводу завжди зберігається на кінці рядка, що відповідає поточному рівню вкладення.


0

Пітон, 161 байт

Ось що я придумав, однолінійне функціональне рішення пітона:

p=lambda s:filter(None,sum([''.join([s[i]for i in range(len(s))if s[:i+1].count('(')-s[:i+1].count(')')==d and s[i]!=')']).split('(')for d in range(len(s))],[]))

Цей виклик надихнув https://github.com/samcoppini/Definition-book , який виводить довгий рядок зі словом, визначеним в дужках. Я хотів написати код, який би давав мені кожне речення, з дужками видалено. Функціональне рішення занадто повільне, щоб бути ефективним на довгих струнах, але імперативні рішення (наприклад, рішення @ Quuxplusone) набагато швидше.

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