Skip to content

Commit 800eadf

Browse files
authored
AoC day9 (#6)
* Start day9 puzzle * Add dummy tests. * Fix algorithm. Fix Tests. Implement base case. * Add more failing tests. * Implement partially combine function. * Implement getPermutations function. * Update algorithm. * Add tests for getDistance * Implement first 2 cases. * Implement getDistance, fix tests * Implement parseCityLine * Solve demo sample * Puzzle1, with error. * Solve puzzle1 * Solve puzzle2 (there is no reason to create second file)
1 parent 0fe0802 commit 800eadf

File tree

6 files changed

+406
-0
lines changed

6 files changed

+406
-0
lines changed

scripts/aoc2015/day9/input.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Faerun to Norrath = 129
2+
Faerun to Tristram = 58
3+
Faerun to AlphaCentauri = 13
4+
Faerun to Arbre = 24
5+
Faerun to Snowdin = 60
6+
Faerun to Tambi = 71
7+
Faerun to Straylight = 67
8+
Norrath to Tristram = 142
9+
Norrath to AlphaCentauri = 15
10+
Norrath to Arbre = 135
11+
Norrath to Snowdin = 75
12+
Norrath to Tambi = 82
13+
Norrath to Straylight = 54
14+
Tristram to AlphaCentauri = 118
15+
Tristram to Arbre = 122
16+
Tristram to Snowdin = 103
17+
Tristram to Tambi = 49
18+
Tristram to Straylight = 97
19+
AlphaCentauri to Arbre = 116
20+
AlphaCentauri to Snowdin = 12
21+
AlphaCentauri to Tambi = 18
22+
AlphaCentauri to Straylight = 91
23+
Arbre to Snowdin = 129
24+
Arbre to Tambi = 53
25+
Arbre to Straylight = 40
26+
Snowdin to Tambi = 15
27+
Snowdin to Straylight = 99
28+
Tambi to Straylight = 70

scripts/aoc2015/day9/puzzle1.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
-- Day 9: All in a Single Night ---
3+
Every year, Santa manages to deliver all of his presents in a single night.
4+
5+
This year, however, he has some new locations to visit;
6+
his elves have provided him the distances between every pair of locations.
7+
He can start and end at any two (different) locations he wants,
8+
but he must visit each location exactly once.
9+
What is the shortest distance he can travel to achieve this?
10+
11+
For example, given the following distances:
12+
13+
London to Dublin = 464
14+
London to Belfast = 518
15+
Dublin to Belfast = 141
16+
The possible routes are therefore:
17+
18+
Dublin -> London -> Belfast = 982
19+
London -> Dublin -> Belfast = 605
20+
London -> Belfast -> Dublin = 659
21+
Dublin -> Belfast -> London = 659
22+
Belfast -> Dublin -> London = 605
23+
Belfast -> London -> Dublin = 982
24+
25+
The shortest of these is London -> Dublin -> Belfast = 605, and so the answer is 605 in this example.
26+
27+
What is the distance of the shortest route?
28+
29+
Puzzle 2 is the longest distance
30+
31+
*/
32+
import { Cities, SimpleInputCities } from "./types.ts";
33+
import { getDistance, getPermutations, parseCityLine } from "./utils.ts";
34+
35+
function getProcessFile(cityValues: string[]) {
36+
return function processFile(text: string) {
37+
const lines = text.split("\n");
38+
const resolvedCombinations = new Map<string, number>();
39+
for (const line of lines) {
40+
// parse line by line
41+
const { cityALiteral, cityBLiteral, distance } = parseCityLine(line);
42+
if (cityALiteral && cityBLiteral) {
43+
// fill resolvedCombinations with initial data
44+
resolvedCombinations.set(cityALiteral + cityBLiteral, distance);
45+
} else {
46+
throw new Error("Unknown literals");
47+
}
48+
}
49+
// combine them with combine function. get list of combinations
50+
51+
const allPermutations = getPermutations(
52+
new Set(cityValues),
53+
);
54+
const allDistances = [];
55+
for (const permutation of allPermutations) {
56+
// for each combination, get distance, store it in array of distances
57+
const distance = getDistance(permutation.join(""), resolvedCombinations);
58+
allDistances.push(distance);
59+
}
60+
// find the smallest distance
61+
console.log("Min distance", Math.min(...allDistances));
62+
console.log("Max distance", Math.max(...allDistances));
63+
};
64+
}
65+
66+
// read file with cities and distances
67+
Deno.readTextFile("./simpleInput.txt").then(
68+
getProcessFile(Object.values(SimpleInputCities).map(String)),
69+
);
70+
Deno.readTextFile("./input.txt").then(
71+
getProcessFile(Object.values(Cities).map(String)),
72+
);

scripts/aoc2015/day9/simpleInput.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
London to Dublin = 464
2+
London to Belfast = 518
3+
Dublin to Belfast = 141

scripts/aoc2015/day9/types.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export enum SimpleInputCities {
2+
London = "A",
3+
Dublin = "B",
4+
Belfast = "C",
5+
}
6+
7+
export enum Cities {
8+
Faerun = "A",
9+
Norrath = "B",
10+
Tristram = "C",
11+
AlphaCentauri = "D",
12+
Arbre = "E",
13+
Snowdin = "F",
14+
Tambi = "G",
15+
Straylight = "H",
16+
}

scripts/aoc2015/day9/utils.test.ts

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { assertEquals, assertThrows } from "jsr:@std/assert@1";
2+
import { beforeEach, describe, it } from "@std/testing/bdd";
3+
import { combine, getDistance, parseCityLine } from "./utils.ts";
4+
5+
describe("combine", () => {
6+
describe('for set {"A"}', () => {
7+
const uncombinedValues = new Set(["A"]);
8+
it('Should return [["A"]] for empty currentArrays', function () {
9+
assertEquals(
10+
combine([[]], uncombinedValues),
11+
[["A"]],
12+
);
13+
});
14+
it('Should return [["X", "A"]] for currentArrays [["X"]]', function () {
15+
assertEquals(
16+
combine([["X"]], uncombinedValues),
17+
[["X", "A"]],
18+
);
19+
});
20+
it('Should add ["A"] to every array in currentArrays', function () {
21+
assertEquals(
22+
combine([["X", "Y"], ["Y", "X"]], uncombinedValues),
23+
[["X", "Y", "A"], ["Y", "X", "A"]],
24+
);
25+
});
26+
});
27+
28+
describe('for set {"A", "B"}', function () {
29+
const uncombinedValues = new Set(["A", "B"]);
30+
it('Should return result with arrays ["A", "B"], ["B", "A"] for empty currentArrays', function () {
31+
assertEquals(combine([[]], uncombinedValues), [
32+
["A", "B"],
33+
["B", "A"],
34+
]);
35+
});
36+
it('Should return result with arrays ["X", "A", "B"], ["X", "B", "A"] for currentArrays [["X"]]', function () {
37+
assertEquals(combine([["X"]], uncombinedValues), [
38+
["X", "A", "B"],
39+
["X", "B", "A"],
40+
]);
41+
});
42+
43+
it('Should add arrays ["A", "B"], ["B", "A"] to every array in currentArrays', function () {
44+
assertEquals(combine([["X", "Y"], ["Y", "X"]], uncombinedValues), [
45+
["X", "Y", "A", "B"],
46+
["X", "Y", "B", "A"],
47+
["Y", "X", "A", "B"],
48+
["Y", "X", "B", "A"],
49+
]);
50+
});
51+
});
52+
53+
describe('for set {"A", "B", "C"}', function () {
54+
const uncombinedValues = new Set(["A", "B", "C"]);
55+
it("Should return result with 6 arrays for empty currentArrays", function () {
56+
assertEquals(combine([[]], uncombinedValues), [
57+
["A", "B", "C"],
58+
["A", "C", "B"],
59+
["B", "A", "C"],
60+
["B", "C", "A"],
61+
["C", "A", "B"],
62+
["C", "B", "A"],
63+
]);
64+
});
65+
it('Should return result with 6 arrays for currentArrays ["X"]', function () {
66+
assertEquals(combine([["X"]], uncombinedValues), [
67+
["X", "A", "B", "C"],
68+
["X", "A", "C", "B"],
69+
["X", "B", "A", "C"],
70+
["X", "B", "C", "A"],
71+
["X", "C", "A", "B"],
72+
["X", "C", "B", "A"],
73+
]);
74+
});
75+
});
76+
});
77+
78+
describe("getDistance", function () {
79+
const resolvedCombinations = new Map<string, number>();
80+
beforeEach(() => {
81+
resolvedCombinations.clear();
82+
resolvedCombinations.set("AB", 1);
83+
resolvedCombinations.set("BC", 2);
84+
resolvedCombinations.set("CD", 3);
85+
resolvedCombinations.set("DE", 4);
86+
});
87+
it("Should throw error for unresolvable combination", function () {
88+
assertThrows(() => {
89+
getDistance("XY", resolvedCombinations);
90+
});
91+
});
92+
it("Should resolve AB combination", function () {
93+
assertEquals(getDistance("AB", resolvedCombinations), 1);
94+
});
95+
it("Should resolve BA combination", function () {
96+
assertEquals(getDistance("BA", resolvedCombinations), 1);
97+
assertEquals(resolvedCombinations.get("BA"), 1);
98+
});
99+
it("Should resolve ABC combination", function () {
100+
assertEquals(getDistance("ABC", resolvedCombinations), 3);
101+
assertEquals(resolvedCombinations.get("ABC"), 3);
102+
});
103+
it("Should resolve CBA combination", function () {
104+
assertEquals(getDistance("CBA", resolvedCombinations), 3);
105+
assertEquals(resolvedCombinations.get("CB"), 2);
106+
assertEquals(resolvedCombinations.get("BA"), 1);
107+
assertEquals(resolvedCombinations.get("CBA"), 3);
108+
});
109+
it("Should resolve ABCDE combination", function () {
110+
assertEquals(getDistance("ABCDE", resolvedCombinations), 10);
111+
assertEquals(resolvedCombinations.get("CDE"), 7);
112+
assertEquals(resolvedCombinations.get("BCDE"), 9);
113+
assertEquals(resolvedCombinations.get("ABCDE"), 10);
114+
});
115+
});
116+
117+
describe("parseCityLine", function () {
118+
it("Should throw error for invalid city line", function () {
119+
assertThrows(() => {
120+
parseCityLine("ascsdf");
121+
});
122+
});
123+
it("Should parse valid city line", function () {
124+
assertEquals(parseCityLine("London to Dublin = 464"), {
125+
cityALiteral: "A",
126+
cityBLiteral: "B",
127+
distance: 464,
128+
});
129+
});
130+
});

0 commit comments

Comments
 (0)