Stackylogic - это язык программирования, который я создал в предыдущем испытании: Run Stackylogic . Прочтите этот пост для получения полной информации и примеров, но вот как это работает, перефразируя:
Stackylogic принимает
0
и вводит1
и выводит один0
или1
после завершения.Программа состоит из строк, которые содержат только символы,
01?
а также ровно одну<
в конце одной из строк. Линии не могут быть пустыми и линия с<
должна иметь по крайней мере один0
,1
, или?
перед ним.Вот пример программы, которая вычисляет NAND из двух битов:
1 ?< 11 ? 0
Каждая строка в программе считается стеком , нижняя часть слева и верхняя справа. Неявно, есть пустой стек (т.е. пустая строка) перед первой строкой в программе и после последней строки.
<
, Называемый курсором, отмечает стек , чтобы начать при запуске программы. Исполнение происходит следующим образом:
Удалите верхний символ из стека, на который в данный момент указывает курсор.
- Если это символ
?
, предложите пользователю ввести a0
или a1
и действуйте так, как если бы это был символ.- Если это символ
0
, переместите курсор на одну стопку вверх (на строку выше текущей строки).- Если это символ
1
, переместите курсор на одну стопку вниз (на строку ниже текущей строки).Если стек, в который перемещается курсор, пуст, выведите последнее значение, извлеченное из стека (всегда a
0
или1
), и завершите программу.В противном случае, если стек, в который перемещается курсор, не пуст, вернитесь к шагу 1 и повторите процесс.
Главное, что нужно понять для решения этой проблемы, заключается в том, что все программы Stackylogic соответствуют таблице истинности . Некоторое заранее определенное число логических значений вводится, и точно одно логическое значение выводится детерминистически.
Итак, ваша задача - создать программу Stackylogic, которая удовлетворяет или имитирует, то есть имеет тот же результат, что и любая заданная таблица истинности. Но не очевидно, что Stackylogic может моделировать любую таблицу истинности, поэтому вот доказательство по индукции :
Базовый вариант
Две таблицы истинности с 0 входами - это таблицы, которые всегда выводят
0
или1
. Стекилогические эквиваленты этих таблиц есть0<
и1<
соответственно.Индуктивный шаг
Предположим, что Stackylogic может моделировать любую таблицу истинности N-входных данных. Пусть M = N + 1.
M-входная таблица T может быть выражена в виде двух N-входных таблиц, T 0 и T 1 , плюс дополнительный входной бит B. Когда B равно 0, используется результат T 0 . Когда B равно 1, используется результат T 1 .
Например, таблица истинности с 3 входами, соответствующая псевдокоду
if B: result = x OR y else: result = x NAND y
является
B x y | result 0 0 0 | 1 0 0 1 | 1 0 1 0 | 1 0 1 1 | 0 1 0 0 | 0 1 0 1 | 1 1 1 0 | 1 1 1 1 | 1
это две таблицы истинности с двумя входами для NAND и OR, расположенные друг над другом битом мультиплексирования B.
Пусть S 0 и S 1 - программы Stackylogic, которые удовлетворяют T 0 и T 1 соответственно (мы знаем, что они существуют на основе первого предположения). Программа S, которая удовлетворяет T, может тогда быть построена как:
[lines of S0 excluding the cursor, with 0 appended to all lines below the cursor] ?< [lines of S1 excluding the cursor, with 1 appended to all lines above the cursor]
Эта компоновка эффективно мультиплексирует между S 0 и S 1 на основе первого входного бита (из строки
?<
). Если это так0
, курсор переместит добавленные0
до исходной позиции курсора S 0 , которая затем будет ограничена сверху и снизу пустыми стеками и, таким образом, будет работать точно так же, как и исходная S 0 . Аналогичным образом, если1
введен, курсор переместится1
вниз до S 1 положения курсора и продолжит выполнять его, как если бы он был один.Например, программы Stackylogic для OR и NAND
? ?<
и
1 ?< 11 ? 0
Их можно комбинировать для симуляции
if B: result = x OR y else: result = x NAND y
вот так:
1 ? 110 ?0 00 0 ?< ?1 ?
Таким образом, любая таблица истинности может быть смоделирована программой Stackylogic.
Вызов
Напишите программу или функцию, которая принимает N входной таблицы истинности (N> 0) в форме списка из 2 N логических значений, которые представляют выходные данные таблицы в возрастающем двоичном порядке.
Любой разумный формат ввода в порядке. например, для таблицы истинности ИЛИ
x y | OR
0 0 | 0
0 1 | 1
1 0 | 1
1 1 | 1
любой из этих стилей ввода будет хорошо:
0111
0, 1, 1, 1
0
1
1
1
[False, True, True, True]
Распечатайте или верните программу Stackylogic, которая удовлетворяет таблице истинности, то есть имеет точно такой же вывод при том же вводе. Любая конечная программа, удовлетворяющая этой таблице, является допустимым выводом. Вам не нужно следовать методу построения индуктивного доказательства. Программы Stackylogic не обязательно должны быть оптимально короткими.
Например, если бы вход был 11100111
, один действительный выход был бы
1
?
110
?0
00
0
?<
?1
?
но есть много других.
Самый короткий код в байтах побеждает.
Посмотрите оригинальное задание Stackylogic, если вам нужен переводчик.
источник
Ответы:
Pyth, 53 байта
Попробуй онлайн
Это точная реализация системы, описанной в задаче о том, как реализовать произвольные таблицы истинности в Stackylogic. Мы просто разрезаем таблицу истинности пополам, реализуем ее рекурсивно, а затем добавляем 0 и 1 соответственно.
Это определяет рекурсивную функцию, чье возвращаемое значение равно
[1, ['0', '?', '1']]
, где первое число - это местоположение указателя, а остальное - стилогическая программа.источник
Python 3,
352208205 байтЭто все еще очень безрассудно, и я постараюсь добавить объяснение позже.После некоторых модификаций мне удалось удалить144147 байт.Функция,
f
которая принимает ввод значений таблицы истинности в виде списка логических значений вида['1','1','1','0','0','1'...]
, где'1'
истина и'0'
ложь, и возвращает программу Stackylogic.Попробуйте это на Ideone
Если вы хотите протестировать созданную программу, вы можете использовать интерпретатор GamrCorps Convex здесь .
Как это устроено
Это рекурсивная функция и использует индуктивный метод, описанный в вопросе.
На уровне рекурсии с нулевым индексом
a
функция создаетn/2
a+1
программы Stackylogic -input из программn
a
-input из списка. Это делается путем объединения всех соседних пар двух программ в списке с помощью?
; Поскольку курсор всегда находится в среднем элементе каждой составляющей программы, необходимое добавление0
или1
может быть выполнено путем итерации по каждой строке соединяемых программ и добавления, если индекс текущей строки меньше или равен / больше чем или равно среднему индексу в зависимости от ситуации. Если список содержит только две программы, следующий рекурсивный вызов даст окончательную программу; поскольку для этого требуется курсор, вместо этого происходит соединение?<
.Когда список имеет длину
1
, список должен содержать только один элемент, содержащий полную программу. Следовательно, все строки в программе объединяются на новую строку, а затем возвращаются.Пример помогает проиллюстрировать это:
источник