Merge branch '2022-04'
This commit is contained in:
commit
0a55d68dfd
11
2022/01/main.js
Normal file
11
2022/01/main.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { expect } from "vitest";
|
||||
|
||||
export const spy = (x) => {
|
||||
console.debug(x);
|
||||
return x;
|
||||
};
|
||||
|
||||
export function expectSolution(result) {
|
||||
console.info(result);
|
||||
return expect(result);
|
||||
}
|
@ -1,16 +1,14 @@
|
||||
import * as R from "remeda";
|
||||
import { test, expect } from "vitest";
|
||||
import fs from "fs-extra";
|
||||
import path from 'path';
|
||||
import { expectSolution } from './main.js';
|
||||
|
||||
const split = (splitter) => (text) => text.split(splitter);
|
||||
const sum = R.sumBy(R.identity);
|
||||
const spy = (x) => {
|
||||
console.debug(x);
|
||||
return x;
|
||||
};
|
||||
|
||||
const input = R.pipe(
|
||||
fs.readFileSync("input", "utf8"),
|
||||
fs.readFileSync( path.join( path.dirname(import.meta.url), "input").replace('file:',''), "utf8"),
|
||||
split("\n\n"),
|
||||
R.map((x) =>
|
||||
split("\n")(x)
|
||||
@ -20,10 +18,6 @@ const input = R.pipe(
|
||||
R.map(sum)
|
||||
);
|
||||
|
||||
function expectSolution(result) {
|
||||
console.info(result);
|
||||
return expect(result);
|
||||
}
|
||||
|
||||
test("part 1", () => {
|
||||
const maxCalories = R.pipe(input, (calories) => Math.max(...calories));
|
||||
|
60
2022/02/part1.js
Normal file
60
2022/02/part1.js
Normal file
@ -0,0 +1,60 @@
|
||||
import * as R from "remeda";
|
||||
import fs from "fs-extra";
|
||||
import path from "path";
|
||||
|
||||
export const sampleInput = `A Y
|
||||
B X
|
||||
C Z`;
|
||||
|
||||
export const puzzleInput = fs.readFileSync(
|
||||
path.join(path.dirname(import.meta.url), "input").replace("file:", ""),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
const playMap = {
|
||||
X: "A", // rock
|
||||
Y: "B", // paper
|
||||
Z: "C", // scissors
|
||||
};
|
||||
|
||||
export const parseInput = R.createPipe(
|
||||
(text) => text.split("\n"),
|
||||
R.filter(R.identity), // remove last line
|
||||
R.map((entry) => entry.split(" "))
|
||||
);
|
||||
|
||||
export const movePositions = ["A", "B", "C"];
|
||||
|
||||
const playScore = {
|
||||
A: 1,
|
||||
B: 2,
|
||||
C: 3,
|
||||
};
|
||||
|
||||
const draw = 3;
|
||||
const lost = 0;
|
||||
const win = 6;
|
||||
|
||||
const outcome = (opponent, me) => {
|
||||
if (opponent === me) return draw;
|
||||
if (opponent === "A") {
|
||||
return me === "C" ? lost : win;
|
||||
}
|
||||
if (opponent === "B") {
|
||||
return me === "A" ? lost : win;
|
||||
}
|
||||
return me === "B" ? lost : win;
|
||||
};
|
||||
|
||||
export const mapScores = ([opponent, me]) => [
|
||||
outcome(opponent, me),
|
||||
playScore[me],
|
||||
];
|
||||
|
||||
export const solutionPart1 = R.createPipe(
|
||||
parseInput,
|
||||
R.map(([a, b]) => [a, playMap[b]]),
|
||||
R.map(mapScores),
|
||||
R.map(R.sumBy(R.identity)),
|
||||
R.sumBy(R.identity)
|
||||
);
|
25
2022/02/part2.js
Normal file
25
2022/02/part2.js
Normal file
@ -0,0 +1,25 @@
|
||||
import * as R from "remeda";
|
||||
|
||||
import { movePositions, mapScores, playMap, parseInput } from "./part1.js";
|
||||
|
||||
function calculateMove(opponent, verdict) {
|
||||
const incr = {
|
||||
Y: 0,
|
||||
X: 2,
|
||||
Z: 1,
|
||||
};
|
||||
|
||||
const index =
|
||||
(movePositions.findIndex((x) => x === opponent) + incr[verdict]) %
|
||||
movePositions.length;
|
||||
|
||||
return movePositions[index];
|
||||
}
|
||||
|
||||
export const solutionPart2 = R.createPipe(
|
||||
parseInput,
|
||||
R.map(([a, b]) => [a, calculateMove(a, b)]),
|
||||
R.map(mapScores),
|
||||
R.map(R.sumBy(R.identity)),
|
||||
R.sumBy(R.identity)
|
||||
);
|
41
2022/02/test.js
Normal file
41
2022/02/test.js
Normal file
@ -0,0 +1,41 @@
|
||||
import { test, expect, describe } from "vitest";
|
||||
|
||||
import { expectSolution } from "../01/main.js";
|
||||
import {
|
||||
parseInput,
|
||||
sampleInput,
|
||||
puzzleInput,
|
||||
mapScores,
|
||||
solutionPart1,
|
||||
} from "./part1.js";
|
||||
import { solutionPart2 } from "./part2.js";
|
||||
|
||||
describe("part 1", () => {
|
||||
test("input parsing", () => {
|
||||
expect(parseInput(sampleInput)).toEqual([
|
||||
["A", "Y"],
|
||||
["B", "X"],
|
||||
["C", "Z"],
|
||||
]);
|
||||
});
|
||||
|
||||
test("mapScore", () => {
|
||||
expect(mapScores(["A", "B"])).toEqual([6, 2]);
|
||||
expect(mapScores(["B", "A"])).toEqual([0, 1]);
|
||||
expect(mapScores(["C", "C"])).toEqual([3, 3]);
|
||||
});
|
||||
|
||||
test("part 1, sample", () => {
|
||||
expect(solutionPart1(sampleInput)).toEqual(15);
|
||||
});
|
||||
|
||||
test("solution", () => {
|
||||
expectSolution(solutionPart1(puzzleInput)).toEqual(12458);
|
||||
});
|
||||
});
|
||||
|
||||
describe("part 2", () => {
|
||||
test("part 2", () => {
|
||||
expectSolution(solutionPart2(puzzleInput)).toEqual(12683);
|
||||
});
|
||||
});
|
20
2022/03/part1.js
Normal file
20
2022/03/part1.js
Normal file
@ -0,0 +1,20 @@
|
||||
import * as R from "remeda";
|
||||
import fs from "fs-extra";
|
||||
import path from "path";
|
||||
|
||||
export const readFile = (year, day, file) =>
|
||||
fs.readFileSync(path.join(year, day, file), "utf8");
|
||||
|
||||
export const sample = readFile("2022", "03", "sample");
|
||||
export const puzzleInput = readFile("2022", "03", "input");
|
||||
|
||||
export const solutionPart1 = R.createPipe(
|
||||
(text) => text.split("\n"),
|
||||
R.filter(R.identity),
|
||||
R.map((line) => line.split("")),
|
||||
R.map((line) => [line, line.splice(line.length / 2)]),
|
||||
R.map((line) => R.intersection(...line)),
|
||||
R.map((line) => line[0].charCodeAt(0)),
|
||||
R.map((code) => (code > 96 ? code - 96 : code - 38)),
|
||||
R.sumBy(R.identity)
|
||||
);
|
12
2022/03/part2.js
Normal file
12
2022/03/part2.js
Normal file
@ -0,0 +1,12 @@
|
||||
import * as R from "remeda";
|
||||
|
||||
export const solutionPart2 = R.createPipe(
|
||||
(text) => text.split("\n"),
|
||||
R.filter(R.identity),
|
||||
R.map((line) => line.split("")),
|
||||
R.chunk(3),
|
||||
R.map((group) => group.reduce((a, b) => R.intersection(a, b))),
|
||||
R.map((line) => line[0].charCodeAt(0)),
|
||||
R.map((code) => (code > 96 ? code - 96 : code - 38)),
|
||||
R.sumBy(R.identity)
|
||||
);
|
6
2022/03/sample
Normal file
6
2022/03/sample
Normal file
@ -0,0 +1,6 @@
|
||||
vJrwpWtwJgWrhcsFMMfFFhFp
|
||||
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
|
||||
PmmdzqPrVvPwwTWBwg
|
||||
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
|
||||
ttgJtRGJQctTZtZT
|
||||
CrZsJsPPZsGzwwsLwLmpwMDw
|
25
2022/03/test.js
Normal file
25
2022/03/test.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { test, expect, describe } from "vitest";
|
||||
|
||||
import { solutionPart1, sample, puzzleInput } from "./part1.js";
|
||||
|
||||
import { solutionPart2 } from "./part2.js";
|
||||
|
||||
function expectSolution(result) {
|
||||
console.info(result);
|
||||
return expect(result);
|
||||
}
|
||||
|
||||
describe("part 1", () => {
|
||||
test("sample", () => {
|
||||
expect(solutionPart1(sample)).toEqual(157);
|
||||
});
|
||||
test("solution", () => {
|
||||
expectSolution(solutionPart1(puzzleInput)).toEqual(8515);
|
||||
});
|
||||
});
|
||||
|
||||
describe("part 2", () => {
|
||||
test("solution", () => {
|
||||
expectSolution(solutionPart2(puzzleInput)).toEqual(2434);
|
||||
});
|
||||
});
|
20
2022/04/part1.js
Normal file
20
2022/04/part1.js
Normal file
@ -0,0 +1,20 @@
|
||||
import * as R from "remeda";
|
||||
|
||||
import { readFile } from "../03/part1.js";
|
||||
|
||||
export const sample = readFile("2022", "04", "sample");
|
||||
export const puzzleInput = readFile("2022", "04", "input");
|
||||
|
||||
const rangeLength = ([a, b]) => b - a + 1;
|
||||
|
||||
const isContainedBy = ([a1, a2], [b1, b2]) => a1 >= b1 && a2 <= b2;
|
||||
|
||||
export const solutionPart1 = R.createPipe(
|
||||
(text) => text.split("\n"),
|
||||
R.filter(R.identity),
|
||||
R.map((line) =>
|
||||
line.split(",").map((range) => range.split("-").map((x) => parseInt(x)))
|
||||
),
|
||||
R.map(R.sortBy((x) => rangeLength(x))),
|
||||
R.countBy(([a, b]) => isContainedBy(a, b))
|
||||
);
|
13
2022/04/part2.js
Normal file
13
2022/04/part2.js
Normal file
@ -0,0 +1,13 @@
|
||||
import * as R from "remeda";
|
||||
|
||||
const overlapsWith = ([a1, a2], [b1, b2]) => a2 >= b1;
|
||||
|
||||
export const solutionPart2 = R.createPipe(
|
||||
(text) => text.split("\n"),
|
||||
R.filter(R.identity),
|
||||
R.map((line) =>
|
||||
line.split(",").map((range) => range.split("-").map((x) => parseInt(x)))
|
||||
),
|
||||
R.map(R.sortBy(([x]) => x)),
|
||||
R.countBy(([a, b]) => overlapsWith(a, b))
|
||||
);
|
6
2022/04/sample
Normal file
6
2022/04/sample
Normal file
@ -0,0 +1,6 @@
|
||||
2-4,6-8
|
||||
2-3,4-5
|
||||
5-7,7-9
|
||||
2-8,3-7
|
||||
6-6,4-6
|
||||
2-6,4-8
|
23
2022/04/test.js
Normal file
23
2022/04/test.js
Normal file
@ -0,0 +1,23 @@
|
||||
import { test, describe } from "vitest";
|
||||
|
||||
import { expectSolution } from "../01/main.js";
|
||||
import { solutionPart1, puzzleInput, sample } from "./part1.js";
|
||||
import { solutionPart2 } from "./part2.js";
|
||||
|
||||
describe("part 1", () => {
|
||||
test("sample", () => {
|
||||
expectSolution(solutionPart1(sample)).toEqual(2);
|
||||
});
|
||||
test("solution", () => {
|
||||
expectSolution(solutionPart1(puzzleInput)).toEqual(605);
|
||||
});
|
||||
});
|
||||
|
||||
describe("part 2", () => {
|
||||
test("sample", () => {
|
||||
expectSolution(solutionPart2(sample)).toEqual(4);
|
||||
});
|
||||
test("solution", () => {
|
||||
expectSolution(solutionPart2(puzzleInput)).toEqual(914);
|
||||
});
|
||||
});
|
1
2022/template/part1.js
Normal file
1
2022/template/part1.js
Normal file
@ -0,0 +1 @@
|
||||
import * as R from "remeda";
|
2
2022/template/part2.js
Normal file
2
2022/template/part2.js
Normal file
@ -0,0 +1,2 @@
|
||||
import * as R from "remeda";
|
||||
|
20
2022/template/test.js
Normal file
20
2022/template/test.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { test, expect, describe } from "vitest";
|
||||
|
||||
import { expectSolution } from "../01/main.js";
|
||||
import {
|
||||
solutionPart1,
|
||||
puzzleInput,
|
||||
} from "./part1.js";
|
||||
import { solutionPart2 } from "./part2.js";
|
||||
|
||||
describe("part 1", () => {
|
||||
test.todo("solution", () => {
|
||||
expectSolution(solutionPart1(puzzleInput)).toEqual('TODO');
|
||||
});
|
||||
});
|
||||
|
||||
describe("part 2", () => {
|
||||
test.todo("solution", () => {
|
||||
expectSolution(solutionPart2(puzzleInput)).toEqual('TODO');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user