Turing-Complete Language Interpreter

42

Задача, которая, на мой взгляд, была бы очень крутой, состоит в том, чтобы создать переводчика для полного по Тьюрингу языка по вашему выбору.

Правила просты:

  1. Вы можете использовать любой язык для создания этого переводчика, даже если он новее, чем этот вызов.
  2. Вы можете использовать любой язык, полный Тьюринга, если он не совпадает с тем, на котором вы его пишете.
  3. Вы не можете просто оценить код, например, использовать функции eval.
  4. Объяснение того, как вы подошли к этому, будет неплохо, но не обязательно.
  5. Это будет оценено в байтах.
  6. Каждое представление должно быть полностью работоспособным, это означает, что должна присутствовать каждая функция, которую имеет ваш выбранный язык.

Проще говоря:

Ваша задача - создать работающего переводчика для любого языка, полного тьюринга, на любом языке по вашему выбору.

Удачи!

arodebaugh
источник
3
Я также рекомендовал бы правило, согласно которому реализованный язык должен отличаться от языка, который вы используете для его реализации, чтобы избежать тривиальных evalрешений.
ETHproductions
1
На самом деле, вы можете просто запретить evalкоманды / функции, так как некоторые языки имеют встроенные модули для оценки кода на другом языке.
ETHproductions
2
@arodebaugh Для будущих задач вы можете опубликовать свою идею в песочнице, где вы можете получить обратную связь и проработать детали до того, как вызовы будут запущены и получат ответы.
Мартин Эндер
1
Хорошо, вы, вероятно, должны быть немного более конкретны и сказать что-то вроде: «Вы не можете просто выполнить код любым способом», чтобы избежать других тривиальных ответов, таких как Bash + perl.
ETHproductions
1
Соответствующее видео: О тьюринговой полноте PowerPoint (SIGBOVIK)
sergiol

Ответы:

16

Brachylog (2) → Проблема почтовой корреспонденции , 9 байт

~h=∋ᵐ\cᵐ=

Попробуйте онлайн!

Ввод представляет собой список списков строк. (В задаче переписки Post, определенной в Википедии, каждый из внутренних списков состоит из двух элементов, хотя эта программа на самом деле может обрабатывать обобщение на любое количество элементов.) Эта программа решает проблемы методом грубой силы в порядке длины, пока решение найдено. Известно, что проблема почтовой переписки способна моделировать машину Тьюринга, и, таким образом, ее решение является грубым. Если он запускается как функция, а не как программа, он на самом деле также производит значимый вывод.

Программа в ссылке TIO выше есть [["a","baa"],["ab","aa"],["bba","bb"]], которую я скопировал из Википедии. Решение (которое программа находит довольно быстро) это ["bbaabbbaa","bbaabbbaa"].

объяснение

Это в значительной степени просто прямой перевод проблемы почтовой переписки в брахилог.

~h=∋ᵐ\cᵐ=
~h         Find {the shortest possible} list which starts with {the input}
  =        and for which all elements are equal
   ∋ᵐ      such that taking an element of each element,
     \cᵐ   and concatenating elements in corresponding positions,
        =  produces a list all of whose elements are equal.

По сути, мы создаем список, который повторяет входные данные (как можно меньше, что означает, что мы не упускаем никаких возможностей при грубом форсировании), берем один элемент из каждой копии, затем объединяем соответствующие элементы (как в корреспонденции Post). проблема).


источник
1
И обычное «краткое изложение вещей, которые имеют смысл и могут сохранить байты, но интерпретатор брахилога не может с этим справиться»: первые пять байтов могут быть выражены как ~dp(что не означает, что то же самое, но достаточно близко, чтобы все еще быть Turing-complete), за исключением того, что интерпретатор брахилога еще не знает, как повернуть вспять d.
12

Желе → «Добавить минимум для транспонирования», 5 4 байта

+"Ṃẞ

Попробуйте онлайн! (выполняется только одна итерация, чтобы избежать тайм-аутов)

Очень простая конструкция, полная по Тьюрингу: мы берем квадратную матрицу в качестве программы и выполняем цикл навсегда, идентифицируя лексикографически наименьшую строку, затем увеличивая каждый элемент первой строки на первый элемент лексикографически наименьшего, каждый элемент второй строки вторым элементом лексикографически наименьшего и т. д. (Программа Jelly - это « +"добавить соответствующие элементы {входных данных и} минимальный {исходный}, цикл»; это на байт короче, чем моя предыдущая программа Z+ṂZß, которая делала то же самое. Очевидно, я должен был сосредоточиться на игре в гольф Желе, а не просто игра в гольф реализованный язык.)

Получившийся в результате язык Тьюринга полон по той же причине, что и кенгуру, Первый элемент каждой строки действует как количество пропусков (хотя вместо количества пропусков каждой команды, уменьшающегося при ее пропуске, мы вместо этого увеличиваем количество пропусков каждой команды при ее запуске, и ищем команду с наименьшим количеством пропусков, а не чем команды с нулевым количеством пропусков, это то же самое). Мы гарантируем, что этот первый элемент выше, чем другие элементы (которые представляют количество раз, когда каждая команда появляется в мультимножестве каждой команды), таким образом гарантируя, что первая строка никогда не будет минимальной; остальная часть первого ряда может быть мусором. Единственная оставшаяся проблема заключается в моделировании способа, которым команды с одинаковым количеством пропусков выполняются циклически по порядку, но мы можем сделать это, умножив все значения пропусков на большую константу, а затем добавив маленькую «начальную» пропустить отсчет до первого столбца, чтобы послужить разрывом связей. Это дает нам связь между «первыми пропущенными командами без пропусков», а не «непропущенными командами, запускаемыми циклически по порядку», но конструкцию полноты по Тьюрингу для Kangaroo не заботит об этом различии.


источник
10

Mathematica интерпретирует игру жизни Конвея, 64 байта

CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}~Nest~##&

Игра жизни Конвея, как известно, завершена по Тьюрингу; и клеточные автоматы - самая настоящая одержимость Стивена Вольфрама. CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}это правило, которое преобразует двумерный массив из 0 и 1 в соответствии с одним из этапов игры жизни Конвея. (Я думаю, что поведение по умолчанию состоит в том, что этот массив обвивает его края, поэтому на самом деле это отдельный дискретный тор.) ~Nest~##&Превращает это правило в функцию, которая при задании начального состояния платы (любых размеров) и целого числа в nкачестве аргументов выводит результат nитераций правила игры жизни.

Для собственного удовольствия вы можете использовать упакованную версию

b = RandomInteger[1,{50,50}];
Manipulate[ArrayPlot[
  CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}~Nest~##&
    [b, n] ]
, {{n,0}, 0, 100, 1}]

и пролистайте свой путь через 100 поколений на доске 50х50.

Грег Мартин
источник
Если я правильно понимаю, это имеет фиксированный размер платы? В таком случае, я думаю, что это не может быть полным по Тьюрингу, не так ли?
DLosc
Любой конкретный вызов функции имеет фиксированный размер платы, но этот размер платы может быть произвольно большим. (Обратите внимание, что во второй половине поста описан пример наблюдения кода в действии, а не самого кода.)
Грег Мартин,
Я хочу сказать, что для того, чтобы GoL был завершенным по Тьюрингу, он должен быть способен к бесконечно растущему шаблону. (Например, планерная пушка.) Если эта реализация не может увеличить массив с одного шага на другой, но вместо этого оборачивает его тороидально, тогда она не проходит тест бесконечного роста.
DLosc
Это разумная перспектива, чтобы быть уверенным. Но реализации языков программирования на физических компьютерах даже не проходят этот тест! Можно довольствоваться (гипотетической) последовательностью физических компьютеров с большим и большим количеством памяти, каждый из которых способен вычислить еще одно значение этой вычислимой функции; однако в этот момент следует одинаково довольствоваться (гипотетической) последовательностью входов в такую ​​программу GoL.
Грег Мартин
9

Turtlèd интерпретация CT , 49 байтов

Я мог бы в гольф это

Кроме того, это не выводит ничего полезного. он просто останавливается, если и только если останавливается данная программа CT.

это тот, который я сделал некоторое время назад на самом деле (тогда игра в гольф сейчас)

!-l[*+.r_]' !l[ l]r[ u.(;d' u)d(1[ r].[ l])( r)+]

Как это работает:

Turtlèd использует ячейки сетки. Когда я говорю «напишите что-нибудь на сетке», я имею в виду, что на сетке расположена непрерывная группа символов. пример

[ ][ ][ ][ ][ ][ ][ ]
[ ][H][E][L][L][O][ ]
[ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ]

на программу

данные вводятся первыми:

!-l[*+.r_]' 

по сути это программа для кошек. он записывает ввод в сетку.

затем команды вводятся:

!

что он делает с этими командами:

Эти команды являются «продукцией». если крайний левый бит данных равен 1, он копирует производство в конец строки данных. в противном случае ничего не происходит. затем самый левый бит данных удаляется, и он использует следующую продукцию со следующим самым левым битом данных. программа останавливается, когда в строке данных нет битов. Способ создания этих производств состоит в том, чтобы иметь дело с битами и окончанием производства отдельно. это то, что делает наша программа. он отдельно копирует биты из командной строки в конец строки данных и отдельно удаляет биты из строки данных

о том, как эта программа делает это. после ввода команд указатель черепаха / сетка возвращается к крайнему левому биту строки данных. затем он идет в петлю

[ u.(;d' u)d(1[ r].[ l])( r)+]

что он делает в этом цикле, так это перемещается вверх от крайней левой строки данных и записывает текущий символ команды (и.). если это;; конец производства, он перемещается вниз и удаляет самый левый бит данных под ним и перемещается обратно вверх ( (;d' u)). тогда, так или иначе, это понижается один ( d). если бит там не был удален, это означает, что он должен проверить, копировать ли бит из команд в конце. поэтому, если этот символ, который является или был самой левой базой данных, равен 1, он переместится в конец правого конца строки данных, скопирует бит из командной строки и вернется в пространство слева от крайних левых данных. бит ( (1[ r].[ l])). теперь это либо левый край данных, который был нулем, либо левый крайний край данных. Итак, мы движемся вправо, если на пробел (( r)). затем указатель команды увеличивается, поэтому мы запишем следующую команду в следующей итерации цикла. Если больше нет строки данных, это означает, что мы окажемся в пространстве, и цикл закончится. в противном случае мы перезапустим цикл.

Разрушаемый Лимон
источник
Попробуйте в гольф это больше!
arodebaugh
9

Perl → вариант трехзвенного программатора , 26 + 1 = 27 байт

++$a[$a[$a[$_]]]for@F;redo

Попробуйте онлайн! (Эта ссылка содержит заголовок, который выходит из программы после заданного количества итераций (чтобы время ожидания не было у TIO), и для печати внутреннего состояния при каждой итерации (чтобы он что-то наблюдал).)

Запуск с -a(штраф 1 байт, так как вы можете установить его до того, -M5.010как произвести -aM5.010).

В частности, здесь реализован Three Star Programmer, в котором команды разделены пробелами, и в файле запрещены комментарии без расширений ввода / вывода. (Эти изменения не имеют никакого значения для полноты по Тьюрингу языка, очевидно.) Нет онлайн-подтверждения полноты по Тьюрингу для трехзвездного программиста в Интернете, но это полная по Тьюрингу (я поделился эскизным доказательством его тьюринга). -полнота с другими эзопрограммистами, но перестала работать над языком, когда я обнаружила, что на самом деле довольно легко программировать, как только вы преодолели первоначальный шок).

Программа на самом деле не нуждается в большом объяснении; Программа «Три звезды» имеет очень простую спецификацию, и это ее прямой перевод. Единственные тонкие моменты: @Fэто ввод в программу в виде массива (это является следствием -a); и redoбудет повторять всю программу, поскольку она находится в неявном цикле (также является следствием -a).


источник
1
Я думаю, что стрелка имеет больше смысла означать «сводится к», чем «интерпретирует».
Quintopia
9

сборка x86 (синтаксис Intel / MASM) -Brainfuck 2127 байт.

Все еще в состоянии гольфа

.386
.model flat,stdcall
.stack 4096
include \masm32\include\masm32.inc
includelib \masm32\lib\masm32.lib
ExitProcess proto,dwExitCode:dword
.data
bfsrc BYTE 200 dup(0) 
bfcells BYTE 100 dup(0) 
loopStack DD 5 dup(0) 
charBuf BYTE 5 dup(0) 
newline BYTE 10,0 
prompt BYTE "$",0 
hr BYTE 50 dup('-'),0 
space BYTE ' ',0
.code
EvalBf proc
    start:
    invoke StdOut, addr prompt
    invoke StdIn, addr bfsrc,200
    cmp bfsrc,0
    je exit
    mov eax,0 
    mov ebx,0 
    mov ecx,0 
    processInstruction:
    cmp BYTE PTR bfsrc[ebx], '+'
    je plus
    cmp BYTE PTR bfsrc[ebx], '-'
    je minus
    cmp BYTE PTR bfsrc[ebx], '>'
    je fwd
    cmp BYTE PTR bfsrc[ebx], '<'
    je back
    cmp BYTE PTR bfsrc[ebx], '['
    je open
    cmp BYTE PTR bfsrc[ebx], ']'
    je close
    cmp BYTE PTR bfsrc[ebx], '.'
    je dot
    jmp processNextInstruction
    plus:
    inc BYTE PTR bfcells[eax]
    jmp processNextInstruction
    minus:
    dec BYTE PTR bfcells[eax]
    jmp processNextInstruction
    fwd:
    inc eax
    jmp processNextInstruction
    back:
    dec eax
    jmp processNextInstruction
    open:
    mov loopStack[ecx*4],ebx
    inc ecx
    jmp processNextInstruction
    close:
    dec ecx
    cmp BYTE PTR bfcells[eax], 0
    je processNextInstruction
    mov ebx,loopStack[ecx*4]
    inc ecx
    jmp processNextInstruction
    dot:
    mov dl, BYTE PTR bfcells[eax]
    mov BYTE PTR charBuf[0], dl
    mov BYTE PTR charBuf[1],0anything
    push eax
    push ecx
    invoke StdOut, addr charBuf
    pop ecx
    pop eax
    jmp processNextInstruction
    processNextInstruction:
    inc ebx
    cmp BYTE PTR bfsrc[ebx], 0
    je done
    jmp processInstruction
    done:
    invoke StdOut, addr newline
    mov eax, 0
    printNext:
    cmp eax, 100
    jge reset
    push eax
    invoke dwtoa, BYTE PTR bfcells[eax], addr charBuf
    invoke StdOut, addr charBuf
    invoke StdOut, addr space
    pop eax
    inc eax
    jmp printNext
    reset:
    invoke StdOut, addr newline
    invoke StdOut, addr hr
    invoke StdOut, addr newline
    jmp start

    exit:
    invoke ExitProcess,0
EvalBf endp
end EvalBf
Кристофер
источник
3
Обычно ответы на сборку учитываются в размере полученного машинного кода, поэтому вам вообще не нужно разбирать сборку, просто сведите к минимуму количество / размер инструкций.
Роберт Фрейзер
@RobertFraser э-э-э, я не знаю, как это посчитать: P
Кристофер
3
На самом деле, сначала я как - то прочитал название как «x86 ASM реализован в Brainfuck» и был своего рода впечатление :)
Кетцалькоатля
@Quetzalcoatl Это было бы впечатляюще
Кристофер
1
Пожалуйста, переменная названия / названия для гольфа ty
ASCII-only
8

Pip- интерпретация систем циклических тегов , 16 байтов

YqWyyPBg@++vXPOy

Принимает продукцию системы тегов в качестве аргументов командной строки и исходную строку данных из stdin.

Приведенный выше код довольно сложно проверить, потому что он не производит никакого вывода (поэтому единственное наблюдаемое поведение - «завершается» против «не заканчивается»). Таким образом, вот версия без заглавных букв, которая выводит строку данных после каждого шага, а также завершается через 20 шагов, поэтому TIO не приходится иметь дело с тоннами вывода из бесконечных циклов: попробуйте онлайн!

Системы циклических меток

Системы циклических тегов являются чрезвычайно простой, но полной по Тьюрингу вычислительной моделью. Они состоят из списка производств, которые определяют операции над строкой данных . Продукция и строка данных состоят из 1 и 0.

На каждом шаге крайний левый символ строки данных удаляется.

  • Если символ равен 1, текущее производство добавляется к правой стороне строки данных.
  • Если символ равен 0, ничего не добавляется.

В любом случае текущее производство циклически перемещается к следующему производству в списке: если мы были на последнем производстве, мы возвращаемся к первому. Выполнение продолжается до тех пор, пока строка данных не станет пустой.

объяснение

                  g is list of cmdline args; v is -1 (implicit)
 q                Read a line of stdin for the data string
Y                 and yank it into the y variable
  Wy              While data string is nonempty:
       g@++v       Retrieve the next production from g (using cyclic indexing)
             POy   Pop the first character of y
            X      String-multiply: result is the production if the first character of y
                   was 1, or empty string if it was 0
    yPB            Push that string to the back end of y
DLosc
источник
эй, я только что вспомнил, что вам не нужно вводить строку данных; это может быть просто 1источник: esolangs ссылки на этот arxiv.org/abs/1312.6700 . Я скоро отредактирую свой ответ, и если это поможет вашему ответу, вы должны это сделать (т. Е. Ваш вклад кажется довольно гольфы на самом деле)
Разрушаемый лимон
8

Итерированные обобщенные функции Коллатца -> Python 2, 46 байт

a,b,x,m=input()
while-~x%m:x=x/m*a[x%m]+b[x%m]

Вызовите эту функцию со списками m-1 a и b, начальным значением x и делителем m, которые вместе составляют «программу» для IGCF. Вместо того, чтобы брать третий массив, чтобы указать, на каких модулях остановиться, он просто останавливается всякий раз, когда модуль равен m-1. Это упрощение означает, что может потребоваться дополнительное усилие для преобразования данной программы Fractran в этот вариант, но оно сохраняет пару байтов в интерпретаторе.

Попробуйте онлайн! Этот TIO демонстрирует, как добавить 5 + 5 с этим языком. Программа a = [3], b = [0], m = 2 выполняет сложение и, начиная с 7776 = 2 ^ 5 * 3 ^ 5, в конечном итоге дает 59049 = 3 ^ 10.

quintopia
источник
Черт, хорошая работа. Я надеялся выиграть награду, но хорошая работа
Кристофер
7

ResPlicate вариант -> Python 2, 47 байт

l=input()
while l:l=l[2+l[0]:]+l[2:2+l[0]]*l[1]

Эта функция интерпретирует вариант ResPlicate

  • для которого программа представляет собой список в Python четной длины с четными элементами с четными индексами.
  • без ввода / вывода.
  • для которого попытка скопировать больше значений, чем существует в оставшейся части очереди, просто копирует оставшуюся часть очереди (т. е. скопированный бит не дополняется нулями до необходимой длины).

Последнее изменение означает, что некоторые программы ResPlicate (которые соответствуют первому условию) не будут вести себя одинаково в этом варианте, но, к счастью, интерпретаторы BCT не требуют удаленной функциональности, и поэтому язык остается TC.

Попробуйте онлайн! В этот TIO встроен отпечаток, показывающий его работоспособность, а также заголовок, который убивает программу через 1 секунду, и пример, который способен генерировать больше выходных данных, чем TIO может обработать за одну секунду.

quintopia
источник
2
Почему нет l=input()? Был бы байта короче.
feersum
7

Perl -aI / D machine , 24 байта

$p=$a[$p]+=$_ for@F;redo

Попробуйте онлайн! (содержит заголовок, который печатает внутреннее состояние и останавливается после 10 итераций, чтобы поведение можно было наблюдать)

О языке

Я провел последние пару дней, работая над машиной ввода-вывода , одной из моих последних идей для очень простых языков программирования. Он работает следующим образом: хранилище данных состоит из неограниченной оперативной памяти, изначально все нули. Каждый элемент может хранить неограниченное целое число (хотя на практике большинство машинных программ I / D сохраняют только маленькие целые числа в большинстве из них и используют неограниченные целые числа только для адресации ячеек с большими адресами). Также есть указатель данных, который указывает на ячейку (т.е. содержит адрес как ячейку); изначально тоже ноль.

Есть только две команды:

  • I: Увеличить ячейку, на которую указывает указатель данных. (Сам указатель данных остается неизменным.)
  • D: Разыменовать указатель данных, то есть прочитать значение ячейки, на которую указывает указатель данных. Затем сохраните полученное значение обратно в указатель данных.

Выполнение просто запускает программу в цикле многократно, навсегда.

Довольно удивительно, что этот простой язык завершен по Тьюрингу, поэтому я работаю над тем, чтобы доказать это. Вот доказательство . Это очень похоже на (но проще, чем) доказательство для Three Star Programmer, очень похожего языка (и на самом деле в этом представлении используется одна и та же базовая «оболочка» OISC вокруг программы, отличающаяся только фактической выполненной инструкцией).

О программе

использование

Входные данные должны быть заданы на стандартном вводе и являются машинной программой I / D без комментариев и с использованием синтаксиса RLE / OISC. (Машина I / D имеет два разных, эквивалентных синтаксиса, но для удобства игры эта программа поддерживает только один из них.) В этом синтаксисе программа представляет собой последовательность чисел в десятичном формате, представляющую длины серий Iкоманд между Dкомандами. (Вы можете указать две или более последовательных Dкоманды, поместив Iмежду ними «прогон 0 команд», так что синтаксис полностью общий.)

объяснение

Как видно из программы, это не осуществляет Iи Dкоманды по отдельности. На самом деле, это (очень немного) оптимизирующий интерпретатор (просто потому, что так писать короче). Ключ в том, чтобы увидеть, что выполнение n команд приращения увеличивает целевую точку указателя данных n раз, то есть добавляет к ней n ; и запуск 0 команд приращения также может быть реализован таким образом, так как добавление 0 в память не имеет никакого эффекта. Таким образом, операция, которую мы на самом деле реализуем, заключается в чередовании реализации серий Iи a D. Или, другими словами, "добавить ндо значения, на которое указывает указатель данных (сохраняя его обратно в значении, на которое указывает указатель данных), затем считайте значение, на которое указывает указатель данных, и сохраните его в указателе данных ". Это явно более многословно, чем необходимо быть, и мы можем еще больше упростить это, чтобы «добавить n к значению, на которое указывает указатель данных, а затем сохранить это значение как в целевом указателе данных, так и в самом указателе данных».

Так что это составляет ядро ​​нашей программы. Мы используем массив $aдля хранения оперативной памяти и $pв качестве указателя данных (индексация в массиве):

$p=$a[$p]+=$_
         + $_  add {the run length}
   $a[$p]      to the element of $a pointed to by $p
   $a[$p] =    storing the result back into that element
$p=            and also in the pointer itself

Удобно, что Perl интерпретирует неинициализированные элементы массива как 0, когда они обрабатываются как числа, поэтому массив будет лениво инициализироваться для нас нулями без какого-либо явного кода для этого. (Одна потенциальная проблема - числовая точность, когда числа становятся большими; однако, это произойдет, только если объем используемого массива превышает адресное пространство машины (целые числа Perl достаточно велики, чтобы содержать указатели), чего не может случиться на идеализированной машине.)

Наконец, все, что нам нужно сделать, это поместить эту программу в несколько циклов. for@FПетля, в сочетании с -aпараметром командной строки, будет цикл над полями стандартным вводом (определение по умолчанию «поля» здесь будет разделено на пробельном). redoЦикл будет поместить всю программу в неявном цикле (кроме, удобно, чтение стандартного ввода), что приведет к тому , программа для запуска в цикле многократно, в соответствии с требованиями семантики машины I / D.

оборота ais523
источник
Добро пожаловать! Нам больше не нужно оценивать флаги для интерпретаторов, просто отметьте, что это «Perl with -a». codegolf.meta.stackexchange.com/a/14339/9365
Дом Гастингс
6

Желе2-теговая система , 8 байт

µḢị⁴⁸;Ḋß

Попробуйте онлайн!

У меня есть награда в пользу практических языков, но я подумал, что с таким же успехом я могу попытаться выиграть оригинальное задание, поскольку я не могу точно выиграть свою собственную награду).

Реализует вариант систем тегов без состояния остановки, так как он не нужен для полноты по Тьюрингу. Состояния нумеруются последовательно от 1, и начальная строка предшествует программе.

Например, Википедия дает пример системы тегов { a, b, c}, { abc, ba, caaa} с начальной строкой aaa; в этом формате ввода, это [1,1,1], [[2,3],[1],[1,1,1]]. (Системы тегов не имеют фиксированного синтаксиса, и это кажется разумным способом сделать это.)

Ссылка TIO имеет добавленное («записать внутреннее состояние и перевод новой строки в стандартный вывод»), чтобы показать, что программа действительно работает.

объяснение

µḢị⁴⁸;Ḋß
           {implicit: initialise internal state from first argument}
µ          Disregard the second command-line argument by default
 Ḣ         Take the first element, removing it from the internal state
  ị⁴       Use the value to index into the second argument
    ⁸;     Prepend (the rest of) the internal state
      Ḋ    Discard the first element of the internal state
       ß   Loop forever

источник
6

BF / P ", реализованный в машине Тьюринга, 842 байта

Таблица переходов (связана из-за длины)

Переходный стол, менее гольф-версия

Симулятор машины Тьюринга, который я использовал

Это, конечно, не принесет никаких наград за длину, но это то, что я всегда хотел сделать, так как BF очень похож на машину Тьюринга. Каждая ячейка хранит значение из 0x0- 0xF. Тем не менее, ширина сайта Turing Machine далеко не может привести к сбою браузера. Функции ,и .(вход и выход) не определены, так что это немного больше похоже на P, чем на истинный BF.

Чтобы запустить его, вставьте таблицу переходов в симулятор Turing Machine, установите для ввода некоторый код BF и нажмите run.

Лента ТМ хранит как код BF, так и данные BF, с одним пробелом в середине. Он отслеживает свою позицию в коде, изменяя символ, который он в данный момент выполняет ( [-> (и т. Д.), И свою позицию в данных с символом ^перед ячейкой. Как только он читает командный символ, он перемещается, пока не достигнет каретки, не переместится на одну ячейку вправо и не выполнит соответствующую функцию. Затем он возвращается к поиску одного из «модифицированных» командных символов в коде BF и переходит к следующему, повторяя весь процесс. Когда код заканчивается, он останавливается.

Лучший способ понять, как это работает, - запустить версию без игры, перевести ее в пошаговый режим и посмотреть, какие строки ведут к каким другим, и что делает каждое состояние / блок строк.

Версии для игры в гольф и без игры одинаково с точки зрения того, как они работают, но версия без гольфа имеет более понятные для человека имена и разбита на разделы.

a52
источник
1
Предел длины сообщения более чем достаточен, чтобы соответствовать таблице переходов
только ASCII
6

C реализует (2,3) машину Тьюринга , 236 205 байт ( 46 31 меньше, если вам не нужны неловкие входные данные)

Благодаря Appleshell для -11 байт, VisualMelon для -12 байт и Johan du Toit для -7 байт.

CeilingCat сделал версию, которая использует только 144 байта, смотрите здесь .

(Я добавил несколько разрывов строк здесь, чтобы вам не приходилось прокручивать, но обычно большинство из них будут удалены)

#define c char
j;i;k;c s,d[256];c main(){c*p=d+128;gets(d);
for(;k<256&&d[k];)d[k++]-=48;for(;++j<256;)
{c t=*p;*p=-t*t+(2-s)*t+1+s;p+=(s^t==0)*2-1;s=s?t%2:!t%3;
for(i=0;++i<256;)printf("%d",d[i]);puts("");}}

Попробуйте онлайн!

Использование: введите строку до 256 единиц, нулей и двойок, чтобы инициализировать ленту. Любые неинициализированные значения будут равны нулю. (Значения, отличные от 0, 1 и 2, могут вызывать неопределенное поведение.) Программа выполнит итерацию за 256 шагов. Количество шагов, которые он повторяет, можно увеличить, изменив код, но, очевидно, для этого требуется больше символов.

Это довольно длинный вход, но я впервые делаю один из них, и я не использовал специальный язык для игры в гольф. Мне было очень весело, даже если получилось дольше, чем я ожидал.

Большая часть байтов связана с вводом и выводом, и я потерял целые 42 байта, заставив его принимать 0, 1 и 2 вместо NUL, SOH, STX. (Чтобы изменить это, удалите k;спереди и for(;k<256&&d[k];)d[k++]-=48;со второй строки.)

Таблица переходов, особенно строка *p=-t*t+(2-s)*t+1+s;(которая устанавливает значения на ленте), вероятно, также может быть сжата больше.

a52
источник
1
Ух ты, а это твой первый гольф-код здесь! Замечательно!
Захари
Вы можете сократить объявления глобальных переменных следующим образом: k,j;c s,d[256];( intнеявно в C, затем вы также можете перейти iк глобальному объявлению, чтобы сохранить на 3 байта больше)
Appleshell
@Appleshell Спасибо, я сделаю это.
а52
Вы можете переместить строку проверки нулевого терминала внутри цикла for. Вставка k++и удаление {}сохраняет еще пару байтов: for(;k<256&d[k];)d[k++]-=-48;поскольку jэто просто хронометраж (значение, которое никогда не использовалось), вы можете заменить его (и i) kна обратный отсчет: вы знаете, k==256после первого цикла, так что отсчитайте до нуля во втором for(;k>0;), который уходит k==-1, так что последний цикл может стать for(;++k<256;). (Отказ от ответственности: я обычно играю в гольф C#, но это, кажется, компилируется).
VisualMelon
1
@ VisualMelon Я определил проблему. Мне нужно было использовать k<256&&d[k], а не &потому, что меня d[k]оценивали k==256. Кроме того, так kкак больше не гарантировалось, что 256после этого цикла я должен был сбросить его впоследствии, чтобы гарантировать 256 шагов. (Если у вас (то есть, у VisualMelon) есть какие-то другие предложения, мы, вероятно, должны поместить их в чат, чтобы не получать слишком много комментариев)
a52
5

Röda, реализующий Fractran , 114 112 106 байтов

1 байт сохранен благодаря @fergusq путем изменения параметров

f&n,a{x=1{x=0;(a/" ")()|[_/`/`]|[parseInteger(_[0],_1[1])]|{|q,w|{n*=q/w;x=1}if[n%w<1,x<1]}_,_}while[x>0]}

Попробуйте онлайн!

Вызов функции следующим образом: f reference_to_input program. Вывод будет сохранен в расположении input.

Kritixi Lithos
источник
Точка с запятой после e[1]является избыточной. Также вы можете сохранить один байт, изменив порядок параметров: f&n,a.
fergusq
@fergusq Спасибо за f&n,aтрюк, и я как раз собирался удалить эту
точку с запятой,
5

Clojure, 82 81 байт (машина Тьюринга)

Обновление: убрал пробел из t{} s.

#(loop[p 0 t{}s 1](if-let[[S M N](%[(or(t p)0)s])](recur(+ p M)(assoc t p S)N)t))

Реализует машину Тьюринга как цикл, возвращает ленту при достижении состояния остановки. В правилах перехода состояний это указывается путем пропуска переходного состояния. Это settins Nк nilи последующее if-letпрервет как соответствующий переход состояния не найден из входного хэш-карте %. На самом деле подойдет любое значение для этого состояния, например :abort0 или -1.

Ungolfed с примером занятого бобра с 3 символами из 2 состояний из Википедии .

(def f #(loop[pos 0 tape {} state 1]
          (if-let [[sym move next-state](%[(get tape pos 0)state])]
            (do (println [pos tape state])
                (recur(+ pos move)(assoc tape pos sym)next-state))
            tape)))

(f {[0 1] [1  1 2]
    [0 2] [1 -1 1]
    [0 3] [1 -1 2] 
    [1 1] [1 -1 3]
    [1 2] [1  1 2]
    [1 3] [1  1]})

{0 1, 1 1, -1 1, -2 1, -3 1, 2 1}

Попробуйте онлайн .

На одном ядре 6700K он запускает 5-символьного занятого бобра с 47 символами (47,1 миллиона шагов) примерно за 29 секунд, или 1,6 миллиона шагов в секунду.

NikoNyrh
источник
5

MTip , 4 байта

Ṅ×ịß

Попробуйте онлайн!

Ссылка TIO добавляет нижний колонтитул для вызова функции с примером программы Tip, показанной на странице Esolang («автоматическая обертка» M для вызова функций, как если бы они были программами, которые не могут обрабатывать рациональные числа или числа с фиксированной запятой, или, по крайней мере, у меня есть Я не понял, как это объяснить, поэтому мне нужно превратить функцию в полноценную программу вручную, чтобы иметь возможность ее запускать.)

Это на самом деле печатает полезные выходные данные отладки; программа не может быть записана в 3 байта в M, потому что программа, состоящая ровно из трех диад, вызывает особый случай в синтаксическом анализаторе, поэтому мне пришлось добавить дополнительную команду, чтобы избежать особого случая. Создание этого (печать с новой строкой) по крайней мере дает ему полезную цель.

ıi=1

Не реализует ввод / вывод (кроме останова / без остановки). Ввод / вывод является расширением для Tip (не является частью самого языка) и не требуется для полноты по Тьюрингу.

Объяснение / фон

Ṅ×ịß
Ṅ     Print {the left argument} and a newline; also resolves a parser ambiguity
  ị   {The left argument}th element of {the right argument}, wrapping on OoB
 ×    Multiply {the left argument} by {the chosen element}
   ß  Recursive call; arguments: {the product} and {the same right argument}

[1,2,3][1,2,3,1,2,3,1,2,3,…]rx+s, который является полиномом, а встроенная «базовая конверсия», которую имеют многие языки игры в гольф, на самом деле является замаскированным полиномиальным оценщиком общего назначения. Таким образом, все, что нам нужно сделать, это проиндексировать список списков цифр, преобразовать их в базу, и все готово, верно?

xx

x(xy)xy, Конечно, мы можем переопределить поведение цепочки практически на все, что захотим, но это будет стоить целый байт, и записи языка для игры в гольф на этот вопрос становятся настолько короткими, что байт много.

Поэтому я оглянулся и немного переоценил. Есть ли какие-либо операции, которые мы могли бы использовать вместо полиномиальной оценки? В идеале, те, которые являются коммутативными, поэтому нам не нужно беспокоиться о порядке аргументов? Вскоре после этого я понял, что функции Коллатца являются более сложными, чем они должны быть.

s

И, конечно, в отличие от base translation ( ), multiplication ( ×) является коммутативным, и, таким образом, не имеет значения, в каком порядке размещены аргументы. Поэтому все, что нам нужно написать, - это ×ịзатем поместить программу в бесконечную рекурсию с помощью ß, и у нас есть полный по Тьюрингу язык. Правильно?

(xy)(xy)¹×ịß¹¹ это хороший выбор, потому что он дает полезные выходные данные отладки.

Возможны ли три байта? Если только я что-то упустил, не с этим конкретным выбором реализуемого и реализованного языка, но в этот момент наверняка кажется, что это как-то возможно, так как существует четыре способа сделать это за четыре и так много Turing-complete языки, которые вы могли бы реализовать.

оборота ais523
источник
Подумав об этом еще немного, мы могли бы уменьшить это до трех байтов, используя и вместо ×и ; результирующий язык не совсем совпадает с языком Tip, но он довольно похож и почти наверняка завершен по Тьюрингу по той же причине. К сожалению, не реализовано в M, и я не могу найти способ заставить Jelly выполнять вычисления произвольной точности, когда любой из входных данных является нецелым действительным числом. Если кто-то знает какие-либо другие языки игры в гольф, где эта конструкция могла бы работать, не стесняйтесь попробовать.
ais523
4

C интерпретация Brainfuck, 187 байт

t[999],*p=t,c,i,l;f(char*t){for(i=0;c=t[i];i++){c^62?c^60?c^43?c^45?c^46?c^44?c^91:(*p=getchar()):putchar(*p):--*p:++*p:--p:++p;if(c==93&&*p)for(l=1;l>0;)c=t[--i],c==91?l--:c==93?l++:0;}}

Попробуйте онлайн

Йохан дю Туа
источник
3
Welp, должен был быть ответ, используя BF.
Захари
4

Lua интерпретация Brainf ***, 467 байт

b,r,a,i,n,s=0,io.read,{0},1,1,"><+-.,[]"c,f=r(),{function()n=n+1;a[n]=a[n]or 0;end,function()n=n-1;a[n]=a[n]or 0;end,function()a[n]=a[n]+1;end,function()a[n]=a[n]-1;end,function()io.write(string.char(a[n]))end,function()a[n]=io.read():byte()end,function()i=a[n]~=0 and i or c:find("]",i)end,function()if a[n]~=0 then b,x=1,""repeat i=i-1 x=c:sub(i,i)b=x=="["and b-1 or x=="]"and b+1 or b until b==0 and x=="["end end}repeat f[s:find(c:sub(i,i),1,1)]()i=i+1 until i>#c

Я знаю, что есть еще какое-то похудение, которое я могу сделать позже, но на этом мой первый проход закончился. Принимает код brainf из стандартного ввода.

болтун
источник
2
+1 для brains, это всегда весело, когда игроки в гольф назначить список переменных.
Захари
4

CJam → ResPlicate Variant, 15 14 13 байт

-1 байт благодаря @ ais523

l~{(/((*+e_}h

Вариант такой же, как и в этом ответе , за исключением того, что количество элементов, извлеченных из очереди, на единицу меньше, чем верхнее число в очереди.

l~{ ... }hЧасть просто принимает массив в качестве входных данных и повторяется до тех пор , что массив не пуст.

Пояснение к основному циклу:

    e# Stack:             | [3 2 1 1 2 2 2 1]
(   e# Pop first element: | [2 1 1 2 2 2 1] 3
/   e# Split chunks:      | [[2 1 1] [2 2 2] [1]]
(   e# Pop first:         | [[2 2 2] [1]] [2 1 1]
(   e# Pop first:         | [[2 2 2] [1]] [1 1] 2
*   e# Repeat array:      | [[2 2 2] [1]] [1 1 1 1]
+   e# Concatenate:       | [[2 2 2] [1] 1 1 1 1]
e_  e# Flatten:           | [2 2 2 1 1 1 1 1]
Esolanging Fruit
источник
Вам действительно не нужно увеличение здесь. Просто укажите, что длины блоков должны быть увеличены на 1 в исходной программе; это не повредит Turing-завершенности ResPlicate (есть конструкции TC, в которых длины блоков и количество повторений никогда не смешиваются друг с другом).
3

Чип , 20 + 3 = 23 байта (правило 110)

AZZ
>}/a
`)\'E~Zte*f

+3 за флаг -z

Попробуйте онлайн!

Эта передача не идеальна, поскольку у Chip (пока) нет возможности зацикливания, поэтому выходные данные должны передаваться как входные данные для имитации нескольких поколений, с чем-то вроде этого (конечно, вы можете запускать этот цикл бесконечно, и Chip может обрабатывать произвольно длинный ввод, поэтому эта комбинация является завершением по Тьюрингу).

Эта реализация принимает входные и выходные данные в форме ASCII 0и 1s. Логика здесь следующая:

p := value of left neighbor cell    AZZ
q := value of current cell          AZ
r := value of right neighbor cell   A

q' := ((r xor q) and p) or          >}/a
      ((r or q) and ~p)             `)\'

Остальные элементы предназначены для служебного пользования: e*fвызывают цифровой вывод ASCII и E~Ztпрекращают выполнение через два байта после исчерпания ввода (поскольку ширина увеличивается на 2 при каждом поколении).

Phlarx
источник
3

Clojure, 75 байтов (система циклических тегов)

Обновление 1: заменено some?на nil?.

Обновление 2: исправлено отсутствие Sв другой ветке if s.

#(loop[[p & P](cycle %)[s & S]%2](if(nil? s)S(recur P(if s(concat S p)S))))

Реализует систему циклических тегов , возвращает, nilесли программа останавливается, в противном случае зацикливается. Clojure действительно сияет здесь бесконечными ленивыми последовательностями (такими как цикл ) и деструктуризацией . Единицы и нули обозначаются как истинные и ложные значения. Когда строка данных заканчивается, sстановится nil.

Ungolfed:

(def f #(loop[[p & P] (cycle %) [s & S] %2 i 5]
          (do
            (pprint [p (concat [s] S)])
            (if (and (some? s) (pos? i))
              (recur P (if s (concat S p) S) (dec i))))))

Пример результатов:

(f [[false]] [true true])
[[false] (true true)]
[[false] (true false)]
[[false] (false false)]
[[false] (false)]
[[false] (nil)]

(f [[false true true] [true false] [true false true]] [true])
[[false true true] (true)]
[[true false]      (false true true)]
[[true false true] (true true)]
[[false true true] (true true false true)]
[[true false]      (true false true false true true)]
[[true false true] (false true false true true true false)]
NikoNyrh
источник
2

JavaScript интерпретирует правило 110 , 131 байт (99 байт ?, 28 байт?)

a=(p,q,r)=>q+r+q*r+p*q*r
b=l=>{r="";for(i=0;i<l.length-2;i++)r+=a(l[i],+l[i+1],+l[i+2])%2;return r}
c=(l,n)=>!n?l:c(b(0+l+0),n-1)

Как видите, код определяет 3 функции a, bи c. Возможно, можно сохранить байты, объединив их в одну функцию (я не понимаю, как), но хорошо, что они разделены, потому что каждый из них уже выполняет эту задачу в некотором смысле.

Функция aпринимает 3 числа в качестве входных данных и вычисляет некоторый странный полином из них. Когда эти 3 числа 0или 1они могут быть замечены как клетки Правила 110. Тогда паритет выходных данных aможно рассматривать как значение средней ячейки в следующем поколении. Так что в некотором смысле эта простая функция уже является «интерпретатором» правила 110 (28 байт):

a=(p,q,r)=>(q+r+q*r+p*q*r)%2

Затем мы можем создать новую функцию, bкоторая оценивает aкаждый символ строки из нулей и единиц. Это bлучше, чем aинтерпретатор правила 110. Взяв мод 2 после оценки сохраненных скобок (99 байт):

a=(p,q,r)=>q+r+q*r+p*q*r
b=l=>{r="";for(i=0;i<l.length-2;i++)r+=a(l[i],+l[i+1],+l[i+2])%2;return r}

Чтобы фактически вычислить функцию с помощью правила 110, пользователь должен указать начальное состояние и количество поколений, после которых вывод будет «появляться». Мы можем создать третью функцию, cкоторая принимает строку из нулей и единиц, а также положительное целое число n, которое затем оценивает bстроку, nвремена. Таким образом, мы действительно можем видеть Правило 110 как язык программирования, где программа - это начальное состояние и число n, а вывод - это состояние после nпоколений. Теперь эта функция cявляется настоящим интерпретатором для этого языка программирования, поэтому окончательный код для этой задачи - это то, что я представил выше.

Йенс Рендерс
источник
Это вычисляет 110 с надлежащим фоном? Мой предыдущий ответ был удален, потому что у него не было фона.
Пшеничный волшебник
@WheatWizard фон является частью ввода, ваш ответ не должен был быть удален для этого
Jens Renders
Фон должен быть бесконечным, вы можете принять бесконечный ввод?
Пшеничный волшебник
@WheatWizard это не должно быть бесконечным, оно должно быть в состоянии быть сколь угодно большим, и это возможно
Jens Renders
1
Правило 110 не является полным по Тьюрингу, если вы решаете генерацию заранее, и вам нужен бесконечный вклад в конструкцию, о которой я знаю. Даже если кто-то обнаружил конструкцию с конечным начальным состоянием, вы не сможете узнать объем памяти или время, необходимое для запуска программы, потому что тогда вы сможете решить проблему остановки.
Орджан Йохансен
2

JS -> Новая строка 854 байта

(function(d){var b=0;var n=!0;var c=[];var h=[];var e=0;var l=[];var m=0;var f=2;var a=0;var g=!1;var k=function(a){if(a===1)return!1;if(a%2===0&&a!==2)return!1;if(a%3===0&&a!==3)return!1;if(a%5===0&&a!==5)return!1;if(a%7===0&&a!==7)return!1;for(var b=7;b<d.round(d.sqrt(a))+1;b++)if(a%b===0)return!1;return f=a,!0;};var j=0;var i=0;var o=function(q){var o=d.__split(q,'\n');d.println(o);for(var n=0;n<o.length;n++)if(n>=f^2&&n<=f+1^2&&k(n)){f=n;for(var p=0;p<o[n].length;p++){if(o[n]==='+'&&(a+=c[b],b++),o[n]==='-')if(g===!0&&a<=0)break;else a-=c[b],b++;if(o[n]==='*'&&(a*=c[b],b++),o[n]==='/'&&(a/=c[b],b++),o[n]==='s'&&(a=d.sqrt(a)),o[n]==='%'&&(a%=c[b],b++),o[n]==='a'&&l.push(a),o[n]==='g'&&(a=c[b],b++),o[n]==='q'&&c.push(a),o[n]==='i'&&a++,o[n]==='d')if(g===!0&&a<=0)break;else a--;o[n]==='r'&&(g=!0),o[n]==='w'&&(g=!1),o[n]==='['&&(j=n),o[n]===']'&&a>0&&(n=j,h[e]--),o[n]==='{'&&(i=n),o[n]==='}'&&h[e]>0&&(n=i,h[e]--),m=a,o[n]==='k'&&e++;}}};});

Супер гольф благодаря Google.

Кристофер
источник
Я думаю, что вы отправили этот ответ на неправильный вызов. Вы хотели опубликовать это на этот вызов ?
1
В этом случае вам нужно изменить реализацию для достижения другого условия победы; это код-гольф , а не конкурс популярности . Например, у вас есть множество имен переменных, которые могут быть явно короче, что означает, что это решение не является серьезным соперником. Вы можете удалить его сейчас, а затем восстановить его, когда у вас есть время сыграть в гольф.
1
Тем не менее, ответы, которые не делают серьезной попытки оптимизировать условия победы, противоречат правилам . Это достаточно веская причина, чтобы удалить его, пока вы не сможете привести его в соответствие с правилами.
1
Вы можете объединить все varутверждения:var b=0,n=!0,c=[],h=[],e=0,l=[],m=0,f=2,a=0,g=!1;
Esolanging Fruit
1
Просьба удалить все varты
ASCII-только
1

Clojure, 87 байт (правило 110)

Кредит на код паритета переходит к Jens Renders! Я действительно боролся за то, как это выразить, и собирался перейти [p q r]от двоичного к целочисленному и использовать таблицу поиска.

#(iterate(fn[S](for[[p q r](partition 3 1(concat[0]S[0]))](mod(+ q(* q(+ 1 p)r)r)2)))%)

Здесь partitionи деструктуризация Clojure делает применение логики довольно простым. Эта функция возвращает бесконечную последовательность состояний, поэтому вызывающая сторона отвечает за takeстолько, сколько им нужно, или просто nthза переход к определенному состоянию. Если бы отступы с нулем были двумя элементами вместо одного, то лента постоянно росла бы, избегая проблем с границами. Теперь он остается оригинальной ширины.

Пример:

(def f #(iterate(fn[S](for[[p q r](partition 3 1(concat[0]S[0]))](mod(+ q(* q(+ 1 p)r)r)2)))%))

(pprint (take 5 (f '(0 0 0 0 0 1 1 1 0 0 1 0 0))))
((0 0 0 0 0 1 1 1 0 0 1 0 0)
 (0 0 0 0 1 1 0 1 0 1 1 0 0)
 (0 0 0 1 1 1 1 1 1 1 1 0 0)
 (0 0 1 1 0 0 0 0 0 0 1 0 0)
 (0 1 1 1 0 0 0 0 0 1 1 0 0))
NikoNyrh
источник
1
Если вы когда-либо работаете только с исходной шириной, это не может быть завершением по Тьюрингу, поскольку у него только ограниченная память. (На самом деле, все известные конструкции полноты по Тьюрингу из правила 110 требуют "заполнения", которое используется для расширения ширины, поскольку программа продолжает иметь шаблон, указанный из пользовательского ввода, и отличающийся слева и справа, а не просто используя нули.)
Я вижу, что это делает его моделирование довольно сложным. Clojure cycleмог бы построить бесконечный шаблон заполнения, но выполнение первого шага заняло бы бесконечное количество времени: /
NikoNyrh
Если подумать, было бы не слишком сложно взять этот шаблон заполнения в качестве дополнительных аргументов и расширить смоделированную ленту на 1 блок влево и вправо. Скорость информации здесь составляет 1 блок / итерацию, поэтому нам просто нужно смоделировать «световой конус» вокруг центрального блока, который имеет асимметричную структуру. (CMIIW)
NikoNyrh
1

APL (Dyalog)Fractran вариант, 15 байтов

(⊃0~⍨××0=1|×)⍣≡

Попробуйте онлайн!

Функция принимает рациональные числа в виде списка чисел, а не двух списков, содержащих числитель и знаменатель, и выводит результат, если программа заканчивается. Это реализует вариант Fractran, который имеет рациональную 1/1 (= 1) в конце программы. 1 не влияет на полноту по Тьюрингу (насколько я понимаю), потому что вход в программу попадает в 1 только тогда, когда не работает ни одно из других рациональных чисел, а когда это происходит, вход не изменяется. Это используется только для того, чтобы функция знала, когда заканчивать.

Ссылка TIO запускает функцию в течение 2 итераций (чтобы вы могли видеть выходные данные, поскольку программа не заканчивается) на первом входе и выполняет второй ввод до завершения, после чего возвращает результат.

(⊃0~⍨××0=1|×)⍣≡ принимает список рациональных аргументов в качестве левого аргумента, именуемого ⊣, и ввод в качестве правого аргумента, именуемого ⊢

(⊃0~⍨××0=1|×) функциональный поезд

  • 1|×получить часть после десятичной точки (по модулю 1) произведения ×⊣ и ⊢

  • 0= это равно 0?

  • ×× умножьте этот результат на ⊣ × ⊢, где рациональное × not не является целым числом, оно заменяется на 0

  • 0~⍨ удалить все 0

  • получить первый элемент

Цикл до тех пор, пока вход не изменится, обратите внимание, что результат (⊃0~⍨××0=1|×)используется повторно в качестве входа, поэтому, если он перестает изменяться (в результате 1 в конце), программа останавливается

Kritixi Lithos
источник
1

JavaScript: лямбда-исчисление ( 123 114)

Представлено с помощью Debruijn Indicies в Duples.

V=function b(c,d){if(!isNaN(c)){for(;--c;)d=d[1];return d[0]}return 0==c[0]?e=>b(c[1],[e,d]):b(c[0],d)(b(c[1],d))}

S комбинатор есть [0, [0, [0, [[3, 1], [2, 1]]]]]

К есть [0, [0, 2]]

Я есть [0, 1]

Изменить: побрил 9 байтов, заменив "number"==typeof cна!isNaN(c)

SYZYGY-DEV 333
источник
0

APL (Dyalog Unicode) , 15 байтов SBCS

Полная программа, которая реализует обобщенный одномерный исполнитель клеточных автоматов. Это включает в себя правило 110, которое является полным по Тьюрингу. Запрашивает стандартный ввод для начального состояния, количества итераций (или для продолжения до стабильного состояния, или {⍵≡⎕←⍺}для отображения всех промежуточных значений до стабильного) и для набора правил.

⎕∊⍨∘(⊢∘⊂⌺3)⍣⎕⊢⎕

Попробуйте онлайн! (4 итерации правила 110)

 запросить начальное состояние и

 вывести это (отделяет состояние от количества итераций)

⍣⎕ запросите количество итераций и примените следующую функцию много раз:

() Применить следующую молчаливую функцию:

  ⌺3 получить все окрестности длины 3 (с информацией о том, находятся ли они на краю) и применить следующую молчаливую функцию к каждой паре:

    окружить окрестности

    а также

    дать это (отбрасывая информацию о том, чтобы быть на грани)

 тогда

∊⍨ проверьте, являются ли они членами

 запросить список окрестностей, ведущих к включению в следующую итерацию

Адам
источник