Обратите внимание: я готов дать вознаграждение за любой ответ, который мне кажется интересным.
Ваша задача состоит в том, чтобы спроектировать компьютер с полным набором инструкций по Тьюрингу (OISC):
OISC - это абстрактная машина, которая использует только одну инструкцию - избавляя от необходимости кода операции машинного языка. Благодаря разумному выбору одной инструкции и неограниченным ресурсам, OISC может быть универсальным компьютером так же, как традиционные компьютеры с несколькими инструкциями.
Вот несколько примеров отдельных команд, которые делают OISC-полный по Тьюрингу.
Правила:
Вы должны предоставить интерпретацию или доказательство этого
Вы должны предоставить переводчика для вашего языка. Этот интерпретатор должен быть ограничен только памятью / временем (например, он не должен иметь никаких ограничений, наложенных пользователем). Если вы не предоставляете переводчика для вашего языка (по любой причине, кроме лени), вы должны доказать, что он может быть написан. Переводчик должен быть возможным .
Вы должны доказать его Тьюринговую полноту
Вы должны приложить формальное доказательство того, что ваш язык завершен по Тьюрингу. Простой способ сделать это - доказать, что он может интерпретировать или иметь то же поведение, что и другой язык, полный по Тьюрингу. Основным языком для интерпретации будет Brainf ** k .
Например, обычный язык, который имеет все те же команды, что и Brainf ** k (и такое же отсутствие ограничений памяти, наложенных пользователем), является полным по Тьюрингу, потому что все, что может быть реализовано в Brainf ** k, может быть реализовано на языке ,
Вот список очень простых в реализации языков, полных тьюринга.
Дополнительные требования OISC
Этот OISC должен иметь только одну инструкцию - он не может иметь несколько инструкций, одна из которых делает его выполненным по Тьюрингу.
Ваш OISC может использовать любой синтаксис, который вам нравится. Вы должны определить в своем ответе, что такое инструкция, что такое данные, а что нет (например, пробел). Будь креативным!
Аргументы не просто должны быть целыми числами. Например, /// является прекрасным примером OISC, полного по Тьюрингу.
Как и если ввод и вывод взяты и даны, остается на ваше усмотрение. Большинство OISC реализуют ввод / вывод через определенные области памяти, но могут быть другие способы сделать это, и вам рекомендуется найти один из них.
Правильный ответ должен содержать пример кода в вашем OISC, либо путем включения его в сообщение, либо с помощью ссылки на простую задачу, решаемую на языке.
голосование
Избиратели, пожалуйста, помните, чтобы не голосовать против скучных представлений. Примеры:
- Lenguage -эквиваленты
- Реализация существующего OISC (ответчики, пожалуйста, создайте свой собственный!)
- «OISC», в котором первый аргумент указывает команду для вызова ( пример )
Тем не менее, вы должны поддержать интересные, творческие материалы, такие как:
- OISC на основе математического уравнения
- Завершенный по Тьюрингу ZISC на основе нейронной сети
- OISC, в котором вывод ввода-вывода происходит другими способами, чем определенные области памяти
выигрыш
Как и в конкурсе популярности , ответ с наибольшим количеством голосов выигрывает! Удачи!
Ответы:
XOISC
Этот OISC основан на X-комбинаторе Фоккера, который определяется следующим образом:
Если мы признаем тот факт, что SKI-исчисление завершено по Тьюрингу, то вышеупомянутый комбинатор также завершается по Тьюрингу. Это потому , что S , K и I можно записать в терминах X , например:X S K I X
Как работает XOISC
Внутренне XOISC имеет (изначально пустой) стек, оттуда инструкция, принимающая в качестве аргумента, делает следующее:n
Когда больше не осталось инструкций, XOISC поместит все аргументы командной строки (если они есть) в стек, например:
Окончательный расчет будет .(…((…(s1 s2)…) sM) a1)…)aN
Поскольку одна инструкция в XOISC принимает только один аргумент (смещение памяти), нет никаких оснований даже использовать имя для этой инструкции. Таким образом, допустимый исходный файл будет состоять только из целых чисел, разделенных символами новой строки или пробелами, как, например:
Попробуйте онлайн!
пример
Давайте возьмем приведенный выше пример (стек растет справа):
Наконец, оцените стек: или с меньшими скобками X ( X X ) ( X X ) ( X X ), который мы распознаем как старый добрый тождество S K K функция.((X (X X)) (X X)) (X X) X (X X) (X X) (X X) S K K
Полнота по Тьюрингу
Доказательство идеи
Чтобы XOISC был полным по Тьюрингу, мы должны иметь возможность переводить любое (допустимое) чередование скобок и комбинаторов. Это возможно, потому что при высовывании, применении и толкании это происходит ассоциативно справа (приложение-функция левоассоциативно).X
Для перевода любого такого выражения есть простой способ сделать это: всегда выдвигать столько элементов, чтобы с начала текущего уровня скобок оставался только один элемент.X
В качестве примера, ранее использовалось выражение:((X (X X)) (X X)) (X X)
0
0
2
0
2
Таким образом, мы получаем другую (но семантически эквивалентную) XOISC-программу:
0 0 2 0 2 0 2
Попробуйте онлайн!Если мы будем придерживаться этой стратегии, мы можем легко преобразовать любое выражение, состоящее из комбинаторов, в программу XOISC, которая оставляет в стеке только одну функцию.X
Формальное доказательство
Учитывая, что SKI-исчисление завершено по Тьюрингу, нам нужно показать две вещи:
Первая часть - доказательство трех равенств во введении - очень утомительна и занимает много места, а также не очень интересна. Таким образом, вместо того, чтобы поместить это в этот пост, вы можете найти здесь * .
Вторая часть может быть доказана структурной индукцией , хотя легче доказать немного более сильное утверждение: А именно, для любого выражения, образованного комбинаторами, существует программа, которая оставляет это выражение как одно выражение в стеке:X
Существует два способа построения такого выражения : либо само X , либо f g для некоторых выражений f и g :X X f g f g
Первый из них тривиален, так какX F1…FN G1…GK f g f g
0
оставит в стеке как одно выражение. Теперь предположим, что есть две программы ( F 1 … F N и G 1 … G K ), которые оставят f и g как одно выражение в стеке и докажут, что утверждение верно и для f g :Программа сначала сгенерирует f в стеке, а затем сгенерирует g, но вместо того, чтобы извлекать только части g, она также вытолкнет f и применит ее, такой, что он оставляет единственное выражение f g в стеке. ∎F1…FN G1…GK−1 (GK+1) f g g f f g
переводчик
входные
Поскольку нетипизированное лямбда-исчисление требует, чтобы мы определяли наши собственные типы данных для всего, что мы хотим, и это громоздко, интерпретатор знает о церковных цифрах - это означает, что когда вы вводите входные данные, он автоматически преобразует числа в соответствующие им церковные цифры.
В качестве примера вот программа, которая умножает два числа: Попробуйте онлайн!
Вы также можете предоставить функции в качестве аргументов, используя индексы Де Брюина , например,
S
комбинатор\\\(3 1 (2 1))
(илиλλλ(3 1 (2 1))
). Однако он также признаетS
,K
,I
и, конечно жеX
комбинатор.Выход
По умолчанию интерпретатор проверяет, кодирует ли выход целое число, если он это делает, он выведет соответствующее число (в дополнение к результату). Для удобства есть
-b
флаг, который говорит интерпретатору попытаться сопоставить логическое значение (см. Последний пример).ассемблер
Конечно, любой низкоуровневый язык нуждается в ассемблере, который преобразует в него высокоуровневый язык, вы можете просто использовать любой ввод (см. Выше) и преобразовать его в XOISC-программу, используя
-a
флаг, попробуйте его онлайн! *** Если ссылка не работает, в этом посте есть копия HTML-комментария.
** Это приводит к программе, которая проверяет на простоту, попробуйте онлайн!
источник
Привлечь
Draw - это OISC, действующий на двумерной сетке, помечающий квадраты аналогично B-машине Wang. Однако, чтобы язык был как можно более простым и OISC-y, насколько это возможно, все инструкции (из которых всего один) отмечают квадрат, на который только что ступили, и, чтобы иметь возможность остановиться, наступают на отмеченный квадрат завершает программу
Программа состоит из последовательности строк, содержащих идентификатор строки (произвольная строка, не включая # или пробел), два целых числа (
x
иy
) и еще два идентификатора строки (a
иb
).Трассы программы выглядит следующим образом :
Начиная с линией идентифицированной как
start
с указателем , указывающим на позицию (0, 0), переместите указатель на величине заданнойx
иy
и отметьте квадрат указатель находится теперь (если квадрат не уже отмечалось, в этом случае исполнение прекращается). Затем перейдите к строке,a
если хотя бы один из непосредственно смежных квадратов также помечен, и к строке вb
противном случае.Переводчикам рекомендуется выводить конечный результат таблицы как изображение, холст и т. Д.
Тьюринга Полнота
Draw завершен по Тьюрингу, так как в язык можно скомпилировать модифицированную версию (называемую Alternate) машины Minsky.
Альтернатива действует аналогично машине Мински с двумя счетчиками, но на команды накладывается большое ограничение: команды должны чередоваться для нацеливания на первый и второй счетчики. Чтобы обойти эту модификацию, дополнительная команда была добавлена:
nop
. Эта команда вообще не изменяет целевой счетчик, что позволяет «дополнять» последовательные изменения одним счетчиком, удовлетворяя ограничению, описанному выше. Это также означает, что регистр, который должен быть изменен, не должен быть задан и для любой данной инструкции может быть непосредственно получен вывод из инструкций, из которых выполнение может перейти к нему.Пример: это минский аппарат
превращается в эту альтернативную программу:
Это ограничение необходимо из-за способа, которым конечная программа Draw обрабатывает регистры, то есть она вообще не различает их. Вместо этого программа Draw просто копирует регистр, который не был изменен предыдущей инструкцией, изменяя его в соответствии с выполняемой инструкцией.
Затем альтернативная программа напрямую переводится в Draw следующим образом:
Программа начинается с этого блока.
inc
,dec
Иnop
переводится почти так же, как друг с другом. Во всех случаях нет разницы между изменением первого или второго регистра (как объяснено выше). Вот приращение, эквивалентноеinc 2
:Измените числа в
i1_x
частях на индекс текущей инструкции, а вi2_x
частях на индекс следующей инструкции, которая будет выполнена.nop
Инструкция может быть переведена как таковые:Это декремент:
i3_x
относится к инструкции, которая будет вызвана, если счетчик уже равен 1.Останов:
Измените метки соответствующим образом и просто соедините все вместе. Выполнение этого для примера сверху дает программу Draw в хранилище сверху.
интерпретаторы
В настоящее время есть два переводчика, оба написаны на Python. Их можно найти в репозитории Draw GitHub .
совершенно неправильной цели,облегчая графический вывод, беря исходный код через всплывающее окно при запуске скрипта. Golly может быть немного привередливым с Python, поэтому убедитесь, что у вас установлен Python 2 (и не смешивайте 32-битный Golly с 64-битным Python или наоборот). Вывод осуществляется через встроенную ячейку Golly.Следующее изображение является примером для вывода из второго интерпретатора. Запуск примера программы в репозитории дает это (или подобное):
источник
-3
Вот суть.
объем памяти
Память - это карта лент, где ключи - это строки, а значения - целые числа произвольного размера.
Кроме того, есть набор меток, на которые программа может перейти.
Существует стек, который содержит операнды, которые являются строками.
Существует предложение, которое контролирует, где в лентах памяти он может получить доступ.
Одна инструкция
-
, Во-первых, он выталкивает строкуLABEL
из стека. ЕслиLABEL
он не определен как метка, он определяет метку и очищает источник этой метки (то есть, откуда она была выдвинута) и текущую инструкцию. В противном случае он выполняет следующие вычисления, используя два верхних значения,A
иB
:Обратите внимание, что при наличии избыточных или недостаточных аргументов программа выдаст ошибку, показывая состояние программы.
Смещение может быть изменено путем доступа к значению
.
.Пример кода
Это устанавливает переменную
i
в7
, приращением7
раз.Это умножается
i+1
на константу2
.Доказательство полноты по Тьюрингу
Независимо от размеров int в C ++ (то есть, предполагая, что они бесконечны), -3 - это Turing Complete путем сокращения до 3-клеточного мозгового отвращения . Я могу пренебречь этим размером, потому что на компьютере с бесконечной памятью, имеющей произвольно большие ячейки, можно написать интерпретатор для -3.
Я также считаю, что любой BCT может быть записан как программа -3.
источник