Skip to content

Commit

Permalink
day 3 (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
spalberg authored Dec 3, 2024
1 parent 11b403f commit a1541ee
Show file tree
Hide file tree
Showing 17 changed files with 201 additions and 59 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: denoland/setup-deno@v2
- run: deno test --junit-path=./junit.xml
- run: deno test --allow-read --parallel --junit-path=./junit.xml
- uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
Expand Down
14 changes: 7 additions & 7 deletions cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { colors } from "@cliffy/ansi/colors";
import { Command } from "@cliffy/command";
import { Input, Select } from "@cliffy/prompt";
import { readLinesFromFile } from "utils";
import { days, getSolution } from "./days/mod.ts";
import { days } from "./days/mod.ts";
import denoJson from "./deno.json" with { type: "json" };
import {
readLinesFromStdin,
Expand All @@ -13,7 +13,7 @@ const list = new Command()
.description("List all available solutions")
.action(() => {
console.log("Available solutions:");
for (const day of Object.keys(days)) {
for (const day of days.keys()) {
console.log(`- ${day}`);
}
});
Expand All @@ -22,7 +22,7 @@ const main = new Command()
.name("Advent of Code - 2024")
.version(denoJson.version)
.description("...")
.option("-d, --day <day:string>", "Day to run")
.option("-d, --day <day:number>", "Day to run")
.option("-i, --input <input:file>", "Input file, local path or remote URL")
.action(async (options) => {
let input: Array<string> | null = null;
Expand All @@ -43,7 +43,7 @@ const main = new Command()
Deno.exit(1);
}
const day = options.day ?? await selectDay();
const solution = getSolution(day);
const solution = days.get(day);
if (solution == null) {
console.error(`Day ${day} not found`);
Deno.exit(1);
Expand All @@ -60,11 +60,11 @@ async function provideInput(): Promise<string> {
});
}

async function selectDay(): Promise<string> {
async function selectDay(): Promise<number> {
return await Select.prompt({
message: "Select day",
options: Object.keys(days).map((day) => ({
name: day.toString().padStart(2, "0"),
options: [...days.keys()].map((day) => ({
name: day.toString(),
value: day,
})),
});
Expand Down
19 changes: 0 additions & 19 deletions days/01/main_test.ts

This file was deleted.

19 changes: 0 additions & 19 deletions days/02/main_test.ts

This file was deleted.

File renamed without changes.
33 changes: 33 additions & 0 deletions days/1/main_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { expect } from "@std/expect";
import { describe, it } from "@std/testing/bdd";
import { part1, part2 } from "./main.ts";
import { loadInput } from "utils";

describe("day 1 example", () => {
const input = [
"3 4",
"4 3",
"2 5",
"1 3",
"3 9",
"3 3",
];

it("part 1", () => {
expect(part1(input)).toBe(11);
});

it("part 2", () => {
expect(part2(input)).toBe(31);
});
});

describe("day 1 solution", () => {
it("part 1", async () => {
expect(part1(await loadInput(1))).toBe(2378066);
});

it("part 2", async () => {
expect(part2(await loadInput(1))).toBe(18934359);
});
});
File renamed without changes.
33 changes: 33 additions & 0 deletions days/2/main_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { expect } from "@std/expect";
import { describe, it } from "@std/testing/bdd";
import { part1, part2 } from "./main.ts";
import { loadInput } from "utils";

describe("day 2 example", () => {
const input = [
"7 6 4 2 1",
"1 2 7 8 9",
"9 7 6 2 1",
"1 3 2 4 5",
"8 6 4 4 1",
"1 3 6 7 9",
];

it("part 1", () => {
expect(part1(input)).toBe(2);
});

it("part 2", () => {
expect(part2(input)).toBe(4);
});
});

describe("day 2 solution", () => {
it("part 1", async () => {
expect(part1(await loadInput(2))).toBe(421);
});

it("part 2", async () => {
expect(part2(await loadInput(2))).toBe(476);
});
});
59 changes: 59 additions & 0 deletions days/3/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { loadInput } from "utils";

type Mul = readonly [number, number];

export function part1(input: Array<string>) {
return [...getAllMuls(input.join("|"))].map(([a, b]) => a * b).reduce(
(acc, n) => acc + n,
0,
);
}

export function part2(input: Array<string>) {
return [...getAllConditionalMuls(input.join("|"))].map(([a, b]) => a * b)
.reduce(
(acc, n) => acc + n,
0,
);
}

function matchMul(input: string): [Mul, string, number] | null {
const match = input.match(/mul\((\d{1,3}),(\d{1,3})\)/);
if (match == null) return null;
const remaining = input.slice(match.index! + match[0].length);
return [
[parseInt(match[1], 10), parseInt(match[2], 10)],
remaining,
match.index!,
];
}

function* getAllMuls(input: string) {
let remaining = input;
while (true) {
const match = matchMul(remaining);
if (match == null) {
break;
}
yield match[0];
remaining = match[1];
}
}

function* getAllConditionalMuls(input: string) {
const doables = input.split("do()");
for (let doable of doables) {
const indexOfDont = doable.indexOf("don't()");
if (indexOfDont !== -1) {
doable = doable.slice(0, indexOfDont);
}
for (const mul of getAllMuls(doable)) {
yield mul;
}
}
}

if (import.meta.main) {
console.log(part1(await loadInput(3)));
console.log(part2(await loadInput(3)));
}
32 changes: 32 additions & 0 deletions days/3/main_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { expect } from "@std/expect";
import { describe, it } from "@std/testing/bdd";
import { part1, part2 } from "./main.ts";
import { loadInput } from "utils";

describe("day 3 example", () => {
it("part 1", () => {
expect(
part1([
"xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))",
]),
).toBe(161);
});

it("part 2", () => {
expect(
part2([
"xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))",
]),
).toBe(48);
});
});

describe("day 3 solution", () => {
it("part 1", async () => {
expect(part1(await loadInput(3))).toBe(162813399);
});

it("part 2", async () => {
expect(part2(await loadInput(3))).toBe(53783319);
});
});
14 changes: 3 additions & 11 deletions days/mod.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
type PartFunction = (input: Array<string>) => number;
type Solution = { part1: PartFunction; part2: PartFunction };

const days: Record<string, Solution> = {};
const days = new Map<number, Solution>();

for (const day of [1, 2]) {
days[pad(day)] = await import(`./${pad(day)}/main.ts`);
}

export function getSolution(day: string | number): Solution | null {
return days[pad(day)];
for (const day of [1, 2, 3]) {
days.set(day, await import(`./${day}/main.ts`));
}

export { days };

function pad(day: string | number) {
return day.toString().padStart(2, "0");
}
1 change: 1 addition & 0 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@std/collections": "jsr:@std/collections@1",
"@std/path": "jsr:@std/path@1",
"@std/streams": "jsr:@std/streams@^1.0.8",
"@std/testing": "jsr:@std/testing@^1.0.5",
"utils": "./utils/mod.ts"
}
}
26 changes: 25 additions & 1 deletion deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
File renamed without changes.
Loading

0 comments on commit a1541ee

Please sign in to comment.