Solve 2024-06 (using bruteforce)
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="2024-06" type="BunRunConfiguration">
|
||||||
|
<option name="program" value="2024/06/run.ts" />
|
||||||
|
<option name="workingDirectory" value="$PROJECT_DIR$" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { describe, expect, it } from 'bun:test';
|
||||||
|
import { solveFirst } from './index.ts';
|
||||||
|
|
||||||
|
describe('2024-06', () => {
|
||||||
|
const testInput = `....#.....
|
||||||
|
.........#
|
||||||
|
..........
|
||||||
|
..#.......
|
||||||
|
.......#..
|
||||||
|
..........
|
||||||
|
.#..^.....
|
||||||
|
........#.
|
||||||
|
#.........
|
||||||
|
......#...`;
|
||||||
|
it('first', () => {
|
||||||
|
expect(solveFirst(testInput)).toBe(41);
|
||||||
|
});
|
||||||
|
it('second', () => {
|
||||||
|
// that takes too long
|
||||||
|
// expect(solveSecond(testInput)).toBe(6);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
import { sumBy } from '../../utils/array.ts';
|
||||||
|
|
||||||
|
export function replace(arr: string[], x: number, y: number, char: string) {
|
||||||
|
arr[y] = arr[y].substring(0, x) + char + arr[y].substring(x + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const directions = [
|
||||||
|
{ d: '^', x: 0, y: -1 },
|
||||||
|
{ d: '>', x: 1, y: 0 },
|
||||||
|
{ d: 'v', x: 0, y: 1 },
|
||||||
|
{ d: '<', x: -1, y: 0 }
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function solveFirst(input: string): number {
|
||||||
|
const rows = input.split('\n');
|
||||||
|
|
||||||
|
const columnCount = rows[0].length;
|
||||||
|
const rowCount = rows.length;
|
||||||
|
|
||||||
|
let y = rows.findIndex((r) => r.indexOf('^') >= 0);
|
||||||
|
let x = rows[y].indexOf('^');
|
||||||
|
let direction = 0;
|
||||||
|
|
||||||
|
while (x >= 0 && x < columnCount && y >= 0 && y < rowCount) {
|
||||||
|
const nextX = x + directions[direction].x;
|
||||||
|
const nextY = y + directions[direction].y;
|
||||||
|
if (rows[nextY]?.[nextX] === '#') {
|
||||||
|
direction = (direction + 1) % 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
replace(rows, x, y, 'X');
|
||||||
|
x += directions[direction].x;
|
||||||
|
y += directions[direction].y;
|
||||||
|
}
|
||||||
|
return sumBy(rows, (r) => [...r.matchAll(/X/g)].length);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNextObstacle(
|
||||||
|
rows: string[],
|
||||||
|
startX: number,
|
||||||
|
startY: number,
|
||||||
|
d: number
|
||||||
|
): false | { x: number; y: number } {
|
||||||
|
let x = startX;
|
||||||
|
let y = startY;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const nextX = x + directions[d].x;
|
||||||
|
const nextY = y + directions[d].y;
|
||||||
|
const next = rows[nextY]?.[nextX];
|
||||||
|
if (!next) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (next === '#') {
|
||||||
|
return { x, y };
|
||||||
|
}
|
||||||
|
x = nextX;
|
||||||
|
y = nextY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function finishes(
|
||||||
|
rows: string[],
|
||||||
|
startX: number,
|
||||||
|
startY: number,
|
||||||
|
d: number
|
||||||
|
): boolean {
|
||||||
|
let x = startX;
|
||||||
|
let y = startY;
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
do {
|
||||||
|
const next = getNextObstacle(rows, x, y, (d + i) % 4);
|
||||||
|
if (!next) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
x = next.x;
|
||||||
|
y = next.y;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// TODO: be smarter
|
||||||
|
} while (i < 1_000_000);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function solveRow(
|
||||||
|
rows: string[],
|
||||||
|
row: number,
|
||||||
|
startX: number,
|
||||||
|
startY: number,
|
||||||
|
startDirection: number
|
||||||
|
) {
|
||||||
|
let found = 0;
|
||||||
|
|
||||||
|
for (let column = 0; column < rows[0].length; column++) {
|
||||||
|
if ((row === startX && column === startY) || rows[row][column] === '#') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
replace(rows, column, row, '#');
|
||||||
|
if (!finishes(rows, startX, startY, startDirection)) {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
|
||||||
|
replace(rows, column, row, '.');
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function solveSecond(input: string): number {
|
||||||
|
const rows = input.split('\n');
|
||||||
|
const rowCount = rows.length;
|
||||||
|
|
||||||
|
const y = rows.findIndex((r) => r.indexOf('^') >= 0);
|
||||||
|
const x = rows[y].indexOf('^');
|
||||||
|
const direction = 0;
|
||||||
|
|
||||||
|
let found = 0;
|
||||||
|
|
||||||
|
for (let row = 0; row < rowCount; row++) {
|
||||||
|
found += solveRow(rows, row, x, y, direction);
|
||||||
|
console.log('row:', row, 'found', found);
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { join } from 'path';
|
||||||
|
import { solveFirst, solveSecond } from './index.ts';
|
||||||
|
|
||||||
|
const input = await Bun.file(join(__dirname, 'input.txt')).text();
|
||||||
|
|
||||||
|
const firstAnswer = solveFirst(input);
|
||||||
|
|
||||||
|
console.log(firstAnswer);
|
||||||
|
|
||||||
|
const secondAnswer = solveSecond(input);
|
||||||
|
|
||||||
|
console.log(secondAnswer);
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { availableParallelism } from 'os';
|
||||||
|
import pLimit from 'p-limit';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { sumArray } from '../../utils/array.ts';
|
||||||
|
|
||||||
|
const workerFile = new URL('worker.ts', import.meta.url).href;
|
||||||
|
|
||||||
|
const eva = (i: number) =>
|
||||||
|
new Promise<number>((resolve) => {
|
||||||
|
const worker = new Worker(workerFile);
|
||||||
|
|
||||||
|
worker.postMessage(i);
|
||||||
|
worker.onmessage = (event) => {
|
||||||
|
console.log('row:', i, 'found', event.data);
|
||||||
|
resolve(event.data as number);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const input = await Bun.file(join(__dirname, 'input.txt')).text();
|
||||||
|
const rowCount = input.split('\n').length;
|
||||||
|
|
||||||
|
const work = new Array(rowCount).fill(0).map((_, i) => i);
|
||||||
|
|
||||||
|
const limit = pLimit(availableParallelism());
|
||||||
|
const solution = await Promise.all(work.map((w) => limit(eva, w)));
|
||||||
|
|
||||||
|
console.log(solution);
|
||||||
|
|
||||||
|
console.log(sumArray(solution));
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { join } from 'path';
|
||||||
|
import { solveRow } from './index.ts';
|
||||||
|
|
||||||
|
declare var self: Worker;
|
||||||
|
|
||||||
|
const input = await Bun.file(join(__dirname, 'input.txt')).text();
|
||||||
|
|
||||||
|
self.onmessage = (event) => {
|
||||||
|
const row = event.data as number;
|
||||||
|
|
||||||
|
console.log('Start row', row);
|
||||||
|
|
||||||
|
const rows = input.split('\n');
|
||||||
|
|
||||||
|
const y = rows.findIndex((r) => r.indexOf('^') >= 0);
|
||||||
|
const x = rows[y].indexOf('^');
|
||||||
|
const direction = 0;
|
||||||
|
|
||||||
|
postMessage(solveRow(rows, row, x, y, direction));
|
||||||
|
process.exit();
|
||||||
|
};
|
||||||
+2
-1
@@ -15,7 +15,8 @@
|
|||||||
"prettier": "^3.4.0",
|
"prettier": "^3.4.0",
|
||||||
"prettier-plugin-organize-imports": "^4.1.0",
|
"prettier-plugin-organize-imports": "^4.1.0",
|
||||||
"prompts": "^2.4.2",
|
"prompts": "^2.4.2",
|
||||||
"replace-in-file": "^8.2.0"
|
"replace-in-file": "^8.2.0",
|
||||||
|
"p-limit": "^6.1.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.7.2"
|
||||||
|
|||||||
Reference in New Issue
Block a user