import { assertEquals, assertThrows } from "jsr:@std/assert";
import {
Command,
DIRPAD_FIRST_POS,
executeCommandsOnDirpadRobot,
executeCommandsOnNumpadRobot,
getDirpadNumber,
getNextDirpadRobotState,
getNextNumpadRobotState,
getNumpadNumber,
getPosFromDirpadNumber,
getPosFromNumpadNumber,
NUMPAD_FIRST_POS,
Pos,
shortestPathesOnDirpadRobot,
shortestPathesOnNumpadRobot,
solve_1,
} from "./solve_1.ts";
Deno.test("getNumbericKeypadNumber", () => {
assertEquals(getNumpadNumber([0, 0]), "7");
assertEquals(getNumpadNumber([1, 0]), "8");
assertEquals(getNumpadNumber([2, 0]), "9");
assertEquals(getNumpadNumber([0, 1]), "4");
assertEquals(getNumpadNumber([1, 1]), "5");
assertEquals(getNumpadNumber([2, 1]), "6");
assertEquals(getNumpadNumber([0, 2]), "1");
assertEquals(getNumpadNumber([1, 2]), "2");
assertEquals(getNumpadNumber([2, 2]), "3");
assertEquals(getNumpadNumber([0, 3]), " ");
assertEquals(getNumpadNumber([1, 3]), "0");
assertEquals(getNumpadNumber([2, 3]), "A");
});
Deno.test("getPosFromNumpadNumber", () => {
assertEquals(getPosFromNumpadNumber("7"), [0, 0]);
assertEquals(getPosFromNumpadNumber("8"), [1, 0]);
assertEquals(getPosFromNumpadNumber("9"), [2, 0]);
assertEquals(getPosFromNumpadNumber("4"), [0, 1]);
assertEquals(getPosFromNumpadNumber("5"), [1, 1]);
assertEquals(getPosFromNumpadNumber("6"), [2, 1]);
assertEquals(getPosFromNumpadNumber("1"), [0, 2]);
assertEquals(getPosFromNumpadNumber("2"), [1, 2]);
assertEquals(getPosFromNumpadNumber("3"), [2, 2]);
assertEquals(getPosFromNumpadNumber("0"), [1, 3]);
assertEquals(getPosFromNumpadNumber("A"), [2, 3]);
});
Deno.test("getNextKeypadRobotState", () => {
assertThrows(() => getNextNumpadRobotState({ pos: [0, 0] }, "^"));
assertEquals(getNextNumpadRobotState({ pos: [0, 0] }, "v"), {
pos: [0, 1],
});
assertThrows(() => getNextNumpadRobotState({ pos: [0, 0] }, "<"));
assertEquals(getNextNumpadRobotState({ pos: [0, 0] }, ">"), {
pos: [1, 0],
});
assertEquals(getNextNumpadRobotState({ pos: [0, 0] }, "A"), {
pos: [0, 0],
});
assertEquals(getNextNumpadRobotState({ pos: [1, 1] }, "^"), {
pos: [1, 0],
});
assertEquals(getNextNumpadRobotState({ pos: [1, 1] }, "v"), {
pos: [1, 2],
});
assertEquals(getNextNumpadRobotState({ pos: [1, 1] }, "<"), {
pos: [0, 1],
});
assertEquals(getNextNumpadRobotState({ pos: [1, 1] }, ">"), {
pos: [2, 1],
});
assertEquals(getNextNumpadRobotState({ pos: [1, 1] }, "A"), {
pos: [1, 1],
});
});
Deno.test("getDirKeypadNumber", () => {
assertEquals(getDirpadNumber([0, 0]), " ");
assertEquals(getDirpadNumber([1, 0]), "^");
assertEquals(getDirpadNumber([2, 0]), "A");
assertEquals(getDirpadNumber([0, 1]), "<");
assertEquals(getDirpadNumber([1, 1]), "v");
assertEquals(getDirpadNumber([2, 1]), ">");
});
Deno.test("getPosFromDirKeypadNumber", () => {
assertEquals(getPosFromDirpadNumber(" "), [0, 0]);
assertEquals(getPosFromDirpadNumber("^"), [1, 0]);
assertEquals(getPosFromDirpadNumber("A"), [2, 0]);
assertEquals(getPosFromDirpadNumber("<"), [0, 1]);
assertEquals(getPosFromDirpadNumber("v"), [1, 1]);
assertEquals(getPosFromDirpadNumber(">"), [2, 1]);
});
Deno.test("getNextDirKeypadRobotState", () => {
assertEquals(getNextDirpadRobotState({ pos: [1, 1] }, "^"), {
pos: [1, 0],
});
assertThrows(() => getNextDirpadRobotState({ pos: [1, 1] }, "v"));
assertEquals(getNextDirpadRobotState({ pos: [1, 1] }, "<"), {
pos: [0, 1],
});
assertEquals(getNextDirpadRobotState({ pos: [1, 1] }, ">"), {
pos: [2, 1],
});
assertEquals(getNextDirpadRobotState({ pos: [1, 1] }, "A"), {
pos: [1, 1],
});
});
Deno.test("executeCommandsOnNumpadRobot", () => {
const commands = [
"^^AvvvA".split("") as Command[],
"^AvvvA".split("") as Command[],
"AvvvA".split("") as Command[],
];
for (const command of commands) {
const out: string[] = [];
executeCommandsOnNumpadRobot(
{
pos: NUMPAD_FIRST_POS,
},
command,
(o) => {
out.push(o);
},
);
assertEquals(out, ["0", "2", "9", "A"]);
}
});
Deno.test("executeCommandsOnDirKeypadRobot", () => {
const input_result = [
[
">^AvAA<^A>A>^AvA^A^A^A>AAvA^AA>^AAAvA<^A>A"
.split("") as Command[],
"v<>^AAvA<^AA>A^A",
],
["v<>^AAvA<^AA>A^A".split("") as Command[], "^^AvvvA"],
] as const;
for (const [input, result] of input_result) {
const out: string[] = [];
executeCommandsOnDirpadRobot(
{
pos: DIRPAD_FIRST_POS,
},
input,
(o) => {
out.push(o);
},
);
assertEquals(out.join(""), result);
}
});
Deno.test("shortestPathesOnNumpadRobot", () => {
const testCase: {
pos: Pos;
target: string;
expect: string[][];
msg: string;
}[] = [
{
pos: NUMPAD_FIRST_POS,
target: "A",
expect: [[]],
msg: "should return empty array when target is same as pos",
},
{
pos: [0, 0],
target: "7",
expect: [[]],
msg: "should return empty array when target is same as pos",
},
{
pos: NUMPAD_FIRST_POS,
target: "9",
expect: [["^", "^", "^"]],
msg: "should return shortest path to target",
},
{
pos: [0, 0],
target: "5",
expect: [["v", ">"], [">", "v"]],
msg: "should return shortest path to target",
},
{
pos: [1, 3],
target: "1",
expect: [["^", "<"]],
msg: "should return shortest path to target",
},
];
for (const { pos, target, expect, msg } of testCase) {
assertEquals(shortestPathesOnNumpadRobot({ pos }, target), expect, msg);
}
});
Deno.test("shortestPathesOnDirpadRobot", () => {
const testCase: {
pos: Pos;
target: string;
expect: string[][];
msg: string;
}[] = [
{
pos: DIRPAD_FIRST_POS,
target: "A",
expect: [["A"]],
msg: "should return empty array when target is same as pos",
},
{
pos: [1, 0],
target: "^",
expect: [["A"]],
msg: "should return empty array when target is same as pos",
},
{
pos: DIRPAD_FIRST_POS,
target: ">",
expect: [["v", "A"]],
msg: "should return shortest path to target",
},
{
pos: [1, 0],
target: ">",
expect: [["v", ">", "A"], [">", "v", "A"]],
msg: "should return shortest path to target",
},
{
pos: [0, 1],
target: "^",
expect: [[">", "^", "A"]],
msg: "should return shortest path to target",
},
];
for (const { pos, target, expect, msg } of testCase) {
assertEquals(shortestPathesOnDirpadRobot({ pos }, target), expect, msg);
}
});
Deno.test("example test", () => {
const testCase: [string, string][] = [
[
"029A",
">^AvAA<^A>A>^AvA^A^A^A>AAvA^AA>^AAAvA<^A>A",
],
[
"980A",
">^AAAvA^A>^AvAA<^A>AA>^AAAvA<^A>A^AA",
],
[
"179A",
">^A>^AAvAA<^A>A>^AAvA^A^AAAA>^AAAvA<^A>A",
],
[
"456A",
">^AA>^AAvAA<^A>A^AA^AAA>^AAvA<^A>A",
],
[
"379A",
">^AvA^A>^AAvA<^A>AAvA^A^AAAA>^AAAvA<^A>A",
],
];
for (const [input, expect] of testCase) {
assertEquals(solve_1(input), expect.length);
}
});