Четко заключите в скобки поезда APL

19

В APL вы можете писать неявные функции, называемые поездами . Как они работают, не имеет значения для этой проблемы. Вот различные способы их группировки, используя в качестве функции:

⍴      -> ⍴
⍴⍴     -> ⍴⍴
⍴⍴⍴    -> ⍴⍴⍴
⍴⍴⍴⍴   -> ⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴  -> ⍴⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴⍴ -> ⍴(⍴⍴(⍴⍴⍴))
...

Порядок остается прежним. Процедура заключается в том, что до тех пор, пока существует строго более 3 функций, последние 3 функции сгруппированы в одну функцию. Если мы встречаем вложенный поезд, мы сначала ставим его в скобки, прежде чем продолжить. Вот процедура, применяемая к ⍴⍴⍴⍴⍴⍴:

Step 0: ⍴⍴⍴⍴⍴⍴
There are strictly more than 3 functions, repeat.
Step 1: ⍴⍴⍴(⍴⍴⍴)
There are strictly more than 3 functions, repeat.
Step 2: ⍴(⍴⍴(⍴⍴⍴))
There are 3 or less functions, we're done.

Вот та же самая процедура, примененная к ⍴⍴⍴(⍴⍴)⍴(⍴⍴⍴⍴(⍴⍴⍴))⍴⍴:

Step 0: ⍴⍴⍴(⍴⍴)⍴(⍴⍴⍴⍴(⍴⍴⍴))⍴⍴
There are strictly more than 3 functions, repeat.
We have met a nested train, applying procedure to that first:
  Step 0: ⍴⍴⍴⍴(⍴⍴⍴)
  There are strictly more than 3 functions, repeat.
  We have met a nested train, applying procedure to that first:
    Step 0: ⍴⍴⍴
    There are 3 or less functions, we're done.
  Step 1: ⍴⍴(⍴⍴(⍴⍴⍴))
  There are 3 or less functions, we're done.
Step 1: ⍴⍴⍴(⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴)
There are strictly more than 3 functions, repeat.
We have met a nested train, applying procedure to that first:
  Step 0: ⍴⍴
  There are 3 or less functions, we're done.
Step 2: ⍴⍴⍴((⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴))
There are strictly more than 3 functions, repeat.
Step 3: ⍴(⍴⍴((⍴⍴)⍴((⍴⍴(⍴⍴(⍴⍴⍴)))⍴⍴)))
There are 3 functions or less, we're done.

вход

Для этой задачи ввод будет упрощен. Это означает, что вы можете выбрать 2 разных символа для открывающих и закрывающих скобок и 1 символ для функций, отличных от выбранных для скобок. Символы, которые вы выбираете, должны быть последовательными. Входные данные не будут пустыми и не будут содержать скобок без содержимого (то есть ()).

Выход

Опять же, вы можете выбрать 3 разных символа, 2 для скобок и 1 для функций. Обратите внимание, что они не должны совпадать с выбранными для ввода, но они должны быть согласованными.

правила

  • Если есть скобки, которые заключают в себя только одну функцию во входных данных, вы должны удалить их в выходных данных. Ваш вывод может не содержать ненужных скобок (т.е. содержать только одну функцию или весь вывод).
  • Вам не нужно реализовывать алгоритм, используемый здесь, если ваше решение действительно для этой задачи.
  • Вход и выход - это строки в формате, описанном в разделах «Вход и выход». На входе будет хотя бы один символ.
  • Использование стандартных лазеек строго запрещено.
  • Это , поэтому выигрывает самый короткий ответ. Однако, не будет принятого ответа, так как это соревнование для каждого языка, и поощрять ответы на языках, на которых эта задача приведет к более длинному коду по сравнению с кодом, написанным на других языках.

Контрольные примеры

Символы, используемые здесь ()⍴, вы должны заменить их на выбранные вами символы.

⍴                          -> ⍴
⍴                          -> ⍴
⍴⍴                         -> ⍴⍴
⍴⍴⍴                        -> ⍴⍴⍴
⍴⍴⍴⍴                       -> ⍴(⍴⍴⍴)
⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴⍴            -> ⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴(⍴⍴⍴))))))
⍴⍴⍴⍴⍴(⍴⍴⍴)⍴⍴(⍴(⍴⍴⍴)⍴⍴⍴)⍴⍴⍴ -> ⍴(⍴⍴(⍴⍴((⍴⍴⍴)⍴(⍴(⍴(⍴⍴⍴)(⍴⍴⍴))(⍴⍴⍴)))))
(⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)            -> (⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)
(⍴⍴⍴)(⍴⍴⍴)⍴⍴⍴              -> (⍴⍴⍴)(⍴⍴⍴)(⍴⍴⍴)
⍴⍴(⍴)⍴⍴                    -> ⍴⍴(⍴⍴⍴)
((⍴⍴))                     -> ⍴⍴
⍴⍴((⍴⍴))⍴⍴                 -> ⍴⍴((⍴⍴)⍴⍴)

Этот вызов был размещен в Песочнице. Если у вас есть необходимые привилегии, вы можете просмотреть пост песочницы здесь .

Эрик Outgolfer
источник
2
Я думаю, что Fully - лучший заголовок, чем Clearly .
Адам
@ Adám Я действительно ожидал, что эталонный ответ, он не получит много голосов, хотя;)
Эрик Outgolfer
@ Adám Часть « Понятно» в заголовке относится к тому факту, что вы должны удалить ненужные скобки. Полностью это то, что вы должны делать, когда отвечаете на вызов; p
Эрик Игрок в гольф
Правда ли, что эта функция всегда будет идемпотентной?
Esolanging Fruit

Ответы:

7

APL (Dyalog Classic) , 71 68 65 63 байта

0{⍵≡⍕⍵:⍵⋄⍬≡⍵:'⍬'1=≢⍵:⍺∇⊃⍵⋄3≥≢⍵:⍺⌽')(',⍣⍺∊1∇¨⍵⋄⍺∇¯3(↓,∘⊂1∇↑)⍵}⍎

Попробуйте онлайн!

Символы , которые я выбрал для ввода / вывода '(', ')'и '⍬'.

Это решение само по себе является поездом APL.

анализирует входные данные, как если бы это был вложенный массив - дерево с пустыми числовыми векторами ( ) в виде листьев.

Функция dfn (т.е. lambda - { }) рекурсивно обходит дерево и преобразует его в строку в скобках. Левый аргумент определяет, должны ли скобки добавляться к текущему уровню, если это необходимо.

DFN обрабатывает следующие случаи на основе правильного аргумента:

  • если это уже строка ( ⍵≡⍕⍵), верните ее

  • если это так , верните символ'⍬'

  • если это синглтон, просто копайте глубже ( это символ для рекурсивного вызова)

  • если его длина ≤3, повторите для каждого из пунктов и окружите ()при необходимости

  • в противном случае вернитесь к 3-хвосту, добавьте все, кроме 3-хвоста, и повторите снова

СПП
источник
Похоже, 63 символа, большинство из них Unicode. Какая кодировка символов дает 63 байта для этого? Я делаю это 141 байт в UTF8.
Кори
@ Adám Спасибо за это. Я посмотрел, но не знал, что искать, чтобы получить этот ответ.
Кори
3

Python 2 , 224 208 204 байта

-16 байтов благодаря г-ну Xcoder -4 байта благодаря овсам

r=str.replace
p='p'
def c(l):
 while len(l)>3:l=l[:-3]+(l[-3:],)
 return l and map(c,l)or l
print r(r(r(r(r(`c(eval(r(r(r(input(),'(p)',p),p,'[],'),')','),')))`,'[]',p),*'[('),*'])'),' ',''),',','')[1:-1]

Попробуйте онлайн! или попробуйте все тестовые случаи

Код можно разделить на 3 основных этапа:
преобразование входных данных во вложенный список и замена (p)->p. Одна функция pбудет заменена пустым списком.

eval(r(r(r(input(),'(p)',p),p,'[],'),')','),'))

Рекурсивная функция для применения правила «3 или меньше» к текущему списку и вызова себя для всех подсписков.

def c(l):
 while len(l)>3:l=l[:-3]+(l[-3:],)
 return l and map(c,l)or l

Много замен для форматирования в желаемый выходной формат

r(r(r(r(r(`c(...)`,'[]',p),*'[('),*'])'),' ',''),',','')[1:-1]
прут
источник
204 байт
овс
1
Это не упрощает ((pp))(или p((pp))p).
Мартин Эндер
2

CJam , 56 байт

Бьет APL!

lW%~]]]{{_,{K_,({~}|}&}%{_,3>}{3/(aa\+:~}w}:K~~`1>W<W%S/

Попробуйте онлайн!

Это работает (я думаю), и я понятия не имею, почему ...

Входные символы предназначены ][Tдля ()⍴, а выходные символы - ][0для ()⍴(да, это означает, что они обратны от того, что вы ожидаете; например, вы можете передать TTT]TT[T]TTTT]TTT[[TT).

Обзор высокого уровня

Программа работает с вводом задом наперед, потому что это удобнее. Для анализа входных данных мы используем синтаксический анализатор CJam - реверсирование и выполнение входных данных обеспечивает (обратную) проанализированную форму входных данных.

Затем мы определяем процедуру K. Kвыполняет большую часть работы для нашего представления и работает следующим образом:

  • Входной массив будет представлять собой смесь нулей и непустых подмассивов. Определите подмассивы и рекурсивно примените Kк ним. Результатом должен быть другой массив, и если этот массив состоит только из одного элемента, распакуйте его (это избавит от лишних скобок).
  • Поскольку результат содержит более трех элементов, сгруппируйте его первые три (не последние три; напомним, что вход обрабатывается в обратном направлении) в один список.
  • Вернуть результат.

Применяя Kк вводу, мы получаем правильно введенную в скобки форму ввода (единственное, на что нужно обратить внимание, это то, что мы фактически оборачиваем ввод в одноэлементный список и разворачиваем его впоследствии; причина этого в том, что нам нужен фрагмент, распаковывающий синглтоны применять к программе верхнего уровня, а не только к ее подмассивам). После этого мы просто применяем минимальное форматирование, чтобы получить наш результат.

Некоторое объяснение битов в гольфе

Гольф, которым я больше всего горжусь, использует ,проверку целых чисел и массивов.

  • Если вершиной стека является целое число n , ,генерируется диапазон [0..n) . Поскольку единственное целое число , с которым мы столкнемся, - 0это всегда пустой список [], который является ложным.
  • Если вершина стека является массивом, ,принимает его длину. Поскольку все массивы, с которыми мы сталкиваемся, будут непустыми, это всегда дает нам положительное целое число, что является правдой.

Еще один интересный гольф - метод, который я использую для группировки первых трех элементов массива; это немного похоже на мою «Turing полная интерпретация кода гольф-код языка» . У CJam нет короткого способа разбить массив на две части (вы можете попробовать нарезать первую часть, а затем другую часть, сохраняя исходный массив и индекс в стеке, но это не очень хорошо работает) Вместо этого я использую 3/, который группирует массив в блоки по 3. Затем я могу вытолкнуть первый элемент (, дважды обернуть массив aa, а затем добавить обратно в начало списка \+. Причина, по которой мы оборачиваем массив дважды, заключается в том, что нам нужно снять слой :~, так как мы просто сгруппировали остальную часть массива в секции.

Esolanging Fruit
источник
Nitpick: это превосходит APL без встроенных функций .
Эрик Outgolfer
@EriktheOutgolfer Справедливо достаточно.
Esolanging Fruit
0

JavaScript (ES6), 149 146 байт

i='a';f=s=>s==(s=s[R='replace'](/\((\w+)\)/,(q,t)=>(f[q=i+=0]=f(t),q)))&&s==(s=s[R](/(?!^)((a0+|p){3})$/,"($1)"))?s[R](/a0+/g,t=>`(${f[t]})`):f(s)
<textarea cols=80 id=I>ppp(pp)p(pppp(ppp))pp</textarea><br>
<button onclick=O.innerText=f(I.value)>Run</button><br>
<pre id=O></pre>

Использует ()p, хотя вы используете другую букву, вы можете просто изменить pк концу.

ETHproductions
источник