Неплохо для довольно многословного тарпита Тьюринга ...
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) каждый раз. Вуаля!