Позвольте мне рассказать вам о простой системе счисления. (который я сделал только для этого вызова)
Эта система содержит функции ()
, []
, {}
и <>
.
1. ()
Когда ()
не приводятся аргументы, он оценивается как 0
.
Когда ()
дается один или несколько аргументов, он оценивается как сумма аргументов.
2. []
Когда []
не приводятся аргументы, он оценивается как -1
.
Когда []
дается один или несколько аргументов, он оценивается как первый аргумент минус сумма других аргументов.
3. {}
Когда {}
не приводятся аргументы, он оценивается как 1
.
Когда {}
дается один или несколько аргументов, он оценивается как произведение этих аргументов.
4. <>
Когда <>
не приводятся аргументы, он оценивается как 1
.
Когда <>
дается один или несколько аргументов, он вычисляется как целое число первого аргумента, деленное на произведение других аргументов.
Твое задание
Если в этой простой системе счисления задана строка, которая содержит действительное число (это означает, что скобки сбалансированы, без деления на 0 и т. Д.), Выведите ее значение.
Контрольные примеры
() -> 0
(()()) -> 0
([][]) -> -2
({}<>) -> 2
({}[]) -> 0
[] -> -1
[[][]] -> 0
[()<>] -> -1
{()} -> 0
{([]<>)} -> 0
Помните, что это код-гольф , поэтому выигрывает код с наименьшим количеством байтов.
источник
5/3
,5/-3
,-5/3
и-5/-3
?Ответы:
Дьялог АПЛ , 94 байта
o←{(⊂(1⊃⍵),⍺⍺⊃⍵),2↓⍵}⋄u←{(⊃⍵,⍺⍺1)⍺⍺⍵⍵/1↓⍵}⋄⍎⍕'+/o' '-u+o' '×/o' '÷u×o' '(⊂⍬),'[')]}>'⍳⌽⍞],'⊂⍬'
использования
⎕IO←0
заменяет
)]}>
на вызов функции, который берет стек, применяет операцию к верхнему кадру, удаляет ее и добавляет результат к следующему кадру (o
для этого используется монадический оператор ; двоичный операторu
обрабатывает более сложные случаи-
и÷
)заменяется
([{<
кодом, который добавляет кадр в стек ((⊂⍬),
)выполняет результирующее выражение (обратное, чтобы соответствовать порядку выполнения APL) с начальным стеком одного пустого кадра (
⊂⍬
)источник
Haskell,
357306277251228224188185180 байтПарсер на основе токенов с явным стеком.
(%)
принимает стек токена и символ и нажимает (код операции, номер по умолчанию) или (0, число) для({[<
, или выдает самые верхние числа и один код операции и нажимает ответ для)}]>
. Коды операций кодируются путем взлома перечисления ascii.Престижность @ChristianSievers за его отличный ответ , из которого я позаимствовал некоторые идеи.
Один лайнер!
Теперь с меньшей обработкой ошибок! Использование:
Спасибо @ChristianSievers за сохранение 14 + 3 байтов!
Спасибо @Zgarb за сохранение + 4 байта!
источник
(0,[0,0,1,-1,1]!!o):s
пятой строки?!
, так что вы можете сделать(s:_)!_=d s
как второй случай. Кроме того, я думаю, что вы могли бы связатьx<-p$d<$>init a,y<-d$last a
в последнем случае%
.%
вы можете упасть вокруг скобки_:b
иg c
.Python 2,
292265248235223206204 байтаЗаменяет все скобки на лямбду, которая делает то же, что и скобка, а затем оценивает полученный код Python. Требуется его ввод в кавычках, вроде
'[<><>([]{})]'
.Эта программа сохраняет тип скобки в качестве первого символа в каждой строке в
for
, и все после ключевого словаlambda
в качестве остальных. Затем он использует первый символ для замены; остальное объединяется в лямбда-лайк(lambda*x:sum(x))()
.Попробуйте это на Ideone!
источник
PEG.js (ES6) , 132 байта
Должно быть исправлено сейчас.
объяснение
Более читабельно:
PEG.js - это расширенная версия Javascript, специально созданная для анализа. Это очень строго, поэтому я должен был использовать
var
. Кроме того, кажется, есть ошибка с скобками внутри строк, что значительно увеличило объем кода.Для начала мы определим правило
x
, соответствующее любой скобке,a
которая может содержать или не содержать несколько выражений, соответствующих правилуx
.Для каждого соответствия правилу
x
мы помещаем 0 в массив внутреннего соответствия,b
еслиb
длина равна 1.Если
b
длина> 0, то мы находим индексa
в([<
и получаем символ от+-/
использования этого индекса. Если результат не определен (имеется в виду, чтоa
был{
), то мы превращаем результат в*
. Наконец, мы выбираем место и присоединяемсяb
к результату.Если
b
длина = 0, то мы находим индексa
в([<
и получаем символ от10
использования этого индекса. Если результат не определен ( это означает , чтоa
было{
или<
), то мы переходим результат в 2. Наконец, мы просто декремент.В конце мы можем просто оценить выражение и получить результат.
источник
Perl, 113 + 2 = 115 байт
Выполнить с
-lp
(штраф 2 байта).Более читабельный (примечание: эта «более читаемая версия» на самом деле не будет работать, потому что я размещаю комментарии там, где они синтаксически не разрешены):
Основная идея заключается в том, что мы преобразуем входные данные, например,
[()<>]
в программу Perl, сb(a(0),d(0),0),
помощью обработки текста; Perl просто в порядке с запятой. Ранее мы определили функцииa
,b
,c
,d
чтобы иметь такое же воздействие , как()
,[]
,{}
,<>
конструкции из языка мы реализующий; каждый из них игнорирует свой последний аргумент (0 в конце), который включен, чтобы гарантировать, что все входные данные анализируются правильно, и работать с использованием реализации, обычно наблюдаемой в функциональном программировании, где голова и хвост обрабатываются отдельно. Потому чтоb(e,f,g,0)
означаетe-f-g
, т.е. обрабатывает свой первый аргумент специально, тогда какa
обрабатывает его аргументы симметрично (a(e,f,g,0)
означаетe+f+g
), мы реализуемa
рекурсивно иb
через вызовa
.c
иd
иметь похожие отношения. Все четыре из этих функций очень похожи, поэтому мы генерируем их во время выполнения, а не реализуем их отдельно; мы храним шаблон, который применяется ко всем четырем функциям в строке, а затем генерируем функции, подставляя символы в шаблон.Поскольку Perl
/
выполняет деление с плавающей точкой, реализованное{}
тоже. Я предполагаю, что либо это не является проблемой само по себе, либо-Minteger
(выбор варианта языка, где все арифметические операции являются целочисленными операциями) является бесплатным, потому что в противном случае мне пришлось бы тратить дополнительные байты на написание целочисленного деления на Perl, которая, кажется, не в чем суть проблемы. (Я думаю , что вам придется потратить четыре байта изменения(shift)
кint+(shift)
;. Я не проверял это)источник
Октава,
215206198 байтпопробуйте это онлайн
источник
PHP,
315300285258250244 байтазаменяет подвыражения символом подчеркивания + значение; разрывы цикла, когда итерация не заменяет.
19 лет с тех пор, как я впервые познакомился с C, 17 лет работал с PHP;
это первый раз, когда
strtok
имеет смысл ... помогает сэкономить 24 байта!сломать
источник
ES6 (Javascript),
250,171,154,149147 байтЧистая версия Javascript.
«Метапрограммирование» (как и большинство других ответов здесь) преобразует текст входной программы в соответствующую программу Javascript, применяя к ней ряд прямых подстановок текста (т.е. сохраняя структуру программы как есть).
Может быть, можно играть в гольф дальше.
ОБНОВЛЕНИЕ (v2.1)
ОБНОВЛЕНИЕ (v2)
Просто понял, что ожидающие запятые в массивах ES полностью действительны, поэтому весь код нормализации запятой можно удалить. Также последовал отличный совет @Titus по оптимизации поиска по алфавиту.
ОБНОВЛЕНИЕ (v1)
Удален дубликат "заменить" псевдоним.
ОБНОВЛЕНИЕ (v1)
Используйте лучший алфавит: () => 1+ [] => 0 {} => 2 * <> => 2 / (каждый символ может быть непосредственно повторно использован в качестве значения или оператора)
Замените, чтобы уменьшить () с заменой () (сопоставление алфавита)
Объединение постоянной вставки, обработки открытых и закрывающих скобок в один шаг
Гольф (v2.1)
Гольф (v1)
Гольф (v0)
Объяснил (v0)
Тестовое задание
Тестовый вывод
источник
s.reduce((r,c)=>r+="abcdefgh"["()[]{}<>".indexOf(c)],'')
(-5)? если это так, вы можете запомнитьindexOf
переменную и взять оператор из третьего строкового литерала.Haskell,
184 179 172 161 160 159 151 148145 байтовРекурсивный спуск, поток ввода, потому что Haskell. Как обычно, последняя строка не является определением, но описывает функцию, которая решает проблему. Чтобы проверить, поместите строки, кроме последней, в файл, загрузите его и сделайте что-то вроде этого:
Спасибо @Zgarb за вдохновение и множество подробных советов, а также @Angs за вдохновение от его решения и дальнейших советов.
Не было указано, как деление должно вести себя с отрицательными целыми числами. В любом случае, повторное использование
div
кажется неправильным, поскольку это не то же самое, что использованиеdiv
один раз с произведением оставшихся значений. Теперь, используяquot
, я получаю те же результаты для<{}([][])[]>
и<{}{([][])[]}>
.Для хорошего, почти читаемого кода посмотрите на первую версию. Промежуточные версии содержат все виды приятного и пугающего кода и помогают понять эту версию.
источник
(!)=(,)
и используя!
вместо явных кортежей.m x
и ,d x
как1#x
и0#x
вы можете объединить делаm[x]
иd[x]
в одну, что я думаю , что экономит некоторые байты тоже.!
трюк не окупается. Ваше второе предложение - зло, вот мой почти читаемый код ... Умно!s%(c:i)=(s?c,i)
иs?')'=sum s
т. Д. Будет намного короче, так как вы можете избавиться от повторяющихсяi
с. ..Не ждите, это, вероятно, не сработает из-заs%(_:i)
дела.elem
иdiv
, что должно сэкономить еще несколько байтов.JavaScript (ES6), нет
eval
, 156 байтОбъяснение: Регулярное выражение находит первую необработанную закрывающую скобку и сопоставляет (предположительно) соответствующую открывающую скобку и любые аргументы между ними. Аргументы разделяются и уменьшаются в соответствии с операцией (к сожалению, '(' и '[' не являются оптимальной парой для
+
и-
), или, если аргументов нет, то вычисляется соответствующее значение (опять же, сопоставление символов со значениями является неоптимальным). с моей точки зрения.) Затем результат заменяется начальным пробелом, чтобы отделить его от других результатов. Затем функция вызывает себя рекурсивно до тех пор, пока не останется никаких изменений, и в этом случае она возвращает полученное значение. Пример:источник