Вступление
Этот вызов вдохновлен Grime , моим языком сопоставления двухмерных паттернов. По сути, вам предоставляется «грамматика», описывающая двумерные сетки символов, и ваша задача - создать сетку в соответствии с грамматикой. Кроме того, сетка должна быть как можно меньше в определенном слабом смысле.
вход
Ваш ввод - это строка, содержащая строчные ASCII-символы, а также символы |
и -
. Для простоты ввод не содержит повторяющихся строчных букв. Строка является спецификацией для класса прямоугольных сеток символов и анализируется слева направо, используя стек следующим образом.
- Если задан строчный символ
c
, поместите в стекm×n
сетку символаc
для любогоm, n ≥ 1
. - Получив трубу
|
, вытолкните две сеткиA
иB
из стека (B
был сверху), и протолкните сетку,AB
полученную путем объединения,B
справа отA
. Для этого требуетсяA
иB
одинаковая высота. - Получив дефис
-
, извлеките две сеткиA
иB
из стека (B
был сверху) и вставьте сетку,A/B
полученную путем объединения,B
в нижнюю частьA
. Это требует тогоA
иB
иметь равную ширину.
Гарантируется, что для некоторых вариантов m
и n
сделанных в процессе анализа (которые могут отличаться для каждой буквы) спецификация ввода правильно описывает некоторый прямоугольник, который остается в стеке в конце.
Выход
Ваш вывод представляет собой прямоугольную сетку символов, указанную при вводе. Сетка должна быть минимальной в том смысле, что удаление любой строки или столбца сделает ее недействительной. Вы можете вернуть строку, разделенную новой строкой (с завершающей новой строкой или без нее), двумерный массив символов или массив строк, в зависимости от того, какой формат является наиболее удобным.
Обратите внимание, что вы не обязаны обрабатывать ввод точно так, как описано выше; единственная важная вещь - то, что Ваш вывод правильный.
пример
Рассмотрим спецификацию
par-s||e-
Во-первых, мы решили нажать 1×2
прямоугольник p
и 1×1
прямоугольники a
и r
(причина этого будет ясна позже). Затем мы совать a
и r
прямоугольники, и толкать их по вертикали конкатенации
a
r
Затем мы нажимаем 1×2
прямоугольник , выталкиваем s
его и вышеупомянутый прямоугольник и выдвигаем их горизонтальную конкатенацию
as
rs
Затем мы p
выталкиваем этот прямоугольник и прямоугольник и выдвигаем их конкатенацию
pas
prs
Наконец, мы нажимаем 3×1
прямоугольник , выталкиваем e
его и вышеупомянутый прямоугольник и выдвигаем вертикальную конкатенацию
pas
prs
eee
Это вывод программы или хотя бы одна из возможностей. Обратите внимание, что хотя
ppas
ppas
pprs
eeee
также генерируется спецификацией, это недопустимый вывод, так как многие строки и столбцы могут быть удалены.
В качестве более тонкого примера рассмотрим
co|m|p|il|e|r|-
Эта спецификация генерирует прямоугольник
comp
iler
который является действительным выводом. Тем не менее, он также генерирует
commp
iiler
что также верно, поскольку ни одна строка или столбец не могут быть удалены без признания их недействительными.
правила
Вы можете дать полную программу или функцию. Побеждает меньшее количество байтов, и стандартные лазейки запрещены.
Дополнительные тестовые случаи
Вы можете использовать их для проверки вашей программы.
Input:
a
Output:
a
Input:
co|mp|l|-ex|i|f|-y|
Example output:
cccoy
mplly
exify
Input:
ja-r|g-o|ni-|ze|d-|
Example output:
jronze
arondd
ggoidd
Input:
un|co|p-yr|i|gh-t-ab|-|le-||-
Example output:
unnnnnnn
coyriggl
ppyrihhe
ppyritte
ppyriabe
n
иm
выбираются недетерминированно. Гарантируется, что подходящие значения для них существуют, но задача вашей программы - найти их.un|co|p-|yr|i|gh--t-ab|-|le-||-
невозможно быть действительным. Последний-
имеет арность 2, тогда как в стеке есть только 1 элемент.Ответы:
К,
123110 байтЯ использовал похожий подход к решению картона.
Эта программа представляет собой серию вспомогательных определений, за которыми следует скрытая функция, которая принимает строку в качестве правильного аргумента. Переформатирование для удобочитаемости и назначение конечной функции как
f
:Пример использования:
Протестировано с использованием Kona, но оно также будет работать в порядке, если вы замените
:
в определенииf
на$
- k5, изменив синтаксис "cond".Ключевым моментом является признание того, что вертикальное добавление является транспонированием горизонтального добавления транспонирования обеих матриц. (См. Определение
v
.) Я думаю, что еще есть место, чтобы выжать несколько символов здесь и там. Если кого-то интересует более подробное объяснение, я могу его предоставить.редактировать:
Обновлена программа вверху этой записи. Безголовая версия:
Заметные оптимизации длины включают в себя использование «точка применить» в
a
, заменив «Cond» со списком индексацииf
(менее эффективным, но короче) и замещающие члены видаa[b;c]
вa[b]c
которых допускается группировка. Так как я больше не использую "cond" или любые другие примитивы, которые отличаются между k3 и k5, эта версия теперь работает в ОК без изменений.источник
Пролог, 539 байт
объяснение
Мы начинаем с предиката
g
, который принимает строку, преобразует ее в список символов и вызываетp
качестве второго аргумента предикат (parse) с пустым стеком.Предикат
p
вызывает себя рекурсивно с соответствующим образом измененным стеком (ищите[H|T]
шаблоны деструктуризации и конструктора). При вызове в базовом случае, когда список ввода пуст,p
печатается уникальный элемент стека. Если в стеке на данный момент меньше или больше одного элемента, это означает, что у нас есть пустая строка ввода, неверная строка ввода или ошибка (со строкой emtpy, предикат завершается ошибкой (говорит ПрологNo
), но ничего не печатается, это нормально, так как мы не должны ничего печатать для пустых строк).решение
Стек содержит описание построенных прямоугольников, обозначенных
S:W:H
гдеS
это символическое представление прямоугольника,W
его ширину иH
высоту (примечание,A:B
это синтаксический сахар для:(A,B)
кортежа с функтором именем:
, это просто короче , чтобы писать , чем иметь кортеж с префиксной нотацией).С
A
иB
спецификации прямоугольника,S
может быть:h(A,B)
: горизонтальный конкат А и Вv(A,B)
: вертикальный конкат A и Bf(C)
: заполните C, где C - код символаШирина и высота сетки являются переменными программирования ограничений: во время вертикальной (соответственно горизонтальной) конкатенации ширина (соответственно высота) управляемых прямоугольников унифицируется, тогда как результирующая высота (соответственно ширина) ограничена суммой высота каждой подсетки (соответственно ширина).
Шаг маркировки в конце процесса создает переменные, соблюдая при этом ограничения, используя минимально возможные значения (это свойство порядка, в котором пробуются решения).
Я мог бы получить более короткий ответ, используя те же рассуждения, что и в других ответах, без ограничений, но сейчас уже слишком поздно.
Также обратите внимание, что, поскольку домен по умолчанию для переменных установлен на
1..100
, существует ограничение на возможные размеры сеток. Верхняя граница может быть изменена при необходимости. Это влияет на производительность, так как может потребоваться много времени, чтобы определить, что конкретное решение не допускает решения. Я сказал « мог », потому что ограничения могут резко сократить экспоненциальный поиск. Если вы нашли входную строку, которую трудно / дорого отклонить, пожалуйста, поделитесь.печать
Печатная часть интересна тем, что в структуре есть своего рода алгоритм приведения лучей : я перебираю каждую ячейку результирующей сетки, от точки
(1,1)
к точке,(W,H)
и вызываюw
предикат для печати содержимого сетки в главном дереве, в это местоположение (конечно, новая строка печатается после обработки каждой строки).В
w
позициях относительно текущей сетки (корневая сетка определяет абсолютные координаты).При печати
h(A,B)
структуры в точке(X,Y)
, я безоговорочно печатаю в обеих ветках:A
в точке(X,Y)
, иB
в точке(H,Y)
, гдеH
находитсяX
минус ширинаA
.Листовые ветви дерева сетки,
f(C)
наконец, либо печатают символC
, если относительное местоположение находится внутри сетки, либо ничего не делают. Так я могу печатать содержимое сетки в выходной поток сверху вниз, слева направо. Фактические массивы не создаются.тесты
Выполнение теста:
источник
No actual arrays are produced.
так и надо. Избыточность в этом случае, так как грамматика очень проста, и есть ярлыки.Python 2.7, 259
g
это функция, которая принимает спецификацию и выдает двумерный массив символов. Если вы хотите более удобную для пользователя версию, добавьте эту строку, чтобы она взяла спецификацию из stdin и распечатала сетку:Тестовые случаи
объяснение
Стратегия проста: если сетка
G
действительна для спецификацииS
, то повторение самого правого столбцаG
также дает действительную спецификациюS
, и то же самое верно и для повторения нижней строки (доказательство этого - структурная индукцияS
). Поэтому, когда мы хотим объединить два прямоугольника, мы можем просто добавить последний столбец / строку меньшего, пока они не совпадут по размеру (это то, что делает функция p).источник
Haskell,
388367352 байтаИспользование:
f "par-s||e-"
->["pas","prs","eee"]
Тестовый запуск с красивой печатью:
Как это работает: функция
#
разбирает входную строку в древовидную структуру,C
которая является либо листом,L
содержащим символ для печати, либо узломN
.N
может быть а) соединение бок о бок (t==2
), б) соединение сверху вниз (t==1
) или в) квадрат с одной буквой (t==0
). Все узлы имеют поле ширины и высоты и левый и правый дочерний элемент. После анализаp
печатает оставшийся корневой узел, рекурсивно корректируя размер (ширина х высота) его дочерних узлов и соединяя их.Редактировать: вывод в виде списка строк вместо красивой печати
источник
JavaScript (ES6), 283
295редактировать Теперь это (в значительной степени игра в гольф) решение JS по крайней мере короче, чем эталонное (вполне пригодное для игры в гольф) решение Python.
Аналогично картону, просто повторяет самый левый столбец или самый верхний ряд.
Ungolfed Это мое первое, не Golphed решение.
Тест в консоли Firefox / FireBug
Выход
источник
Python 3, 251 байт
Вот эталонный ответ, который я обещал, сыграв немного дальше.
Это полная программа, которая берет строку из STDIN и печатает в STDOUT. Подход такой же, как и дляboard_box: выдвинуть массив 1x1 для символа и дублировать строки, если это необходимо для объединения.
Детальное объяснение
T
транспонирует заданный список списков. Большая часть работы выполняется путемzip(*m)
обмена строк на столбцы, а остальная часть просто конвертирует результат в список списков, посколькуzip
возвращает генератор кортежей.E(a,b)
возвращаетсяa
с первым элементом, повторенным достаточно раз, чтобы соответствовать длинеb
. Обратите внимание, что умножение списка на отрицательное число дает пустой список, поэтому, еслиb
оно меньшеa
, возвращаетсяa
.H(a,b)
возвращает горизонтальное сцеплениеa
иb
, при необходимости, более короткое удлиняетсяE
.s
это стек.for
цикле мы перебираем входную строку и заменяемs
ее новым значением: если оно|
(больше чемz
), мы выталкиваем два значения и толкаем ихH
, если оно-
(меньше чемa
), мы выталкиваем два значения, транспонируем, передаемH
, транспонировать снова и выдвинуть результат, а в противном случае передать массив 1x1 с буквой.s
.источник