commit 7bfe0eb0d7354c0c13889926e03e409f7eb5e469 Author: Alex Cube Date: Tue Oct 27 18:56:24 2026 +0300 ДЛМ: оцифрованное руководство 1987 года, эмулятор и проверка программ Эмулятор в одном файле index.html, руководство в PDF (сканы, набранный текст, расшифровка рисунков программ). check.mjs сверяет все программы с руководством на всех входах, игру 4 решает перебором партий, игру 8 проверяет перебором раскладок карточек. Co-Authored-By: Claude Opus 5.5 diff --git a/DLM_rukovodstvo_1987.pdf b/DLM_rukovodstvo_1987.pdf new file mode 100644 index 0000000..6593db1 Binary files /dev/null and b/DLM_rukovodstvo_1987.pdf differ diff --git a/check.mjs b/check.mjs new file mode 100644 index 0000000..f00f33b --- /dev/null +++ b/check.mjs @@ -0,0 +1,135 @@ +// Checks every program in index.html against the booklet on all 8 inputs. +// The machine is simulated here independently of the page: a column fires when all three of its +// contacts are closed, a lamp lights when a jumper chain connects it to a firing column. +// Run: node check.mjs (exit code 1 if anything breaks, apart from the two known errata) +import { readFileSync } from 'node:fs'; + +const html = readFileSync(new URL('./index.html', import.meta.url), 'utf8'); +const PROGRAMS = Function('return ' + html.match(/const PROGRAMS = (\[[\s\S]*?\n \]);/)[1])(); +const P = Object.fromEntries(PROGRAMS.map(p => [p.id, p])); + +// input n = А·4 + Б·2 + В·1; result = V·8 + X·4 + Y·2 + Z·1 +function run(p, n) { + const inp = [n >> 2 & 1, n >> 1 & 1, n & 1]; + const parent = {}; + const find = a => (parent[a] ??= a) === a ? a : (parent[a] = find(parent[a])); + p.wires.forEach(([a, b]) => { parent[find(a)] = find(b); }); + const fired = []; + for (let c = 0; c < 7; c++) { + const ok = p.rows.every((row, r) => { const ch = row[c]; return ch === 'B' || ch === (inp[r] ? 'L' : 'R'); }); + if (ok) fired.push(find('C' + (c + 1))); + } + return [0, 1, 2, 3].reduce((s, k) => s + (fired.includes(find('L' + k)) ? 8 >> k : 0), 0); +} + +const b3 = n => n.toString(2).padStart(3, '0'), b4 = n => n.toString(2).padStart(4, '0'); +let failed = 0; +const errata = []; +function expect(id, n, want, why, erratum) { + const got = run(P[id], n); + if (got === want) return; + const line = `${id}: вход ${b3(n)} → ${b4(got)}, ожидалось ${b4(want)}. ${why}`; + if (erratum) errata.push(line); else { failed++; console.log('ОШИБКА ' + line); } +} +const all = f => { for (let n = 0; n < 8; n++) f(n); }; + +// Game 1: answers to the three questions → the number thought of. Game 9 uses the same figure. +const answers = x => (x % 2 === 0) * 4 + (x + x + 1 < 8) * 2 + [4, 5].includes((x + 10) % 6); +const numberOf = {}; +all(x => { numberOf[answers(x)] = x; }); +all(x => expect('game1', answers(x), x, `задумано ${x}`)); +for (let x = 1; x <= 6; x++) expect('game3', answers(x), x + 7, `на кубике ${x}, плюс противоположные грани 7`); + +// Game 2: everyone claims to be honest, so y is honest iff А = 1; z is honest iff В matches y. +all(n => { + const A = n >> 2 & 1, B = n >> 1 & 1, C = n & 1; + const y = A, z = +(C === y), x = z ? B : 1 - B; + expect('game2', n, x * 4 + y * 2 + z, `x=${x} y=${y} z=${z}`); +}); + +// Games 5 and 6: 24 matches; players 1, 2, 3 took 1, 2, 3 and then the owners of А, Б, В took 1×, 2×, 4× more. +const CODE = { А: 0, Б: 1, В: 2 }; +const left = {}; +for (const [a, b, c] of [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]) { + const owner = { [a]: 'А', [b]: 'Б', [c]: 'В' }; + left[24 - 6 - (a + 2 * b + 4 * c)] = CODE[owner[1]] * 4 + CODE[owner[2]]; +} +all(m => expect('game5', m, left[m] ?? 0, `осталось ${m} спичек`)); +all(n => expect('game6', n, left[numberOf[n]] ?? 0, `осталось ${numberOf[n]} спичек`)); + +// Game 9: answer number → comment number, from the booklet's table of answers and comments. +const COMMENT = [0b101, 0b111, 0b011, 0b001, 0b100, 0b110, 0b010, 0b000]; +all(n => expect('game9', n, COMMENT[n], 'таблица комментариев')); + +// Game 11: Y — motor runs if there is any call, X — door unlocked when it does not, +// Z — up for an up call alone, keep direction А for both calls (no calls: Z does not matter). +all(n => { + const A = n >> 2 & 1, up = n >> 1 & 1, down = n & 1; + const y = up | down, z = up && down ? A : up; + const got = run(P.game11, n); + if (!up && !down) expect('game11', n, (got & 1) | 4, 'лифт стоит, дверь открыта'); + else expect('game11', n, (1 - y) * 4 + y * 2 + z, 'лифт'); +}); + +// Game 4: turn the die onto a side face and add it; the sum must not pass 12; whoever reaches +// exactly 12 wins; if nobody can, it is a draw. The machine gets the sum (minus 8 if over 7); +// if the advised face is not on a side, the player takes the nearest smaller side face. +// Solve the game outright (1 win, 0 draw, -1 loss for the player to move) and walk every game +// that can happen: the machine must never get less than the position allows. +const sides = t => [1, 2, 3, 4, 5, 6].filter(f => f !== t && f !== 7 - t); +const memo = {}; +const after = (s, f) => s + f === 12 ? 1 : -value(s + f, f); +const value = (s, t) => memo[s + ',' + t] ??= Math.max(0, ...sides(t).filter(f => s + f <= 12).map(f => after(s, f))); +const machineMove = (s, t) => sides(t).filter(f => f <= run(P.game4, s % 8) && s + f <= 12).pop(); +const RESULT = { 1: 'выигрыш', 0: 'ничья', '-1': 'проигрыш' }; +const seen = new Set(); +const machineTurn = (s, t) => { + if (seen.has(s + ',' + t)) return; seen.add(s + ',' + t); + const f = machineMove(s, t), got = f ? after(s, f) : 0; + if (got < value(s, t)) + errata.push(`game4: сумма ${s}, сверху ${t}: машина советует ${run(P.game4, s % 8)}, игрок ставит ${f ?? '—'}, ` + + `и вместо «${RESULT[value(s, t)]}» выходит «${RESULT[got]}»`); + if (!f || s + f === 12) return; + for (const g of sides(f)) if (s + f + g < 12) machineTurn(s + f + g, g); +}; +for (let t = 1; t <= 6; t++) machineTurn(t, t); + +// Game 8: deal 4 birds, 4 beasts, 4 insects into three piles of four every possible way and play +// the booklet's patience. Questions: А — the bottom card at «Насекомые» is an insect, +// Б — the bottom card at «Звери» is a beast, В — one of these two cards is a bird. +// Lamps, as the booklet reads them: V X Y — full success; X — birds and insects; Y — birds and +// beasts; Z — birds, probably the rest too; none — birds only. +const outcomes = {}; +(function deal(cards, left) { + if (!left.P && !left.Z && !left.N) { + const piles = { P: cards.slice(0, 4), Z: cards.slice(4, 8), N: cards.slice(8) }; + const placed = { P: 0, Z: 0, N: 0 }; + for (let cur = 'P'; piles[cur].length;) { const c = piles[cur].shift(); placed[c]++; cur = c; } + const done = 'PZN'.split('').filter(k => placed[k] === 4).join(''); + const n = (cards[11] === 'N') * 4 + (cards[7] === 'Z') * 2 + (cards[11] === 'P' || cards[7] === 'P'); + (outcomes[n] ??= new Set()).add(done); + return; + } + for (const k of 'PZN') if (left[k]) deal([...cards, k], { ...left, [k]: left[k] - 1 }); +})([], { P: 4, Z: 4, N: 4 }); +const LAMPS8 = { PZN: 0b1110, PN: 0b0100, PZ: 0b0010, P: 0 }; +all(n => { + if (!outcomes[n]) return; // such answers cannot happen + const o = [...outcomes[n]], want = o.length === 1 ? LAMPS8[o[0]] : 0b0001; + expect('game8', n, want, `раскладка кончается так: ${o.join(' или ')}`, true); +}); + +// Logic elements from the Habr article. +all(n => { + const A = n >> 2 & 1, B = n >> 1 & 1, C = n & 1; + expect('not', n, (1 - A) * 4 + (1 - B) * 2 + (1 - C), 'НЕ'); + expect('nand', n, +!(A && B && C), 'И-НЕ'); + expect('nor', n, +!(A || B || C), 'ИЛИ-НЕ'); + expect('xor', n, A ^ B ^ C, 'XOR'); + expect('adder', n, (A + B + C > 1) * 8 + ((A + B + C) & 1), 'сумматор'); + expect('cipher', n, n ^ 0b100, 'шифр'); +}); + +console.log(errata.length ? 'Ошибки в самом руководстве:\n ' + errata.join('\n ') : 'Ошибок в руководстве не найдено'); +console.log(failed ? `Расхождений с руководством: ${failed}` : 'Все остальные проверки прошли'); +process.exit(failed ? 1 : 0); diff --git a/index.html b/index.html new file mode 100644 index 0000000..e6aaf6a --- /dev/null +++ b/index.html @@ -0,0 +1,865 @@ + + + + + +Детская логическая машина + + + + + + + +
+
+ +
+

детская логическая машина

+

Советская программируемая игрушка 1984–1989 годов, в которой нет ни транзистора, ни реле: только планки, штеккеры, пружинные контакты и лампочки. Справа видно, как поворот переключателя двигает планку, штеккеры нажимают контакты и куда идёт ток. Все 11 игр из руководства 1987 года набираются одной кнопкой.

+
+
+ +
+
+

Пульт

штеккеров: 0 / 30
+ +
+ + +
+
+ + + +
+

Гнездо: вставить или вынуть штеккер. Пружина, затем вторая пружина: поставить перемычку. Перемычка: снять. Переключатель: щелчок по ручке или по «0» и «1».

+
+ +
+

Вид изнутри

+
токнапряжение, тока нетобесточено
+
+ +

Переключатель — это кривошип: поворот сдвигает планку. Под каждым столбцом, под каждой планкой, стоит пружинящая пластина, по бокам от неё два неподвижных контакта. При «1» планка уходит вправо, и штеккер из левого гнезда отгибает пластину на правый контакт. При «0» штеккер из правого гнезда отгибает её на левый. В среднем положении пластины никто не касается. Каждый столбец — три такие пластины подряд, по одной под каждой планкой, то есть логическое И. Перемычки собирают несколько столбцов на одну лампу — это ИЛИ. Вот и весь «процессор»: программа — это расстановка штеккеров и перемычек. Механизм под крышкой — реконструкция: в брошюре его нет, фотографий тоже не нашлось.

+
+
+ +
+
+

Программы

+
+
+
+

Что ответит машина

+
+
+
+

Столбцы программирования

+
    +
    +
    + +
    +
    +

    Игры из руководства 1987 года

    +

    Правила сокращены по оригинальной брошюре. Кнопка под каждой игрой набирает программу с её рисунка: штеккеры и перемычки ставятся точно как на рисунке.

    +
    +
    +

    Как читать ответ

    +

    Ввод — переключатели А (4), Б (2), В (1): числа от 0 до 7. Вывод — лампы V (8), X (4), Y (2), Z (1): горящая лампа означает «1», «Да», «Правильно». Сумма чисел над горящими лампами даёт ответ от 0 до 15.

    +

    Штеккер в левом гнезде замыкает звено столбца, когда переключатель стоит на «1», в правом — на «0». Столбец срабатывает, если замкнуты все три его звена. Перемычки соединяют столбцы с лампами.

    +
    + +
    +

    Игра 1. Какое число задумано?

    +

    Играющий задумывает число от 0 до 7 и отвечает на три вопроса. «Да» — переключатель в «1», «Нет» — в «0».

    +

    А: Задуманное число чётное? (Ноль — чётное.)
    Б: Сумма задуманного числа и следующего за ним меньше восьми?
    В: К задуманному числу прибавьте 10 и разделите на 6. Остаток 4 или 5?

    +

    Лампы X, Y, Z показывают задуманное число. Пример: для 5 все ответы «Нет», горят X и Z: 101 = 5.

    + +
    +
    +

    Игра 2. Честные и лгуны

    +

    В стране живут честные (всегда говорят правду) и лгуны (всегда лгут). На вопрос «Вы честный или лгун?» житель x отвечает на непонятном языке.

    +

    А: житель y: «Он сказал, что он честный» — «1», «…что он лгун» — «0».
    Б: житель z о жителе x: «честный» — «1», «лгун» — «0».
    В: житель z о жителе y: «честный» — «1», «лгун» — «0».

    +

    Горящие X, Y, Z означают, что x, y, z честные. Пример: Дима (x) честный, Витя (y) и Коля (z) лгуны. Ответы 0, 0, 1 — горит только X.

    + +
    +
    +

    Игра 3. Сумма трёх чисел

    +

    Играющий тайком бросает кубик и запоминает число. Его ответы на вопросы игры 1 фиксируются планками А, Б, В. Затем он бросает ещё раз, запоминает верхнее число и число на противоположной грани и складывает все три.

    +

    Нажмите кнопку: лампы покажут сумму. Пример: 5, затем 4 и 3, сумма 12. Ответы «Нет, Нет, Нет», горят V и X: 1100 = 12.

    + +
    +
    +

    Игра 4. Двенадцать — выигрыш!

    +

    Противник бросает кубик первым. Дальше игроки по очереди поворачивают кубик на одну из боковых граней и прибавляют её число к сумме. Кто первым наберёт ровно 12, тот выиграл.

    +

    Введите текущую сумму (если она больше 7, вычтите 8). Лампы X, Y, Z покажут число, которое нужно поставить наверх. Если такой грани сбоку нет, берите ближайшее меньшее. Пример: выпало 2, машина говорит 2, но двойка сверху, ставим 1 (сумма 3). Противник делает 5, машина 4 (сумма 9). Противник делает 10, вводим 2, машина 2, сумма 12.

    + +
    +
    +

    Игра 5. Какой предмет выбран?

    +

    Возьмите 24 спички. Игроки № 1, 2, 3 берут 1, 2 и 3 спички и тайком делят фишки А, Б, В. Затем владелец А добирает столько же, сколько взял, владелец Б — вдвое больше, владелец В — вчетверо.

    +

    Введите число оставшихся спичек. Пара V X — игрок № 1, пара Y Z — игрок № 2. Код: 00 — фишка А, 01 — Б, 10 — В. Если все лампы погашены, правила нарушены. Пример: осталось 5, горят X и Y. Игрок № 1 — Б, игрок № 2 — В, игроку № 3 досталась А.

    + +
    +
    +

    Игра 6. ДЛМ превосходит себя!

    +

    Всё как в игре 5, но оператор не узнаёт, сколько спичек осталось. Он задаёт одному из игроков вопросы игры 1 про это число и читает ответ по коду игры 5.

    + +
    +
    +

    Игра 7. Семь спичек

    +

    Двое по очереди берут со стола одну или две спички в «общий котёл», пока стол не опустеет. Потом в том же порядке возвращают по одной-две. Выигрывает тот, кто положит седьмую. Противник ходит первым.

    +

    Вводите число спичек, уже взятых (во второй половине — уже положенных). Лампы покажут, сколько их должно стать после вашего хода. Во второй половине вместо 2 вводите 111, вместо 5 — 110.

    + +
    +
    +

    Игра 8. Зоологические карточки

    +

    Двенадцать карточек (по 4 птицы, зверя, насекомых) лежат тремя стопками рубашкой вверх, возле стопок в любом порядке — надписи. Берите верхнюю карточку стопки «Птицы» и кладите к нужной надписи. Затем берите карточку из той стопки, куда положили, и так далее.

    +

    А: нижняя карточка у надписи «Насекомые» — насекомое?
    Б: нижняя карточка у надписи «Звери» — зверь?
    В: среди двух просмотренных карточек есть птица?

    +

    V, X, Y — возможен полный успех. Только X — сойдутся птицы или насекомые. Только Y — птицы или звери. Только Z — птицы, вероятно, и остальные. Ничего не горит — сойдутся только птицы.

    + +
    +
    +

    Игра 9. ДЛМ — экзаменатор

    +

    Введите номер выбранного ответа. Лампы X, Y, Z покажут номер комментария.

    +

    1. Основные блоки ВМ? 000 — пульт, считыватель перфокарт, магнитофон, печатающее устройство; 001 — центральный блок (память и обработка), входные и выходные устройства.
    + 2. Как ВМ обрабатывает информацию? 010 — нужна программа вычислений; 011 — центральный блок сам решает любую задачу.
    + 3. В каком виде идёт обработка? 100 — в двоичном коде; 101 — на языке программирования.
    + 4. Почему ВМ и считает, и выполняет логические операции? 110 — она обрабатывает аналоговые данные; 111 — она построена на логических схемах, имитирующих алгебру Буля.

    +

    Комментарии: 000 — Да (алгебра Буля); 001 — Нет (нужна программа); 010 — Нет (обработка цифровая); 011 — Да (ВМ работает по программе); 100 — Да (двоичный код); 101 — Нет (это внешние устройства); 110 — Нет (язык программирования нужен для общения с машиной); 111 — Да (центральный блок и внешние устройства).

    + +
    +
    +

    Игра 10. Ваш характер

    +

    Четыре группы по три вопроса. В каждой группе ответьте «Да» или «Нет» переключателями А, Б, В и нажмите кнопку. Если горит Z, вставьте штеккер в правое гнездо планки А в столбце с номером группы (1–4). Когда все группы пройдены, вставьте штеккеры в правые гнёзда столбцов 1–4 планки Б, поставьте переключатели на 0 и нажмите кнопку.

    +

    I. Можешь ли ты говорить неправду? Миришься ли ты со своими недостатками? Легко ли ты изменяешь своё мнение?
    + II. Часто ли ты говоришь о недостатках других людей? Свободно ли ты чувствуешь себя в незнакомой компании? Доверяешь ли ты людям?
    + III. Нравится ли тебе, когда тебя хвалят? Доволен ли ты собой? Любишь ли ты говорить о себе?
    + IV. Доводишь ли ты начатое дело до конца? Настойчиво ли ты добиваешься своей цели? Проявляешь ли ты инициативу в работе?

    +

    Шестнадцать характеристик, от «0000 — замкнутый, скромный, целеустремлённый, но ленивый» до «1111 — деятельный, откровенный, но беспринципный и себялюбивый», приведены в полном тексте руководства.

    + +
    +
    +

    Игра 11. Автоматическое управление лифтом

    +

    А — направление до вызова (1 — вверх). Б — вызов вверх. В — вызов вниз.

    +

    X — дверь разблокирована. Y — мотор работает. Z — лифт поедет вверх. При двух вызовах сразу лифт сохраняет прежнее направление.

    + +
    +
    +
    Источник: «Игрушка Детская логическая машина ДЛМ. Руководство по эксплуатации». ВНИИ «Электронстандарт», Гатчина, 1987. Логические элементы взяты из статьи «Криптография и другие вычисления на детских логических машинах» (Хабр).
    +
    +
    +
    + + + + + diff --git a/post.md b/post.md new file mode 100644 index 0000000..53c3700 --- /dev/null +++ b/post.md @@ -0,0 +1,67 @@ +# Компьютер без электроники: оцифровано руководство к «Детской логической машине» 1987 года + +В конце 1980-х в советских магазинах продавалась игрушка «Детская логическая машина», ДЛМ. Выпускал её ВНИИ «Электронстандарт» в Гатчине. Это программируемое устройство, в котором нет ни транзистора, ни реле, ни микросхемы: только пластмассовые планки, штеккеры, пружинные контакты, три батарейки и четыре лампочки. И всё же машина отгадывает задуманное число, вычисляет честных и лгунов, играет со спичками и даже экзаменует по вычислительной технике. + +Руководство к ней в сети найти было невозможно. Были только описания игрушки, фото коробки и несколько снимков страниц в статье на Хабре. Полный экземпляр нашёлся у меня дома: сама машина давно потерялась, а брошюра уцелела. Теперь она отсканирована, набрана заново, и по ней сделан работающий эмулятор. + +**Скачать руководство (PDF, 69 стр.):** [ссылка на PDF] +**Эмулятор в браузере:** [ссылка на эмулятор] + +## Что это за машина + +На передней панели сверху четыре лампы: V, X, Y, Z. Над каждой стоит её «вес» в двоичной системе: 8, 4, 2, 1. Ниже три красные планки, по 14 гнёзд в каждой, и семь столбцов программирования. Справа кнопка и три поворотных переключателя А, Б, В с «весами» 4, 2, 1. + +В комплект входили 30 штеккеров, 7 перемычек, игральный кубик, три фишки, 12 карточек с птицами, зверями и насекомыми и три карточки с надписями. Питание — три элемента А-332 (4,5 В), потребляемый ток 200 мА, от одного комплекта батарей машина работала не меньше 80 часов. На коробке указан возраст: 13–15 лет. + +## Как она «думает» + +Самое интересное в ДЛМ — что вся её логика механическая. + +1. **Ввод.** Переключатель сдвигает свою планку на полшага гнезда: в положении «1» вправо, в «0» влево. В среднем положении планка отведена, и все её контакты разомкнуты. +2. **Программа.** Под каждым столбцом, под каждой планкой, внутри корпуса стоит пружинящая пластина, а по бокам от неё два неподвижных контакта. Когда планка уходит вправо (положение «1»), штеккер из левого гнезда отгибает пластину на правый контакт. Когда влево («0»), штеккер из правого гнезда отгибает её на левый. Нет штеккера в нужном гнезде — нет и контакта. Штеккер в левом гнезде значит «А», в правом — «не А», в обоих — «А не важно», ни одного — «столбец не работает никогда». +3. **И.** В каждом столбце три контакта соединены подряд, по одному на каждую планку. Ток проходит через столбец, только если замкнуты все три. +4. **ИЛИ.** Перемычками столбцы соединяют с лампами. Если к одной лампе подведено несколько столбцов, она загорается, когда сработал хотя бы один из них. +5. **Вывод.** Нажимаете кнопку — горят лампы. Ответ читается как двоичное число от 0 до 15. + +То есть машина одновременно вычисляет семь выражений вида «А и не Б и В» и складывает их по ИЛИ на четыре выхода. Говоря современным языком, это программируемая логическая матрица с тремя входами и четырьмя выходами, собранная из пластмассы и пружинок. + +В эмуляторе всё это видно: справа нарисован разрез машины. Честно оговорюсь: это реконструкция. В брошюре механизма нет, снимков вскрытой машины я не нашёл, так что рисунок сделан по брошюре («цепи разомкнуты в среднем положении планок») и по моей памяти. Повернёте переключатель — планка поедет, штеккеры нажмут контакты, а при нажатой кнопке видно, по каким столбцам и перемычкам идёт ток. + +## Одиннадцать игр + +1. **Какое число задумано?** Три вопроса — и машина называет число от 0 до 7. Вопросы хитрые, например: «К задуманному числу прибавьте 10 и разделите на 6. Остаток 4 или 5?» +2. **Честные и лгуны.** Классическая логическая задача про страну, где одни всегда говорят правду, а другие всегда лгут. +3. **Сумма трёх чисел.** Фокус с кубиком: машина «угадывает» сумму, потому что противоположные грани кубика в сумме всегда дают 7. +4. **Двенадцать — выигрыш!** Игра с кубиком против машины: кто первым наберёт ровно 12. +5. **Какой предмет выбран?** Угадывание, кому из трёх игроков досталась какая фишка, по числу оставшихся спичек. +6. **ДЛМ превосходит себя!** То же самое, но число спичек машине не сообщают. +7. **Семь спичек.** Беспроигрышная стратегия, если противник ходит первым. +8. **Зоологические карточки.** Предсказание того, как разложатся карточки. +9. **ДЛМ — экзаменатор.** Вопросы о вычислительной технике с комментариями машины. Там есть ответы в духе эпохи: «пульт управления, устройство считывания с перфокарт, магнитофон, печатающее устройство». +10. **Ваш характер.** Психологический тест из двенадцати вопросов. Здесь машину перепрограммируют прямо по ходу игры, по результатам каждой группы вопросов. +11. **Автоматическое управление лифтом.** Логика двери, мотора и направления движения. + +## Ошибки в оригинале + +Все 11 программ я перенёс в эмулятор точно по рисункам и проверил на всех комбинациях входов, а игру 4 ещё и решил полным перебором партий. Проверка лежит в репозитории, её можно запустить самому: `node check.mjs`. Игры 7 и 10 так проверить нельзя: в тексте мало примеров и нет полной таблицы ответов. Остальные работают ровно так, как написано в тексте, включая все примеры. А в двух нашлось кое-что любопытное. + +Рисунки при этом сверены со сканами гнездо за гнездом. Есть и независимая проверка: на фотографии настоящей ДЛМ из статьи на Хабре набран сумматор, все три переключателя стоят на «1», горят V и Z. Эмулятор на той же программе зажигает те же лампы. + +- **Игра 4.** Авторы честно предупреждают: «при достаточной практике Вы можете обыграть ДЛМ». Перебор всех партий показывает, где именно. Таких позиций четыре, и виновата не таблица ходов, а правило «если такой грани сбоку нет, берите меньшую, наиболее близкую». Самая обидная: сумма 6, сверху тройка. Машина советует 3, тройки сбоку нет, правило велит поставить 2, и выигрыш уходит противнику. А ведь сбоку лежит шестёрка, и она сразу даёт 12. +- **Игра 8.** Здесь ошибка в самой программе. Я перебрал все 34 650 раскладок карточек и сравнил, чем кончается игра, с тем, что показывает машина. В двух случаях из семи возможных она ошибается. Если на вопросы ответить «Да, Нет, Да», карточки всегда сходятся у птиц и зверей, то есть должна гореть Y, а не горит ничего. Если на все вопросы ответить «Нет», сойдутся только птицы, а машина зажигает Z и обещает, что «вероятно», сойдутся и остальные. Кстати, ответить «Да» на все три вопроса нельзя вообще: если внизу у «Насекомых» насекомое, а у «Зверей» зверь, птицы среди этих двух карточек быть не может. + +Кто знает, сколько советских школьников в 1988 году ломали голову, почему машина в «Зоологических карточках» иногда ошибается. + +Есть и опечатки попроще: на схеме панели третий переключатель подписан «Б-1» вместо «В-1», а в примере к игре 5 фишка достаётся «игроку № 8», хотя игроков всего трое. + +## Об экземпляре + +Брошюра 32 страницы, сдана в набор 17 февраля 1987 года, распространялась бесплатно, в комплекте с игрушкой. Ответственный редактор — Г. С. Стерин. Мой экземпляр сопровождал машину с заводским номером 005957, принятую ОТК в декабре 1987 года и проданную 23 февраля 1988-го. + +В PDF есть и сканы всех страниц, и набранный текст. Отдельным приложением приведена расшифровка всех рисунков программ, чтобы машину можно было запрограммировать, не разглядывая мелкие кружочки. + +## Благодарности + +Устройство машины изнутри впервые подробно разобрано в статье «Криптография и другие вычисления на детских логических машинах» на Хабре: https://habr.com/ru/articles/807187/. Оттуда же в эмулятор попали логические элементы: НЕ, И-НЕ, ИЛИ-НЕ, исключающее ИЛИ, сумматор и XOR-шифр. Руководство подтвердило выводы автора: левое гнездо действительно срабатывает при «1». + +Если у вас сохранилась своя ДЛМ, особенно с карточками, или есть фото её внутренностей, напишите. Хочется сделать эмулятор ещё точнее.