В популярной (и обязательной) книге по информатике Питера Линца « Введение в формальные языки и автоматы » часто упоминается следующий формальный язык:
главным образом потому, что этот язык не может быть обработан с помощью конечных автоматов. Это выражение означает «Язык L состоит из всех строк« a », за которыми следуют« b », в которых число« a »и« b »равно и не равно нулю».
Вызов
Напишите работающую программу / функцию, которая получает строку, содержащую только «a» и «b» , в качестве входных данных и возвращает / выводит значение истинности , говоря, является ли эта строка допустимой для формального языка L.
Ваша программа не может использовать какие-либо внешние вычислительные инструменты, включая сеть, внешние программы и т. Д. Оболочки являются исключением из этого правила; Bash, например, может использовать утилиты командной строки.
Ваша программа должна возвращать / выводить результат «логическим» способом, например: возвращать 10 вместо 0, «звуковой сигнал», выводить на стандартный вывод и т. Д. Подробнее здесь.
Применяются стандартные правила игры в гольф.
Это код-гольф . Самый короткий код в байтах побеждает. Удачи!
Правдивые тесты
"ab"
"aabb"
"aaabbb"
"aaaabbbb"
"aaaaabbbbb"
"aaaaaabbbbbb"
Ложные тесты
""
"a"
"b"
"aa"
"ba"
"bb"
"aaa"
"aab"
"aba"
"abb"
"baa"
"bab"
"bba"
"bbb"
"aaaa"
"aaab"
"aaba"
"abaa"
"abab"
"abba"
"abbb"
"baaa"
"baab"
"baba"
"babb"
"bbaa"
"bbab"
"bbba"
"bbbb"
источник
empty string == truthy
иnon-empty string == falsy
приемлемо?a^n b^n
или подобное, а не просто числоa
s, равное количествуb
s)Ответы:
MATL ,
54 байтаПечатает непустой массив 1 с, если строка принадлежит L , и пустой массив или массив с 0 с (оба ложные) в противном случае.
Спасибо @LuisMendo за отыгрывание 1 байта!
Попробуйте онлайн!
Как это устроено
источник
Python 3, 32 байта
Выходы через код выхода : ошибка для false, нет ошибки для True.
Строка оценивается как код Python, заменяя символы «
(
за»a
и «)
за»b
. Только выражения формыa^n b^n
становятся правильно сформированными выражениями, такими как скобки((()))
, вычисляя их как кортеж()
.Любые несовпадающие парены дают ошибку, как и в случае нескольких групп
(()())
, так как разделителя нет. Пустая строка также терпит неудачу (это будет успешноexec
).Преобразования
( -> a
,) -> b
осуществляется с помощьюstr.translate
, которая заменяет символы , как показано на строку , которая служит в качестве таблицы преобразования. Учитывая строку длиной 100 ") (" * 50, таблицы отображают первые 100 значений ASCII каккоторая принимает
( -> a
,) -> b
. В Python 2 должны быть обеспечены преобразования для всех 256 значений ASCII, требующих на"ab"*128
один байт больше; спасибо isaacg за указание на это.источник
*128
?128
может быть заменен50
(или, если99
на то пошло) для сохранения байта.Сетчатка , 12 байт
Кредиты FryAmTheEggman, который нашел это решение самостоятельно.
Печать
1
для правильного ввода и в0
противном случае.Попробуйте онлайн! (Первая строка включает набор тестов, разделенных переводом строки.)
объяснение
Балансирующие группы требуют дорогого синтаксиса, поэтому вместо этого я пытаюсь свести действительный ввод к простой форме.
Этап 1
+
Говорит Retina повторить этот этап в цикле , пока на выходе не перестает изменяться. Соответствует либоab
или,a;b
и заменяет его на;
. Давайте рассмотрим несколько случаев:a
s иb
s в строке не сбалансированы таким же образом, как(
и)
обычно должно быть, некоторыеa
илиb
останутся в строке, так какba
, илиb;a
не могут быть разрешены, и одинa
или самb
по себе не может или. Чтобы избавиться от всехa
s иb
s, должен быть один, соответствующийb
праву каждогоa
.a
иb
не все вложенные (например, если у нас есть что-то вродеabab
илиaabaabbb
), то в итоге мы получим несколько;
(и, возможно, несколькоa
s иb
s), потому что первая итерация найдет несколькоab
s, чтобы вставить их, и дальнейшие итерации сохранят количество;
в строке.Следовательно, если и только если вход имеет форму , мы закончим с единственным в строке.
anbn
;
Этап 2:
Проверьте, содержит ли полученная строка только одну точку с запятой. (Когда я говорю «проверить», я на самом деле имею в виду «подсчитывать количество совпадений данного регулярного выражения, но поскольку это регулярное выражение может совпадать не более одного раза из-за привязок, это дает либо
0
или1
.)источник
Haskell, 31 байт
Понимание списка
[c|c<-"ab",'a'<-s]
создает строку по одному'a'
для каждого'a'
входаs
, а затем по одному'b'
для каждого'a'
входаs
. Это позволяет избежать подсчета путем сопоставления с константой и создания выходных данных для каждого совпадения.Эта строка проверяется, чтобы быть равной исходной строке, а исходная строка проверяется, чтобы быть непустой.
источник
f=g.span id.map(=='a');g(a,b)=or a&&b==(not<$>a)
). Отлично сработано.Грязь , 12 байт
Попробуйте онлайн!
объяснение
Первая строка определяет нетерминал
A
, который соответствует одной буквеa
, возможно, нетерминалуA
, а затем одной буквеb
. Вторая строка сопоставляет весь input (e
) с нетерминаломA
.8-байтовая неконкурентная версия
После написания первой версии этого ответа я обновил Grime, чтобы он рассматривался
_
как имя выражения верхнего уровня. Это решение эквивалентно вышеупомянутому, но избегает повторения этикеткиA
.источник
Брахилог ,
2319 байтПопробуйте онлайн!
объяснение
источник
05AB1E , 9 байтов
Код:
Объяснение:
Последние два байта могут быть отброшены, если входные данные гарантированно не являются пустыми.
Использует кодировку CP-1252 . Попробуйте онлайн! ,
источник
.M{J¹ÔQ0r
для себя.Желе , 6 байт
Печатает саму строку, если она принадлежит L или пуста, и 0 в противном случае.
Попробуйте онлайн! или проверьте все контрольные примеры .
Как это устроено
Альтернативная версия, 4 байта (не конкурирующая)
Печать 1 или 0 . Попробуйте онлайн! или проверьте все контрольные примеры .
Как это устроено
источник
J, 17 байт
Это работает правильно для предоставления фальси для пустой строки. Ошибка ложная.
Старые версии:
Доказательство и объяснение
Основным глаголом является вилка, состоящая из этих трех глаголов:
Это означает: «Меньшее из (
<.
) length (#
) и результат правого зубца ((-:'ab'#~-:@#)
)».Правильный зуб - 4 поезда , состоящие из:
Позвольте
k
представить наш вклад. Тогда это эквивалентно:-:
является оператором совпадения, поэтому ведущие-:
тесты на инвариантность под монадическим форком'ab' #~ -:@#
.Поскольку левый зубец вилки является глаголом, он становится постоянной функцией. Итак, вилка эквивалентна:
Правый зуб вилки (
-:
) длина (#
) изk
. Соблюдайте#
:Теперь, это
k
только на допустимых входных данных, поэтому мы сделали здесь.#
ошибки для строк нечетной длины, которые никогда не удовлетворяют языку, поэтому мы также закончили.В сочетании с меньшей длиной и этим, пустая строка, которая не является частью нашего языка, дает свою длину
0
, и мы покончим с этим.источник
2&#-:'ab'#~#
чтобы он позволял вам избежать ошибки и просто выводил ее0
, продолжая использовать 12 байтов.Бизон / YACC 60 (или 29) байтов
(Ну, компиляция для программы YACC - это пара шагов, поэтому может потребоваться включить некоторые для этого. Подробности см. Ниже.)
Функция должна быть достаточно очевидной, если вы знаете, как интерпретировать ее в терминах формальной грамматики. Синтаксический анализатор принимает любой
ab
илиa
сопровождаемый любой приемлемой последовательностью, сопровождаемой ab
.Эта реализация опирается на компилятор, который принимает семантику K & R для потери нескольких символов.
Это более многословно, чем я хотел бы с необходимостью определить
yylex
и позвонитьgetchar
.Компилировать с
(большинство опций для gcc относятся к моей системе и не должны учитываться в счетчиках байтов; возможно, вы захотите сосчитать,
-std=c89
что добавляет 8 к указанному значению).Бежать с
или эквивалент.
Значение истинности возвращается в ОС, а ошибки также передаются
syntax error
в командную строку. Если я могу посчитать только ту часть кода, которая определяет функцию синтаксического анализа (то есть игнорировать вторую%%
и все последующие), я получу счетчик в 29 байт.источник
Perl 5.10,
3517 байт (с флагом -n )Гарантирует, что строка начинается с
a
s, а затем повторяется наb
s. Это соответствует только если обе длины равны.Спасибо Мартину Эндеру за то, что он сократил вдвое число байтов и научил меня немного о рекурсии в регулярных выражениях: D
Возвращает всю строку, если она совпадает, и ничего, если нет.
Попробуй это здесь!
источник
$_&&=y/a//==y/b//
(требуется-p
), без пустого вы можете сбросить его&&
на 16! Так близко ...echo -n 'aaabbb'|perl -pe '$_+=y/a//==y/b//'
но я не могу сдвинуть еще один байт ... Возможно, придется отказаться от этого!JavaScript,
545544Создает простое регулярное выражение на основе длины строки и проверяет ее. Для строки длиной 4 (
aabb
) регулярное выражение выглядит так:^a{2}b{2}$
Возвращает истинное или ложное значение.
11 байт сэкономлено благодаря Нейлу.
источник
f=
Могут быть опущены.s=>s.match(`^a{${s.length/2}}b+$`)
?C
5753 байтаСтарое решение длиной 57 байт:
Скомпилировано с gcc v. 4.8.2 @Ubuntu
Спасибо Угорен за советы!
Попробуйте это на Ideone!
источник
(t+=2)
вt++++
течение -1 байт.t++++
не является допустимым кодом Си.t+=*s%2*2
и:*s*!1[s]
Сетчатка , 22 байта
Другой короткий ответ на том же языке только что пришел ...
Попробуйте онлайн!
Это демонстрация балансирующих групп в регулярных выражениях, которая полностью объясняется Мартином Эндером .
Поскольку мое объяснение не приблизится к половине этого, я просто буду ссылаться на него и не буду пытаться объяснить, так как это нанесло бы ущерб славе его объяснения.
источник
Befunge-93, 67 байт
Попробуй это здесь! Могу объяснить, как это работает позже. Могу также попытаться сыграть в гольф, чуть больше, просто для ударов.
источник
MATL , 9 байт
Попробуйте онлайн!
Выходной массив верен, если он не пуст и все его записи отличны от нуля. В противном случае это ложь. Вот несколько примеров .
источник
машинный код x86,
2927 байтHexDump:
Код сборки:
Итерирует
a
в начале байты, затем в следующих байтах 'b'. Первый цикл увеличивает счетчик, а второй цикл уменьшает его. Затем выполняет побитовое ИЛИ между следующими условиями:b
s, не равен 0, строка также не совпадаетЗатем он должен «инвертировать» значение истинности в
eax
- установить его в 0, если оно не было 0, и наоборот. Оказывается, самый короткий код для этого - следующий 5-байтовый код, который я украл из вывода моего компилятора C ++result = (result == 0)
:источник
neg eax
установить флаг переноса, как раньше,cmc
инвертировать флаг переноса иsalc
установить AL в FFh или 0 в зависимости от того, установлен флаг переноса или нет. Сохраняет 2 байта, хотя в итоге получается 8-битный результат, а не 32-битный.xor eax,eax | xor ecx,ecx | l1: inc ecx | lodsb | cmp al, 'a' | jz l1 | dec esi | l2: lodsb | cmp al,'b' | loopz l2 | or eax,ecx | setz al | ret
Рубин, 24 байта
(Это просто блестящая идея xnor в форме Ruby. Мой другой ответ - это решение, которое я сам придумал.)
Программа принимает входные данные , преобразует
a
иb
к[
и ,]
соответственно, и оценивает его.Допустимый ввод сформирует вложенный массив, и ничего не произойдет. Несбалансированное выражение приведет к сбою программы. В Ruby пустой ввод оценивается как
nil
, что приведет к сбою, потомуnil
что не определил*
метод.источник
Sed, 38 + 2 = 40 байт
Непустая строка вывод правдоподобна
Конечные автоматы не могут этого сделать, говорите? Как насчет конечных автоматов с петлями . :П
Запуск с
r
иn
флагами.объяснение
источник
JavaScript,
4442Вычеркнуто 44 все еще регулярно 44; (
Работает путем рекурсивного удаления внешнего
a
иb
и рекурсивного использования внутреннего значения, выбранного, но.+
. Если^a.+b$
слева не найдено совпадений , то окончательный результат заключается в том, является ли оставшаяся строка точным значениемab
.Тестовые случаи:
источник
ANTLR, 31 байт
Используется та же концепция, что и в ответе YACC @ dmckee , только чуть больше в гольфе.
Чтобы проверить, выполните шаги, описанные в руководстве по началу работы ANTLR . Затем поместите приведенный выше код в файл с именем
A.g4
и выполните следующие команды:Затем проверьте, введя STDIN
grun A r
так:Если ввод действителен, ничего не будет выведено; если он является недействительным,
grun
выдаст сообщение об ошибке (илиtoken recognition error
,extraneous input
,mismatched input
илиno viable alternative
).Пример использования:
источник
grammer
Ключевое слово стерва для игры в гольф с ANTLR, хотя. Вроде как использовать фортран .C 69 байтов
69 байт:
#define f(s)strlen(s)==2*strcspn(s,"b")&strrchr(s,97)+1==strchr(s,98)
Для незнакомых:
strlen
определяет длину строкиstrcspn
возвращает первый индекс в строке, где найдена другая строкаstrchr
возвращает указатель на первое вхождение символаstrrchr
возвращает указатель на последнее вхождение символаБольшое спасибо Титу!
источник
>97
вместо==98
R,
646155 байтов,7367 байтов (устойчивый) или 46 байтов (если разрешены пустые строки)Опять же, ответ кснора переработан. Если по правилам подразумевается, что входные данные будут состоять из строки
a
s иb
s, он должен работать: возвращает NULL, если выражение допустимо, throws и error или ничего другого.Если входные данные не устойчивы и могут содержать некоторый мусор, например
aa3bb
, следует рассмотреть следующую версию (должна возвращатьсяTRUE
для истинных тестовых случаев, а не NULL):Наконец, если разрешены пустые строки, мы можем игнорировать условие для непустого ввода:
Опять NULL, если успех, все остальное иначе.
источник
NULL
), версия 2: просто ничего (правильный вход возвращает толькоTRUE
), версия 3 (предполагающие пустые строки в порядке, так как состояние):NULL
. R - это статистический объектно-ориентированный язык, который все типизирует без ошибок.if((y<-scan(,''))>'')eval(parse(t=chartr('ab','{}',y)))
Japt , 11 байт
Попробуйте онлайн!
Дает или
true
илиfalse
, за исключением того, что""
дает""
ложь в JS.Распаковано и как это работает
Принято из решения MATL Денниса .
источник
C (Ansi),
6575 байтGolfed:
Объяснение:
Устанавливает значение j и увеличивает j на каждом b и уменьшает j на любом другом. Проверяется, если буква перед меньше или равна следующей букве, чтобы предотвратить работу abab
Правки
Добавлены проверки для abab случаев.
источник
ba
илиabab
?Пакет, 133 байта
Возвращает
ERRORLEVEL
0 при успехе, 1 при ошибке. Пакетный режим не любит заменять подстроки на пустых строках, поэтому мы должны проверить это заранее; если бы пустой параметр был допустимым, строка 6 не была бы необходима.источник
PowerShell v2 +,
6152 байтаПринимает ввод
$n
в виде строки, создает$x
какhalf the length
. Создает-and
булево сравнение между$n
и-match
оператором регулярного выражения с регулярным выражением равного числаa
's иb
' s. Выходы логические$TRUE
или$FALSE
. Это$n-and
там для учета""
=$FALSE
.Альтернативный, 35 байт
При этом используется регулярное выражение из ответа Лики , основанное на балансирующих группах .NET, только что инкапсулированное в
-match
операторе PowerShell . Возвращает строку для truey или пустую строку для falsey.источник
-match
против$args[0]
, иначе-match
будет работать в качестве фильтра[0]
здесь, потому что нам дан только один вход, и нам нужно только одно значение true / falsey в качестве вывода. Поскольку пустая строка является ложной, а непустая строка является достоверной, мы можем фильтровать массив и либо возвращать входную строку, либо ничего не возвращать, что удовлетворяет требованиям вызова.Pyth - 13 байт
Разъяснение:
источник
&qS*/lQ2"ab
+4
расширимся до+4Q
(неявное заполнение аргументов)Haskell, 39 байт
Пример использования:
p "aabb"
->True
.scanl(\s _->'a':s++"b")"ab"x
построить список всех["ab", "aabb", "aaabbb", ...]
с общим количеством(length x)
элементов.elem
проверяет, есть лиx
в этом списке.источник
Python,
4340 байтрассмотрел очевидное решение благодаря Leaky Nun
другая идея, 45 байт:
-4 байта с помощью len / 2 (я получаю ошибку, когда половина приходит последней)
теперь дает false для пустой строки
-3 байта благодаря xnor
источник
lambda s:list(s)==sorted("ab"*len(s)//2)
(Питон 3)lambda s:s=="a"*len(s)//2+"b"*len(s)//2
(Питон 3)''<
вместо того,s and
чтобы исключить пустой случай.