179 lines
6.7 KiB
Markdown
179 lines
6.7 KiB
Markdown
![]() |
---
|
|||
|
id: 5a23c84252665b21eecc8038
|
|||
|
title: Subleq
|
|||
|
challengeType: 5
|
|||
|
forumTopicId: 302328
|
|||
|
dashedName: subleq
|
|||
|
---
|
|||
|
|
|||
|
# --description--
|
|||
|
|
|||
|
[Subleq](https://rosettacode.org/wiki/eso:Subleq) — приклад a [One-Instruction Set Computer (OISC) (Комп'ютер із набором однієї інструкції)](https://en.wikipedia.org/wiki/One_instruction_set_computer).
|
|||
|
|
|||
|
Назва пішла від перших літер інструкції: **SU**btract і **B**ranch if **L**ess than or **EQ**ual to zero (відняти й перейти, якщо результат менший або рівний нулю).
|
|||
|
|
|||
|
Ваше завдання — створити дешифрувальник, який змоделює принцип дії такої машини.
|
|||
|
|
|||
|
Пам'ять машини складається з масиву цілих чисел зі знаком. Підійде будь-який допустимий розмір слова, але пам'ять повинна підтримувати від'ємні та додатні числа.
|
|||
|
|
|||
|
Виконання починається з лічильника команд, спрямованого на перше слово, яке є адресою 0. Це відбувається наступним чином:
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>Нехай А, В та С будуть значеннями, що зберігаються в трьох послідовних словах у пам'яті, починаючи з лічильника команд.</li>
|
|||
|
<li>Розширте лічильник команд, розташувавши курсор у адресному рядку після компонента, що містить значення C.</li>
|
|||
|
<li>Якщо A = -1, тоді символ зчитується зі стандартного вводу та його кодова точка, що зберігається в адресі, зазначеному у B. C не використовується.</li>
|
|||
|
<li>Якщо B — -1, тоді число, що міститься в адресі, вказаній А, інтерпретується як кодова точка та відповідний символ виходу. C знову не використовується.</li>
|
|||
|
<li>В іншому випадку і A, і B розглядаються як адреси комірок пам'яті. Число, що знаходиться в адресі, що вказана A, віднімається від числа в адресі, вказаній B (а результат зберігається назад в адрес B). Якщо результат дорівнює нулю або від'ємний, значення C стає новим лічильником команд.</li>
|
|||
|
<li>Якщо лічильник команд стає від'ємним — виконання припиняється.</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
Інші негативні адреси, окрім -1, можна вважати еквівалентом -1 або згенерувати помилку — робіть так, як вважаєте за потрібне.
|
|||
|
|
|||
|
Ваше рішення повинно показати, чи надаєте Ви дозвіл програмі виконати дану операцію в комп'ютері незалежно від вхідного потоку самої програми.
|
|||
|
|
|||
|
Ця програма має бути в сирому "машинному коді" subleq — десяткові числа, розділені пробілом з символьним ім'ям чи інші розширення рівня асемблера, які завантажаться у пам'ять, починаючи з адреси 0. Покажіть вивід свого рішення, коли запустите цю програму "Hello, world!". (Зверніть увагу, що цей приклад припускає використання ASCII або його надмножину, таку як будь-який сет символів чи Unicode. Ви можете перекласти його на іншу кодову систему, якщо ваше виконання засноване на середовищі, не сумісному з ASCIL.)
|
|||
|
|
|||
|
<pre>15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0</pre>
|
|||
|
|
|||
|
Що відповідає чомусь схожому на це у гіпотетичній мові асемблера:
|
|||
|
|
|||
|
<pre>start:
|
|||
|
zero, message, -1
|
|||
|
message, -1, -1
|
|||
|
neg1, start+1, -1
|
|||
|
neg1, start+3, -1
|
|||
|
zero, zero, start
|
|||
|
zero: 0
|
|||
|
neg1: -1
|
|||
|
message: "Hello, world!\n\0"
|
|||
|
</pre>
|
|||
|
|
|||
|
# --instructions--
|
|||
|
|
|||
|
Напишіть функцію, що використовує набір цілих чисел як параметр. Це відображає елементи пам'яті. Функція повинна інтерпретувати послідовність та виводити вихідний рядок. Для цього завдання припустимо, що стандартного вводу немає.
|
|||
|
|
|||
|
# --hints--
|
|||
|
|
|||
|
`Subleq` має бути функцією.
|
|||
|
|
|||
|
```js
|
|||
|
assert(typeof Subleq == 'function');
|
|||
|
```
|
|||
|
|
|||
|
`Subleq([15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 0])` має виводити рядок.
|
|||
|
|
|||
|
```js
|
|||
|
assert(
|
|||
|
typeof Subleq([
|
|||
|
15,
|
|||
|
17,
|
|||
|
-1,
|
|||
|
17,
|
|||
|
-1,
|
|||
|
-1,
|
|||
|
16,
|
|||
|
1,
|
|||
|
-1,
|
|||
|
16,
|
|||
|
3,
|
|||
|
-1,
|
|||
|
15,
|
|||
|
15,
|
|||
|
0,
|
|||
|
0,
|
|||
|
-1,
|
|||
|
72,
|
|||
|
101,
|
|||
|
108,
|
|||
|
108,
|
|||
|
111,
|
|||
|
44,
|
|||
|
32,
|
|||
|
119,
|
|||
|
111,
|
|||
|
114,
|
|||
|
108,
|
|||
|
100,
|
|||
|
33,
|
|||
|
0
|
|||
|
]) == 'string'
|
|||
|
);
|
|||
|
```
|
|||
|
|
|||
|
`Subleq([15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 0])` має відображати `"Hello, world!"`.
|
|||
|
|
|||
|
```js
|
|||
|
assert.equal(
|
|||
|
Subleq([
|
|||
|
15,
|
|||
|
17,
|
|||
|
-1,
|
|||
|
17,
|
|||
|
-1,
|
|||
|
-1,
|
|||
|
16,
|
|||
|
1,
|
|||
|
-1,
|
|||
|
16,
|
|||
|
3,
|
|||
|
-1,
|
|||
|
15,
|
|||
|
15,
|
|||
|
0,
|
|||
|
0,
|
|||
|
-1,
|
|||
|
72,
|
|||
|
101,
|
|||
|
108,
|
|||
|
108,
|
|||
|
111,
|
|||
|
44,
|
|||
|
32,
|
|||
|
119,
|
|||
|
111,
|
|||
|
114,
|
|||
|
108,
|
|||
|
100,
|
|||
|
33,
|
|||
|
0
|
|||
|
]),
|
|||
|
'Hello, world!'
|
|||
|
);
|
|||
|
```
|
|||
|
|
|||
|
# --seed--
|
|||
|
|
|||
|
## --seed-contents--
|
|||
|
|
|||
|
```js
|
|||
|
function Subleq(mem) {
|
|||
|
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
# --solutions--
|
|||
|
|
|||
|
```js
|
|||
|
function Subleq(mem) {
|
|||
|
var out = '';
|
|||
|
var instructionPointer = 0;
|
|||
|
do {
|
|||
|
var a = mem[instructionPointer];
|
|||
|
var b = mem[instructionPointer + 1];
|
|||
|
if (a === -1) {
|
|||
|
} else if (b === -1) {
|
|||
|
out += String.fromCharCode(mem[a]);
|
|||
|
} else {
|
|||
|
mem[b] -= mem[a];
|
|||
|
if (mem[b] < 1) {
|
|||
|
instructionPointer = mem[instructionPointer + 2];
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
instructionPointer += 3;
|
|||
|
} while (instructionPointer >= 0);
|
|||
|
|
|||
|
return out;
|
|||
|
}
|
|||
|
```
|