Skip to content

Commit

Permalink
Merge pull request #17 from hildjj/day7
Browse files Browse the repository at this point in the history
day7
  • Loading branch information
hildjj authored Dec 7, 2024
2 parents 276ef4f + 9450671 commit af573b9
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 1 deletion.
1 change: 1 addition & 0 deletions day6.peggy
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lines = (@[^\n]+ "\n")*
78 changes: 78 additions & 0 deletions day6.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Dir, Point, Rect } from './lib/rect.ts';
import { type MainArgs, parseFile } from './lib/utils.ts';

type Parsed = string[][];

function path(r: Rect): [Set<number>, Point] {
const [start] = r.filter((val) => val === '^');
let pos = start;
let dir = Dir.N;
const visited = new Set<number>();
while (true) {
visited.add(pos.toNumber());
const ahead = pos.inDir(dir);
if (!r.check(ahead)) {
break;
}
const char = r.get(ahead);
if (char === '.' || char === '^') {
pos = ahead;
} else {
dir = (dir + 1) % 4;
}
}
return [visited, start];
}

function path2(r: Rect): boolean {
const [start] = r.filter((val) => val === '^');
let pos = start;
let dir = Dir.N;
const visitedWithDir = new Set<string>();
while (true) {
const pwd = `${pos},${dir}`;
if (visitedWithDir.has(pwd)) {
return true;
}
visitedWithDir.add(pwd);
const ahead = pos.inDir(dir);
if (!r.check(ahead)) {
return false;
}
const char = r.get(ahead);
if (char === '.' || char === '^') {
pos = ahead;
} else {
dir = (dir + 1) % 4;
}
}
}

function part1(inp: Parsed): number {
const r = new Rect(inp);
const [visited] = path(r);
return visited.size;
}

function part2(inp: Parsed): number {
const r = new Rect(inp);
const [visited, start] = path(r);
const points = [...visited].map((v) => Point.fromNumber(v));
let tot = 0;
for (const p of points) {
if (p.equals(start)) {
continue;
}
r.set(p, '#');
if (path2(r)) {
tot++;
}
r.set(p, '.');
}
return tot;
}

export default async function main(args: MainArgs): Promise<[number, number]> {
const inp = await parseFile<Parsed>(args);
return [part1(inp), part2(inp)];
}
4 changes: 4 additions & 0 deletions day7.peggy
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
lines = (@num ":" _ @num|1.., _|"\n")*

num = n:$[0-9]+ { return parseInt(n, 10) }
_ = [ \t]+
51 changes: 51 additions & 0 deletions day7.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { type MainArgs, parseFile } from './lib/utils.ts';

type Line = [number, number[]];
type Parsed = Line[];

// Starting from the front of the reversed list (the endq), see if we can rule
// out any of the operations
function calc(left: number, operands: number[], concat = false): boolean {
if (!operands.length) {
return left === 0;
}
const [first, ...rest] = operands;
if (concat) { // Part 2 adds concatenation operator
const sleft = String(left);
const sfirst = String(first);
const prefix = sleft.slice(0, -sfirst.length);
if ((prefix + sfirst === sleft) && calc(Number(prefix), rest, concat)) {
return true;
}
}

const dleft = left / first;
if (Number.isInteger(dleft) && calc(dleft, rest, concat)) {
return true;
}

const mleft = left - first;
return (mleft >= 0) && calc(mleft, rest, concat);
}

function part1(inp: Parsed): number {
return inp.reduce(
(t, [tot, operands]) => t + (calc(tot, operands) ? tot : 0),
0,
);
}

function part2(inp: Parsed): number {
return inp.reduce(
(t, [tot, operands]) => t + (calc(tot, operands, true) ? tot : 0),
0,
);
}

export default async function main(args: MainArgs): Promise<[number, number]> {
const inp = await parseFile<Parsed>(args);
for (const [_tot, operands] of inp) {
operands.reverse();
}
return [part1(inp), part2(inp)];
}
2 changes: 1 addition & 1 deletion inputs
16 changes: 16 additions & 0 deletions lib/rect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,22 @@ export class Point implements PointLike {
return `${this.x},${this.y}`;
}

toNumber(size = 16): number {
return (this.x << size) | this.y;
}

static fromNumber(num: number, size = 16): Point {
return new Point(num >> size, num & ((1 << size) - 1));
}

static fromString(str: string): Point {
const m = str.match(/(\d+),(\d+)/);
if (!m) {
throw new Error(`Invalid format: "${str}"`);
}
return new Point(Number(m[1]), Number(m[2]));
}

[Symbol.for('Deno.customInspect')](): string {
return this.toString();
}
Expand Down
9 changes: 9 additions & 0 deletions t
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
190: 10 19
3267: 81 40 27
83: 17 5
156: 15 6
7290: 6 8 6 15
161011: 16 10 13
192: 17 8 14
21037: 9 7 18 13
292: 11 6 16 20
1 change: 1 addition & 0 deletions test/day6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default [4374, 1705];
1 change: 1 addition & 0 deletions test/day7.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default [1038838357795, 254136560217241];

0 comments on commit af573b9

Please sign in to comment.