Неплохо для довольно многословного тарпита Тьюринга ...
N
Count i while _%128-9 {
Count x while _/128%2 {
Write 40
_+128
}
Write _%128
_+128-_%128+N
}
Count j while _/256-j {
Write 41
}
(Да, все эти пробелы являются обязательными.)
Примечание: из-за ограничений ввода Acc! , невозможно прочитать произвольную строку символов без некоторого конечного разделителя. Поэтому эта программа ожидает ввода (в stdin) в виде строки, за которой следует символ табуляции.
Точность !! ?
Это язык, который я создал, который кажется непригодным для использования . Единственным типом данных являются целые числа, единственной конструкцией потока управления является Count x while y
цикл, а единственным способом хранения данных является один аккумулятор _
. Ввод и вывод выполняются по одному символу за раз, используя специальное значение N
и Write
оператор. Несмотря на эти ограничения, я вполне уверен, что Acc !! завершена по Тьюрингу.
объяснение
Основная стратегия в Acc !! программирование заключается в использовании модового %
и целочисленного деления /
для концептуального разбиения аккумулятора, что позволяет ему хранить несколько значений одновременно. В этой программе мы используем три таких раздела: семь битов младшего порядка ( _%128
) хранят код ASCII из ввода; следующий бит ( _/128%2
) хранит значение флага; а оставшиеся биты ( _/256
) подсчитывают количество близких паренов, которые нам понадобятся.
Вход в Acc !! происходит от специального значения N
, которое считывает один символ и оценивает его код ASCII. Любой оператор, который состоит исключительно из выражения, присваивает результат этого выражения аккумулятору. Итак, начнем с хранения кода первого символа в аккумуляторе.
_%128
будет хранить последний прочитанный символ Таким образом, первый цикл выполняется, пока он не _%128-9
равен нулю, то есть до тех пор, пока текущий символ не станет вкладкой.
Внутри цикла мы хотим печатать, (
если не будем на первой итерации. С Акк !! не имеет оператора if, мы должны использовать циклы для условных выражений. Мы используем 128-разрядный бит аккумулятора _/128%2
как значение флага. На первом проходе единственное, что в аккумуляторе - это значение ASCII <128, поэтому флаг равен 0 и цикл пропускается. На каждом последующем проходе мы будем следить за тем, чтобы флаг был равен 1.
Внутри Count x
цикла (всякий раз, когда флаг равен 1), мы записываем открытый код (ASCII 40
) и добавляем 128 к аккумулятору, тем самым устанавливая флаг в 0 и выходя из цикла. Это также происходит, чтобы _/256
увеличить значение , которое мы будем использовать в качестве нашего подсчета близких паренов, которые будут выведены.
Независимо от значения флага мы пишем самый последний входной символ, который просто _%128
.
Следующее присваивание ( _+128-_%128+N
) делает две вещи. Сначала, добавив 128, он устанавливает флаг в следующий раз в цикле. Во-вторых, он обнуляет _%128
слот, читает другой символ и сохраняет его там. Затем мы делаем петлю.
Когда Count i
цикл завершается, мы только что прочитали символ табуляции, и значение аккумулятора распадается следующим образом:
_%128
: 9
(символ табуляции)
_/128%2
: 1
(флаг)
_/256
: количество прочитанных символов, минус 1
(Минус 1 в том, что мы добавляем 128 к аккумулятору только один раз во время первого прохода через главный цикл.) Все, что нам сейчас нужно, это близкие скобки. Count j while _/256-j
зацикливание _/256
раз, запись близкого парня (ASCII 41
) каждый раз. Вуаля!