Створіть комп’ютер з однією інструкцією!


31

Зауважте: я готовий дати нагороду за будь-яку відповідь, який мені здається цікавим.

Вашим завданням є розробити комп'ютер із набору інструкцій Тюрінга (OISC):

OISC - це абстрактна машина, яка використовує лише одну інструкцію - позбавляючи необхідності коду машинної мови. Завдяки розумному вибору єдиної інструкції та надаючи нескінченних ресурсів, OISC може бути універсальним комп'ютером так само, як і традиційні комп'ютери, що мають кілька інструкцій.

Ось кілька прикладів одиночних команд, які створюють OISC-повний Тьюрінг.

Правила:

Ви повинні надати тлумачення або доказ цього

Ви повинні надати перекладача для вашої мови. Цей перекладач повинен обмежуватися лише пам'яттю / часом (наприклад, не повинен мати обмежень, накладених користувачем). Якщо ви не надаєте перекладача для вашої мови (з будь-якої причини, крім лінощів), ви повинні довести, що це можливо написати. Перекладач повинен бути можливим .

Ви повинні довести його Тюрінг-повноту

Ви повинні надати офіційний доказ того, що ваша мова є повною для Тюрінга. Простий спосіб зробити це - довести, що він може інтерпретувати або мати таку саму поведінку, як інша мова Тюрінга. Найбільш основною мовою для інтерпретації буде Brainf ** k .

Наприклад, нормальна мова, яка має всі ті ж команди, що і Brainf ** k (і той самий брак обмежень, накладених користувачем), є Turing-завершеною, оскільки все, що може бути реалізовано в Brainf ** k, може бути реалізовано мовою .

Ось список дуже простих у здійсненні мов, повних для Тюрінга.

Додаткові вимоги OISC

  • Цей OISC повинен мати лише одну інструкцію - він не може мати декілька інструкцій з однією з них, що робить його Тюрінг-завершеним.

  • Ваш OISC може використовувати будь-який синтаксис, який вам подобається. Вам слід визначити у своїй відповіді, що таке інструкція, що таке дані, а що - неоперативні (наприклад, пробіли). Будь креативним!

  • Аргументи не просто повинні бути цілими числами. Наприклад, /// є прекрасним прикладом OISC, повного Тьюрінга.

  • Як і якщо вхід і вихід приймаються і даються, залежить від вас. Більшість OISC реалізують введення-виведення через конкретні місця пам'яті, але можуть бути й інші способи, і вам рекомендується знайти його.

  • Дійсна відповідь повинна містити деякий приклад коду у вашому OISC, або додаючи його у допис, або посилаючись на просту проблему, вирішену мовою.

Голосування

Виборці, будь ласка, пам’ятайте, що не підтримуйте нудні подання. Приклади:

  • Lenguage -еквіваленти
  • Впровадження існуючого OISC (відповідачі, будь ласка, створіть свій власний!)
  • "OISC", в якому перший аргумент вказує команду для виклику ( приклад )

Однак вам слід подати цікаві, креативні матеріали, такі як:

  • OISC на основі математичного рівняння
  • ЦІРС-повний ZISC на базі нейронної мережі
  • OISC, в якому вихідний введення / вивід відбувається іншими способами, ніж певні місця пам'яті

Перемога

Як і у , відповідь з найбільшою кількістю голосів виграє! Удачі!


10
Що таке "інструкція"? І як ми їх рахуємо?
Пшеничний майстер

1
@NoOneIsHere Я хотів би, щоб я знав достатньо лише проголосувати за xD
Брайан Х.

2
Я спростував це. Я думаю, що це дуже цікава ідея, але ви не пояснюєте, що саме є OISC, і як щось підтвердити. Я зробив BF OISC, але це явно проти духу питання, але технічно справедливе.
NoOneIsHere

1
@MDXF Я не думаю, що ви отримуєте ///: у нього є команда підстановки, і вона має команди друку, що не є лише побічним ефектом команди підстановки
Destructible Lemon

1
@NoOneIsHere Тому що популярність-конкурс . Так, це дійсно, але він має низький бал (підрахунок голосів), тому не виграє.
користувач202729

Відповіді:


20

XOISC

Цей OISC базується на X-комбінаторі Фоккера, який визначається наступним чином:

X=λf .f (λg h x .g x (h x)) (λa b c .a)

XSKIX

S=X (X X)K=X XI=S K K=X (X X) (X X) (X X)

Як працює XOISC

n

  • nf1fNf1 (f2 ((fN X)))

Після того, як не залишиться більше інструкцій, XOISC натисне всі аргументи командного рядка (якщо такі є), наприклад:

[s1,, sMstack before, a1,, aNarguments]

((((s1 s2)) sM) a1))aN


Оскільки одна інструкція в XOISC приймає лише один аргумент (зміщення пам'яті), немає ніяких причин навіть використовувати ім’я для цієї інструкції. Отже, дійсний вихідний файл буде складатися виключно з цілих чисел, розділених новими рядками або пробілами, як, наприклад:

0 0 2 0 1 0 1

Спробуйте в Інтернеті!

Приклад

Візьмемо наведений вище приклад (стек росте праворуч):

0pop 0 and apply (ie. push single X):[X]0again simply push X:[X, X]2pop 2 (a,b) and push a (b X):[X (X X)]0simply push X:[X (X X), X]1pop 1 (a) and push a X:[X (X X), X X]0simply push X:[X (X X), X X, X]1pop 1 (a) and push a X:[X (X X), X X, X X]

((X (X X)) (X X)) (X X)X (X X) (X X) (X X)S K K

Тюрінг повноти

Доказ ідеї

X

X

((X (X X)) (X X)) (X X)

  • X0
  • далі ми знаходимося в новому рівні в дужках, тому нам знову потрібно лише 0
  • тепер два круглі дужки закриті, тому нам потрібно вставити 2 елементи: 2
  • знову ми знаходимося на новому рівні в дужках, тому нам потрібен 0
  • дві дужки, закрийте так знову a 2
  • і знову те саме

Отже, ми закінчуємо іншу (але семантично еквівалентну) програму XOISC:

0 0 2 0 2 0 2 Спробуйте в Інтернеті!

X

Офіційне підтвердження

З огляду на те, що підрахунок SKI є Тюрінг завершеним, нам потрібно показати дві речі:

  1. X
  2. X

Перша частина - доведення трьох рівностей у вступі - дуже втомлива і забирає багато місця, вона також не дуже цікава. Тож замість того, щоб розмістити його в цій публікації, ви можете знайти тут * .

X

XXf gfg

0XF1FNG1GKfgf g

F1FN G1GK1 (GK+1)fggff g

Перекладач

Вхідні дані

Оскільки нетипічне обчислення лямбда вимагає від нас визначення власних типів даних для всього, що ми хочемо, і це громіздко, інтерпретатор знає церковні цифри - це означає, що коли ви надасте введення, він автоматично перетворює числа у відповідні церковні цифри.

Як приклад, ось програма, що множить два числа: Спробуйте в Інтернеті!

Ви також можете надати функції як аргументи, використовуючи індекси De Bruijn , наприклад Sкомбінатор \\\(3 1 (2 1))(або λλλ(3 1 (2 1))). Однак він також визнає S, K, Iі, звичайно ж Xкомбінатор.

Вихід

За замовчуванням інтерпретатор перевіряє, чи є вихідний кодує ціле число, якщо він робить, він виводить відповідне число (на додаток до результату). Для зручності є -bпрапор, який повідомляє інтерпретатору спробувати замість булевого типу (див. Останній приклад).

Асемблер

Звичайно, будь-яка мова низького рівня потребує асемблера, який перетворює на неї мову високого рівня, ви можете просто скористатися будь-яким входом (див. Вище) і перевести його в XOISC-програму, використовуючи -aпрапор, спробуйте в Інтернеті! **


* Якщо посилання не працює, у цій публікації є копія у вигляді коментаря HTML.

** У результаті виходить програма, яка перевіряє первинність, спробуйте її в Інтернеті!


1
Чи є причина, що ви вибрали комбінатор X замість комбінатора Iota?
Esolanging Fruit

1
@EsolangingFruit: Так, є також кілька інших варіантів, врешті-решт я вибрав саме цей варіант, оскільки для створення SK використовується найменше програм. Здавалося, це буде найкраще (тбх, я сам не робив порівняння).
ბიმო

1
Btw. приємне порівняння кількох комбінаторів у зв'язаному папері, якщо вас цікавить.
ბიმო

19

Малюємо

Малюнок - це OISC, що діє на 2D сітці, позначаючи квадрати таким чином, як машина Wang B. Однак, щоб зберегти мову якомога простішою та OISC-y, усі інструкції (яких існує загальна сума в одному) означають щойно наступив квадрат і, щоб можна було зупинитися, ступаючи на позначений квадрат припиняє програму.

Програма складається з послідовності рядків, що містять ідентифікатор рядка (довільний рядок, що не включає # або пробіл), двох цілих чисел ( xі y) та ще двох ідентифікаторів рядків ( aі b).

Програма працює наступним чином:
починаючи з рядка, визначеного як startвказівник, що вказує на позицію (0, 0), перемістіть вказівник на величину, задану xта, yі позначте квадрат, на якому зараз вказівник (якщо квадрат уже не позначений, у цьому випадку виконання припиняється). Потім переходьте до рядка, aякщо хоча б один із прямо сусідніх квадратів також позначений, а на bінший рядок .

Перекладачам рекомендується виводити кінцевий результат сітки як якесь зображення, полотно тощо.

Тюрінг-повнота

Малюнок є повним Тьюрінгом, оскільки можна скласти модифіковану версію (називається альтернативною) машини Менського на мову.

Alternate діє аналогічно двоколірній машині Мінського, але в командах є велике обмеження: команди повинні чергуватися між націлюванням першого та другого лічильника. Щоб обійти цю модифікацію, додаткова команда була додана: nop. Ця команда взагалі не змінює цільовий лічильник, що дає можливість "прокладати" послідовні зміни на один лічильник, задовольняючи обмеження, викладене вище. Це також означає, що реєстр, який має бути змінений, не потрібно давати, і для будь-якої заданої інструкції можна безпосередньо зробити висновок з інструкцій, з яких виконання може перейти до нього.

Приклад: ця машина Менського

1 inc A 2
2 inc A 3
3 dec A 3 4
4 halt

перетворюється на цю альтернативну програму:

1 inc 2
2 nop 3
3 inc 4
4 nop 5
5 dec 6 8
6 nop 5
7 halt
8 halt

Це обмеження є необхідним через те, що кінцева програма Draw обробляє регістри, що означає, що вона взагалі не відрізняє їх. Натомість програма Draw просто копіює реєстр, який не був змінений попередньою інструкцією, змінюючи його відповідно до виконуваної інструкції.

Потім програма Alternate безпосередньо переводиться на Draw наступним чином:

Програма починається з цього блоку.

start 0 0 a a
a 3 0 b b
b -3 1 c c
c 3 0 d d
d -3 2 e e
e 3 0 f f
f 3 -3 i1_a i1_a

inc, decі nopперекладаються майже так само, як один одного. У всіх випадках різниці між зміною першого або другого регістра (як пояснено вище) немає. Ось приріст, еквівалентний inc 2:

i1_y 0 -2 i1_z i1_y
i1_z 3 -1 i1_a i1_a
i1_a -5 1 i1_b i1_b
i1_b 0 2 i1_c i1_c
i1_c 0 2 i1_d i1_e
i1_d 0 2 i1_d i1_f

i1_e 5 0 i2_z i2_y
i1_f 5 0 i2_z i2_y

Змініть числа в i1_xчастинах до індексу поточної інструкції, а в i2_xчастинах - до індексу наступної інструкції, яку потрібно виконати.

nopІнструкція може бути переведена як такі:

i1_y 0 -2 i1_z i1_y
i1_z 3 -1 i1_a i1_a
i1_a -5 1 i1_b i1_b
i1_b 0 2 i1_c i1_c
i1_c 0 2 i1_d i1_e
i1_d 0 2 i1_d i1_f

i1_e 5 -2 i2_z i2_y
i1_f 5 -2 i2_z i2_y

Це декрет:

i1_y 0 -2 i1_z i1_y
i1_z 3 -1 i1_a i1_a
i1_a -5 1 i1_b i1_b
i1_b 0 2 i1_c i1_c
i1_c 0 2 i1_d i1_e
i1_d 0 2 i1_d i1_f

i1_e 5 -2 i3_z i3_y
i1_f 5 -4 i2_z i2_y

i3_x посилається на інструкцію, яку потрібно викликати, якщо лічильник вже 1.

Зупинка:

i1_y 0 0 0 0
i1_z 0 0 0 0

Міняйте етикетки відповідним чином і просто зв'язуйте все разом. Зробивши це для прикладу зверху, програма Draw знаходиться у сховищі зверху.

Перекладачі

В даний час є два перекладачі, обидва написані на Python. Їх можна знайти у сховищі GitHub Draw .

  1. draw.py : Цей інтерпретатор призначений для командного рядка і приймає джерело програми як аргумент. Після кожного кроку він виводить виконану команду та місце розташування вказівника інструкції; після зупинки програми надрукує кількість позначених комірок.
  2. draw_golly.py : Ця версія використовує Golly для зовсім неправильної мети, полегшує графічний вихід, приймаючи джерело через спливаюче вікно при запуску сценарію. Golly може бути трохи хитромудрою з Python, тому переконайтеся, що у вас встановлений Python 2 (і не змішуйте 32-бітний Golly з 64-бітним Python або навпаки). Вихід забезпечується через вбудовану клітинну сітку Голлі.

Наступне зображення є прикладом для виводу з другого перекладача. Запуск прикладної програми у сховищі дає це (або подібне):


1
Дивовижний! Вітаю, як знайти дуже унікальний спосіб вирішити завдання.
MD XF

Ваша мова зовсім не повинна зупинятися, щоб бути завершеною. Правило 110 не припиняється, але все-таки воно є повним.
Акангка

+1 для Golly - найкращого симулятора стільникових автоматів.
HighlyRadioactive

14

-3

Ось суть.

Пам'ять

Пам'ять - це карта стрічок, де клавішами є рядки, а значення - цілі числа довільного розміру.

Крім того, є набір міток, куди програма може перейти.

Є стек, який містить операнди, які є рядками.

Є кривдник, який контролює, куди в стрічках пам'яті вона може отримати доступ.

Одна інструкція

-. По-перше, він вискакує рядок LABELзі стека. Якщо це LABELне визначено як мітка, він визначає мітку та очищає джерело цієї мітки (тобто звідки її було висунуто) та поточну інструкцію. В іншому випадку він виконує наступний обчислення, використовуючи два перших значення, Aі B:

if mem[A] < mem[B]:
    jump to LABEL
if mem[A] != mem[B]:
    mem[A]--
else:
    mem[B]++

Зауважте, що якщо є надлишки аргументів або недостатньо аргументів, програма помилиться, показуючи стан програми.

Зсув може бути змінено за допомогою доступу до значення ..

Приклад коду

X-

i i X-
i i X-
i i X-
i i X-
i i X-
i i X-
i i X-

Це встановлює змінну iна 7, збільшуючи 7час.

X-

i i X-
i i X-
i i X-
LOOP-
    a a X-
    a a X-
    j i LOOP-

Це множиться i+1на постійне 2.

Доказ завершеності Тюрінга

Не зважаючи на розміри інт C ++ (тобто, якщо припустити, що вони нескінченні), -3 - це Тьюрінг завершений шляхом зменшення до 3-клітинного мозкового руху . Я не можу ігнорувати цей розмір, тому що на комп'ютері з нескінченною пам'яттю, що має довільно великі комірки, може бути записаний перекладач для -3

Я також вважаю, що будь-який BCT можна записати як програму -3.


Оскільки я люблю вдосконалювати свій зміст, будь ласка, будемо вдячні пояснення щодо голосування проти,
Conor O'Brien
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.