Крошечное приключение

14

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

Вызов

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

Правила игры

  • Мир всегда состоит из коридора с 10 смежными комнатами. В каждую комнату требуется ключ для входа, но в любой момент можно выйти без ключа (так что, думаю, это какой-то замок с защелкой);
  • Игрок начинает игру в комнате 0 и выигрывает, если он когда-либо входит в комнату 9 (как только он достигает комнаты 9, он может делать все, что ему нравится, включая переход в другую комнату, и он все равно выиграет);
  • Каждая комната может содержать любое количество предметов;
  • Существует до 26 предметов с именем AZ, и ни один предмет не появится в мире более одного раза;
  • Игрок может забрать предметы из текущей комнаты и поместить их в свой инвентарь (они также могут бросить предметы из своего инвентаря в текущую комнату);
  • Максимальный размер инвентаря игрока конечен, и ему будут предоставлены детали уровня;
  • В начале игры инвентарь игрока всегда пуст;
  • Максимальное количество предметов в комнате не ограничено (хотя неявное ограничение составляет 26, поскольку это общее количество предметов);
  • Пункты AJ - это ключи, которые можно использовать для входа в комнаты 0-9 (т. Е. Игрок может перейти в комнату 0, если у него есть пункт A, в комнату 1, если у них есть B и т. Д., Обратите внимание, что ключи не требуются, чтобы покинуть комнату, и игрок начинает игру в комнате 0, поэтому клавиша «А» требуется только в том случае, если игрок хочет вернуться в комнату 0);
  • Предметы в инвентаре игрока могут быть объединены для создания новых предметов (которые будут созданы в инвентаре игрока) - разрешенные комбинации будут предоставлены с деталями уровня;
  • Объединение предметов потребляет исходные предметы (т. Е. Если один из предметов был ключом, то больше нельзя будет использовать этот ключ);
  • Если игрок пытается сделать что-то невозможное (например, взять предмет, которого нет в текущей комнате / бросить предмет, которого у него нет / объединить предметы, которых у него нет / перейти в комнату, в которой нет ключа) ибо) ничего не происходит и они могут продолжаться;
  • Игрок никогда не даст бессмысленную команду (например, зайдите в комнату 11).

Так что простая игра может выглядеть так:

  v
+---+---+---+---+---+---+---+---+---+---+
| C |   | J |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+---+
|               CORRIDOR                |
+---------------------------------------+
Inventory capacity: 99

Комната 0 содержит пункт «С» (который является ключом к комнате 2). Комната 2 содержит пункт «J» (который является ключом к комнате 9). Игрок может выиграть игру, подняв C, перейдя в комнату 2, подняв J, а затем перейдя в комнату 9.

Более сложная игра может быть:

  v
+---+---+---+---+---+---+---+---+---+---+
| C |   | X |YZ |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+---+
|               CORRIDOR                |
+---------------------------------------+
Inventory capacity: 10
C+X => D
Y+Z => J

Теперь игрок может выиграть, подняв C, перейдя в комнату 2, подняв X, скомбинировав C с X, чтобы создать D, а затем переместившись в комнату 3. Теперь они могут собирать и комбинировать Y и Z, чтобы получить J, что позволяет им перейти в комнату 9.


Формат ввода

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

  • Начальное содержимое каждой комнаты (список из 0 или более предметов для каждой комнаты);
  • Коллекция разрешенных комбинаций элементов (каждая содержит 2 элемента ввода и их элемент вывода - обратите внимание, что элементы ввода неупорядочены);
  • Максимальный размер инвентаря (целое число, 0 <= размер <= 26);
  • Список команд, которые пытался выполнить игрок.

Команды игрока могут быть:

  • [P]ick up <item> - берет предмет из комнаты и кладет его в инвентарь игрока (если есть место)
  • [D]rop <item> - бросает предмет из инвентаря игрока в текущую комнату
  • [C]ombine <item1> <item2> - объединяет 2 предмета в инвентаре игрока, чтобы произвести новый предмет
  • [G]o to <room> - путешествует в выбранную комнату, если у игрока есть требуемый ключ

Например, формат ввода, который я использовал для тестирования, был простыми аргументами программы:

./adventure YZ '' '' '' '' '' '' '' '' ''  1 YZJ         2          PY PZ CYZ G9
#           r0 r1 r2 r3 r4 r5 r6 r7 r8 r9  combinations  inv. size  commands...
# means:
#  room 0 starts with items Y & Z, all other rooms start empty
#  1 combination is possible: Y+Z => J
#  max inventory size is 2
#  player commands are [P]ick up Y, [P]ick up Z, [C]ombine Y and Z, [G]o to room 9
#  (in this example, the player wins)

Но если какой-то другой формат облегчает задачу, это нормально (например, специальные символы-разделители / несколько строк / другой порядок / сериализация в JSON / и т. Д.)

Выходной формат

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

Тестовые случаи

Следующий скрипт bash предоставляет тестовый набор, который будет проверять большинство ситуаций. Он был написан для использования формата, описанного выше, но изменение его для использования другого формата - это всего лишь случай добавления преобразования в invokeфункцию.

#!/bin/sh

PROG="$1";

if [[ -z "$PROG" ]]; then
    echo "Usage: $0 <program-to-test>";
    exit 1;
fi;

function invoke {
    "$PROG" "$@"
}

RED="\033[1;31m";
GREEN="\033[1;32m";
RESET="\033[m";
FAILURES="0";

function pass {
    if ! invoke "$@" >/dev/null 2>&1; then
        echo "${RED}Expected pass, got fail:${RESET} $*" >&2;
        (( FAILURES = "$FAILURES" + 1 ));
        invoke "$@" 2>&1;
    fi;
}

function fail {
    if invoke "$@" >/dev/null 2>&1; then
        echo "${RED}Expected fail, got pass:${RESET} $*" >&2;
        (( FAILURES = "$FAILURES" + 1 ));
        invoke "$@" 2>&1;
    fi;
}

echo "Running tests...";

#    R0  R1  R2  R3  R4  R5  R6  R7  R8  R9  C      I  Cmd...
pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ G9;
fail ''  J   ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ G9;
pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ PJ G9;
fail J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ;
fail J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  G9;
pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  G9 PJ G9;
pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      1  PJ G9;
fail J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      0  PJ G9;
fail J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ DJ G9;
fail J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ PJ DJ G9;
pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ DJ PJ G9;
pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ DJ PJ G9;
pass B   CJ  ''  ''  ''  ''  ''  ''  ''  ''  0      2  PB G1 DB PC PJ G9;
fail B   CJ  ''  ''  ''  ''  ''  ''  ''  ''  0      2  PB G1 DB PB PC PJ G9;
pass AJ  ''  ''  ''  ''  ''  ''  ''  ''  ''  0      2  PA PJ G9;
pass B   D   ''  J   ''  ''  ''  ''  ''  ''  0      2  PB G1 PD G3 DB PJ G9;
fail B   D   ''  J   ''  ''  ''  ''  ''  ''  0      2  PB G1 PD G2 DB PJ G9;
fail B   D   ''  J   ''  ''  ''  ''  ''  ''  0      2  PB G1 PD G3 PJ G9;
fail B   D   J   C   ''  ''  ''  ''  ''  ''  0      2  PB G1 PD G3 PJ G9;
pass AJ  ''  ''  ''  ''  ''  ''  ''  ''  ''  0      2  PA PJ G9 G0;
fail ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      3  PA PD PJ G3 DJ G0 PJ G9;
pass ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      3  PA PD PJ G3 DJ G0 G3 PJ G9;
fail ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      3  PA PD PJ G3 DJ G0 DD G3 PJ G9;
pass ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      3  PA PD PJ DD G3 DJ G0 DD G3 PJ G9;
fail ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      1  PA DA DA PD PJ G9;
pass ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      1  PA DA DA PJ G9;
fail ABCDEFGHIKLMNOPQRSTUVWXYZ  J  '' '' '' '' '' '' '' '' 0 26 PA PB PC PD PE PF PG PH PI PJ PK PL PM PN PO PP PQ PR PS PT PU PV PW PX PY PZ G9;
pass ABCDEFGHIJKLMNOPQRSTUVWXYZ '' '' '' '' '' '' '' '' '' 0 26 PA PB PC PD PE PF PG PH PI PJ PK PL PM PN PO PP PQ PR PS PT PU PV PW PX PY PZ G9;
fail YZJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      2  PY PZ CYZ PJ G9;
pass YZJ ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZW  2  PY PZ CYZ PJ G9;
pass YZJ ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZW  2  PY PZ CYZ PJ CWJ G9;
fail XYZJ '' ''  ''  ''  ''  ''  ''  ''  ''  1 YZW  2  PY PZ CYZ PX PJ G9;
fail XYZJ '' ''  ''  ''  ''  ''  ''  ''  ''  1 YZW  2  PY PZ CYZ PX DY DZ PJ G9;
pass XYZJ '' ''  ''  ''  ''  ''  ''  ''  ''  1 YZW  2  PY PZ CYZ PX DW PJ G9;
pass YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  CYZ G9;
pass YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CYZ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CYZ DJ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CYZ DJ PY PZ CYZ G9;
fail WZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PW PZ CYZ G9;
fail WZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CYZ G9;
pass YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CZY G9;
pass YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 ZYJ  2  PY PZ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  1  PY PZ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  1  PY PZ CYZ PY PZ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  1  PY PZ CYZ PJ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  1  PJ G9;
pass BW  UV  ''  ''  ''  ''  ''  ''  ''  ''  3 BUR WVS RSJ  2  PB PW G1 DW PU CBU DR PW PV CVW PR CRS G9;
fail BW  AUV ''  ''  ''  ''  ''  ''  ''  ''  3 BUR WVS RSJ  2  PB G1 PU CBU DR PA PB G0 DA PW G1 PV CVW PR CRS G9;
pass BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PC PA PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW UV  ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PC PA PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU PA PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PA G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PA PB G0 DA G1 DB PV CVW PR CRS G9;
fail BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PA PB G0 DA PW G1 DB CVW PR CRS G9;
pass BFK LG  M   N   O   CDE PQR U   W   ''  10 BPT CQS TSH HUI IWV VFA GRX MXZ ANY YZJ  5 \
  PB PF PK G1 PL PG G6 DB DK DL G5 PC PD PE G6 DF G2 PM G6 DM DC G3 PN G4 PO G6 DN DO DD DE \
  PB PP CBP PC PQ CCQ CTS G7 PU CUH G8 PW CWI G6 PF CVF PR PM PN CGR CMX CAN CYZ G9
fail BFK LG  M   N   O   CDE PQR U   W   ''  10 BPT CQS TSH HUI IWV VFA GRX MXZ ANY YZJ  5 \
  PB PF PK G1 PL PG G6 DB DK DL G5 PC PD PE G6 DF G6 DM DC G3 PN G4 PO PM G6 DN DO DD DE \
  PB PP CBP PC PQ CCQ CTS G7 PU CUH G8 PW CWI G6 PF CVF PR PM PN CGR CMX CAN CYZ G9

if (( "$FAILURES" == "0" )); then
    echo "${GREEN}All tests passed${RESET}";
else
    echo "${RED}Total failures: $FAILURES${RESET}";
fi;

выигрыш

Стандартный код гольфа: выигрывает самый короткий код (в байтах). Записи должны соответствовать правилам игры, что на практике означает, что они должны пройти все тестовые случаи (при необходимости может быть добавлено больше тестов).

Дейв
источник
Вы можете не верить мне, но я подумал о вызове, который почти такой же, как этот, несколько дней назад ...
Акролит
Мне нравится этот вызов. Тем не менее, я бы определенно включил тестовые случаи вне вашего тестового сценария
Натан Меррилл
@NathanMerrill может сделать, какой формат вы бы предпочли? (тестовые случаи внутри скрипта уже довольно легко анализировать, поэтому я не был уверен, что нужно сделать, чтобы создать тестовую таблицу, не повторяя одни и те же строки!)
Дейв
@daHugLenny Я тоже получил идею несколько дней назад. Я предполагаю, что возможно мы оба были вдохновлены какой-то проблемой, опубликованной на прошлой неделе, или другим вопросом в сети. Я не могу вспомнить, откуда у меня появилась идея.
Дейв
Удаление предмета, которого у пользователя нет. Это невозможно (без оп) или глупость (не произойдет). И бросить несуществующий предмет?
edc65

Ответы:

5

JavaScript (ES6), 244 249 267 280

Редактировать Сохранено 18 (!) Байт thx @Neil

Функция с входом:

  • r = содержимое комнаты (массив из 10 строк)
  • k = комбинации (массив из 3 символов - источник1, источник2, результат)
  • s = максимальный размер инвентаря (число)
  • c = команды (массив строк)

Возвращает истину или ложь

(r,k,s,c,p=0,j={})=>c.some(([c,a,b])=>c<'D'?j[a]>0&j[b]>0&&!k.map(([t,u,v])=>u+t==a+b|u+t==b+a?j[j[a]=j[b]=v]=++s:0):c<'G'?j[a]>0&&!(j[++s,a]=~p):c>'G'?s&&j[a]==~p&&!(j[a]=s--):j['ABCDEFGHIJ'[a]]>0&&(p=a)>8,r.map((o,n)=>[...o].map(c=>j[c]=~n)))

Смотрите тестовый фрагмент ниже для новой версии, разделенной

Тестовое задание

Exec=
(r,k,s,c,p=0,j={})=>
c.some(
  ([c,a,b])=>
   c<'D'?j[a]>0&j[b]>0&&!k.map(([t,u,v])=>u+t==a+b|u+t==b+a?j[j[a]=j[b]=v]=++s:0)
   :c<'G'?j[a]>0&&!(j[++s,a]=~p)
   :c>'G'?s&&j[a]==~p&&!(j[a]=s--)
   :j['ABCDEFGHIJ'[a]]>0&&(p=a)>8
  ,r.map((o,n)=>[...o].map(c=>j[c]=~n))
)

console.log = (...x) => O.textContent += x + '\n';

;`pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ G9;
fail ''  J   ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ G9;
pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ PJ G9;
fail J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ;
fail J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  G9;
pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  G9 PJ G9;
pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      1  PJ G9;
fail J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      0  PJ G9;
fail J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ DJ G9;
fail J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ PJ DJ G9;
pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ DJ PJ G9;
pass J   ''  ''  ''  ''  ''  ''  ''  ''  ''  0      9  PJ DJ PJ G9;
pass B   CJ  ''  ''  ''  ''  ''  ''  ''  ''  0      2  PB G1 DB PC PJ G9;
fail B   CJ  ''  ''  ''  ''  ''  ''  ''  ''  0      2  PB G1 DB PB PC PJ G9;
pass AJ  ''  ''  ''  ''  ''  ''  ''  ''  ''  0      2  PA PJ G9;
pass B   D   ''  J   ''  ''  ''  ''  ''  ''  0      2  PB G1 PD G3 DB PJ G9;
fail B   D   ''  J   ''  ''  ''  ''  ''  ''  0      2  PB G1 PD G2 DB PJ G9;
fail B   D   ''  J   ''  ''  ''  ''  ''  ''  0      2  PB G1 PD G3 PJ G9;
fail B   D   J   C   ''  ''  ''  ''  ''  ''  0      2  PB G1 PD G3 PJ G9;
pass AJ  ''  ''  ''  ''  ''  ''  ''  ''  ''  0      2  PA PJ G9 G0;
fail ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      3  PA PD PJ G3 DJ G0 PJ G9;
pass ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      3  PA PD PJ G3 DJ G0 G3 PJ G9;
fail ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      3  PA PD PJ G3 DJ G0 DD G3 PJ G9;
pass ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      3  PA PD PJ DD G3 DJ G0 DD G3 PJ G9;
fail ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      1  PA DA DA PD PJ G9;
pass ADJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      1  PA DA DA PJ G9;
fail ABCDEFGHIKLMNOPQRSTUVWXYZ  J  '' '' '' '' '' '' '' '' 0 26 PA PB PC PD PE PF PG PH PI PJ PK PL PM PN PO PP PQ PR PS PT PU PV PW PX PY PZ G9;
pass ABCDEFGHIJKLMNOPQRSTUVWXYZ '' '' '' '' '' '' '' '' '' 0 26 PA PB PC PD PE PF PG PH PI PJ PK PL PM PN PO PP PQ PR PS PT PU PV PW PX PY PZ G9;
fail YZJ ''  ''  ''  ''  ''  ''  ''  ''  ''  0      2  PY PZ CYZ PJ G9;
pass YZJ ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZW  2  PY PZ CYZ PJ G9;
pass YZJ ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZW  2  PY PZ CYZ PJ CWJ G9;
fail XYZJ '' ''  ''  ''  ''  ''  ''  ''  ''  1 YZW  2  PY PZ CYZ PX PJ G9;
fail XYZJ '' ''  ''  ''  ''  ''  ''  ''  ''  1 YZW  2  PY PZ CYZ PX DY DZ PJ G9;
pass XYZJ '' ''  ''  ''  ''  ''  ''  ''  ''  1 YZW  2  PY PZ CYZ PX DW PJ G9;
pass YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  CYZ G9;
pass YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CYZ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CYZ DJ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CYZ DJ PY PZ CYZ G9;
fail WZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PW PZ CYZ G9;
fail WZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CYZ G9;
pass YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  2  PY PZ CZY G9;
pass YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 ZYJ  2  PY PZ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  1  PY PZ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  1  PY PZ CYZ PY PZ CYZ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  1  PY PZ CYZ PJ G9;
fail YZ  ''  ''  ''  ''  ''  ''  ''  ''  ''  1 YZJ  1  PJ G9;
pass BW  UV  ''  ''  ''  ''  ''  ''  ''  ''  3 BUR WVS RSJ  2  PB PW G1 DW PU CBU DR PW PV CVW PR CRS G9;
fail BW  AUV ''  ''  ''  ''  ''  ''  ''  ''  3 BUR WVS RSJ  2  PB G1 PU CBU DR PA PB G0 DA PW G1 PV CVW PR CRS G9;
pass BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PC PA PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW UV  ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PC PA PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU PA PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PA G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PA PB G0 DA G1 DB PV CVW PR CRS G9;
fail BCW AUV ''  ''  ''  ''  ''  ''  ''  ''  3 CUR WVS RSJ  2  PB PC G1 DB PU CCU DR PA PB G0 DA PW G1 DB CVW PR CRS G9;
pass BFK LG  M   N   O   CDE PQR U   W   ''  10 BPT CQS TSH HUI IWV VFA GRX MXZ ANY YZJ 5 PB PF PK G1 PL PG G6 DB DK DL G5 PC PD PE G6 DF G2 PM G6 DM DC G3 PN G4 PO G6 DN DO DD DE PB PP CBP PC PQ CCQ CTS G7 PU CUH G8 PW CWI G6 PF CVF PR PM PN CGR CMX CAN CYZ G9
fail BFK LG  M   N   O   CDE PQR U   W   ''  10 BPT CQS TSH HUI IWV VFA GRX MXZ ANY YZJ 5 PB PF PK G1 PL PG G6 DB DK DL G5 PC PD PE G6 DF G6 DM DC G3 PN G4 PO PM G6 DN DO DD DE PB PP CBP PC PQ CCQ CTS G7 PU CUH G8 PW CWI G6 PF CVF PR PM PN CGR CMX CAN CYZ G9`
.split(/;*\n/).map((srow,i)=>{
  var row=srow.split(/\s+/),
  rooms=row.slice(1,11).map(x=>x=="''"?"":x),
  ncomb=+row[11],
  comb=row.slice(12,12+ncomb),
  isize=+row[12+ncomb],
  commands=row.slice(13+ncomb),
  start='['+rooms+'] ['+comb+'] '+isize+' ['+commands+']';
  var result=Exec(rooms,comb,isize,commands),
     ok = row[0] == ['fail','pass'][~~result]
  console.log(i, ok ? 'ok':'ko', start, row[0], result)
})
<pre id=O></pre>

edc65
источник
Хорошее (а) использование .map!
Дейв
Почему a>8внутри ()с? Может j[--s,a]=1стать j[a]=s--? Кроме того, String.fromCharCodeэто слишком долго, почему бы просто не индексировать в "ABCDEFGHIJ"?
Нил
@ Нил спасибо за подсказки, я проверю их все. Очевидно, это результат серии изменений (в какой-то момент мне нужно, чтобы j [] было ровно 1, но теперь, вероятно, они могут иметь любое положительное значение)
edc65
3

C, 338 байтов

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

#define P c[(i<j?i:j)*25+i+j]
#define F for(q=atoi(*++v);r
#define X c[r*91+i]
r,i,j,c[2405];main(q,v)char**v;{for(r=10;--r;)for(++v;i=**v;++*v)++X;++v;F<q;++r)i=**++v,j=1[*v],P=2[*v];r=9;F&&*++v;c[i=1[*v]]&&j==68?c[i]=!++X,++q:j>79&&q*X?c[i]=!--X,--q:j==71&&c[i+17]?r=57-i:j<68&&c[i]*c[j=2[*v]]&&P?c[i]=c[j]=0,c[P]=++q:0)j=**v;return r;}

Это использует несколько приемов для экономии места:

  • Номера загружаются в обратном порядке, поэтому проверка номера 9 становится проверкой номера 0, что дешевле
  • Содержание комнаты 9 никогда не имеет значения, поэтому оно пропускается при чтении входных данных и вместо этого используется для хранения инвентаря
  • Содержимое комнаты и комбинации предметов хранятся в одном массиве. Поскольку элементы хранятся в своих значениях ascii, они никогда не перекрываются.

Сломать:

#define P c[(i<j?i:j)*25+i+j]       // item combination lookup (input: i,j)
#define X c[r*91+i]                 // room item lookup (input: r,i)
r,i,j,c[2405];                      // globals default to 0
main(q,v)char**v;{                  // K&R syntax to save bytes
    for(r=10;--r;)                  // Load rooms 0-8, store as 9-1
        for(++v;i=**v;++*v)
            ++X;
    ++v;                            // Skip room 9
    for(q=atoi(*++v);r<q;++r)       // For each combination
        i=**++v,
        j=1[*v],                    // Use index[array] syntax to avoid (brackets)
        P=2[*v];                    // Record combination
    r=9;                            // Begin in room 0 (9 in memory)
    for(q=atoi(*++v);               // Load inventory size
                     r              // While not in room 9 (0 in memory)...
                      &&*++v;       // ...and still have user commands
                                    // (ISO C promises a NULL at the end of argv)
        c[i=1[*v]]&&j==68?          // If 'D'rop, and we have the item:
            c[i]=!++X,              //  Drop it
            ++q:                    //  Increase our inventory capacity
        j>79&&                      // If 'P'ick up, and...
              q                     // ...we have capacity in our inventory and...
               *X?                  // ...the item is in the room:
            c[i]=!--X,              //  Pick it up
            --q:                    //  Decrease our inventory capacity
        j==71&&c[i+17]?             // If 'G'o to room, and we have the key:
            r=57-i:                 //  Go to the room
        j<68&&                      // If 'C'ombine, and...
              c[i]*c[j=2[*v]]       // ...we have the items and...
                             &&P?   // ...they can be combined
            c[i]=c[j]=0,            //  Remove the items
            c[P]=++q:               //  Add the combined item and increase capacity
        0                           // Unrecognised or invalid command
    )
        j=**v;                      // 'j' is the command letter (happens first)
    return r;                       // Return the final room (0 = truthy in shell)
}

Частично вдохновлен ответом @ edc65.


Я был так близок к получению ;*++*v;и c[P][c]в код конечной путаницы, но , к сожалению , другие варианты оказались короче :(

Дейв
источник
2

Haskell, 354 325 323 байта

(#)=elem
(#)=elem
(%)=filter.(/=)
m!s=g""0.zip[0..]where g _ p _[]=p>8;g i p r(c:d)|p>8=1<2|'P':[k]<-c,k#x,length i<s=g(k:i)p((p,k%x):r)d|'D':[k]<-c,k#i=g(k%i)p((p,k:x):r)d|'C':q@[k,l]<-c,k#i,l#i,[y]<-[f|[d,e,f]<-m,q==[d,e]||q==[e,d]]=g(y:k%(l%i))p r d|'G':n<-c,y<-read n,['A'..]!!y#i=g i y r d|1<2=g i p r d where Just x=lookup p r

Определяет функцию, !которая принимает в порядке

  • возможные комбинации в виде списка из 3 буквенных строк
  • максимальный размер инвентаря
  • номера в виде списка из 9 строк
  • игрок команды в виде списка строк

Возвращает Trueили False. Пример вызова:

*Main> (!) ["YZW"] 2 ["YZJ","","","","","","","","",""] ["PY","PZ","CYZ","PJ","CWJ","G9"]
True

Все тестовые случаи .

Многие байты расходуются на перенос состояния игры. Haskell не может деструктивно обновлять структуры данных, такие как комнаты и инвентарь.

Работа выполняется функцией, gкоторая принимает 4 параметра: инвентарь (строка), текущая комната (целое число), комнаты (ассоциативный список, с ключом: номер комнаты и значение: предметы) и оставленные команды (список строки) ,

g _ p _[] = p>8                     -- base case. if no commands left, return
                                    -- True if we are in room 9
g i p r(c:d)
  | p>8 =   1<2                     -- reached room 9
  | 'P':[k]<-c,                     -- 'Pickup', if
        k#x,                        --   key is in room and
        length i<s                  --   inventory not full
        = g(k:i)p((p,k%x):r)d       --   adjust inventory and room
  | 'D':[k]<-c,                     -- 'Drop', if
        k#i                         --   key is in inventory
        = g(k%i)p((p,k:x):r)d       --   adjust inventory and room
  | 'C':q@[k,l]<-c,                 -- 'Combine', if
        k#i,l#i,                    --   both keys are in inventory and
        [y]<-[f|[d,e,f]<-m,q==[d,e]||q==[e,d]]
                                    --   combination is possible
        = g(y:k%(l%i))p r d         --   adjust inventory
  | 'G':n<-c, y<-read[n],           -- 'Goto', convert digit to integer  
        ['A'..]!!y#i                --   key for room is in inventory
        = g i y r t                 --   go to room
  | 1<2                             -- impossible command
        = g i p r d                 --   ignore it

Может быть, следующие вещи могут сохранить некоторые байты

  • Государственная Монада для игры State
  • Единый Assoc-List для ключей (ключ: буква ключа, значение: номер комнаты с -1инвентарем) вместо номеров / инвентаря Нет, создание такого начального Assoc-List и проверка на максимальный размер инвентаря стоит больше, чем экономит средства с одним меньшим параметром.
Ними
источник
Ницца. Я не знаю достаточно Haskell для проверки, но вы можете сэкономить несколько байтов, увеличивая / уменьшая sпри изменении инвентаря, чтобы избежать необходимости проверять length i( sвместо этого вы можете проверить против 0)
Дейв
@ Дэйв: я не думаю, что это окупается, потому что изменение sсделало бы это пятым параметром, gи это должно было бы быть передано. У меня 5 рекурсивных вызовов g, дополнительный параметр стоит как минимум 6 байтов.
Ними
1

Python 3, 321 311 байт

-10, спасибо Дейв

S,F=set,frozenset
def f(r,c,i,m):
 w,v,r,c=0,S(),list(map(S,r)),{F(k):S(x)for*k,x in c}
 for a,*q in m:
  p=F(q)
  if a<'D'and p in c and p<=v:v-=p;v|=c[p]
  elif a=='D'and p<=v:r[w]|=p;v-=p
  elif a=='G'and F(chr(65+int(q[0])))<=v:w=int(q[0])
  elif a>'G'and p<=r[w]and len(v)<i:r[w]-=p;v|=p
  if w==9:return 1

Комнаты (r), комбинации (c) и ходы (m) - все это списки строк. Макс инвентарь (я) является инт.

Довольно прямолинейная реализация. Использовал set () для содержимого комнаты и инвентаря, чтобы упростить обновление. Использовал frozensets для ввода словаря комбинаций, так что порядок 2 элементов ввода не имеет значения.

RootTwo
источник
Здорово. Проверено на тестовом наборе с этим: import sys;r=sys.argv[1:11];nc=int(sys.argv[11]);c=sys.argv[12:12+nc];i=int(sys.argv[12+nc]);m=sys.argv[13+nc:];exit(not f(r,c,i,m))(точки с запятой -> переводы строки). Кстати, похоже, что вы оставили ,dbg=Falseтам; Вы можете сохранить 10 байтов, удалив его!
Дейв