Compare commits

..

10 Commits

Author SHA1 Message Date
alex 9a03d756b6 start day 3 2023-12-10 19:26:29 -05:00
alex 191308edb3 add day 5 2023-12-10 16:29:22 -05:00
alex 557d12b1e9 day 4 2023-12-10 15:19:14 -05:00
alex 83890cb660 Cleanup 2022 2023-12-02 01:01:12 -05:00
alex 5f6186f14a day 02 2023-12-02 00:54:53 -05:00
alex 7d22957666 simplify 2023-12-01 20:57:47 -05:00
alex 04815f59c3 2023 day 1 2023-12-01 20:11:44 -05:00
alex a7d468df64 add multiyear support 2023-12-01 20:01:55 -05:00
alex 618a65bb5d add script to quickly set up puzzle code templates 2022-12-05 06:58:24 -05:00
alex 0b21259853 day 4: camp cleanup 2022-12-04 00:44:28 -05:00
45 changed files with 4075 additions and 33 deletions

View File

@ -1,27 +1,28 @@
import { readlines } from "../_utils"; import path from "path";
import { readlines } from "../../_utils";
const solution = require("./solution"); const solution = require("./solution");
describe("day 1: calorie counting, pt 1", () => { describe("day 1: calorie counting, pt 1", () => {
test("sample input", async () => { test("sample input", async () => {
const sample = await readlines("./day_01/sample.txt"); const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(solution.part1_solver(sample)).toBe(24000); expect(solution.part1_solver(sample)).toBe(24000);
}); });
test("submission input", async () => { test("submission input", async () => {
const input = await readlines("./day_01/input.txt"); const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(solution.part1_solver(input)).toBe(70613); expect(solution.part1_solver(input)).toBe(70613);
}); });
}); });
describe("day 1: calorie counting, pt 2", () => { describe("day 1: calorie counting, pt 2", () => {
test("sample input", async () => { test("sample input", async () => {
const sample = await readlines("./day_01/sample.txt"); const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(solution.part2_solver(sample)).toBe(45000); expect(solution.part2_solver(sample)).toBe(45000);
}); });
test("submission input", async () => { test("submission input", async () => {
const input = await readlines("./day_01/input.txt"); const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(solution.part2_solver(input)).toBe(205805); expect(solution.part2_solver(input)).toBe(205805);
}); });
}); });

View File

@ -43,7 +43,7 @@ In case the Elves get hungry and need extra snacks, they need to know which Elf
Find the Elf carrying the most Calories. How many total Calories is that Elf carrying? Find the Elf carrying the most Calories. How many total Calories is that Elf carrying?
*/ */
import { group, sum } from "../_utils"; import { group, sum } from "../../_utils";
const groupSnacksByElf = (lines: string[]): string[][] => const groupSnacksByElf = (lines: string[]): string[][] =>
group(lines, (_, line) => line === "", false); group(lines, (_, line) => line === "", false);

View File

@ -1,27 +1,28 @@
import { readlines } from "../_utils"; import path from "path";
import { readlines } from "../../_utils";
const solution = require("./solution"); const solution = require("./solution");
describe("day 2: rock paper scissors, pt 1", () => { describe("day 2: rock paper scissors, pt 1", () => {
test("sample input", async () => { test("sample input", async () => {
const sample = await readlines("./day_02/sample.txt"); const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(solution.part1_solver(sample)).toBe(15); expect(solution.part1_solver(sample)).toBe(15);
}); });
test("submission input", async () => { test("submission input", async () => {
const input = await readlines("./day_02/input.txt"); const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(solution.part1_solver(input)).toBe(13675); expect(solution.part1_solver(input)).toBe(13675);
}); });
}); });
describe("day 2: rock paper scissors, pt 2", () => { describe("day 2: rock paper scissors, pt 2", () => {
test("sample input", async () => { test("sample input", async () => {
const sample = await readlines("./day_02/sample.txt"); const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(solution.part2_solver(sample)).toBe(12); expect(solution.part2_solver(sample)).toBe(12);
}); });
test("submission input", async () => { test("submission input", async () => {
const input = await readlines("./day_02/input.txt"); const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(solution.part2_solver(input)).toBe(14184); expect(solution.part2_solver(input)).toBe(14184);
}); });
}); });

View File

@ -30,7 +30,7 @@ In this example, if you were to follow the strategy guide, you would get a total
What would your total score be if everything goes exactly according to your strategy guide? What would your total score be if everything goes exactly according to your strategy guide?
*/ */
import { emptyLines, sum } from "../_utils"; import { emptyLines, sum } from "../../_utils";
export function part1_solver(lines: string[]): number { export function part1_solver(lines: string[]): number {
const score_map = { const score_map = {

View File

@ -1,27 +1,28 @@
import { readlines } from "../_utils"; import path from "path";
import { readlines } from "../../_utils";
const solution = require("./solution"); const solution = require("./solution");
describe("day 3: rucksack reorganization, pt 1", () => { describe("day 3: rucksack reorganization, pt 1", () => {
test("sample input", async () => { test("sample input", async () => {
const sample = await readlines("./day_03/sample.txt"); const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(solution.part1_solver(sample)).toBe(157); expect(solution.part1_solver(sample)).toBe(157);
}); });
test("submission input", async () => { test("submission input", async () => {
const input = await readlines("./day_03/input.txt"); const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(solution.part1_solver(input)).toBe(8109); expect(solution.part1_solver(input)).toBe(8109);
}); });
}); });
describe("day 3: rucksack reorganization, pt 2", () => { describe("day 3: rucksack reorganization, pt 2", () => {
test("sample input", async () => { test("sample input", async () => {
const sample = await readlines("./day_03/sample.txt"); const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(solution.part2_solver(sample)).toBe(70); expect(solution.part2_solver(sample)).toBe(70);
}); });
test("submission input", async () => { test("submission input", async () => {
const input = await readlines("./day_03/input.txt"); const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(solution.part2_solver(input)).toBe(2738); expect(solution.part2_solver(input)).toBe(2738);
}); });
}); });

View File

@ -35,7 +35,7 @@ In the above example, the priority of the item type that appears in both compart
Find the item type that appears in both compartments of each rucksack. What is the sum of the priorities of those item types? Find the item type that appears in both compartments of each rucksack. What is the sum of the priorities of those item types?
*/ */
import { emptyLines, group, sum } from "../_utils"; import { emptyLines, group, sum } from "../../_utils";
/** /**
* *

1000
2022/day_04/input.txt Normal file

File diff suppressed because it is too large Load Diff

6
2022/day_04/sample.txt Normal file
View 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

View File

@ -0,0 +1,28 @@
import path from "path";
import { readlines } from "../../_utils";
const solution = require("./solution");
describe("day 4: camp cleanup, pt 1", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(solution.part1_solver(sample)).toBe(2);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(solution.part1_solver(input)).toBe(450);
});
});
describe("day 4: camp cleanup, pt 2", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(solution.part2_solver(sample)).toBe(4);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(solution.part2_solver(input)).toBe(837);
});
});

121
2022/day_04/solution.ts Normal file
View File

@ -0,0 +1,121 @@
/*
--- Day 4: Camp Cleanup ---
Space needs to be cleared before the last supplies can be unloaded from the ships, and so several Elves have been assigned the job of cleaning up sections of the camp. Every section has a unique ID number, and each Elf is assigned a range of section IDs.
However, as some of the Elves compare their section assignments with each other, they've noticed that many of the assignments overlap. To try to quickly find overlaps and reduce duplicated effort, the Elves pair up and make a big list of the section assignments for each pair (your puzzle input).
For example, consider the following list of section assignment pairs:
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8
For the first few pairs, this list means:
Within the first pair of Elves, the first Elf was assigned sections 2-4 (sections 2, 3, and 4), while the second Elf was assigned sections 6-8 (sections 6, 7, 8).
The Elves in the second pair were each assigned two sections.
The Elves in the third pair were each assigned three sections: one got sections 5, 6, and 7, while the other also got 7, plus 8 and 9.
This example list uses single-digit section IDs to make it easier to draw; your actual list might contain larger numbers. Visually, these pairs of section assignments look like this:
.234..... 2-4
.....678. 6-8
.23...... 2-3
...45.... 4-5
....567.. 5-7
......789 7-9
.2345678. 2-8
..34567.. 3-7
.....6... 6-6
...456... 4-6
.23456... 2-6
...45678. 4-8
Some of the pairs have noticed that one of their assignments fully contains the other. For example, 2-8 fully contains 3-7, and 6-6 is fully contained by 4-6. In pairs where one assignment fully contains the other, one Elf in the pair would be exclusively cleaning sections their partner will already be cleaning, so these seem like the most in need of reconsideration. In this example, there are 2 such pairs.
In how many assignment pairs does one range fully contain the other?
*/
import { emptyLines, sum } from "../../_utils";
class Range {
min: number;
max: number;
size: number;
constructor(range: string) {
const [min, max] = range.split("-").map((n) => parseInt(n));
this.min = min;
this.max = max;
this.size = max - min + 1;
}
/**
* Determines whether other range is fully contained by (or fully contains) `this` range
* @param r
* @returns
*/
contains(r: Range): boolean {
const [larger, smaller] = r.size > this.size ? [r, this] : [this, r];
return smaller.min >= larger.min && smaller.max <= larger.max;
}
/**
* Determines whether other range partially overlaps `this` range
* @param r
*/
overlaps(r: Range): boolean {
const [sooner, later] = r.min < this.min ? [r, this] : [this, r];
return later.min <= sooner.max;
}
}
const toRanges = (line: string): Range[] =>
line.split(",").map((r) => new Range(r));
const toOneOrZero = (b: boolean) => (b ? 1 : 0);
export function part1_solver(lines: string[]): number {
return lines
.filter(emptyLines)
.map(toRanges)
.map(([elf1Range, elf2Range]) => elf1Range.contains(elf2Range))
.map(toOneOrZero) // convert boolean to number for counting
.reduce(sum, 0);
}
/*
--- Part Two ---
It seems like there is still quite a bit of duplicate work planned. Instead, the Elves would like to know the number of pairs that overlap at all.
In the above example, the first two pairs (2-4,6-8 and 2-3,4-5) don't overlap, while the remaining four pairs (5-7,7-9, 2-8,3-7, 6-6,4-6, and 2-6,4-8) do overlap:
5-7,7-9 overlaps in a single section, 7.
2-8,3-7 overlaps all of the sections 3 through 7.
6-6,4-6 overlaps in a single section, 6.
2-6,4-8 overlaps in sections 4, 5, and 6.
So, in this example, the number of overlapping assignment pairs is 4.
In how many assignment pairs do the ranges overlap?
*/
export function part2_solver(lines: string[]): number {
return lines
.filter(emptyLines)
.map(toRanges)
.map(([elf1Range, elf2Range]) => elf1Range.overlaps(elf2Range))
.map(toOneOrZero)
.reduce(sum, 0);
}

1000
2023/day_01/input.txt Normal file

File diff suppressed because it is too large Load Diff

4
2023/day_01/sample.txt Normal file
View File

@ -0,0 +1,4 @@
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet

7
2023/day_01/sample2.txt Normal file
View File

@ -0,0 +1,7 @@
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen

View File

@ -0,0 +1,28 @@
import path from "path";
import { readlines } from "../../_utils";
import { part1_solver, part2_solver } from "./solution";
describe("day 1: trebuchet, pt 1", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(part1_solver(sample)).toBe(142);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part1_solver(input)).toBe(55090);
});
});
describe("day 1: trebuchet, pt 2", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample2.txt"));
expect(part2_solver(sample)).toBe(281);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part2_solver(input)).toBe(54845);
});
});

117
2023/day_01/solution.ts Normal file
View File

@ -0,0 +1,117 @@
/*
--- Day 1: Trebuchet?! ---
Something is wrong with global snow production, and you've been selected to take a look. The Elves have even given you a map; on it, they've used stars to mark the top fifty locations that are likely to be having problems.
You've been doing this long enough to know that to restore snow operations, you need to check all fifty stars by December 25th.
Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck!
You try to ask why they can't just use a weather machine ("not powerful enough") and where they're even sending you ("the sky") and why your map looks mostly blank ("you sure ask a lot of questions") and hang on did you just say the sky ("of course, where do you think snow comes from") when you realize that the Elves are already loading you into a trebuchet ("please hold still, we need to strap you in").
As they're making the final adjustments, they discover that their calibration document (your puzzle input) has been amended by a very young Elf who was apparently just excited to show off her art skills. Consequently, the Elves are having trouble reading the values on the document.
The newly-improved calibration document consists of lines of text; each line originally contained a specific calibration value that the Elves now need to recover. On each line, the calibration value can be found by combining the first digit and the last digit (in that order) to form a single two-digit number.
For example:
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet
In this example, the calibration values of these four lines are 12, 38, 15, and 77. Adding these together produces 142.
Consider your entire calibration document. What is the sum of all of the calibration values?
*/
import { sum, allIndicesOf } from "../../_utils";
const extractDigits = (s: string): string => s.replaceAll(/[a-zA-Z]/g, "");
const firstLast = (s: string): number => +`${s[0]}${s[s.length - 1]}`;
export function part1_solver(lines: string[]): number {
return lines
.map(extractDigits)
.map(firstLast)
.filter((x) => !isNaN(x))
.reduce(sum, 0);
}
/*
--- Part Two ---
Your calculation isn't quite right. It looks like some of the digits are actually spelled out with letters: one, two, three, four, five, six, seven, eight, and nine also count as valid "digits".
Equipped with this new information, you now need to find the real first and last digit on each line. For example:
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen
In this example, the calibration values are 29, 83, 13, 24, 42, 14, and 76. Adding these together produces 281.
What is the sum of all of the calibration values?
*/
const digits = [
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
];
type Match = {
digitNum: number;
startPos: number;
};
const wordsToDigits = (s: string): string => {
let res = "";
// Find the starting indices of all word numbers in the string
const matches: Match[] = digits.reduce((indices, digitStr, i) => {
const digitNum = i + 1;
const matchedIndices = allIndicesOf(s, digitStr);
return [
...indices,
...matchedIndices.map((startPos) => ({ digitNum, startPos })),
];
}, [] as Match[]);
// Sort the starting indices so we process the matches in order
matches.sort((a, b) => a.startPos - b.startPos);
// For each match...
// 1. Append the characters between the last match to the current match, unmodified.
// 2. Append the numerical value of the digit string to the result.
// 3. Update the last match value for the next iteration.
let lastmatch = 0;
matches.forEach((match) => {
res = res + s.slice(lastmatch, match.startPos);
res = res + match.digitNum;
lastmatch = match.startPos + digits[match.digitNum - 1].length;
});
// In case there are no more matches, but the string contains more random characters...
// append the rest of them to the result.
if (lastmatch < s.length) {
res = res + s.slice(lastmatch, s.length);
}
return res;
};
export function part2_solver(lines: string[]): number {
return part1_solver(lines.map(wordsToDigits));
}

100
2023/day_02/input.txt Normal file
View File

@ -0,0 +1,100 @@
Game 1: 6 green, 3 blue; 3 red, 1 green; 4 green, 3 red, 5 blue
Game 2: 2 red, 7 green; 13 green, 2 blue, 4 red; 4 green, 5 red, 1 blue; 1 blue, 9 red, 1 green
Game 3: 2 green, 3 blue, 9 red; 3 red, 2 green; 6 red, 4 blue; 6 red
Game 4: 9 red, 3 green; 3 green, 8 red, 6 blue; 12 blue, 4 green, 6 red; 4 green, 18 blue, 11 red; 9 blue, 2 green, 3 red; 14 blue, 7 red
Game 5: 1 blue, 2 green, 3 red; 16 red, 6 green; 6 green, 2 red; 9 red, 1 green
Game 6: 4 green, 7 red, 1 blue; 18 green, 6 blue, 7 red; 1 blue, 3 red, 9 green; 9 red, 19 green, 1 blue; 7 red, 9 green, 4 blue; 5 red, 5 blue, 10 green
Game 7: 16 blue, 5 green, 6 red; 1 blue, 6 red, 9 green; 6 green, 3 red, 2 blue; 2 red, 12 blue, 2 green
Game 8: 6 green, 10 red; 7 red, 6 green, 17 blue; 13 blue, 1 red
Game 9: 2 red, 4 green, 5 blue; 2 green, 5 blue; 4 green, 1 blue; 3 green, 3 red, 6 blue; 3 green
Game 10: 3 green, 5 red, 6 blue; 4 blue, 4 red, 5 green; 5 green, 9 red, 5 blue; 4 green, 6 blue, 10 red
Game 11: 1 blue, 7 red, 9 green; 1 blue, 13 red, 7 green; 5 red; 4 red, 7 green, 2 blue; 7 green, 12 red; 13 red, 2 blue, 12 green
Game 12: 4 blue, 2 red; 9 blue, 2 green, 3 red; 8 blue, 1 green, 1 red; 2 red, 3 green, 11 blue
Game 13: 6 red, 8 green, 2 blue; 6 red, 7 green; 3 green, 3 red; 2 blue; 3 red, 5 green
Game 14: 2 green, 11 blue, 1 red; 5 blue, 1 red, 1 green; 3 green, 12 blue, 2 red
Game 15: 4 blue, 6 red, 7 green; 1 red, 2 blue, 5 green; 6 red, 3 green, 8 blue; 7 green, 8 blue, 4 red
Game 16: 2 red, 16 blue; 2 green, 7 red; 15 blue, 7 red; 2 red, 3 green, 3 blue; 3 red, 1 green, 4 blue; 4 blue, 3 green
Game 17: 2 red, 3 green, 10 blue; 9 red, 4 blue, 3 green; 3 green, 11 red, 6 blue
Game 18: 1 red; 6 green, 1 red, 9 blue; 4 blue, 2 green; 6 blue, 10 green
Game 19: 2 red, 9 green; 2 red, 1 blue; 5 blue, 12 green; 5 green; 8 green, 2 red, 3 blue; 1 red, 11 green
Game 20: 3 green, 2 red, 7 blue; 1 blue, 10 green; 1 red, 14 blue, 13 green; 3 green, 19 blue, 4 red
Game 21: 8 red, 10 blue, 8 green; 2 red, 7 green, 18 blue; 4 green, 11 blue, 4 red; 5 green, 3 blue, 10 red
Game 22: 17 blue, 2 green, 2 red; 8 red, 7 blue; 1 red, 9 blue, 1 green
Game 23: 4 blue, 18 red, 4 green; 3 blue, 7 red; 11 red; 3 blue, 6 red; 19 red
Game 24: 10 red, 1 blue, 17 green; 17 green, 6 red; 14 green, 4 blue
Game 25: 4 blue, 9 green, 4 red; 3 green, 5 blue; 5 blue, 8 green; 3 green, 3 blue, 1 red; 10 green, 1 blue, 4 red; 2 green, 2 blue, 1 red
Game 26: 18 green, 3 red, 12 blue; 2 red, 7 green; 11 blue, 17 green; 12 green, 11 blue; 12 green, 4 blue, 3 red
Game 27: 1 red, 3 blue, 8 green; 15 blue, 8 red, 4 green; 6 red, 9 blue; 6 red, 12 blue, 9 green; 4 red, 7 blue, 15 green
Game 28: 1 red, 14 green; 1 blue, 11 green; 2 green; 4 red, 6 green, 1 blue
Game 29: 1 green, 13 red; 4 red, 16 green, 7 blue; 2 red, 4 blue; 12 green, 8 blue, 4 red; 2 red; 12 red, 5 green
Game 30: 3 green, 4 blue, 3 red; 5 blue, 4 green, 7 red; 5 blue, 2 green, 2 red; 3 red, 1 blue
Game 31: 1 blue, 8 green; 9 green, 2 blue, 1 red; 1 red, 2 blue
Game 32: 11 red, 5 green, 4 blue; 3 blue, 11 red, 8 green; 6 blue, 3 green, 17 red; 4 red, 7 green, 10 blue
Game 33: 6 blue, 4 red; 1 green; 1 green, 4 red, 4 blue; 1 green, 3 red, 10 blue; 10 blue, 1 red
Game 34: 2 green, 3 blue, 3 red; 4 red; 2 red, 2 blue
Game 35: 9 green, 13 blue; 13 blue, 14 red, 1 green; 11 blue, 4 red, 7 green; 5 blue, 5 red, 8 green; 4 red, 2 blue, 2 green
Game 36: 9 red, 5 blue, 8 green; 7 red, 20 blue; 6 green, 16 blue, 5 red; 12 red, 3 blue, 3 green; 3 green, 6 blue, 11 red; 11 red, 8 blue, 3 green
Game 37: 10 green, 11 red, 3 blue; 2 blue, 6 green, 11 red; 9 green, 8 red, 2 blue
Game 38: 2 red, 2 green, 4 blue; 3 red, 4 green, 3 blue; 8 green, 1 blue, 1 red; 3 red, 5 blue, 5 green
Game 39: 3 green, 17 red, 4 blue; 2 green, 20 red; 4 blue, 4 red, 5 green; 5 blue, 7 green, 7 red; 4 blue, 5 green, 16 red
Game 40: 2 green, 2 blue, 4 red; 3 blue, 16 green; 1 green, 2 blue; 1 red; 3 blue, 15 green; 13 green, 1 red, 2 blue
Game 41: 12 red, 10 blue, 9 green; 1 green, 15 red, 4 blue; 2 green, 8 blue, 12 red; 3 red, 4 green, 2 blue; 8 blue, 14 red, 10 green; 9 blue, 7 green, 6 red
Game 42: 5 red, 3 green, 6 blue; 4 blue, 6 green, 2 red; 10 blue; 3 red, 6 green, 10 blue
Game 43: 9 blue, 7 green, 1 red; 2 green, 2 red, 8 blue; 3 red, 15 blue, 11 green; 1 red, 6 blue, 1 green; 2 red, 1 blue; 1 red, 3 green, 7 blue
Game 44: 4 green, 6 red; 15 green, 6 red; 9 green, 16 red, 7 blue; 11 green, 4 blue, 12 red
Game 45: 3 blue, 6 green, 1 red; 4 green, 3 blue; 8 green, 3 blue
Game 46: 10 red, 8 blue; 12 red, 2 green, 17 blue; 17 blue, 6 red, 1 green; 18 red, 6 green, 3 blue; 16 blue, 2 green, 3 red
Game 47: 8 green, 13 red; 8 green, 8 red, 4 blue; 10 red, 3 green; 14 red, 5 green, 8 blue; 7 green, 19 red, 3 blue; 2 red, 5 green, 5 blue
Game 48: 7 green, 9 blue, 3 red; 7 blue, 1 green, 9 red; 7 green, 4 red, 1 blue; 6 green, 3 red, 1 blue
Game 49: 2 red, 3 green; 3 blue, 2 red; 4 red, 3 blue
Game 50: 3 red, 7 blue, 4 green; 2 green, 1 blue, 7 red; 4 red, 1 green, 5 blue
Game 51: 11 red, 6 green, 1 blue; 7 red, 1 blue, 9 green; 15 red, 18 green; 11 green, 1 blue, 11 red; 10 green, 14 red; 1 red, 11 green, 1 blue
Game 52: 18 blue, 1 red, 2 green; 18 blue, 3 green, 1 red; 2 green, 13 blue, 1 red
Game 53: 2 blue, 9 red, 6 green; 1 blue, 3 red; 7 red, 6 blue, 8 green; 2 red, 3 blue, 4 green; 1 green, 2 blue, 2 red
Game 54: 16 red, 4 blue; 1 green, 3 blue, 3 red; 2 green, 12 red; 2 green, 1 blue, 3 red; 10 blue, 6 red, 2 green
Game 55: 1 blue, 4 red, 1 green; 2 blue, 2 red; 13 red, 4 blue, 1 green; 4 blue, 9 red; 1 green, 1 blue, 16 red
Game 56: 12 blue, 12 green; 4 blue, 1 red, 3 green; 2 red, 12 green; 1 red, 11 green, 13 blue; 16 blue, 5 green
Game 57: 1 blue, 3 red; 10 green, 5 red; 5 green, 2 red; 1 red, 13 green
Game 58: 6 blue, 1 red, 6 green; 3 red, 9 blue; 4 red, 9 blue, 5 green; 1 green, 5 red, 7 blue
Game 59: 10 red, 3 green, 3 blue; 6 blue, 11 red, 1 green; 5 green, 10 red; 16 red, 2 blue, 4 green; 3 green, 10 red
Game 60: 2 green, 1 blue; 1 green, 1 blue, 4 red; 3 blue, 1 red, 1 green; 2 red, 2 green; 4 red
Game 61: 5 red, 1 green, 10 blue; 9 red, 10 blue; 1 red, 2 green, 4 blue; 10 blue, 2 green, 9 red; 1 red, 12 blue, 2 green
Game 62: 1 blue, 5 green; 4 blue, 12 green, 1 red; 7 blue, 3 green; 7 blue, 3 green; 3 blue, 1 green, 2 red; 7 blue, 1 red, 12 green
Game 63: 4 blue, 2 green, 5 red; 1 green, 2 red, 2 blue; 4 blue, 2 red, 2 green; 1 blue, 6 red, 2 green; 6 blue, 1 red; 1 green, 9 red, 6 blue
Game 64: 1 green; 3 green, 5 blue, 5 red; 3 red, 3 blue, 3 green; 1 green, 4 red, 6 blue; 5 red
Game 65: 2 red; 1 blue, 1 red; 7 red, 2 blue; 1 green, 4 blue, 3 red
Game 66: 3 red, 9 blue; 1 red, 6 blue, 15 green; 3 green, 3 red, 11 blue
Game 67: 2 red, 1 green, 2 blue; 6 red, 1 green; 1 blue, 1 red, 4 green
Game 68: 3 red, 1 blue; 1 green, 3 red, 2 blue; 1 green, 8 red; 2 blue, 3 red
Game 69: 5 blue, 6 red; 1 green, 15 blue, 10 red; 1 green, 2 red, 4 blue; 5 blue, 7 red; 3 red, 1 green, 11 blue
Game 70: 4 green, 2 red, 8 blue; 5 red, 3 blue; 10 green, 5 blue
Game 71: 1 red, 2 blue, 9 green; 3 red, 8 green; 1 red, 2 blue, 6 green; 3 red, 6 blue, 8 green; 6 green, 3 blue, 2 red; 3 red, 8 green, 6 blue
Game 72: 1 red, 11 green; 1 blue, 7 green, 1 red; 2 red, 12 green; 10 green, 6 red
Game 73: 9 green, 2 red; 1 blue, 3 green; 1 blue, 1 red, 7 green; 2 blue, 9 green, 4 red; 2 blue, 3 red, 8 green; 2 green, 9 red
Game 74: 2 green, 7 red; 1 green, 3 blue, 6 red; 4 green, 3 blue, 6 red; 2 green, 3 blue, 1 red; 3 red, 2 blue, 1 green
Game 75: 15 green, 2 blue; 15 green, 6 red, 2 blue; 12 green, 2 blue, 1 red
Game 76: 1 red, 9 green, 12 blue; 6 red, 12 green, 1 blue; 7 green, 2 blue, 1 red
Game 77: 11 blue, 1 red; 7 blue, 2 red, 13 green; 10 blue, 10 green; 12 blue, 3 red
Game 78: 4 green; 1 blue, 5 green; 5 green, 1 blue, 1 red
Game 79: 4 green, 7 blue, 16 red; 1 blue, 10 red, 5 green; 3 green, 4 red, 3 blue; 11 blue, 18 red, 5 green
Game 80: 1 red, 4 blue, 6 green; 14 blue, 16 red, 2 green; 2 blue, 5 red, 4 green; 2 green, 8 red; 18 red, 6 green, 2 blue; 18 red, 9 blue
Game 81: 11 red, 8 blue, 1 green; 12 blue, 2 green, 14 red; 16 red, 2 green, 6 blue; 17 red, 2 green; 3 green, 3 blue, 15 red
Game 82: 13 red, 1 blue, 6 green; 3 green, 12 red, 3 blue; 5 red, 3 green, 18 blue; 15 blue, 8 red
Game 83: 9 green, 5 blue, 5 red; 8 green, 15 blue, 7 red; 4 green, 6 red, 10 blue; 5 green, 2 red
Game 84: 2 blue, 2 green, 6 red; 2 green, 7 red, 1 blue; 3 green, 3 blue; 2 green, 3 red, 3 blue; 6 green, 4 red
Game 85: 1 blue, 3 green, 5 red; 2 green, 2 red; 4 red, 3 blue; 2 green, 3 blue, 1 red; 4 red, 2 green, 4 blue
Game 86: 6 red, 1 blue; 1 green, 16 red; 2 green, 1 red; 12 red, 1 blue
Game 87: 6 red, 12 green, 1 blue; 5 blue, 6 red, 4 green; 2 blue, 5 red, 8 green
Game 88: 3 green, 6 red, 2 blue; 3 blue, 2 green, 6 red; 1 red, 11 blue, 2 green
Game 89: 7 red, 3 blue, 9 green; 6 red, 3 blue, 15 green; 2 blue, 6 red, 12 green; 5 red, 8 green; 3 blue, 7 red, 9 green; 5 red, 7 green
Game 90: 2 green, 4 red, 19 blue; 13 blue, 4 red, 1 green; 14 blue, 8 green
Game 91: 12 green, 5 blue, 4 red; 9 green, 10 blue, 1 red; 13 green, 1 blue, 4 red; 2 red, 5 blue; 2 blue, 7 green, 2 red; 5 blue, 5 green, 3 red
Game 92: 9 red, 6 blue, 16 green; 11 green, 2 red, 7 blue; 1 green, 1 red, 3 blue; 4 green, 8 red
Game 93: 1 green, 4 blue, 8 red; 2 red, 1 green, 2 blue; 2 blue, 9 red; 1 green, 4 blue, 3 red; 3 red, 1 green, 4 blue
Game 94: 1 green, 7 red, 4 blue; 4 red, 3 blue; 16 blue, 9 red, 7 green; 9 red, 15 blue; 15 blue, 3 red, 6 green; 7 red, 10 blue, 12 green
Game 95: 5 green, 6 blue; 10 green, 9 blue; 4 blue, 8 green, 2 red; 5 blue, 5 green, 1 red
Game 96: 13 blue, 10 red, 2 green; 10 red, 2 green, 1 blue; 6 blue, 5 red, 3 green; 11 red, 3 green, 5 blue; 11 red, 2 green; 3 green, 6 blue
Game 97: 9 green, 11 red, 8 blue; 6 red, 9 blue, 2 green; 3 red, 17 blue, 1 green
Game 98: 14 blue, 3 green; 2 red, 15 blue, 3 green; 15 blue, 8 green, 1 red; 1 red, 8 green
Game 99: 2 green, 7 blue; 14 red, 1 green, 4 blue; 8 blue, 13 red, 2 green; 10 green, 7 red, 10 blue
Game 100: 5 green, 11 blue, 6 red; 5 green, 12 blue; 1 green, 14 blue, 1 red; 3 blue, 5 red, 6 green; 9 blue; 6 red

5
2023/day_02/sample.txt Normal file
View File

@ -0,0 +1,5 @@
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green

View File

@ -0,0 +1,28 @@
import path from "path";
import { readlines } from "../../_utils";
import { part1_solver, part2_solver } from "./solution";
describe("day 2: cube conundrum, pt 1", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(part1_solver(sample)).toBe(8);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part1_solver(input)).toBe(2683);
});
});
describe("day 2: cube conundrum, pt 2", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(part2_solver(sample)).toBe(2286);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part2_solver(input)).toBe(49710);
});
});

140
2023/day_02/solution.ts Normal file
View File

@ -0,0 +1,140 @@
/*
--- Day 2: Cube Conundrum ---
You're launched high into the atmosphere! The apex of your trajectory just barely reaches the surface of a large island floating in the sky. You gently land in a fluffy pile of leaves. It's quite cold, but you don't see much snow. An Elf runs over to greet you.
The Elf explains that you've arrived at Snow Island and apologizes for the lack of snow. He'll be happy to explain the situation, but it's a bit of a walk, so you have some time. They don't get many visitors up here; would you like to play a game in the meantime?
As you walk, the Elf shows you a small bag and some cubes which are either red, green, or blue. Each time you play this game, he will hide a secret number of cubes of each color in the bag, and your goal is to figure out information about the number of cubes.
To get information, once a bag has been loaded with cubes, the Elf will reach into the bag, grab a handful of random cubes, show them to you, and then put them back in the bag. He'll do this a few times per game.
You play several games and record the information from each game (your puzzle input). Each game is listed with its ID number (like the 11 in Game 11: ...) followed by a semicolon-separated list of subsets of cubes that were revealed from the bag (like 3 red, 5 green, 4 blue).
For example, the record of a few games might look like this:
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
In game 1, three sets of cubes are revealed from the bag (and then put back again). The first set is 3 blue cubes and 4 red cubes; the second set is 1 red cube, 2 green cubes, and 6 blue cubes; the third set is only 2 green cubes.
The Elf would first like to know which games would have been possible if the bag contained only 12 red cubes, 13 green cubes, and 14 blue cubes?
In the example above, games 1, 2, and 5 would have been possible if the bag had been loaded with that configuration. However, game 3 would have been impossible because at one point the Elf showed you 20 red cubes at once; similarly, game 4 would also have been impossible because the Elf showed you 15 blue cubes at once. If you add up the IDs of the games that would have been possible, you get 8.
Determine which games would have been possible if the bag had been loaded with only 12 red cubes, 13 green cubes, and 14 blue cubes. What is the sum of the IDs of those games?
*/
import { emptyLines, sum } from "../../_utils";
const colors = ["red", "blue", "green"];
const constraints = {
red: 12,
green: 13,
blue: 14,
};
type Game = {
id: number;
sets: Set[];
};
type Set = {
red?: number;
green?: number;
blue?: number;
};
const normalizeSet = (s: Set): Set => {
const { red = 0, green = 0, blue = 0 } = s;
return { red, green, blue };
};
const parseGameId = (s: string): number => +s.replace("Game", "").trim();
const parseSets = (set: string): Set =>
set
.split(",")
.map((s) => s.trim())
.reduce((set, cube) => {
const color = colors.filter((c) => cube.includes(c))[0];
const number = +cube.replace(color, "").trim();
return { ...set, [color]: number };
}, {} as Set);
const parseGames = (s: string): Game => {
const [gid, game] = s.split(":");
const id = parseGameId(gid);
const sets = game.split(";").map(parseSets).map(normalizeSet);
return { id, sets };
};
const withinConstraints = (g: Game): boolean =>
g.sets.every(
(set) =>
set.blue <= constraints.blue &&
set.green <= constraints.green &&
set.red <= constraints.red
);
export function part1_solver(lines: string[]): number {
return lines
.filter(emptyLines)
.map(parseGames)
.filter(withinConstraints)
.map((g) => g.id)
.reduce(sum, 0);
}
/*
--- Part Two ---
The Elf says they've stopped producing snow because they aren't getting any water! He isn't sure why the water stopped; however, he can show you how to get to the water source to check it out for yourself. It's just up ahead!
As you continue your walk, the Elf poses a second question: in each game you played, what is the fewest number of cubes of each color that could have been in the bag to make the game possible?
Again consider the example games from earlier:
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
In game 1, the game could have been played with as few as 4 red, 2 green, and 6 blue cubes. If any color had even one fewer cube, the game would have been impossible.
Game 2 could have been played with a minimum of 1 red, 3 green, and 4 blue cubes.
Game 3 must have been played with at least 20 red, 13 green, and 6 blue cubes.
Game 4 required at least 14 red, 3 green, and 15 blue cubes.
Game 5 needed no fewer than 6 red, 3 green, and 2 blue cubes in the bag.
The power of a set of cubes is equal to the numbers of red, green, and blue cubes multiplied together. The power of the minimum set of cubes in game 1 is 48. In games 2-5 it was 12, 1560, 630, and 36, respectively. Adding up these five powers produces the sum 2286.
For each game, find the minimum set of cubes that must have been present. What is the sum of the power of these sets?
*/
const setPower = (set: Set): number => set.red * set.green * set.blue;
const minimumCubesPossible = (game: Game): Set => {
return game.sets.reduce((maxes, currentSet) => {
const newMaxes = {};
newMaxes["blue"] = Math.max(currentSet.blue, maxes.blue || 0);
newMaxes["green"] = Math.max(currentSet.green, maxes.green || 0);
newMaxes["red"] = Math.max(currentSet.red, maxes.red || 0);
return newMaxes;
}, {} as Set);
};
export function part2_solver(lines: string[]): number {
return lines
.filter(emptyLines)
.map(parseGames)
.map(minimumCubesPossible)
.map(setPower)
.reduce(sum, 0);
}

140
2023/day_03/input.txt Normal file
View File

@ -0,0 +1,140 @@
.854...........................................................................362...........271...732........838.........24................
...*.............................117*...........459........767*648....#.........*...................................$...&..=................
....970.........368.124.+............57................653...........723.....366....*443..60.........536....441....45..879.....789...*......
...........749*...-...+..330.....................215%...*................725.....953........%.................*............639......331.419.
.......706.....59.............*....=...262.............678...........857.*............189....................912.+589.846*...*..............
..........*................393.59..418....*................151...........594...........*....584*258.......................17.997............
.......774....275........................777........841..............988.........121....908.........86.....482..295....................@....
.110..........%.....605..@.......305*18...............*....740.............840..*................52*.......*...........100...........250....
...........*..............856..............412.........761....*....344....*.....505.....................121......709...-....-...............
......980.269..189+............701..............22...$........343..*...684..............-375......223........97.*..........890......443.....
..904*..................555.....*.......38.....*....207............773.......................824.....*.......*..../....618..................
....................355*........362....*......442.$..........613...........%770.......526.....*.......418.....283..76....*....862...........
...450....*292..............735.....149...........143..........*...458...........279.........43..769...................$..48.....*..........
....*..413.........983*....*.................679.......642....214...#........107*......=.........*.....%...........276.39......196.889*624..
...128.................658.515...890#...................../...........................60..../....528..359.....451...*.....56................
...................719...................525.................$502............284-........@...489.................#..287.....@....+..........
...849...............*................../.........................282.+649...............217............240.....................833.....930.
.......666...179.....986.526................./927......73.....176*...............@...459...........=946..*..488...126.....*.................
..........@.....*549.....@...261.....370*951...........+.............114......170.......@...............269............471.891.$859.........
.............................../.................646.....-.327........*..237..............452......../......*620..713...............324.....
..................=716.....753....................-....431..=.......692.%.......210.......*.......860....208...............81*655....$......
......298....17*..........+....................................................*..........603................950.218.$......................
................692...54......+778.809........140..*.........249............%.332..............*.........372*......*.328.....=..............
.......421.............#..............+........*....493.......*..........589..................286...............254..........458...672...258
........*.....949.630.....725...609.........408.............108..............304.517......829.........666*..........724.182...........*.=...
.........435./....*..........*.*................580..................@.........*..&..147.-......221*......544..662/....*...........881......
..750.............561......568.487.@...935.......*....106...........104......808.......*............333...................&900..............
...................................287.$......930.....&.....*528.........332............755..................840../.............583.....209.
.371.299.................503.............................632................*.......&...................500........647..193.......-.........
....*........-902..2.123..*...912.......775......./...............241........734....90.968.513..66.566...................*..&...............
..................*....@.923...*.......*.....289..47.....785..710.......54................*......*....................767....452....=....597
.............348.362............607.....889.....#........*....*........*......$904................694...............................241.....
....955........*.....559*792............................307..25.........449..............*751.404.....134.....841...........................
......&.959...300............446.504.644....692...............................#.................-.....*.......*...758*35....................
.908$...*...........&..861...........=.....%....240............-..+..9.514...615.....&....-646.....538...144.751...........899.........545..
.......806.270*....946.@...............*..........*.555@....803..322.-............410..........514.................510..10..*.....858..-....
...............373....................7.918.....699.........................710.......&...........-.....78%............+....34..............
....653...............................................553.......896.......-......&...721....970.............................................
.......%...........379..377.....770@.................$.....126....*...712.287....951.........*......984*..........+.............+700........
..............924...*....*.............422...................*...233.*........................124...........902....181......................
................&....156..363.....*855....*.................884......509..879..755.......$...........*635......*........283.........661.....
..559..........................393.........766...789.............683..................461..#......910.........904.........$.%......*.....13.
.........=...568.........680/.......................*......*522.#..........................747...........*113................702...952......
....*....334...*...392..........910*...............233..189.........219.879............225......521...941...................................
.146.981......284.*.......*972......391.....789*...................................628*.....*....*................675.......................
..................921..151......................983...............582......983.690.......213.137.268.............*..............24$.........
....561....................600........106-...............226..................*.....996.............................681.....768.......852...
..............................%............................$................=...963..$.....@............421*305.......*.....*........$......
.....923.285*.....961...........*......$812......812..851.............678.29.......*......501.....228..............385...853...........251..
.444*...............*...998...99.711.............+.....*......330.....*.........287...........781..+..........%445..........................
......$....250=.....965...*.............................113...$......766....$.......941........-......658.............894........351........
......335...............463.328*.....411....%.............................981.113......*5.............*...773=.573&....*............$.......
..........%348..................460.....*5..517.......583.261.....889@.......................953.....496...............547............620...
...299.................367.......................+....*................852.442.796.........*.@...............=................834.....*.....
....*....772...487.......................#......938.462.956..41.643...*.....#.....*592....66...809.368..3..549........................772...
.566........*.....*320.....498..775.230.193....................*......961.........................*....*.......%283.....406.......495.......
........292..585..............*.*.....*..........213...*309...................469..549......413........903................*....29..*........
.........*.......@.........551..806...489......................51.655.999*.......*.$.............21*.................300..931....*..595.....
......878......62../...........................871......169..=..&..*......235..788...497..........................68....*.......191.........
.144.........+.....31............-...............*..623*....428.....955...............*.............424....89....*......728.............*665
.............447...............530...203...955.336..........................227........665.......$.........*.....669..............473.......
835...................*323..............*./...........=.....24..........*.........................452.......9.............263.........570...
......568...803@.....................152.......209.933.....*....877..667.895............548...963......................................*....
.......$.........=............................*...........948..-...................171.*........*.605.765..-........90..............992.....
..360..........#.476...........................564../.............755*...............+..709...11.....*......909..........696..124%..........
........74...73................320.........658......739...=...........484...860*....................................314.....................
...=509...*.........79.290........*...222...*.............46...940..............960.....473.....320..........$681......*591..269....../.....
........887.94@......*..*.........302...+.784.554+............+......#......455........./............891..........457........*...609.120....
....................874.246.....................................+.....228..*....&.........272....%..$.....*377.....*..52..604....%..........
.....44.....870*457................905.45......58...............956.........935.551...807..$.....21....356.......317....................%...
.........=...................267......*...300=.........543..............398..............#.................$.......................386...745
..........145......+............................*......*...........7....$.............64...........646....675..1..930..770.....791.$........
................744....462......443&......*389..575..965...805....+..14.......761*578..-...#..776...*..................-........-.......822.
....668.484...............*............875.................*.........*....................227...*..908.............215......*.......270.....
.......*......771..........318....883......881...........655.@26..130..799.......876..91......28...........699.........807...510............
.............-........391*.........*.......+......903..................*.....379.*....@...........713........#............*.................
..........+................196..230...........411....*965..682.......873....$.....916....755....&..=.....................296......+958.983..
...*.....718.......279........%...............................*.271.............@.......*......932.......621..637.843..................*....
..59..........%2...........................................400...*...142.870...746......256..........865*...........%...=.....%...409...761.
............@...........122*157...........394........%.444.....207...-......*.........................................434..827...*..........
.....266..19.....=..............624.......*........398....*................373...........418...16.....654.878*.................890..........
...............487..........884....*......199.227........723......914*411...........228..........%...................872................-...
.....937..608.................*....306........$....................................*..................522..309.@16.....*.............765....
......#....................128../.................%136....140.................773...114...........33....*....*.........615.....303..........
.249.....590..$...949..768.......380......%...996..............833...28...310.#...................*..338.....770...559......................
...+.854.../.678..*....................646...*.........................=...&..............#.....422...................#.231...714.122.......
......*...........552........................741..........+.......437........455*768..134..69..........*........519.......*........*........
.......976.............466......497$.............607......783........*....*.............@..............28........-.........279......394.....
............%....857...*....542.........915.543..$...............979...581.66......555....................331...................281.........
....715......542..#..20....@........241...*...*.........701.......$...........113...../...193..96*305........&................/...#...489...
219*...................................#.599...845.....*.....................$....*.........*...................$....996...240........*.....
..........151.520...554.............................665..........................1.398.=450..426.....198.....326.....+..........-....129....
.........*...........*.................687..............588....62..........504................................................970...........
..........463.....776......804............*..............*.....*..........%....90/...834.790...514...740.770.......667......................
....392..................................371...184........906.56....575.............*.............*.........*......*......435.....308.......
....*..........*......908..........497...........................-.........884....849............374.....620....727......&........../.......
.125........862.326......&........+..........497.....&811.......213.......*...........465....................64.....993.....................
......................%.....288...............*...-.......617...........-..677........*.....32..........-907.+........*.....=....48.475.....
.........787.........400.....*.......420....884.425......*.....420...727........#27..181.....*....414..............986......114./.....#..404
........*.......%...........596....=.*....................863................$................428..*......899.....................114.......
.595=.112.737.699................382.888..........................315...@...325..........480........115..*.........-......368...............
...........*......+.@......652.*...............................&.....@..182.......219$.........945+.............844...........996....744*...
..87......749..535...395..#....339..564.....813....410.........135...........330.......828...........585......................*..........870
...+........................$........+..967*.........*....921......321......%................612@....*......................44..............
.......764...716............818..327..............578.......*...../...........941..................736..@421........762.........282.........
861#......*..@.......982..........*.........+...............714.................*..867.....863........................@....614....=.........
........549................*....260.........91................................85.....$........*.803*895..622.$..............*.........684...
............770*346.....714.652......145.........270...286..........#.......................66..........*.....337.176.813...483...223*......
..........................................*..392..&.........505...957.@.........158...285......881#....497.........+...*....................
.........=../..../.....588........227....639............741*..........443..681..........+..153........................335...................
........201.671.96......$............*.....................................*........415.......*........-.......155...........848.58&........
............................922......92...........180..........................&39...%....208..389......696.....*............=.......883.852
....237.........950.........*............80..............................................*....................657.......................*...
....../..611.......*.....671...443...971.&....366....381...442....458...$.......589.343.397.....463.......60.......&........125......&......
..853...../..945..564...........*......*.......@......-................783..........*.......................*.......28......=.........373...
................*.......+843..550..998.973.........+.....208.565..@..............231......292............+.365..172............+............
......117......615..................*............299............&..862.895............/86...*....114..552........*...697.....733...388......
.....................................212..261........885...............*...903..26*..........50.....-..........158................*.........
...../........11..360....748......................67....*272.....320...16.....*....137.905......239......470......................433.......
...141........*.....%......+......967........-...%...........243...*.......904............*....*..............88.377......619...............
................=.....-668....%.....=.+461..525.....662.....*......196..28..............778...940..400..682...*...*.........*..638*.........
779#..113........209...........744....................*...144..811....../...#......................-...*.....297..713.....50................
.........$................#.........844...6...........62.......*.............957...&.......112@.......211.............173....989............
..749.......$......989..931................*....&............424.........709.......867............590...................*.......*..645......
...*..290...573......*............437....227.....53......132............#....471%.............501..%..................733.....270.....=.....
..637...*............596............................=....*.......400...............*...........*....................................#.......
......958.....757%.........=.........228......624...746.81../.....*........../..718.198..38...184..............*820..774......./830.693.....
.........................453...405.=...=....................100.144.......728...........*...................498............$................
..616............................*.756...310.........#52.............130.......=........506.....509.779..........723.......182..+...........
...*....49.....-..............551..........*................789./.....*......306...613........./......*..491....*...............791..931....
...863.....%.72......832.653........*490....814.....984.....=...741...568..........*.................998........567........+........#.......
.........171..........*..-.......406...............*....389.....................486.....630............../...............457.576............
..............308..515..................373@......709..&..............*185..................689..........751........44..........*764........
..............*..............661....=.........*.............993....984.....*.......908......=...273............../.*........................
.......582..335...260....59......998../.....39.760.313*174...*..........@.183......................*47....&994.887.577........*464.....22...
......*...............................449..................802........762.....522..139+..154..266$......................46.323.....712*.....
....827.....................................35......600*29.....724........488............*...............149*227.........*..................
........@......278*............@..135..........594.........470*...........*....540*.......42..............................775.536..790......
.....990...........742......181....*..............*..@521................743.......552............310...*....+738.....................*.....
.......................125.......311............715........263...........................................173...................235....291...

10
2023/day_03/sample.txt Normal file
View File

@ -0,0 +1,10 @@
467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..

7
2023/day_03/sample2.txt Normal file
View File

@ -0,0 +1,7 @@
123.456...
...*......
..........
123*456...
..........
..123*....
......456

View File

@ -0,0 +1,31 @@
import path from "path";
import { readlines } from "../../_utils";
import { part1_solver, part2_solver } from "./solution";
describe("day 3: gear ratios, pt 1", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(part1_solver(sample)).toBe(4361);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part1_solver(input)).toBe(553825);
});
});
describe("day 3: gear ratios, pt 2", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(part2_solver(sample)).toBe(467835);
const sample2 = await readlines(path.resolve(__dirname, "./sample2.txt"));
expect(part2_solver(sample2)).toBe(168264);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part2_solver(input)).toBe(82962801);
});
});

410
2023/day_03/solution.ts Normal file
View File

@ -0,0 +1,410 @@
/*
*/
import { sum } from "../../_utils";
function isDigit(char: string): boolean {
return /^\d$/.test(char);
}
function isSymbol(char: string): boolean {
return !isDigit(char) && char !== ".";
}
function getCharAt(
m: string[],
row: number,
column: number,
fallback: string = "."
): string {
if (typeof m[row] !== "undefined") {
return m[row][column] || fallback;
} else {
return fallback;
}
}
export function part1_solver(lines: string[]): number {
// approach:
// 1. assume all numbers are invalid at first (pending)
// 2. continuously check the pending numbers to see if they can be moved to valid (a symbol is found)
// 3. once the iterator is out of range of a number, move it to invalid list
let valid_part_numbers = [];
lines.forEach((line, row) => {
// const elements = line.split(".");
let column = 0;
let buffer = "";
let is_valid = false;
while (column <= line.length) {
const current_char = line[column];
if (isDigit(current_char)) {
buffer += current_char;
// check previous row
const up_left = getCharAt(lines, row - 1, column - 1);
const up_mid = getCharAt(lines, row - 1, column);
const up_right = getCharAt(lines, row - 1, column + 1);
const left = getCharAt(lines, row, column - 1);
const right = getCharAt(lines, row, column + 1);
const down_left = getCharAt(lines, row + 1, column - 1);
const down_mid = getCharAt(lines, row + 1, column);
const down_right = getCharAt(lines, row + 1, column + 1);
if (!is_valid) {
is_valid =
isSymbol(up_left) ||
isSymbol(up_mid) ||
isSymbol(up_right) ||
isSymbol(left) ||
isSymbol(right) ||
isSymbol(down_left) ||
isSymbol(down_mid) ||
isSymbol(down_right);
}
if (isDigit(right)) {
column += 1;
continue;
} else if (isSymbol(right)) {
valid_part_numbers.push(buffer);
is_valid = false;
buffer = "";
} else {
if (is_valid) {
valid_part_numbers.push(buffer);
}
is_valid = false;
buffer = "";
}
} else {
buffer = "";
is_valid = false;
column += 1;
continue;
}
column += 1;
}
});
return valid_part_numbers
.map((nstr) => +nstr)
.filter((n) => !isNaN(n))
.reduce(sum, 0);
}
/*
*/
type Element = {
kind: "number" | "gear";
value: string;
position: [number, number];
};
type Gear = {
n1: number;
n2: number;
};
const checkColumsFor = (
lines: string[],
row: number,
columns: number[]
): number[] => {
let matched_nums = [];
columns.forEach((column) => {
if (isDigit(getCharAt(lines, row, column))) {
// The target value was a digit. There are two cases:
// 1. The digit belongs to the same number we've seen before. E.g.
// ...123.......
// ....*........
// 2. The digit belongs to a new number on that row. E.g.
// ...123.456...
// ......*......
} else {
// The target value was not a digit, so ignore
}
});
// columns.map(col => isDigit(getCharAt(lines, row, col))).every()
return columns.reduce((matched_nums, column) => {
if (isDigit(getCharAt(lines, row, column))) {
}
}, []);
};
const checkTopRow = (
lines: string[],
currentRow: number,
currentColumn: number
): number[] => {
const row = currentRow - 1;
const column = currentColumn;
let adjacent_nums = [];
const up_left = getCharAt(lines, row, currentColumn - 1);
const up_mid = getCharAt(lines, row, currentColumn);
const up_right = getCharAt(lines, row, currentColumn + 1);
if (isDigit(up_left) || isDigit(up_mid) || isDigit(up_right)) {
console.log("found on prev row");
// get all the nums from the previous row
const nums = (lines[row - 1] || "")
.split(".")
.filter((s) => s.length > 0)
.map((s) =>
s
.split("")
.filter((c) => isDigit(c))
.join("")
);
// figure out which num overlaps this gear
const res1 = nums.find((n) => {
const foundNumIndex = lines[row - 1].indexOf(n);
const lastDigit = foundNumIndex + n.length - 1;
console.log(JSON.stringify({ foundNumIndex, lastDigit, column }));
return (
foundNumIndex === column - 1 ||
foundNumIndex === column ||
foundNumIndex === column + 1 ||
lastDigit === column - 1 ||
lastDigit === column ||
lastDigit === column + 1 ||
(column - 1 >= foundNumIndex && column + 1 <= lastDigit)
);
});
if (res1) {
adjacent_nums.push(res1);
const res2 = nums.slice(nums.indexOf(res1)).find((n) => {
const foundNumIndex = lines[row - 1].indexOf(n);
const lastDigit = foundNumIndex + n.length - 1;
console.log(JSON.stringify({ foundNumIndex, lastDigit, column }));
return (
foundNumIndex === column - 1 ||
foundNumIndex === column ||
foundNumIndex === column + 1 ||
lastDigit === column - 1 ||
lastDigit === column ||
lastDigit === column + 1 ||
(column - 1 >= foundNumIndex && column + 1 <= lastDigit)
);
});
if (res2) {
adjacent_nums.push(res2);
}
console.log(
"res is " +
JSON.stringify({
res1,
res2,
nums,
last: lines[row - 1],
column,
})
);
}
}
return adjacent_nums;
};
const checkCurrentRow = (
lines: string[],
currentRow: number,
currentColumn: number
): number[] => {
const row = currentRow - 1;
const column = currentColumn;
let adjacent_nums = [];
const left = getCharAt(lines, row, column - 1);
const right = getCharAt(lines, row, column + 1);
if (isDigit(left) || isDigit(right)) {
console.log("found on this row");
// get all the nums from this row
const nums = lines[row]
.split(".")
.filter((s) => s.length > 0)
.map((s) =>
s
.split("")
.filter((c) => isDigit(c))
.join("")
);
// figure out which num overlaps this gear
const res1 = nums.find((n) => {
const foundNumIndex = lines[row].indexOf(n);
const lastDigit = foundNumIndex + n.length - 1;
return (
foundNumIndex === column - 1 ||
foundNumIndex === column ||
foundNumIndex === column + 1 ||
lastDigit === column - 1 ||
lastDigit === column ||
lastDigit === column + 1 ||
(column - 1 >= foundNumIndex && column + 1 <= lastDigit)
);
});
if (res1) {
adjacent_nums.push(res1);
const res2 = nums.find((n) => {
const foundNumIndex = lines[row].indexOf(n);
const lastDigit = foundNumIndex + n.length - 1;
return (
foundNumIndex === column - 1 ||
foundNumIndex === column ||
foundNumIndex === column + 1 ||
lastDigit === column - 1 ||
lastDigit === column ||
lastDigit === column + 1 ||
(column - 1 >= foundNumIndex && column + 1 <= lastDigit)
);
});
if (res2) {
adjacent_nums.push(res2);
}
}
}
return adjacent_nums;
};
const checkBottomRow = (
lines: string[],
currentRow: number,
currentColumn: number
): number[] => {
const row = currentRow - 1;
const column = currentColumn;
let adjacent_nums = [];
const down_left = getCharAt(lines, row + 1, column - 1);
const down_mid = getCharAt(lines, row + 1, column);
const down_right = getCharAt(lines, row + 1, column + 1);
if (isDigit(down_left) || isDigit(down_mid) || isDigit(down_right)) {
console.log("found on next row");
// get all the nums from the next row
const nums = lines[row + 1]
.split(".")
.filter((s) => s.length > 0)
.map((s) =>
s
.split("")
.filter((c) => isDigit(c))
.join("")
);
// figure out which num overlaps this gear
const res1 = nums.find((n) => {
// [6 7 8 9]
// [0 1 2 3]
const foundNumIndex = lines[row + 1].indexOf(n);
const lastDigitIndex = foundNumIndex + n.length - 1;
return (
foundNumIndex === column - 1 ||
foundNumIndex === column ||
foundNumIndex === column + 1 ||
lastDigitIndex === column - 1 ||
lastDigitIndex === column ||
lastDigitIndex === column + 1 ||
(column - 1 >= foundNumIndex && column + 1 <= lastDigitIndex)
);
});
if (res1) {
adjacent_nums.push(res1);
const res2 = nums.find((n) => {
// [6 7 8 9]
// [0 1 2 3]
const foundNumIndex = lines[row + 1].indexOf(n);
const lastDigitIndex = foundNumIndex + n.length - 1;
return (
foundNumIndex === column - 1 ||
foundNumIndex === column ||
foundNumIndex === column + 1 ||
lastDigitIndex === column - 1 ||
lastDigitIndex === column ||
lastDigitIndex === column + 1 ||
(column - 1 >= foundNumIndex && column + 1 <= lastDigitIndex)
);
});
if (res2) {
adjacent_nums.push(res2);
}
}
}
return adjacent_nums;
};
export function part2_solver(lines: string[]): number {
let gears: Gear[] = [];
lines.forEach((line, row) => {
let column = 0;
let adjacent_nums = [];
while (column <= line.length) {
const current_char = line[column];
if (current_char === "*") {
const top_nums = checkTopRow(lines, row, column);
adjacent_nums.push(top_nums);
const current_nums = checkCurrentRow(lines, row, column);
adjacent_nums.push(current_nums);
const bottom_nums = checkBottomRow(lines, row, column);
adjacent_nums.push(bottom_nums);
console.log(JSON.stringify({ adjacent_nums }));
if (adjacent_nums.length === 2) {
console.log("found a gear!");
gears.push({ n1: +adjacent_nums[0], n2: +adjacent_nums[1] });
} else {
adjacent_nums = [];
}
} else {
adjacent_nums = [];
column += 1;
continue;
}
column += 1;
}
});
return gears
.map((g) => g.n1 * g.n2)
.filter((n) => !isNaN(n))
.reduce(sum, 0);
}

219
2023/day_04/input.txt Normal file
View File

@ -0,0 +1,219 @@
Card 1: 99 65 21 4 72 20 77 98 27 70 | 34 84 74 18 41 45 72 2 1 75 52 47 50 93 25 10 79 87 42 69 8 12 54 96 92
Card 2: 51 49 25 92 40 31 18 3 83 4 | 4 40 57 75 16 38 25 92 51 3 36 77 70 94 83 49 18 59 19 31 41 99 43 89 15
Card 3: 5 52 69 84 27 47 17 49 32 98 | 76 82 97 2 17 34 32 31 55 84 87 49 91 81 5 72 23 67 21 35 66 65 44 12 98
Card 4: 2 81 24 58 9 82 21 43 85 83 | 38 21 97 67 82 85 40 24 93 59 53 46 5 15 81 33 22 58 8 89 94 2 3 69 72
Card 5: 6 72 50 45 29 12 55 31 68 62 | 45 16 80 68 29 27 55 7 72 31 66 20 39 9 13 12 62 30 50 6 94 49 42 81 4
Card 6: 26 87 63 54 56 79 90 19 23 7 | 55 13 10 66 17 6 91 93 51 22 65 38 16 68 84 64 43 81 24 85 75 69 11 2 3
Card 7: 63 5 44 82 67 85 1 86 43 47 | 27 69 85 64 34 12 1 36 94 82 4 16 46 63 5 92 14 68 49 86 80 84 67 25 44
Card 8: 51 70 64 30 87 82 2 67 39 56 | 11 49 5 40 58 22 19 53 1 41 66 44 4 65 43 72 98 95 52 8 23 45 3 27 48
Card 9: 9 53 83 37 28 10 74 51 47 59 | 51 65 22 5 87 33 23 17 37 72 60 39 20 88 62 25 40 35 8 11 64 26 55 1 34
Card 10: 84 67 52 95 62 83 39 96 6 14 | 95 5 24 10 96 83 22 21 58 84 26 52 68 32 14 1 67 35 45 37 40 6 76 62 97
Card 11: 62 33 65 83 31 20 45 96 8 63 | 98 96 29 69 7 24 15 4 74 14 65 89 34 37 75 78 46 11 17 40 1 57 94 9 55
Card 12: 29 47 83 13 31 58 3 43 6 46 | 6 81 45 26 31 58 3 21 20 47 75 71 13 74 22 93 35 96 38 44 85 83 29 28 50
Card 13: 33 97 31 48 60 98 94 80 30 29 | 16 33 73 49 37 44 41 47 34 83 11 62 54 86 60 84 29 63 94 28 59 61 71 98 40
Card 14: 47 16 73 33 50 46 39 4 98 14 | 70 62 15 52 98 74 17 69 23 4 94 79 10 19 50 7 37 41 1 39 25 5 86 28 87
Card 15: 27 14 33 76 13 55 87 53 44 74 | 23 17 37 91 66 89 24 86 44 49 52 34 79 6 56 1 46 29 9 71 48 30 31 35 60
Card 16: 95 6 8 69 70 72 60 43 76 30 | 37 83 63 36 9 26 6 20 66 39 52 19 69 12 62 85 32 82 35 45 55 51 18 60 17
Card 17: 74 76 40 52 9 43 59 37 17 92 | 73 62 70 27 55 47 11 18 74 1 71 3 88 65 89 2 58 86 10 42 22 56 29 36 30
Card 18: 79 5 97 48 36 10 67 56 7 6 | 21 54 33 95 43 71 14 46 82 23 70 73 74 51 27 78 91 88 42 92 39 64 18 13 59
Card 19: 62 32 7 51 8 22 26 41 30 16 | 28 9 81 2 53 52 78 25 56 86 3 10 67 1 22 79 24 17 43 99 87 82 93 34 58
Card 20: 41 52 12 40 17 56 72 84 98 63 | 71 69 37 74 47 97 9 34 6 36 96 95 8 49 39 15 85 5 46 64 93 54 20 2 89
Card 21: 85 60 95 97 1 33 27 86 57 54 | 65 97 50 86 45 25 33 70 61 19 54 90 60 57 78 1 29 63 27 76 95 52 46 85 47
Card 22: 43 98 37 17 44 70 52 96 61 8 | 60 17 77 34 74 16 14 22 10 98 52 96 67 62 43 49 8 61 47 90 29 63 70 44 37
Card 23: 68 58 25 26 6 65 38 2 17 80 | 99 26 36 22 52 6 13 82 17 10 65 15 58 3 68 14 2 77 80 84 72 46 29 25 38
Card 24: 47 9 24 20 15 57 29 83 75 11 | 33 47 91 75 20 57 11 27 29 10 14 26 83 15 24 43 82 86 9 18 1 61 98 46 76
Card 25: 92 63 7 80 40 90 46 84 78 12 | 63 40 24 84 75 80 87 56 74 79 92 59 2 66 16 96 78 12 67 46 61 90 86 38 7
Card 26: 33 13 64 23 46 81 73 54 25 95 | 7 75 50 67 44 69 70 22 45 30 12 93 17 26 11 55 10 52 53 36 79 62 27 92 9
Card 27: 58 66 74 59 73 17 92 61 80 99 | 2 83 81 31 34 57 7 22 32 74 39 15 44 23 9 90 88 3 46 20 62 51 42 21 95
Card 28: 35 55 89 36 68 49 79 62 4 31 | 1 26 23 88 28 49 58 54 44 60 33 9 5 99 8 2 95 20 40 12 72 82 43 50 25
Card 29: 73 80 6 42 37 33 68 34 31 79 | 6 63 65 57 77 73 99 56 16 28 80 90 31 51 52 45 79 1 17 42 37 68 46 4 91
Card 30: 99 89 9 45 13 6 91 57 73 90 | 92 54 13 2 40 10 78 71 7 3 49 37 60 53 96 73 61 98 1 45 66 24 48 94 19
Card 31: 21 57 2 83 51 17 96 79 16 60 | 72 35 2 83 51 16 41 96 17 80 25 26 46 57 60 10 50 58 49 79 43 75 21 82 1
Card 32: 25 37 47 88 28 84 49 35 27 71 | 90 73 1 13 93 16 52 74 67 62 7 69 56 87 21 63 86 32 58 59 27 97 61 88 83
Card 33: 68 38 12 31 86 27 41 15 21 66 | 56 64 75 86 19 27 61 7 15 29 3 67 28 11 66 21 22 14 40 24 68 94 13 53 18
Card 34: 9 58 8 48 43 78 67 96 62 6 | 59 56 13 92 77 10 89 71 72 65 98 33 23 40 30 44 97 54 52 84 36 82 26 32 19
Card 35: 74 35 15 51 19 2 98 22 5 20 | 68 60 62 22 84 98 15 7 24 30 18 19 56 52 80 37 74 26 54 41 8 31 34 61 49
Card 36: 82 3 19 48 71 65 47 89 21 36 | 43 75 96 2 32 91 28 37 69 71 18 57 15 35 25 24 88 34 52 31 79 17 49 20 26
Card 37: 72 35 36 87 99 38 91 24 3 20 | 9 62 21 28 64 13 8 35 75 69 87 97 15 46 98 89 24 12 43 34 19 86 72 41 92
Card 38: 96 81 10 64 65 84 38 30 80 68 | 84 3 91 30 26 36 69 95 10 40 87 99 13 7 75 38 82 80 2 31 37 28 90 48 52
Card 39: 6 62 96 34 41 98 81 5 11 57 | 95 59 67 46 36 38 27 74 97 87 72 69 32 37 94 98 79 17 49 5 10 42 48 51 30
Card 40: 96 15 86 31 62 56 22 41 93 33 | 90 21 67 65 50 70 35 89 38 84 55 77 59 57 83 69 2 37 20 36 52 80 27 85 19
Card 41: 40 83 52 58 28 56 68 27 34 87 | 39 38 77 93 69 31 60 54 98 35 15 30 25 73 29 14 66 28 42 82 47 50 17 21 49
Card 42: 11 61 94 85 46 30 7 45 18 93 | 83 93 85 34 22 62 92 60 53 98 41 2 96 1 81 49 72 44 59 26 4 97 65 95 39
Card 43: 11 65 98 28 82 33 80 7 5 36 | 93 83 4 97 60 75 19 23 87 57 52 24 41 32 40 69 30 39 45 88 91 74 37 67 17
Card 44: 61 85 7 94 21 75 84 49 43 92 | 34 66 52 97 82 48 55 12 68 47 99 57 8 30 86 73 28 60 22 63 88 74 78 79 11
Card 45: 68 64 67 10 87 6 29 85 54 86 | 95 85 77 64 35 50 87 97 6 89 86 79 36 43 56 2 10 32 29 68 1 54 67 21 48
Card 46: 13 94 35 87 57 95 50 17 91 20 | 75 91 20 13 76 58 77 19 86 36 87 95 8 80 42 17 57 53 15 94 83 60 35 50 48
Card 47: 75 39 44 23 55 37 76 57 96 34 | 92 40 78 57 75 64 67 66 33 27 23 71 31 37 47 83 16 55 76 96 39 34 44 49 3
Card 48: 29 28 65 97 10 36 1 94 42 23 | 42 65 81 61 56 29 19 28 52 22 66 31 1 43 85 84 5 71 36 23 9 89 27 94 72
Card 49: 8 24 35 89 29 80 42 90 79 41 | 16 60 95 58 53 8 55 22 65 15 97 74 64 93 82 51 1 78 73 61 98 23 5 7 37
Card 50: 58 78 6 97 95 36 26 66 56 99 | 67 52 23 15 73 32 95 29 58 99 36 64 94 98 26 60 47 2 78 56 75 77 97 66 6
Card 51: 23 27 66 17 96 8 90 10 39 91 | 83 65 91 43 90 21 75 99 76 66 57 18 94 8 6 96 54 1 23 28 51 17 27 10 39
Card 52: 54 92 42 65 80 68 45 39 59 24 | 42 86 98 93 39 28 68 65 87 71 37 92 43 76 5 45 54 96 88 59 80 34 24 62 78
Card 53: 55 63 13 70 99 42 1 86 92 23 | 30 17 92 78 32 24 94 1 70 5 13 55 49 88 48 45 99 63 67 79 12 42 86 23 19
Card 54: 94 77 65 92 18 59 44 40 53 79 | 34 65 45 6 99 40 44 59 89 94 55 14 25 47 79 81 53 77 18 23 92 35 33 27 13
Card 55: 92 24 56 3 32 36 50 17 1 74 | 52 78 94 1 74 60 98 55 56 97 89 92 61 85 37 22 17 66 57 50 36 32 48 20 24
Card 56: 72 28 38 64 30 52 84 67 71 89 | 44 58 22 88 70 14 74 26 34 13 85 77 3 52 29 45 84 99 66 73 41 80 81 49 17
Card 57: 21 26 46 29 98 38 80 72 52 47 | 77 79 61 36 98 54 9 87 18 85 42 16 48 51 46 32 47 2 95 8 44 38 58 33 21
Card 58: 78 84 40 65 67 3 37 66 90 74 | 16 46 73 30 26 69 11 49 19 80 97 43 98 18 83 8 60 91 6 24 31 52 74 66 92
Card 59: 29 42 92 24 75 32 72 89 48 81 | 75 78 79 22 19 93 61 1 84 49 15 72 55 40 98 76 36 65 59 24 11 58 32 92 18
Card 60: 64 53 27 3 97 39 40 14 90 81 | 69 35 57 39 46 51 74 71 97 14 1 82 61 68 72 56 93 8 34 75 48 3 78 13 32
Card 61: 7 87 17 45 39 52 18 66 32 48 | 83 42 71 19 65 92 56 27 47 24 70 51 34 23 60 36 49 54 11 80 78 69 38 57 76
Card 62: 77 5 80 47 51 70 64 30 62 63 | 24 21 73 4 80 90 53 70 44 26 39 17 72 89 35 55 36 66 83 25 29 52 98 57 43
Card 63: 67 46 98 44 57 9 15 2 16 58 | 13 61 92 81 10 84 96 82 12 55 99 23 8 29 90 91 95 83 32 63 79 85 51 88 97
Card 64: 35 38 83 64 3 48 87 55 75 34 | 85 41 16 9 80 81 18 86 6 66 33 69 61 37 3 99 32 62 82 30 84 5 40 11 90
Card 65: 59 51 90 42 5 70 88 61 96 2 | 80 12 19 76 40 22 86 34 83 74 26 93 72 71 37 14 3 25 91 30 17 62 4 6 89
Card 66: 85 18 5 57 55 34 32 7 69 80 | 12 31 1 33 28 56 11 17 22 29 47 21 38 20 59 15 50 81 89 63 10 62 79 68 75
Card 67: 69 41 76 8 31 95 13 52 93 23 | 92 41 4 55 93 8 3 89 13 82 31 83 44 78 62 7 2 94 52 95 24 51 23 18 87
Card 68: 80 11 17 71 45 35 91 44 70 52 | 57 91 77 3 14 31 30 53 43 34 27 86 54 79 62 85 83 71 65 18 19 17 10 58 92
Card 69: 59 71 39 44 3 27 69 1 60 58 | 1 65 3 40 71 64 80 51 27 69 83 88 81 59 44 74 75 48 78 9 39 14 60 13 58
Card 70: 83 57 59 27 21 73 3 78 40 64 | 83 59 61 36 57 64 18 70 40 21 97 22 50 28 73 69 1 88 3 43 78 53 31 93 27
Card 71: 58 19 53 76 94 22 67 17 79 25 | 73 54 67 58 61 79 22 76 27 48 88 49 16 94 38 25 52 20 53 63 92 17 19 82 1
Card 72: 67 29 4 47 9 63 72 48 59 11 | 91 89 93 2 69 72 92 80 82 15 86 24 87 75 38 85 16 59 12 28 49 66 50 90 71
Card 73: 82 33 83 63 88 86 18 30 14 28 | 90 14 11 86 13 9 91 34 7 63 4 82 18 30 27 12 92 37 88 2 28 33 51 52 83
Card 74: 27 23 62 83 86 95 66 99 46 92 | 11 83 57 99 91 78 23 27 95 66 3 18 16 7 19 89 28 86 31 47 46 2 79 92 50
Card 75: 5 75 50 22 70 77 82 49 73 46 | 4 50 90 11 32 75 82 71 86 68 64 22 46 70 49 37 79 80 12 45 88 73 58 99 5
Card 76: 10 67 27 35 37 31 41 48 57 50 | 5 68 90 21 51 99 43 79 80 6 23 63 24 76 3 75 19 86 42 67 1 52 4 35 15
Card 77: 53 15 10 16 36 26 31 1 67 73 | 81 25 49 9 46 73 10 99 15 36 86 69 38 30 37 51 53 1 41 27 61 91 16 72 58
Card 78: 41 48 9 35 30 75 82 60 29 45 | 79 81 96 43 45 69 21 42 29 78 41 68 48 27 80 67 37 74 6 51 9 60 30 59 82
Card 79: 27 25 20 58 93 9 50 64 56 79 | 29 91 33 4 36 10 92 54 21 66 7 48 44 8 61 67 12 96 81 22 2 31 62 18 59
Card 80: 20 26 82 39 62 8 3 6 53 14 | 61 67 28 73 87 25 29 60 14 72 56 26 50 66 36 46 31 54 39 84 35 48 6 45 82
Card 81: 12 74 28 96 83 27 91 56 20 31 | 25 8 31 94 38 83 53 57 98 17 24 27 76 39 88 78 21 20 4 15 28 74 81 9 96
Card 82: 34 72 89 67 14 32 4 41 28 22 | 12 45 65 59 43 68 71 34 4 23 10 52 21 27 58 3 48 31 92 98 39 44 86 84 62
Card 83: 58 38 24 92 80 41 36 11 16 56 | 93 2 92 16 64 59 56 11 20 67 88 60 81 65 85 94 39 19 41 83 57 47 97 14 8
Card 84: 64 29 78 39 28 33 88 99 13 32 | 82 84 23 88 3 69 67 35 10 58 93 4 44 41 79 92 30 56 59 60 76 83 6 72 62
Card 85: 79 34 49 17 95 63 60 61 48 15 | 21 16 53 93 74 29 44 52 4 95 64 56 31 1 36 33 92 57 66 67 71 79 34 20 7
Card 86: 93 41 52 71 18 28 19 90 66 36 | 50 33 37 88 61 26 77 92 48 84 78 1 54 58 29 10 63 9 21 31 65 6 24 53 51
Card 87: 13 21 25 32 39 30 86 14 45 49 | 51 42 89 15 12 68 87 27 40 59 9 34 94 46 7 25 62 47 52 75 77 17 81 83 57
Card 88: 91 60 14 46 29 30 1 15 21 51 | 83 40 12 67 41 95 8 31 69 90 63 27 57 36 64 82 54 44 50 93 71 79 17 73 89
Card 89: 33 42 70 89 96 81 83 53 57 23 | 35 33 32 15 57 54 5 74 25 36 81 23 64 22 63 38 4 53 18 7 46 97 26 80 89
Card 90: 80 86 96 81 82 97 60 87 74 6 | 39 74 80 81 6 20 38 96 53 75 97 10 87 59 73 4 60 63 16 31 89 82 68 86 27
Card 91: 64 61 96 73 22 19 32 12 97 95 | 61 88 41 7 57 64 13 90 28 38 95 99 19 22 32 73 12 96 81 43 83 21 1 14 97
Card 92: 87 89 91 57 5 23 75 72 29 47 | 73 39 4 8 1 55 26 83 35 96 45 25 86 62 37 53 68 14 19 76 27 31 50 58 69
Card 93: 95 40 71 56 21 44 23 41 75 82 | 44 23 21 76 40 95 73 97 82 17 50 53 41 74 56 61 75 5 10 71 42 93 78 52 46
Card 94: 19 35 37 46 34 17 13 38 40 87 | 78 34 71 6 29 87 40 45 58 13 79 99 46 35 75 15 9 37 43 17 92 76 38 51 19
Card 95: 37 46 85 19 12 91 66 67 88 23 | 88 37 19 30 56 46 81 6 68 3 9 23 32 71 12 7 91 66 39 67 24 60 85 13 38
Card 96: 30 61 21 49 47 85 45 92 55 33 | 56 33 21 1 30 25 75 55 47 89 34 45 22 12 61 32 85 82 24 79 78 92 49 29 51
Card 97: 3 22 70 51 84 97 60 9 47 20 | 47 26 30 70 3 60 36 57 46 22 51 84 86 79 97 21 59 20 61 98 5 74 9 58 16
Card 98: 85 19 52 60 62 51 50 14 67 96 | 19 22 67 59 16 11 38 60 24 39 29 61 4 42 12 7 46 96 94 69 50 99 25 77 17
Card 99: 4 66 29 36 76 45 32 57 39 81 | 32 45 13 76 38 58 29 72 44 2 50 66 57 23 17 4 85 39 99 20 88 5 36 81 56
Card 100: 65 37 15 55 97 43 72 81 79 98 | 15 23 43 69 95 41 59 92 99 77 24 49 65 80 33 60 79 67 9 48 1 71 57 39 3
Card 101: 95 4 67 42 27 84 75 94 68 49 | 19 24 95 1 56 82 27 94 67 91 34 60 71 14 7 12 78 68 4 2 42 84 75 31 49
Card 102: 50 99 57 21 44 79 45 62 59 41 | 57 37 31 79 99 44 89 64 3 96 34 95 14 63 35 16 26 6 93 45 25 47 41 69 1
Card 103: 91 24 36 35 81 12 96 7 99 32 | 6 63 62 94 42 34 69 28 97 41 60 15 91 35 7 8 92 17 70 10 24 31 16 99 73
Card 104: 33 97 77 80 1 27 98 26 11 34 | 62 91 96 64 70 74 61 28 89 19 71 95 82 17 76 92 56 22 16 26 93 79 78 84 7
Card 105: 93 73 31 75 78 19 85 10 59 37 | 53 26 15 94 74 31 90 19 76 64 42 92 60 27 13 70 99 1 3 83 14 67 36 38 93
Card 106: 71 94 63 90 24 14 58 91 13 88 | 41 91 98 14 88 94 64 4 71 48 22 27 49 3 47 74 63 28 62 12 34 99 84 39 37
Card 107: 86 85 43 91 39 7 15 72 93 18 | 72 59 94 9 66 64 10 31 18 54 3 48 53 41 33 1 7 91 55 78 43 52 37 29 82
Card 108: 34 11 16 22 31 46 64 90 23 25 | 94 92 13 24 70 72 65 18 42 6 60 48 5 4 10 39 20 88 53 33 83 35 68 78 77
Card 109: 72 46 71 52 86 23 9 54 62 81 | 29 35 39 81 34 23 75 92 59 45 89 85 38 65 67 47 61 10 12 98 40 43 46 52 33
Card 110: 5 49 21 64 35 61 31 26 90 45 | 68 48 51 19 58 13 2 67 42 25 55 92 94 81 84 69 15 29 66 6 54 11 59 83 4
Card 111: 16 80 77 99 89 28 21 32 36 24 | 31 8 49 45 43 91 2 39 93 9 4 5 50 82 98 17 25 29 52 36 20 23 38 67 53
Card 112: 23 95 38 52 72 81 69 51 76 82 | 65 93 48 50 96 68 11 39 40 13 19 86 53 47 67 10 49 87 59 5 24 81 31 98 78
Card 113: 33 47 81 24 16 4 8 79 50 45 | 10 5 62 92 43 7 63 57 48 20 72 80 87 59 49 14 13 9 98 53 88 64 56 65 99
Card 114: 75 70 62 72 78 74 93 82 66 57 | 94 38 99 8 80 1 62 30 25 97 78 49 19 45 36 42 82 33 43 10 75 29 72 50 53
Card 115: 21 13 70 11 86 28 49 2 47 75 | 5 2 27 59 31 12 93 50 21 51 56 32 86 47 75 7 20 13 49 28 11 64 70 89 52
Card 116: 21 97 16 68 43 42 63 99 90 19 | 53 70 32 46 90 64 19 97 92 21 42 81 2 30 63 25 6 68 5 69 99 80 95 16 49
Card 117: 5 66 59 7 60 86 55 68 80 96 | 63 61 6 30 33 72 94 64 91 8 28 26 15 49 20 5 56 67 23 90 27 1 85 41 52
Card 118: 83 35 11 17 40 79 7 64 60 32 | 10 76 1 97 81 61 83 9 25 64 78 73 95 41 55 69 11 35 62 60 79 96 52 90 50
Card 119: 69 2 53 20 75 82 42 47 81 15 | 15 97 81 59 47 20 85 69 57 53 25 75 65 39 29 84 42 55 82 94 91 2 11 1 23
Card 120: 31 3 28 24 84 89 77 80 87 82 | 28 22 56 66 10 36 17 6 77 34 49 63 57 41 2 38 97 18 39 24 86 65 20 48 27
Card 121: 41 62 77 63 96 52 30 66 71 90 | 29 83 78 52 26 31 77 96 1 70 32 4 60 41 30 99 57 44 19 51 95 62 50 73 35
Card 122: 71 8 37 35 82 19 67 18 53 16 | 89 67 3 53 19 46 12 83 86 18 37 9 99 71 54 8 27 10 26 15 30 62 16 17 82
Card 123: 82 41 94 61 54 62 88 85 33 91 | 40 96 83 41 78 28 1 88 54 60 85 47 99 36 33 74 77 56 82 61 62 94 91 59 84
Card 124: 94 58 63 64 4 93 27 21 60 10 | 3 81 28 6 58 45 77 70 2 22 83 93 29 78 21 48 75 25 64 27 60 94 4 10 63
Card 125: 61 60 23 16 12 69 45 41 40 24 | 23 14 12 84 69 15 16 83 61 21 60 34 74 92 24 13 45 40 55 85 41 50 25 27 80
Card 126: 32 35 70 58 37 83 6 64 17 78 | 35 48 68 19 41 7 83 71 78 5 75 51 11 9 90 74 26 17 49 37 70 73 64 79 32
Card 127: 80 56 89 61 46 39 71 18 42 76 | 31 43 61 46 76 67 54 74 71 89 66 48 18 37 39 42 83 72 96 11 56 80 1 41 20
Card 128: 23 82 32 51 76 11 20 97 4 68 | 93 10 57 60 34 66 23 84 72 37 4 30 21 90 43 7 5 28 87 55 77 22 86 78 75
Card 129: 91 56 5 89 62 53 52 51 72 32 | 5 4 72 32 94 6 61 17 71 22 93 11 33 81 7 9 14 52 58 27 92 36 40 45 20
Card 130: 86 39 21 68 91 98 41 96 36 53 | 7 55 52 77 93 94 68 96 56 41 45 6 44 76 4 50 32 26 28 29 49 8 37 30 59
Card 131: 52 38 80 69 61 74 82 30 59 51 | 8 76 37 12 22 34 88 50 16 17 85 30 61 27 80 89 52 1 82 32 25 40 51 93 69
Card 132: 53 55 14 45 15 38 94 9 29 80 | 14 3 89 69 94 44 29 16 4 72 1 2 38 84 79 40 22 21 88 64 74 48 24 10 34
Card 133: 81 36 43 29 97 78 35 24 63 17 | 67 98 86 11 51 54 35 71 74 95 50 8 91 27 58 76 49 70 64 30 66 23 3 10 44
Card 134: 4 94 99 23 7 33 79 55 50 70 | 35 23 53 71 38 84 99 52 6 28 42 48 54 58 86 83 66 67 97 7 32 94 75 31 59
Card 135: 81 12 23 92 35 25 30 64 47 9 | 74 8 87 2 3 42 54 79 83 14 76 28 44 32 38 59 70 24 43 95 57 5 63 91 52
Card 136: 87 4 49 94 97 35 6 5 39 29 | 97 20 28 22 63 45 31 41 12 13 92 36 7 27 16 60 47 46 33 61 19 37 78 94 50
Card 137: 83 99 9 76 94 40 20 3 72 67 | 13 44 88 49 85 14 5 55 38 1 46 58 28 93 71 30 66 70 89 17 78 39 92 75 16
Card 138: 37 99 22 13 42 36 20 59 29 10 | 92 95 51 80 24 26 38 86 17 9 90 35 83 4 87 94 12 58 6 64 14 33 8 18 49
Card 139: 26 38 94 41 35 60 99 58 96 36 | 8 27 38 49 99 12 26 87 91 96 76 94 97 14 35 58 29 16 60 36 11 56 73 75 41
Card 140: 10 77 39 49 90 96 25 21 13 41 | 41 45 13 3 77 69 73 85 34 86 16 7 96 30 88 39 70 21 75 10 53 90 49 25 47
Card 141: 22 20 43 3 81 52 92 2 19 18 | 84 2 54 41 19 52 9 92 63 18 48 43 53 20 79 40 75 11 22 81 91 42 3 97 30
Card 142: 38 51 76 11 95 10 6 30 73 93 | 38 61 27 11 59 15 73 5 6 85 93 24 7 30 79 33 35 95 74 10 94 51 76 89 66
Card 143: 6 99 70 44 88 50 79 82 34 49 | 54 8 36 14 1 21 37 34 94 6 99 3 91 88 85 20 81 79 70 50 82 44 29 49 98
Card 144: 53 8 52 47 20 11 85 63 91 30 | 99 37 30 11 53 32 75 80 85 3 27 76 39 67 52 56 40 63 21 47 94 8 83 20 10
Card 145: 53 30 13 68 90 79 87 52 84 85 | 18 52 30 69 67 49 79 74 84 5 11 97 85 90 26 95 23 68 83 64 53 87 13 89 70
Card 146: 70 35 94 6 99 64 91 21 52 48 | 25 50 21 94 10 64 48 90 95 35 6 52 74 3 28 11 65 14 70 99 18 86 88 91 92
Card 147: 39 92 77 71 43 25 64 44 13 6 | 63 48 23 71 35 28 64 43 6 53 14 13 12 59 74 56 39 37 92 77 60 65 44 3 25
Card 148: 11 76 24 45 32 23 66 34 25 6 | 66 71 87 93 32 21 88 45 89 34 14 58 17 25 6 8 91 76 23 33 24 22 52 53 26
Card 149: 25 19 37 10 39 52 33 82 74 71 | 56 27 15 76 53 57 1 54 30 48 88 37 23 36 69 74 45 38 19 61 89 41 8 25 21
Card 150: 81 38 13 61 30 19 56 60 99 52 | 27 4 53 24 39 62 5 78 79 31 89 7 22 20 71 58 14 11 88 30 37 60 19 33 74
Card 151: 41 85 78 42 1 27 28 74 65 12 | 52 53 30 80 22 92 17 94 77 48 70 40 11 89 56 69 86 64 87 37 93 97 29 44 12
Card 152: 77 56 88 41 29 6 72 58 46 39 | 11 61 6 29 24 52 56 86 99 66 88 33 14 47 46 41 77 4 35 39 58 18 89 23 72
Card 153: 13 56 45 64 79 27 33 94 63 82 | 27 83 43 63 82 53 30 14 56 3 64 20 79 13 36 42 90 45 17 10 28 15 94 66 33
Card 154: 96 59 51 76 84 80 12 48 94 4 | 83 59 14 51 84 8 67 4 86 37 97 11 42 23 82 60 12 80 6 49 1 71 69 94 48
Card 155: 6 86 48 72 38 81 11 14 21 2 | 55 90 51 11 67 6 52 57 3 88 43 81 75 47 31 38 54 2 4 92 44 60 14 87 17
Card 156: 83 86 39 84 75 10 97 57 70 92 | 50 8 3 97 89 16 34 79 75 84 41 10 65 57 86 78 24 82 7 36 18 37 27 55 49
Card 157: 32 58 59 75 42 20 81 98 95 96 | 81 60 34 98 31 20 40 19 51 4 32 75 39 68 47 11 96 25 49 56 17 14 44 15 99
Card 158: 24 38 76 95 77 79 58 72 64 34 | 55 16 89 18 31 9 13 46 10 1 72 2 50 47 56 62 79 94 33 90 19 26 24 35 66
Card 159: 97 8 29 31 60 27 50 41 4 15 | 28 45 54 21 11 69 20 25 30 76 18 93 96 92 47 1 59 74 77 95 13 86 79 50 39
Card 160: 38 98 88 70 12 3 11 72 92 95 | 15 17 43 6 90 53 79 58 60 10 67 50 69 35 13 23 74 66 76 89 91 83 87 57 63
Card 161: 41 93 52 17 58 79 74 5 96 38 | 72 49 25 46 35 19 74 2 15 26 94 81 90 51 77 41 18 40 9 48 82 1 11 23 61
Card 162: 56 4 76 44 97 39 40 24 77 28 | 80 20 63 37 25 34 11 99 12 13 50 61 38 95 42 72 35 48 27 75 85 2 17 66 47
Card 163: 78 40 59 68 11 5 16 74 46 15 | 25 42 2 45 47 71 52 84 1 7 10 49 53 60 41 56 51 88 9 26 93 8 92 23 28
Card 164: 31 94 69 47 90 21 11 81 41 61 | 71 93 74 36 58 11 77 2 85 66 26 34 59 97 88 24 15 20 62 61 54 35 27 40 53
Card 165: 13 88 71 4 72 94 42 76 40 50 | 35 59 18 90 11 16 96 61 32 22 29 69 25 89 39 97 28 62 21 17 36 79 8 86 53
Card 166: 50 51 82 70 6 37 81 12 1 32 | 78 22 80 12 64 10 88 55 77 51 23 75 50 19 62 89 99 83 71 44 91 85 24 5 46
Card 167: 12 43 33 53 32 25 77 70 7 75 | 58 18 29 46 24 50 25 75 14 39 43 7 6 53 77 80 16 68 32 21 70 12 62 33 76
Card 168: 46 3 99 72 94 95 69 36 1 91 | 80 81 99 72 56 26 3 17 21 42 39 4 94 70 24 69 18 76 40 34 89 31 20 71 90
Card 169: 68 10 62 1 45 98 60 15 18 79 | 58 15 93 41 59 37 28 39 20 35 26 12 60 7 9 90 88 62 68 1 18 75 45 53 36
Card 170: 42 82 12 31 3 1 92 97 81 45 | 8 28 52 74 21 25 55 41 81 7 40 73 67 63 48 2 90 60 58 54 93 26 18 61 43
Card 171: 3 32 45 54 89 21 80 68 10 67 | 67 79 70 98 65 9 30 34 8 41 53 21 84 89 85 77 50 81 73 52 94 6 62 82 45
Card 172: 90 28 2 40 58 30 92 49 94 57 | 38 16 19 36 63 20 54 2 44 72 5 92 90 33 97 22 46 30 35 24 6 11 4 57 58
Card 173: 4 6 98 85 65 69 25 70 35 33 | 67 12 98 82 54 32 33 66 77 93 49 34 92 29 15 58 91 21 85 5 70 47 37 25 26
Card 174: 35 78 15 91 73 8 64 5 57 87 | 85 29 59 78 88 75 40 17 97 69 68 15 56 44 9 48 12 3 24 27 20 1 2 5 87
Card 175: 13 78 69 93 95 49 36 54 98 41 | 99 45 88 77 94 44 55 5 23 37 64 87 58 89 21 95 76 91 7 30 17 82 53 8 92
Card 176: 79 23 52 33 50 94 37 89 3 29 | 30 69 38 43 90 4 2 45 42 98 96 9 25 63 74 61 13 1 56 17 24 86 10 28 11
Card 177: 43 91 33 34 57 73 90 53 85 94 | 4 92 66 25 16 88 14 21 80 36 41 28 56 49 31 15 38 87 40 59 3 77 45 23 18
Card 178: 92 78 56 1 11 61 88 34 20 95 | 80 90 28 83 29 8 16 21 6 85 40 53 77 65 58 82 72 79 69 64 47 49 59 18 13
Card 179: 67 66 6 26 61 75 3 39 38 92 | 3 17 84 32 99 76 85 41 87 65 10 44 24 48 90 95 30 97 39 7 93 67 77 62 70
Card 180: 55 90 31 49 44 80 23 46 92 52 | 81 93 53 82 46 6 8 55 74 92 31 49 58 52 97 20 90 80 60 30 96 44 35 23 83
Card 181: 91 42 96 69 10 32 61 92 60 21 | 13 50 6 61 58 60 32 59 86 69 85 23 47 42 14 71 92 29 96 91 10 19 75 21 78
Card 182: 18 6 53 76 74 48 92 54 34 52 | 17 16 52 34 54 78 45 49 76 92 48 44 74 18 85 43 21 35 53 57 6 36 29 40 73
Card 183: 46 30 56 7 87 23 15 51 48 12 | 52 51 66 82 86 13 56 33 15 77 36 30 48 12 76 60 99 24 4 39 72 28 11 7 59
Card 184: 86 48 72 24 54 50 76 26 10 61 | 74 55 29 76 42 86 62 48 19 43 50 10 22 24 8 54 53 44 39 61 26 46 23 78 72
Card 185: 3 10 74 35 33 4 26 21 45 36 | 92 60 15 61 76 55 67 16 48 71 72 31 68 94 80 59 28 81 49 91 40 98 47 87 44
Card 186: 73 97 14 59 77 63 64 4 67 76 | 98 97 95 21 73 9 71 50 76 3 59 16 63 14 2 99 18 4 28 67 5 64 31 77 52
Card 187: 28 34 68 97 4 66 93 25 30 86 | 15 42 46 54 76 5 44 17 97 79 81 56 58 99 77 64 67 43 87 3 48 53 92 18 27
Card 188: 90 31 93 23 28 58 4 54 15 38 | 4 31 15 69 93 54 90 44 23 58 51 25 34 2 29 27 40 55 28 41 38 56 72 89 1
Card 189: 29 45 89 18 30 77 99 82 60 36 | 15 82 58 60 99 18 26 64 89 6 30 76 11 68 29 85 45 14 36 77 51 22 83 20 93
Card 190: 44 17 38 7 26 54 18 40 48 8 | 37 31 78 85 39 5 76 91 92 64 35 57 24 38 20 86 63 96 59 11 94 82 60 29 41
Card 191: 56 73 38 58 50 81 19 70 2 99 | 4 52 22 93 20 64 12 27 18 88 89 6 68 31 61 66 1 85 36 23 48 26 86 83 75
Card 192: 82 90 14 47 38 39 32 35 19 80 | 60 17 19 48 9 6 57 93 22 99 21 41 24 70 84 30 64 72 7 47 45 44 53 15 88
Card 193: 68 10 83 67 85 98 3 77 33 35 | 88 27 85 67 17 63 48 59 10 52 23 2 55 75 68 96 57 45 33 16 43 77 3 35 69
Card 194: 70 39 54 44 10 24 28 74 55 21 | 57 23 48 64 43 54 44 36 59 7 5 10 2 4 94 77 69 99 47 42 97 21 18 38 66
Card 195: 25 26 18 81 88 51 54 13 45 46 | 7 46 96 85 81 68 88 26 41 13 56 50 93 3 69 51 90 82 16 64 32 23 70 45 33
Card 196: 52 42 6 9 22 67 34 98 47 64 | 13 98 3 40 63 53 99 61 25 92 88 7 42 41 87 1 6 89 84 51 55 16 43 10 59
Card 197: 67 50 53 82 11 72 14 2 18 88 | 45 35 61 56 47 87 79 2 33 31 32 41 98 51 58 72 59 38 89 80 12 92 14 5 39
Card 198: 75 96 69 8 87 98 66 17 39 86 | 1 50 97 11 54 7 12 99 51 23 14 61 81 77 21 92 20 40 74 18 45 90 4 70 71
Card 199: 41 7 83 11 20 51 85 50 71 33 | 69 84 40 55 35 33 89 34 75 2 19 63 50 14 26 76 13 29 66 47 46 22 62 48 58
Card 200: 37 1 67 65 51 47 28 91 81 8 | 36 69 85 14 72 94 60 25 90 34 88 66 23 30 54 39 31 63 40 38 12 5 7 61 41
Card 201: 72 10 99 46 62 14 87 4 77 6 | 51 37 1 43 28 13 81 9 21 20 18 56 94 79 41 57 76 85 30 65 19 67 92 58 61
Card 202: 35 58 73 33 42 19 64 43 10 57 | 76 38 50 14 4 41 25 2 79 99 85 72 62 17 52 95 15 28 66 82 90 9 65 16 7
Card 203: 28 17 98 38 5 43 88 51 2 8 | 87 53 85 13 37 60 18 52 59 54 32 33 48 58 72 62 81 40 12 56 97 74 35 29 42
Card 204: 20 17 43 90 54 82 50 51 52 65 | 34 26 1 12 52 47 51 29 54 24 31 96 90 39 82 43 20 92 15 65 50 13 14 17 69
Card 205: 88 49 79 76 42 77 40 2 73 54 | 36 44 9 38 24 29 73 76 79 46 93 31 88 98 50 57 6 8 17 49 3 59 64 54 52
Card 206: 20 46 95 1 88 32 38 7 12 29 | 42 56 19 41 37 1 88 7 31 96 33 20 47 72 75 9 77 53 29 38 89 46 32 79 95
Card 207: 90 33 85 4 15 34 89 16 38 46 | 92 54 88 73 24 93 78 82 85 2 38 46 34 45 26 74 79 4 62 8 52 32 33 63 76
Card 208: 77 41 55 18 7 57 59 44 93 91 | 20 56 10 78 8 40 63 85 87 3 67 60 28 73 49 17 22 62 68 86 9 84 70 5 47
Card 209: 66 24 5 41 46 30 67 97 54 59 | 49 90 31 10 45 36 46 22 54 5 78 17 89 59 2 38 77 97 20 35 67 9 26 76 41
Card 210: 75 76 90 44 52 19 82 89 4 56 | 43 44 8 68 74 40 38 96 84 76 77 11 65 89 16 20 14 29 52 56 66 33 90 99 75
Card 211: 88 37 9 2 42 20 79 66 45 90 | 81 13 60 40 19 38 50 11 20 4 37 9 69 7 30 27 47 46 78 64 90 99 17 43 51
Card 212: 87 61 34 76 19 3 62 51 63 1 | 19 67 85 34 89 82 17 91 59 62 21 70 23 96 61 29 74 28 87 5 1 46 6 63 22
Card 213: 11 58 56 99 53 74 70 24 51 29 | 58 44 50 53 94 74 95 93 88 59 2 46 91 77 55 99 21 26 98 30 43 86 11 13 79
Card 214: 32 26 80 46 74 69 12 60 71 36 | 45 58 88 28 70 85 26 96 30 1 74 2 97 15 81 87 86 3 94 19 5 8 62 36 29
Card 215: 90 21 84 54 79 31 35 92 2 19 | 86 18 14 57 99 85 62 23 65 28 39 5 2 69 71 30 16 40 82 83 91 37 26 1 27
Card 216: 30 52 95 64 27 68 90 29 12 50 | 9 60 1 33 57 28 81 38 99 39 8 30 76 37 7 91 36 41 50 27 80 93 75 87 16
Card 217: 82 57 48 80 59 58 86 28 56 88 | 15 10 23 62 14 69 84 66 79 86 68 75 90 78 50 17 40 67 3 63 57 12 42 83 20
Card 218: 40 82 47 31 37 77 90 33 1 41 | 26 38 15 45 94 28 17 75 16 23 30 29 54 80 35 37 4 96 34 27 49 32 58 51 73
Card 219: 58 38 53 49 11 10 14 3 89 2 | 8 16 54 18 44 95 31 15 46 45 73 40 61 28 98 5 70 63 69 26 34 80 12 42 90

6
2023/day_04/sample.txt Normal file
View File

@ -0,0 +1,6 @@
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11

View File

@ -0,0 +1,28 @@
import path from "path";
import { readlines } from "../../_utils";
import { part1_solver, part2_solver } from "./solution";
describe("day 4: scratchcards, pt 1", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(part1_solver(sample)).toBe(13);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part1_solver(input)).toBe(32609);
});
});
describe("day 4: scratchcards, pt 2", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(part2_solver(sample)).toBe(30);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part2_solver(input)).toBe(14624680);
});
});

143
2023/day_04/solution.ts Normal file
View File

@ -0,0 +1,143 @@
/*
--- Day 4: Scratchcards ---
The gondola takes you up. Strangely, though, the ground doesn't seem to be coming with you; you're not climbing a mountain. As the circle of Snow Island recedes below you, an entire new landmass suddenly appears above you! The gondola carries you to the surface of the new island and lurches into the station.
As you exit the gondola, the first thing you notice is that the air here is much warmer than it was on Snow Island. It's also quite humid. Is this where the water source is?
The next thing you notice is an Elf sitting on the floor across the station in what seems to be a pile of colorful square cards.
"Oh! Hello!" The Elf excitedly runs over to you. "How may I be of service?" You ask about water sources.
"I'm not sure; I just operate the gondola lift. That does sound like something we'd have, though - this is Island Island, after all! I bet the gardener would know. He's on a different island, though - er, the small kind surrounded by water, not the floating kind. We really need to come up with a better naming scheme. Tell you what: if you can help me with something quick, I'll let you borrow my boat and you can go visit the gardener. I got all these scratchcards as a gift, but I can't figure out what I've won."
The Elf leads you over to the pile of colorful cards. There, you discover dozens of scratchcards, all with their opaque covering already scratched off. Picking one up, it looks like each card has two lists of numbers separated by a vertical bar (|): a list of winning numbers and then a list of numbers you have. You organize the information into a table (your puzzle input).
As far as the Elf has been able to figure out, you have to figure out which of the numbers you have appear in the list of winning numbers. The first match makes the card worth one point and each match after the first doubles the point value of that card.
For example:
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
In the above example, card 1 has five winning numbers (41, 48, 83, 86, and 17) and eight numbers you have (83, 86, 6, 31, 17, 9, 48, and 53). Of the numbers you have, four of them (48, 83, 17, and 86) are winning numbers! That means card 1 is worth 8 points (1 for the first match, then doubled three times for each of the three matches after the first).
Card 2 has two winning numbers (32 and 61), so it is worth 2 points.
Card 3 has two winning numbers (1 and 21), so it is worth 2 points.
Card 4 has one winning number (84), so it is worth 1 point.
Card 5 has no winning numbers, so it is worth no points.
Card 6 has no winning numbers, so it is worth no points.
So, in this example, the Elf's pile of scratchcards is worth 13 points.
Take a seat in the large pile of colorful cards. How many points are they worth in total?
*/
import { emptyLines, extractNumbers, sum } from "../../_utils";
type Card = {
cardNumber: number,
winningNumbers: number[],
scratchedNumbers: number[]
}
function numMatches(card: Card): number {
return card.scratchedNumbers.reduce((numMatches, number) => {
if (card.winningNumbers.includes(number)) {
return numMatches + 1
} else {
return numMatches
}
}, 0)
}
function cardScore(card: Card): number {
const matches = numMatches(card);
const score = matches > 0 ? 2 ** (matches - 1) : 0;
return score;
}
function parseCard(line: string): Card {
const [cardStr, numbersStr] = line.split(":");
const cardNumber = extractNumbers(cardStr)
const [winning, scratched] = numbersStr.split("|");
const winningNumbers = winning.split(" ").filter(emptyLines).map(extractNumbers)
const scratchedNumbers = scratched.split(" ").filter(emptyLines).map(extractNumbers)
return { cardNumber, winningNumbers, scratchedNumbers };
}
export function part1_solver(lines: string[]): number {
return lines.filter(emptyLines).map(parseCard).map(c => cardScore(c)).reduce(sum);
}
/*
--- Part Two ---
Just as you're about to report your findings to the Elf, one of you realizes that the rules have actually been printed on the back of every card this whole time.
There's no such thing as "points". Instead, scratchcards only cause you to win more scratchcards equal to the number of winning numbers you have.
Specifically, you win copies of the scratchcards below the winning card equal to the number of matches. So, if card 10 were to have 5 matching numbers, you would win one copy each of cards 11, 12, 13, 14, and 15.
Copies of scratchcards are scored like normal scratchcards and have the same card number as the card they copied. So, if you win a copy of card 10 and it has 5 matching numbers, it would then win a copy of the same cards that the original card 10 won: cards 11, 12, 13, 14, and 15. This process repeats until none of the copies cause you to win any more cards. (Cards will never make you copy a card past the end of the table.)
This time, the above example goes differently:
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
Card 1 has four matching numbers, so you win one copy each of the next four cards: cards 2, 3, 4, and 5.
Your original card 2 has two matching numbers, so you win one copy each of cards 3 and 4.
Your copy of card 2 also wins one copy each of cards 3 and 4.
Your four instances of card 3 (one original and three copies) have two matching numbers, so you win four copies each of cards 4 and 5.
Your eight instances of card 4 (one original and seven copies) have one matching number, so you win eight copies of card 5.
Your fourteen instances of card 5 (one original and thirteen copies) have no matching numbers and win no more cards.
Your one instance of card 6 (one original) has no matching numbers and wins no more cards.
Once all of the originals and copies have been processed, you end up with 1 instance of card 1, 2 instances of card 2, 4 instances of card 3, 8 instances of card 4, 14 instances of card 5, and 1 instance of card 6. In total, this example pile of scratchcards causes you to ultimately have 30 scratchcards!
Process all of the original and copied scratchcards until no more scratchcards are won. Including the original set of scratchcards, how many total scratchcards do you end up with?
*/
type CardCopies = {
[cardNumber: number]: number
}
export function part2_solver(lines: string[]): number {
const copies = lines.filter(emptyLines).map(parseCard).reduce((copyCounts, card) => {
const newCopyCounts = { ...copyCounts }
newCopyCounts[card.cardNumber] = newCopyCounts[card.cardNumber] || 1;
const currentCount = newCopyCounts[card.cardNumber];
const matches = numMatches(card);
const floor = card.cardNumber + 1;
const ceiling = matches + card.cardNumber + 1;
for (let i = floor; i < ceiling; i++) {
newCopyCounts[i] = (newCopyCounts[i] || 1) + (currentCount)
}
console.log(`${card.cardNumber} === ${matches} =========================================`)
console.log(newCopyCounts)
return newCopyCounts;
}, {} as CardCopies);
// console.log(copies)
return Object.values(copies).reduce(sum)
}

197
2023/day_05/input.txt Normal file
View File

@ -0,0 +1,197 @@
seeds: 565778304 341771914 1736484943 907429186 3928647431 87620927 311881326 149873504 1588660730 119852039 1422681143 13548942 1095049712 216743334 3671387621 186617344 3055786218 213191880 2783359478 44001797
seed-to-soil map:
1136439539 28187015 34421000
4130684560 3591141854 62928737
2493176649 2843539493 216586902
4035246184 3979580848 40675839
784987951 2449883248 10512167
1230114095 458474273 89127842
3591141854 4278550666 16416630
795500118 1007741104 49669915
4075922023 4020256687 54762537
1170860539 385724159 59253556
1754134353 1447758461 710855281
2464989634 0 28187015
3811089926 3654070591 224156258
367106182 564462768 34737691
0 3060126395 64826339
1438999297 87449756 298274403
1319241937 901480302 106260802
1425502739 444977715 13496558
906091129 2158613742 230348410
401843873 2460395415 383144078
1737273700 547602115 16860653
64826339 599200459 302279843
2709763551 1057411019 390347442
845170033 2388962152 60921096
3607558484 4075019224 203531442
3100110993 3124952734 265337006
4193613297 3878226849 101353999
3365447999 62608015 24841741
soil-to-fertilizer map:
2997768542 2385088490 141138894
2483957796 2361581050 23507440
98641524 1346083581 385280737
3138907436 2256873732 8670947
0 2158232208 98641524
3147578383 2265544679 96036371
1035235183 2879344429 108036359
2567031012 2526227384 63435416
740156227 2589662800 180702628
2630466428 1790930094 367302114
1029837856 0 5397327
1143271542 5397327 1340686254
483922261 2987380788 256233966
2507465236 1731364318 59565776
920858855 2770365428 108979001
fertilizer-to-water map:
1539871014 1431400479 38399903
4189242304 3947275099 105724992
2012473116 0 61612686
3673653298 3769966020 177309079
25380533 833117788 21807501
143369400 1411638591 19761888
2698209531 61612686 40666379
401367210 2888296065 27849039
3850962377 4057978463 170640183
1076364770 854925289 39443942
0 2048878915 25380533
2682826842 1483785677 15382689
4026580932 4228618646 66348650
790899137 2074259448 70405647
2738875910 2609016218 230235412
2090748148 1854132037 12185242
163131288 1499168366 238235922
1115808712 3002097202 63461270
545943998 1215727887 195910704
4092929582 3673653298 96312722
1000530579 3065558472 75834191
2074085802 2916145104 16662346
429216249 1737404288 116727749
1578270917 2174814019 434202199
2969111322 102279065 44844471
1179269982 669063687 164054101
2463111278 507301424 161762263
741854702 2839251630 49044435
3013955793 894369231 236513741
861304784 2144665095 30148924
1525885719 1469800382 13985295
132032949 2932807450 11336451
2102933390 147123536 360177888
47188034 1130882972 84844915
4021602560 4053000091 4978372
2624873541 2944143901 57953301
891453708 3141392663 109076871
1343324083 1866317279 182561636
water-to-light map:
1509583382 1639808290 20361832
3841220400 2799952377 116887408
1472887638 3349716751 36695744
1375316591 4197396249 97571047
1030032900 38536653 44339012
3776233310 1557050237 64987090
1857053855 3386412495 71799907
2963593546 2694182899 38493443
3758462347 1622037327 17770963
1018869652 82875665 11163248
1308040556 2732676342 67276035
1928853762 3953749938 243646311
2488961036 3503789336 239267964
3562290347 3458212402 6096433
3568386780 1308040556 190075567
2728229000 1997029610 235364546
215668494 0 38536653
1646361217 3743057300 109790942
1529945214 3233300748 116416003
1756152159 3852848242 100901696
3958107808 1660170122 336859488
3503356233 1498116123 58934114
254205147 552157437 522214475
3002086989 3464308835 39480501
776419622 94038913 242450030
2172500073 2916839785 316460963
0 336488943 215668494
3041567490 2232394156 461788743
light-to-temperature map:
3498288578 2645051323 42074132
608593503 673232568 65024140
0 1287033796 108723708
3979313387 3634135302 315653909
2652759587 3018896130 103365881
1093544955 942695289 7961217
2756125468 3501628238 132507064
419683046 1625547778 126722533
683243352 349510049 26140330
1101506172 511314709 142580382
1283347805 375650379 135664330
673617643 24016268 9625709
709383682 1238532395 48501401
3763762608 2402322728 184668443
3948431051 2621479653 23571670
3660408219 2687125455 102463666
3561232935 2586991171 34488482
2459767392 3122262011 192992195
1244086554 1754618583 31645052
1073753155 1497748002 19791800
3972002721 3949789211 7310666
3540362710 4077337854 20870225
1419012135 738256708 79984976
1746461061 1457945428 39802574
3595721417 4190079809 64686802
1616767336 653895091 19337477
1275731606 823578131 7616199
108723708 818241684 5336447
546405579 1395757504 62187924
1498997111 950656506 117770225
2888632532 3957099877 102103275
1744112789 1752270311 2348272
2233819388 2077946837 225948004
3762871885 2401432005 890723
2136282224 2303894841 97537164
3311914546 3315254206 186374032
2118147522 4059203152 18134702
308182087 831194330 111500959
114060155 0 24016268
2077946837 4254766611 40200685
971525741 33641977 102227414
1636104813 1517539802 108007976
138076423 1068426731 170105664
3220042816 4098208079 91871730
2990735807 2789589121 229307009
757885083 135869391 213640658
temperature-to-humidity map:
1130946446 972737563 146373650
1277320096 1760175559 41760032
4151385320 4147641404 143581976
2634337722 0 466605084
1992884166 956487184 16250379
4147641404 4291223380 3743916
641064346 466605084 489882100
1319080128 1801935591 673804038
2009134545 2475739629 625203177
0 1119111213 641064346
humidity-to-location map:
3903940466 3635148971 125939893
1458128760 2186815403 67353660
3125319983 1458128760 728686643
2261072201 3994982121 66012689
3854006626 2992363154 49933840
1525482420 3780550419 183145699
2233668127 3967578047 27404074
2442260515 3138011064 466023456
740912129 0 327948845
2422798960 3761088864 19461555
1708628119 3963696118 3881929
2327084890 3042296994 95714070
4029880359 3604034520 31114451
1712510048 2471205075 521158079
367508399 695457244 373403730
2908283971 2254169063 217036012
0 327948845 367508399

33
2023/day_05/sample.txt Normal file
View File

@ -0,0 +1,33 @@
seeds: 79 14 55 13
seed-to-soil map:
50 98 2
52 50 48
soil-to-fertilizer map:
0 15 37
37 52 2
39 0 15
fertilizer-to-water map:
49 53 8
0 11 42
42 0 7
57 7 4
water-to-light map:
88 18 7
18 25 70
light-to-temperature map:
45 77 23
81 45 19
68 64 13
temperature-to-humidity map:
0 69 1
1 0 69
humidity-to-location map:
60 56 37
56 93 4

View File

@ -0,0 +1,28 @@
import path from "path";
import { readlines } from "../../_utils";
import { part1_solver, part2_solver } from "./solution";
describe("day 5: fertilizer, pt 1", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(part1_solver(sample)).toBe(-1);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part1_solver(input)).toBe(-1);
});
});
describe("day 5: fertilizer, pt 2", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(part2_solver(sample)).toBe(-1);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part2_solver(input)).toBe(-1);
});
});

121
2023/day_05/solution.ts Normal file
View File

@ -0,0 +1,121 @@
/*
--- Day 5: If You Give A Seed A Fertilizer ---
You take the boat and find the gardener right where you were told he would be: managing a giant "garden" that looks more to you like a farm.
"A water source? Island Island is the water source!" You point out that Snow Island isn't receiving any water.
"Oh, we had to stop the water because we ran out of sand to filter it with! Can't make snow with dirty water. Don't worry, I'm sure we'll get more sand soon; we only turned off the water a few days... weeks... oh no." His face sinks into a look of horrified realization.
"I've been so busy making sure everyone here has food that I completely forgot to check why we stopped getting more sand! There's a ferry leaving soon that is headed over in that direction - it's much faster than your boat. Could you please go check it out?"
You barely have time to agree to this request when he brings up another. "While you wait for the ferry, maybe you can help us with our food production problem. The latest Island Island Almanac just arrived and we're having trouble making sense of it."
The almanac (your puzzle input) lists all of the seeds that need to be planted. It also lists what type of soil to use with each kind of seed, what type of fertilizer to use with each kind of soil, what type of water to use with each kind of fertilizer, and so on. Every type of seed, soil, fertilizer and so on is identified with a number, but numbers are reused by each category - that is, soil 123 and fertilizer 123 aren't necessarily related to each other.
For example:
seeds: 79 14 55 13
seed-to-soil map:
50 98 2
52 50 48
soil-to-fertilizer map:
0 15 37
37 52 2
39 0 15
fertilizer-to-water map:
49 53 8
0 11 42
42 0 7
57 7 4
water-to-light map:
88 18 7
18 25 70
light-to-temperature map:
45 77 23
81 45 19
68 64 13
temperature-to-humidity map:
0 69 1
1 0 69
humidity-to-location map:
60 56 37
56 93 4
The almanac starts by listing which seeds need to be planted: seeds 79, 14, 55, and 13.
The rest of the almanac contains a list of maps which describe how to convert numbers from a source category into numbers in a destination category. That is, the section that starts with seed-to-soil map: describes how to convert a seed number (the source) to a soil number (the destination). This lets the gardener and his team know which soil to use with which seeds, which water to use with which fertilizer, and so on.
Rather than list every source number and its corresponding destination number one by one, the maps describe entire ranges of numbers that can be converted. Each line within a map contains three numbers: the destination range start, the source range start, and the range length.
Consider again the example seed-to-soil map:
50 98 2
52 50 48
The first line has a destination range start of 50, a source range start of 98, and a range length of 2. This line means that the source range starts at 98 and contains two values: 98 and 99. The destination range is the same length, but it starts at 50, so its two values are 50 and 51. With this information, you know that seed number 98 corresponds to soil number 50 and that seed number 99 corresponds to soil number 51.
The second line means that the source range starts at 50 and contains 48 values: 50, 51, ..., 96, 97. This corresponds to a destination range starting at 52 and also containing 48 values: 52, 53, ..., 98, 99. So, seed number 53 corresponds to soil number 55.
Any source numbers that aren't mapped correspond to the same destination number. So, seed number 10 corresponds to soil number 10.
So, the entire list of seed numbers and their corresponding soil numbers looks like this:
seed soil
0 0
1 1
... ...
48 48
49 49
50 52
51 53
... ...
96 98
97 99
98 50
99 51
With this map, you can look up the soil number required for each initial seed number:
Seed number 79 corresponds to soil number 81.
Seed number 14 corresponds to soil number 14.
Seed number 55 corresponds to soil number 57.
Seed number 13 corresponds to soil number 13.
The gardener and his team want to get started as soon as possible, so they'd like to know the closest location that needs a seed. Using these maps, find the lowest location number that corresponds to any of the initial seeds. To do this, you'll need to convert each seed number through other categories until you can find its corresponding location number. In this example, the corresponding types are:
Seed 79, soil 81, fertilizer 81, water 81, light 74, temperature 78, humidity 78, location 82.
Seed 14, soil 14, fertilizer 53, water 49, light 42, temperature 42, humidity 43, location 43.
Seed 55, soil 57, fertilizer 57, water 53, light 46, temperature 82, humidity 82, location 86.
Seed 13, soil 13, fertilizer 52, water 41, light 34, temperature 34, humidity 35, location 35.
So, the lowest location number in this example is 35.
What is the lowest location number that corresponds to any of the initial seed numbers?
*/
type SeedToSoil = {
[seed: number]: number
}
export function part1_solver(lines: string[]): number {
return 1;
}
/*
*/
export function part2_solver(lines: string[]): number {
return 1;
}

View File

@ -48,9 +48,9 @@ export function group<T>(
return isCutoffPoint return isCutoffPoint
? [...previousValue, includeCutoffValue ? [currentValue] : []] ? [...previousValue, includeCutoffValue ? [currentValue] : []]
: [ : [
...previousValue.slice(0, -1), ...previousValue.slice(0, -1),
[...previousValue[previousValue.length - 1], currentValue], [...previousValue[previousValue.length - 1], currentValue],
]; ];
}, },
[[]] as T[][] [[]] as T[][]
); );
@ -63,3 +63,30 @@ export function sum(a: number, b: number): number {
export function emptyLines(line?: string): boolean { export function emptyLines(line?: string): boolean {
return !!line; return !!line;
} }
export function unique<T>(arr: T[]): T[] {
return arr.reduce<T[]>((res, current) => {
if (res.includes(current)) {
return res;
} else {
return [...res, current];
}
}, []);
}
export function allIndicesOf(s: string, search: string): number[] {
return unique(
s
.split("")
.reduce((results, _, index) => [...results, s.indexOf(search, index)], [])
).filter((x: number) => x >= 0);
}
export function extractNumbers(s: string): number {
const res = s.replaceAll(/[^\d]/g, "").trim()
if (isNaN(+res)) {
throw new Error(`Could not extract numbers from '${s}': got '${res}'`)
}
return +res;
}

View File

@ -1,10 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
day=$1
dir=$(printf "day_%02d" "$day")
mkdir -p "$dir"
curl -H "Cookie: $(cat ./session.cookie)" https://adventofcode.com/2022/day/"$day"/input -o "$dir"/input.txt

View File

@ -6,7 +6,8 @@
"main": "index.ts", "main": "index.ts",
"scripts": { "scripts": {
"start": "ts-node-esm index.ts", "start": "ts-node-esm index.ts",
"test": "jest" "test": "jest $(date +%Y)/day_${1:-$(date +%d)}/solution.test.ts",
"test-all": "jest"
}, },
"author": "", "author": "",
"license": "ISC", "license": "ISC",

1
session.cookie.example Normal file
View File

@ -0,0 +1 @@
session=<COOKIEHERE>

21
setup_day.sh Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -euo pipefail
export PUZZLE_NAME="$1"
export DAY="${2:-$(date +%d)}"
export DAY_SHORT=$(($DAY))
year=$(date +%Y)
dir="$year/day_$DAY"
mkdir "$dir"
envsubst < "solution.ts.template" > "$dir/solution.ts"
envsubst < "solution.test.ts.template" > "$dir/solution.test.ts"
touch "$dir/sample.txt"
curl -H "Cookie: $(cat ./session.cookie)" \
"https://adventofcode.com/$year/day/$DAY_SHORT/input" \
-o "$dir"/input.txt

28
solution.test.ts.template Normal file
View File

@ -0,0 +1,28 @@
import path from "path";
import { readlines } from "../../_utils";
import { part1_solver, part2_solver } from "./solution";
describe("day $DAY_SHORT: $PUZZLE_NAME, pt 1", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(part1_solver(sample)).toBe(-1);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part1_solver(input)).toBe(-1);
});
});
describe("day $DAY_SHORT: $PUZZLE_NAME, pt 2", () => {
test("sample input", async () => {
const sample = await readlines(path.resolve(__dirname, "./sample.txt"));
expect(part2_solver(sample)).toBe(-1);
});
test("submission input", async () => {
const input = await readlines(path.resolve(__dirname, "./input.txt"));
expect(part2_solver(input)).toBe(-1);
});
});

14
solution.ts.template Normal file
View File

@ -0,0 +1,14 @@
/*
*/
export function part1_solver(lines: string[]): number {
return 1;
}
/*
*/
export function part2_solver(lines: string[]): number {
return 1;
}