Pyth - язык игры в гольф, основанный на Python. Он использует префиксную нотацию, каждая команда имеет разную арность (количество аргументов, которые она принимает).
Ваша задача - написать средство проверки синтаксиса для (несуществующего) языка, подобного Pyth, Pith.
Синтаксис Pith
У Pith есть только 8 команд с одним символом:
01234()"
01234
у каждого есть арность соответствующего числа, и, следовательно, ожидайте, что после него будет много аргументов. Например,
400010
является правильной программой Pith, потому что 4
за ней следуют четыре аргумента, 0
0
0
а 10
за последним 1
следует единственный аргумент 0
. Чтобы визуализировать это, мы можем взглянуть на следующее дерево:
R
|
4
|
-------------
| | | |
0 0 0 1
|
0
где R
корневой узел Альтернативный способ думать об этом состоит в том, что каждое число относится к числу дочерних элементов, которые соответствующий узел имеет в дереве выше.
Вот еще одна действительная программа Pith с более чем одной базовой командой:
210010
соответствует
R
|
-------------
| |
2 1
| |
--------- 0
| |
1 0
|
0
С другой стороны,
3120102100
это не правильная программа Pith , поскольку исходный 3
имеет только два аргумента, которые мы можем увидеть, посмотрев на дерево ниже:
R
|
3
|
------------------------ ??
| |
1 2
| |
2 ------
| | |
------ 1 0
| | |
0 1 0
|
0
Далее (
начинается неограниченное, и )
заканчивается неограниченное. Неограниченный принимает любое количество аргументов (жадно) и считается одним аргументом для любой родительской команды. Любые неограниченные, все еще открытые к концу программы, автоматически закрываются. )
Команда не является ошибкой , если нет unboundeds открыты - это просто ничего не делает *.
Например, программа Pith
)31(0)0(201000100
соответствует дереву
R
|
3
|
------------------------------
| | |
1 0 (
| |
( -----------------------------
| | | | | |
0 2 0 0 1 0
| |
------- 0
| |
0 1
|
0
Пустые неограниченные в порядке, так ()
что действительная программа Pith.
Недопустимая программа Pith с неограниченной
12(010
так как 2
только получает один аргумент (неограниченный).
Наконец, "
начинается и заканчивается строка, которая всегда равна 0 арности и считается как один аргумент, например
2"010""44)()4"
которому просто 2
передают два строковых аргумента "010"
и "44)()4"
. Как и неограниченные, строки также могут быть пустыми, и любые незакрытые строки к концу программы автоматически закрываются.
* Эта часть отличается от оригинального Pyth, который на самом деле делает что-то в случае, например 1)
, завершает 1-арность и вызывает ошибку.
Ввод, вывод
Ввод будет единственной непустой строкой, состоящей только из символов 01234()"
. При желании вы можете предположить, что дополнительный трейлинг-перевод строки всегда присутствует. Вы можете написать функцию или полную программу для этой задачи.
Вы должны вывести истинное значение, если входной синтаксически правильный Pith, или ложное значение в противном случае. Значения true и false должны быть фиксированными, чтобы вы не могли выводить данные 1
для одной действительной программы и 2
для другой.
счет
Это код-гольф, поэтому выигрывает код в наименьшем количестве байтов.
Контрольные примеры
Truthy:
0
)
(
"
()
""
10
400010
210010
("")00
3"""""
(0)))0)1)0
2(2(2(0)0)0)0
2"010""44)()4"
)31(0)0(201000100
())2)1))0"3())"))
3("4321("301(0)21100"4")"123"00)40"121"31000""01010
Falsy:
1
1(310
(1)0)
12(010
4"00010"
3120102100
20(2((0)(0)))
2(2(2(0)0)0)01)
4(0102)00)00000
2"00"("00"2(""))
[( [2 [0] [1 [0] ] ] [0] [1 [0]] [0] ]
? У того, который у вас есть, есть ветви 2, 0, 0, 1 и 0 - второго не должно быть.())2)1))0"3())"))
(который должен быть правдой, я думаю).()210""
это происходит из-за отсутствия операций)Ответы:
CJam, 65 байт
Черт возьми, я бы хотел, чтобы у CJam было Regex, тогда это могло быть выполнено менее чем за 50 байтов.
Основная идея состоит в том, чтобы продолжать сокращать материал до
0
т.е.10
к0
,200
к0
и так далее. Как только это будет сделано, мы уменьшаем все соответствующие кронштейны к0
, т.е.()
к0
,(0)
к0
,(00)
к0
и так далее. Мы повторяем время циклаL
, гдеL
длина ввода.Входная строка изначально проходит дополнительную обработку, где мы подстраиваемся под несоответствие
"
и добавляем много,)
чтобы компенсировать несоответствие(
Это гарантирует, что после всех итераций у нас останется
0
(и не будет)
) в строке.Обновление - исправлена ошибка, из-за которой неактивные игры верхнего уровня
)
считались вредными.Расширение кода
Попробуйте онлайн здесь или запустите весь пакет
источник
Regex, PCRE аромат, 83 байта
Попробуй это здесь.
Regex, PCRE аромат, 85 байт
Попробуй это здесь.
Использовал некоторые идеи в ответе этого дан1111 .
Некоторые пояснения по поводу
(?2)*(()(?1))?
.источник
(?2)*(()(?1))?
последний кусок головоломки, который я искал. Хорошая находка! ;)(?2)*(()(?1))?
правильно понимаю часть, эта(()(?1))?
часть никогда не совпадает с чем-либо, поскольку(?2)*
уже съедает все, что(()(?1))?
может соответствовать, и эта конструкция используется для установки группы захвата 3, когда мы входим,(
и отмены захвата группы 3, когда мы находимся за пределами()
конструкции (чтобы обеспечить соответствие непарный)
).lex, 182 байта (157 Вт / стек фиксированного размера)
Эти программы требуют, чтобы ввод был отдельной строкой допустимых символов с новой строкой в конце.
Приведенная выше программа будет segfault, если ей не хватит памяти, что теоретически может произойти, если вы дадите ей достаточно
(
. Но поскольку segfault считается неудачей, я воспринимаю это как «ложь», хотя в описании проблемы не сказано, что делать, если ресурсов недостаточно.Я сократил его на 157 байт, просто используя стек фиксированного размера, но это казалось обманом.
Скомпилировать:
Тест:
Тестовый вывод:
источник
80386 Ассемблер, 97 байт
Шестнадцатеричный дамп:
Он проходит через вход один раз, помещая числа больше нуля в стек и уменьшая их при обработке нуля. Неограниченные обрабатываются как -1.
Прототип функции (в C) (функция возвращает 0, если недействительно, и 1, если допустимо):
Эквивалентная сборка (NASM):
Следующий код на C может использоваться с GCC в системе POSIX для тестирования:
источник
Python 2, 353 байта
Функция синтаксического анализа проходит по токенам по одному и строит дерево структуры программы. Недопустимые программы вызывают исключение, которое приводит к печати нуля (Falsy), в противном случае успешный анализ приводит к одному.
Вывод тестов, показывающих вывод парсера:
Код перед минификатором:
источник
==
в тестах - сначала указав строки, вы можете это сделатьif')'==q
. Я полагаю, что одно изbreak
утверждений может быть замененоf=0
, так как это также выведет вас изwhile f
цикла. Наконец, вместоassert x==y
вы можете использовать1/(x==y)
дляZeroDivisionError
. ;)Пип ,
8872 байтаИдея взята из CJam Оптимизатора . Мой первоначальный удар по проблеме с парсером рекурсивного спуска был ... довольно длинным.
Отформатировано с объяснением:
Интересные трюки:
0X,5
, например, есть0 X [0 1 2 3 4] == ["" "0" "00" "000" "0000"]
.R
оператор eplace может взять список для любого из его аргументов:"abracadabra" R ["br" "ca"] 'b
даетababdaba
, например. Я хорошо использую эту функциюz
здесь.""
, пустой список[]
и любой скаляр, который равен нулю. Таким образом,0
ложно, но также0.0
и"0000000"
. Эта функция иногда неудобна (чтобы проверить, пуста ли строка, нужно проверить ее длину, потому что"0"
она тоже ложна), но для этой проблемы она идеальна.источник
Javascript (ES6),
289288285282278244241230 байтисточник