Merge branch '2022-14'
This commit is contained in:
commit
f745366e8b
@ -3,14 +3,14 @@ import Victor from "@a-robu/victor";
|
|||||||
|
|
||||||
import { readFile } from "../05/part1.js";
|
import { readFile } from "../05/part1.js";
|
||||||
|
|
||||||
const V = (x,y) => new Victor(x,y);
|
const V = (x, y) => new Victor(x, y);
|
||||||
|
|
||||||
const readInput = (...args) =>
|
const readInput = (...args) =>
|
||||||
R.pipe(
|
R.pipe(
|
||||||
readFile(...args),
|
readFile(...args),
|
||||||
(lines) => lines.split("\n"),
|
(lines) => lines.split("\n"),
|
||||||
R.compact, // remove last line
|
R.compact, // remove last line
|
||||||
R.map((line) => line.split("").map( c => c ==='S' ? '`' : c === 'E' ? '{' : c ))
|
R.map((l) => l.split(""))
|
||||||
);
|
);
|
||||||
|
|
||||||
export const puzzleInput = readInput(import.meta.url, "input");
|
export const puzzleInput = readInput(import.meta.url, "input");
|
||||||
@ -19,76 +19,81 @@ export const sample = readInput(import.meta.url, "sample");
|
|||||||
export const findStart = (topoMap) => {
|
export const findStart = (topoMap) => {
|
||||||
let y;
|
let y;
|
||||||
let x = R.findIndex(topoMap, (row) => {
|
let x = R.findIndex(topoMap, (row) => {
|
||||||
let z = row.indexOf("`");
|
let z = row.indexOf("S");
|
||||||
if (z === -1) return false;
|
if (z === -1) return false;
|
||||||
y = z;
|
y = z;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
return V(x,y);
|
return V(x, y);
|
||||||
};
|
};
|
||||||
|
|
||||||
const directions = [ [0,1], [0,-1],[1,0],[-1,0] ].map(
|
export const findEnd = (topoMap) => {
|
||||||
d => V(...d)
|
let y;
|
||||||
);
|
let x = R.findIndex(topoMap, (row) => {
|
||||||
|
let z = row.indexOf("E");
|
||||||
|
if (z === -1) return false;
|
||||||
|
y = z;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return V(x, y);
|
||||||
|
};
|
||||||
|
|
||||||
const outOfMap = (maxX,maxY) => (loc) => {
|
const directions = [
|
||||||
if( Math.min( loc.x, loc.y ) < 0 ) return true;
|
[0, 1],
|
||||||
if( loc.x >= maxX ) return true;
|
[0, -1],
|
||||||
if( loc.y >= maxY ) return true;
|
[1, 0],
|
||||||
|
[-1, 0],
|
||||||
|
].map((d) => V(...d));
|
||||||
|
|
||||||
|
const outOfMap = (maxX, maxY) => (loc) => {
|
||||||
|
if (Math.min(loc.x, loc.y) < 0) return true;
|
||||||
|
if (loc.x >= maxX) return true;
|
||||||
|
if (loc.y >= maxY) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
const isReachable = (topoMap,pos) => {
|
const isReachable = (topoMap, pos) => {
|
||||||
const baseline = topoMap[pos.x][pos.y].charCodeAt(0);
|
const baseline = topoMap[pos.x][pos.y].charCodeAt(0);
|
||||||
|
|
||||||
return (next) => {
|
return (next) => {
|
||||||
return [0,1].includes(
|
return topoMap[next.x][next.y].charCodeAt(0) - baseline <= 1;
|
||||||
topoMap[next.x][next.y].charCodeAt(0) - baseline
|
};
|
||||||
)
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function findShortestPath(topoMap) {
|
function findShortestPath(topoMap) {
|
||||||
|
|
||||||
const initial = findStart(topoMap);
|
const initial = findStart(topoMap);
|
||||||
initial.steps = 0;
|
initial.steps = 0;
|
||||||
initial.beenThere = [];
|
const final = findEnd(topoMap);
|
||||||
|
|
||||||
const potentials = [ initial ];
|
topoMap = topoMap.map((line) =>
|
||||||
|
line.map((c) => c.replace("S", "a").replace("E", "z"))
|
||||||
|
);
|
||||||
|
|
||||||
let bestSoFar;
|
const potentials = [initial];
|
||||||
|
|
||||||
const oom = outOfMap(topoMap.length,topoMap[0].length );
|
const beenThere = topoMap.map((line) => line.map(() => 9999));
|
||||||
|
|
||||||
let failsafe = 100000;
|
const oom = outOfMap(topoMap.length, topoMap[0].length);
|
||||||
while( potentials.length > 0 ) {
|
|
||||||
|
let failsafe = 10; //topoMap.length*topoMap[0].length ;
|
||||||
|
while (potentials.length > 0) {
|
||||||
// if(! failsafe--) return;
|
// if(! failsafe--) return;
|
||||||
const pos = potentials.pop(); // depth-first
|
const pos = potentials.shift(); // depth-first
|
||||||
//console.log(pos.steps, bestSoFar);
|
|
||||||
|
|
||||||
if( bestSoFar && (bestSoFar <= pos.steps) ) continue;
|
if (beenThere[pos.x][pos.y] <= pos.steps) continue;
|
||||||
|
beenThere[pos.x][pos.y] = pos.steps;
|
||||||
|
|
||||||
if( topoMap[pos.x][pos.y] === '{' ) {
|
const next = directions
|
||||||
bestSoFar = pos.steps;
|
.map((d) => d.clone().add(pos))
|
||||||
continue;
|
.filter(R.isNot(oom))
|
||||||
}
|
.filter(isReachable(topoMap, pos));
|
||||||
|
|
||||||
const next = directions.map(
|
next.forEach((n) => (n.steps = pos.steps + 1));
|
||||||
d => d.clone().add(pos)
|
|
||||||
).filter( R.isNot(oom ))
|
|
||||||
.filter( isReachable(topoMap,pos) )
|
|
||||||
.filter( next => !pos.beenThere.includes( next.toArray().join(',') ) );
|
|
||||||
|
|
||||||
next.forEach( n => n.steps = pos.steps + 1 );
|
|
||||||
next.forEach( n => n.beenThere = [
|
|
||||||
...pos.beenThere, pos.toArray().join(',')
|
|
||||||
] );
|
|
||||||
|
|
||||||
potentials.push(...next);
|
potentials.push(...next);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bestSoFar;
|
return beenThere[final.x][final.y];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default findShortestPath;
|
export default findShortestPath;
|
||||||
|
@ -1,4 +1,94 @@
|
|||||||
import * as R from "remeda";
|
import * as R from "remeda";
|
||||||
|
import Victor from "@a-robu/victor";
|
||||||
|
|
||||||
|
import { readFile } from "../05/part1.js";
|
||||||
|
|
||||||
export default () => {};
|
const V = (x, y) => new Victor(x, y);
|
||||||
|
|
||||||
|
export const findAs = (topoMap) => {
|
||||||
|
const locations = [];
|
||||||
|
|
||||||
|
topoMap.forEach((line, x) =>
|
||||||
|
line.forEach((v, y) => {
|
||||||
|
if (v === "a") locations.push([x, y]);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return locations;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const findEnd = (topoMap) => {
|
||||||
|
let y;
|
||||||
|
let x = R.findIndex(topoMap, (row) => {
|
||||||
|
let z = row.indexOf("E");
|
||||||
|
if (z === -1) return false;
|
||||||
|
y = z;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return V(x, y);
|
||||||
|
};
|
||||||
|
|
||||||
|
const directions = [
|
||||||
|
[0, 1],
|
||||||
|
[0, -1],
|
||||||
|
[1, 0],
|
||||||
|
[-1, 0],
|
||||||
|
].map((d) => V(...d));
|
||||||
|
|
||||||
|
const outOfMap = (maxX, maxY) => (loc) => {
|
||||||
|
if (Math.min(loc.x, loc.y) < 0) return true;
|
||||||
|
if (loc.x >= maxX) return true;
|
||||||
|
if (loc.y >= maxY) return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isReachable = (topoMap, pos) => {
|
||||||
|
const baseline = topoMap[pos.x][pos.y].charCodeAt(0);
|
||||||
|
|
||||||
|
return (next) => {
|
||||||
|
return baseline - topoMap[next.x][next.y].charCodeAt(0) <= 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function findShortestPath(topoMap) {
|
||||||
|
const final = findEnd(topoMap);
|
||||||
|
final.steps = 0;
|
||||||
|
|
||||||
|
topoMap = topoMap.map((line) =>
|
||||||
|
line.map((c) => c.replace("S", "a").replace("E", "z"))
|
||||||
|
);
|
||||||
|
|
||||||
|
const initial = findAs(topoMap);
|
||||||
|
|
||||||
|
const potentials = [final];
|
||||||
|
|
||||||
|
const beenThere = topoMap.map((line) => line.map(() => 9999));
|
||||||
|
|
||||||
|
const oom = outOfMap(topoMap.length, topoMap[0].length);
|
||||||
|
|
||||||
|
let failsafe = 10; //topoMap.length*topoMap[0].length ;
|
||||||
|
while (potentials.length > 0) {
|
||||||
|
// if(! failsafe--) return;
|
||||||
|
const pos = potentials.shift(); // depth-first
|
||||||
|
|
||||||
|
if (beenThere[pos.x][pos.y] <= pos.steps) continue;
|
||||||
|
beenThere[pos.x][pos.y] = pos.steps;
|
||||||
|
|
||||||
|
const next = directions
|
||||||
|
.map((d) => d.clone().add(pos))
|
||||||
|
.filter(R.isNot(oom))
|
||||||
|
.filter(isReachable(topoMap, pos));
|
||||||
|
|
||||||
|
next.forEach((n) => (n.steps = pos.steps + 1));
|
||||||
|
|
||||||
|
potentials.push(...next);
|
||||||
|
}
|
||||||
|
|
||||||
|
return R.pipe(
|
||||||
|
initial,
|
||||||
|
R.map(([x, y]) => beenThere[x][y]),
|
||||||
|
R.minBy(R.identity)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default findShortestPath;
|
||||||
|
@ -5,22 +5,24 @@ import part1, { findStart, sample, puzzleInput } from "./part1.js";
|
|||||||
import part2 from "./part2.js";
|
import part2 from "./part2.js";
|
||||||
|
|
||||||
describe("part 1", () => {
|
describe("part 1", () => {
|
||||||
test( "findStart", () => {
|
test("findStart", () => {
|
||||||
expect( findStart(sample).toArray() ).toEqual(
|
expect(findStart(sample).toArray()).toEqual([0, 0]);
|
||||||
[0,0]
|
|
||||||
)
|
|
||||||
|
|
||||||
});
|
});
|
||||||
test( "sample", async () => {
|
test("sample", () => {
|
||||||
expect(part1(sample)).toEqual(31);
|
expect(part1(sample)).toEqual(31);
|
||||||
});
|
});
|
||||||
test.only("solution", () => {
|
test("solution", () => {
|
||||||
expectSolution(part1(puzzleInput)).toEqual("TODO");
|
const r = part1(puzzleInput);
|
||||||
|
expect(r).toBeLessThan(9999);
|
||||||
|
expectSolution(r).toEqual(361);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("part 2", () => {
|
describe.only("part 2", () => {
|
||||||
test.todo("solution", () => {
|
test("sample", () => {
|
||||||
expectSolution(part2(puzzleInput)).toEqual("TODO");
|
expect(part2(sample)).toEqual(29);
|
||||||
|
});
|
||||||
|
test("solution", () => {
|
||||||
|
expectSolution(part2(puzzleInput)).toEqual(354);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
42
2022/13/part1.js
Normal file
42
2022/13/part1.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import * as R from "remeda";
|
||||||
|
|
||||||
|
import { readFile } from "../05/part1.js";
|
||||||
|
|
||||||
|
const readInput = (...args) =>
|
||||||
|
R.pipe(
|
||||||
|
readFile(...args),
|
||||||
|
(lines) => lines.split("\n\n"),
|
||||||
|
R.compact, // remove last line
|
||||||
|
R.map((block) => block.split("\n").map((line) => eval(line)))
|
||||||
|
);
|
||||||
|
|
||||||
|
export const puzzleInput = readInput(import.meta.url, "input");
|
||||||
|
export const sample = readInput(import.meta.url, "sample");
|
||||||
|
|
||||||
|
export function isLessThan(x, y) {
|
||||||
|
if ([x, y].every(R.isNumber)) return x < y ? -1 : x == y ? 0 : 1;
|
||||||
|
|
||||||
|
if ([x, y].every(R.isArray)) {
|
||||||
|
for (const [a, b] of R.zip(x, y)) {
|
||||||
|
const res = isLessThan(a, b);
|
||||||
|
if (res !== 0) return res;
|
||||||
|
}
|
||||||
|
if (x.length === y.length) return 0;
|
||||||
|
return x.length < y.length ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isLessThan(...[x, y].map((z) => (R.isNumber(z) ? [z] : z)));
|
||||||
|
}
|
||||||
|
|
||||||
|
const passthru = (x) => (arg) => {
|
||||||
|
x(arg);
|
||||||
|
return arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default R.createPipe(
|
||||||
|
R.map(([x, y]) => isLessThan(x, y)),
|
||||||
|
(results) => results.map((value, index) => ({ value, index: index + 1 })),
|
||||||
|
R.filter(({ value }) => value !== 1),
|
||||||
|
R.map(R.prop("index")),
|
||||||
|
(results) => results.reduce((a, b) => a + b)
|
||||||
|
);
|
14
2022/13/part2.js
Normal file
14
2022/13/part2.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import * as R from "remeda";
|
||||||
|
import { isLessThan } from "./part1";
|
||||||
|
|
||||||
|
const dividers = [[[2]], [[6]]];
|
||||||
|
export default R.createPipe(
|
||||||
|
R.flatten,
|
||||||
|
R.concat(dividers),
|
||||||
|
(packets) => packets.sort(isLessThan),
|
||||||
|
(packets) =>
|
||||||
|
packets.map((p, i) => ({ i: i + 1, divider: dividers.includes(p) })),
|
||||||
|
R.filter(({ divider }) => divider),
|
||||||
|
R.map(R.prop("i")),
|
||||||
|
(v) => v.reduce((a, b) => a * b)
|
||||||
|
);
|
23
2022/13/sample
Normal file
23
2022/13/sample
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
[1,1,3,1,1]
|
||||||
|
[1,1,5,1,1]
|
||||||
|
|
||||||
|
[[1],[2,3,4]]
|
||||||
|
[[1],4]
|
||||||
|
|
||||||
|
[9]
|
||||||
|
[[8,7,6]]
|
||||||
|
|
||||||
|
[[4,4],4,4]
|
||||||
|
[[4,4],4,4,4]
|
||||||
|
|
||||||
|
[7,7,7,7]
|
||||||
|
[7,7,7]
|
||||||
|
|
||||||
|
[]
|
||||||
|
[3]
|
||||||
|
|
||||||
|
[[[]]]
|
||||||
|
[[]]
|
||||||
|
|
||||||
|
[1,[2,[3,[4,[5,6,7]]]],8,9]
|
||||||
|
[1,[2,[3,[4,[5,6,0]]]],8,9]
|
36
2022/13/test.js
Normal file
36
2022/13/test.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { test, expect, describe } from "vitest";
|
||||||
|
|
||||||
|
import { expectSolution } from "../01/main.js";
|
||||||
|
import part1, { sample, puzzleInput, isLessThan } from "./part1.js";
|
||||||
|
import part2 from "./part2.js";
|
||||||
|
|
||||||
|
describe("part 1", () => {
|
||||||
|
test("readInput", () => {
|
||||||
|
expect(sample[0][0]).toEqual([1, 1, 3, 1, 1]);
|
||||||
|
});
|
||||||
|
test("lessThan", () => {
|
||||||
|
expect(isLessThan(1, 2)).toBe(-1);
|
||||||
|
expect(isLessThan(2, 1)).toBe(1);
|
||||||
|
expect(isLessThan(2, 2)).toBe(0);
|
||||||
|
expect(isLessThan(2, [1])).toBe(1);
|
||||||
|
expect(isLessThan([1], [2])).toBe(-1);
|
||||||
|
});
|
||||||
|
test("sample", () => {
|
||||||
|
expect(part1(sample)).toEqual(13);
|
||||||
|
});
|
||||||
|
test("solution", () => {
|
||||||
|
const r = part1(puzzleInput);
|
||||||
|
expect(r).toBeGreaterThan(435);
|
||||||
|
expect(r).toBeLessThan(10980);
|
||||||
|
expectSolution(r).toEqual(5806);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("part 2", () => {
|
||||||
|
test("sample", () => {
|
||||||
|
expect(part2(sample)).toEqual(140);
|
||||||
|
});
|
||||||
|
test("solution", () => {
|
||||||
|
expectSolution(part2(puzzleInput)).toEqual(23600);
|
||||||
|
});
|
||||||
|
});
|
83
2022/14/part1.js
Normal file
83
2022/14/part1.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import * as R from "remeda";
|
||||||
|
import Victor from "@a-robu/victor";
|
||||||
|
|
||||||
|
import { readFile } from "../05/part1.js";
|
||||||
|
|
||||||
|
export const V = (...args) => new Victor(...args);
|
||||||
|
const parseLine = (line) => line.match(/[\d,]+/g).map((x) => eval(`[${x}]`));
|
||||||
|
|
||||||
|
const readInput = (...args) =>
|
||||||
|
R.pipe(
|
||||||
|
readFile(...args),
|
||||||
|
(lines) => lines.split("\n"),
|
||||||
|
R.compact, // remove last line
|
||||||
|
R.map(parseLine)
|
||||||
|
);
|
||||||
|
|
||||||
|
export const puzzleInput = readInput(import.meta.url, "input");
|
||||||
|
export const sample = readInput(import.meta.url, "sample");
|
||||||
|
|
||||||
|
export function genCave(rocks) {
|
||||||
|
const cave = {};
|
||||||
|
for (const rock of rocks) {
|
||||||
|
const points = rock.map(Victor.fromArray);
|
||||||
|
let from = points.shift();
|
||||||
|
|
||||||
|
while (points.length) {
|
||||||
|
/** @type Victor */
|
||||||
|
const to = points.shift();
|
||||||
|
const direction = to.clone().subtract(from).normalize();
|
||||||
|
|
||||||
|
R.times(to.clone().subtract(from).length() + 1, () => {
|
||||||
|
if (!cave[from.y]) cave[from.y] = {};
|
||||||
|
cave[from.y][from.x] = "#";
|
||||||
|
from.add(direction);
|
||||||
|
});
|
||||||
|
|
||||||
|
from = to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cave;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pourSand(cave) {
|
||||||
|
cave = R.clone(cave);
|
||||||
|
|
||||||
|
let sand = 0;
|
||||||
|
|
||||||
|
/** @type Victor */
|
||||||
|
let current;
|
||||||
|
|
||||||
|
const maxDepth = R.pipe(
|
||||||
|
cave,
|
||||||
|
R.keys,
|
||||||
|
R.map((x) => parseInt(x)),
|
||||||
|
R.maxBy(R.identity)
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log({ maxDepth });
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!current) current = V(500, 0);
|
||||||
|
if (current.y > maxDepth) return sand;
|
||||||
|
|
||||||
|
const next = [
|
||||||
|
[0, 1],
|
||||||
|
[-1, 1],
|
||||||
|
[1, 1],
|
||||||
|
]
|
||||||
|
.map((args) => V(...args))
|
||||||
|
.map((v) => v.add(current))
|
||||||
|
.find((v) => !(cave[v.y] && cave[v.y][v.x]));
|
||||||
|
if (next) {
|
||||||
|
current = next;
|
||||||
|
} else {
|
||||||
|
if (!cave[current.y]) cave[current.y] = {};
|
||||||
|
cave[current.y][current.x] = "o";
|
||||||
|
sand++;
|
||||||
|
current = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default R.createPipe(genCave, pourSand);
|
53
2022/14/part2.js
Normal file
53
2022/14/part2.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import * as R from "remeda";
|
||||||
|
import { genCave, V } from "./part1.js";
|
||||||
|
|
||||||
|
function pourSand(cave) {
|
||||||
|
cave = R.clone(cave);
|
||||||
|
|
||||||
|
let sand = 0;
|
||||||
|
|
||||||
|
/** @type Victor */
|
||||||
|
let current;
|
||||||
|
|
||||||
|
const maxDepth =
|
||||||
|
R.pipe(
|
||||||
|
cave,
|
||||||
|
R.keys,
|
||||||
|
R.map((x) => parseInt(x)),
|
||||||
|
R.maxBy(R.identity)
|
||||||
|
) + 1;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!current) current = V(500, 0);
|
||||||
|
|
||||||
|
if (current.y === maxDepth) {
|
||||||
|
if (!cave[current.y]) cave[current.y] = {};
|
||||||
|
cave[current.y][current.x] = "o";
|
||||||
|
sand++;
|
||||||
|
current = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const next = [
|
||||||
|
[0, 1],
|
||||||
|
[-1, 1],
|
||||||
|
[1, 1],
|
||||||
|
]
|
||||||
|
.map((args) => V(...args))
|
||||||
|
.map((v) => v.add(current))
|
||||||
|
.find((v) => !(cave[v.y] && cave[v.y][v.x]));
|
||||||
|
|
||||||
|
if (next) {
|
||||||
|
current = next;
|
||||||
|
} else {
|
||||||
|
if (current.y === 0) return 1 + sand;
|
||||||
|
|
||||||
|
if (!cave[current.y]) cave[current.y] = {};
|
||||||
|
cave[current.y][current.x] = "o";
|
||||||
|
sand++;
|
||||||
|
current = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default R.createPipe(genCave, pourSand);
|
2
2022/14/sample
Normal file
2
2022/14/sample
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
498,4 -> 498,6 -> 496,6
|
||||||
|
503,4 -> 502,4 -> 502,9 -> 494,9
|
43
2022/14/test.js
Normal file
43
2022/14/test.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { test, expect, describe } from "vitest";
|
||||||
|
|
||||||
|
import { expectSolution } from "../01/main.js";
|
||||||
|
import part1, { genCave, sample, puzzleInput } from "./part1.js";
|
||||||
|
import part2 from "./part2.js";
|
||||||
|
|
||||||
|
describe("part 1", () => {
|
||||||
|
test("readInput", () => {
|
||||||
|
expect(sample).toEqual([
|
||||||
|
[
|
||||||
|
[498, 4],
|
||||||
|
[498, 6],
|
||||||
|
[496, 6],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[503, 4],
|
||||||
|
[502, 4],
|
||||||
|
[502, 9],
|
||||||
|
[494, 9],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
test("genCave", () => {
|
||||||
|
expect(genCave(sample)).toMatchObject({
|
||||||
|
4: { 498: "#" },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test("sample", () => {
|
||||||
|
expect(part1(sample)).toEqual(24);
|
||||||
|
});
|
||||||
|
test("solution", () => {
|
||||||
|
expectSolution(part1(puzzleInput)).toEqual(832);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe.only("part 2", () => {
|
||||||
|
test("sample", () => {
|
||||||
|
expect(part2(sample)).toEqual(93);
|
||||||
|
});
|
||||||
|
test("solution", () => {
|
||||||
|
expectSolution(part2(puzzleInput)).toEqual(27601);
|
||||||
|
});
|
||||||
|
});
|
@ -6,9 +6,11 @@ import * as R from "remeda";
|
|||||||
import { readFile } from "../05/part1.js";
|
import { readFile } from "../05/part1.js";
|
||||||
|
|
||||||
const readInput = (...args) =>
|
const readInput = (...args) =>
|
||||||
readFile(...args)
|
R.pipe(
|
||||||
.split("\n")
|
readFile(...args),
|
||||||
.filter((x) => x);
|
(lines) => lines.split("\n"),
|
||||||
|
R.compact, // remove last line
|
||||||
|
);
|
||||||
|
|
||||||
export const puzzleInput = readInput(import.meta.url, "input");
|
export const puzzleInput = readInput(import.meta.url, "input");
|
||||||
export const sample = readInput(import.meta.url, "sample");
|
export const sample = readInput(import.meta.url, "sample");
|
||||||
|
3
_templates/package.json
Normal file
3
_templates/package.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"type": "module",
|
||||||
"name": "2022",
|
"name": "2022",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
@ -16,6 +17,10 @@
|
|||||||
"memoizerific": "^1.11.3",
|
"memoizerific": "^1.11.3",
|
||||||
"prettier": "^2.8.0",
|
"prettier": "^2.8.0",
|
||||||
"remeda": "^1.3.0",
|
"remeda": "^1.3.0",
|
||||||
"vitest": "^0.25.3"
|
"vite": "^4.0.1",
|
||||||
|
"vitest": "0.25.7"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitest/ui": "^0.25.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user