Files

6.7 KiB
Raw Permalink Blame History

id, title, challengeType, forumTopicId, dashedName
id title challengeType forumTopicId dashedName
5a23c84252665b21eecc8038 Subleq 5 302328 subleq

--description--

Subleq — приклад a One-Instruction Set Computer (OISC) (Комп'ютер із набором однієї інструкції).

Назва пішла від перших літер інструкції: SUbtract і Branch if Less than or EQual to zero (відняти й перейти, якщо результат менший або рівний нулю).

Ваше завдання — створити дешифрувальник, який змоделює принцип дії такої машини.

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

Виконання починається з лічильника команд, спрямованого на перше слово, яке є адресою 0. Це відбувається наступним чином:

  1. Нехай А, В та С будуть значеннями, що зберігаються в трьох послідовних словах у пам'яті, починаючи з лічильника команд.
  2. Розширте лічильник команд, розташувавши курсор у адресному рядку після компонента, що містить значення C.
  3. Якщо A = -1, тоді символ зчитується зі стандартного вводу та його кодова точка, що зберігається в адресі, зазначеному у B. C не використовується.
  4. Якщо B — -1, тоді число, що міститься в адресі, вказаній А, інтерпретується як кодова точка та відповідний символ виходу. C знову не використовується.
  5. В іншому випадку і A, і B розглядаються як адреси комірок пам'яті. Число, що знаходиться в адресі, що вказана A, віднімається від числа в адресі, вказаній B (а результат зберігається назад в адрес B). Якщо результат дорівнює нулю або від'ємний, значення C стає новим лічильником команд.
  6. Якщо лічильник команд стає від'ємним — виконання припиняється.

Інші негативні адреси, окрім -1, можна вважати еквівалентом -1 або згенерувати помилку — робіть так, як вважаєте за потрібне.

Ваше рішення повинно показати, чи надаєте Ви дозвіл програмі виконати дану операцію в комп'ютері незалежно від вхідного потоку самої програми.

Ця програма має бути в сирому "машинному коді" subleq — десяткові числа, розділені пробілом з символьним ім'ям чи інші розширення рівня асемблера, які завантажаться у пам'ять, починаючи з адреси 0. Покажіть вивід свого рішення, коли запустите цю програму "Hello, world!". (Зверніть увагу, що цей приклад припускає використання ASCII або його надмножину, таку як будь-який сет символів чи Unicode. Ви можете перекласти його на іншу кодову систему, якщо ваше виконання засноване на середовищі, не сумісному з ASCIL.)

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

Що відповідає чомусь схожому на це у гіпотетичній мові асемблера:

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"

--instructions--

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

--hints--

Subleq має бути функцією.

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]) має виводити рядок.

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!".

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--

function Subleq(mem) {

}

--solutions--

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;
}