day 14
This commit is contained in:
parent
88dfa7677a
commit
0045c63046
85
2022/14/part1.js
Normal file
85
2022/14/part1.js
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import * as R from "remeda";
|
||||||
|
import Victor from '@a-robu/victor';
|
||||||
|
|
||||||
|
import { readFile } from "../05/part1.js";
|
||||||
|
|
||||||
|
export const V = (...args) => new Victor(...args);
|
||||||
|
const parseLine = line => line.match(/[\d,]+/g).map( x => eval(`[${x}]`) );
|
||||||
|
|
||||||
|
const readInput = (...args) =>
|
||||||
|
R.pipe(
|
||||||
|
readFile(...args),
|
||||||
|
(lines) => lines.split("\n"),
|
||||||
|
R.compact, // remove last line
|
||||||
|
R.map( parseLine )
|
||||||
|
);
|
||||||
|
|
||||||
|
export const puzzleInput = readInput(import.meta.url, "input");
|
||||||
|
export const sample = readInput(import.meta.url, "sample");
|
||||||
|
|
||||||
|
|
||||||
|
export function genCave(rocks) {
|
||||||
|
const cave = {};
|
||||||
|
for( const rock of rocks ) {
|
||||||
|
const points = rock.map( Victor.fromArray );
|
||||||
|
let from = points.shift();
|
||||||
|
|
||||||
|
while( points.length ) {
|
||||||
|
/** @type Victor */
|
||||||
|
const to = points.shift();
|
||||||
|
const direction = to.clone().subtract(from).normalize();
|
||||||
|
|
||||||
|
R.times(to.clone().subtract(from).length()+1, () => {
|
||||||
|
if(!cave[from.y]) cave[from.y] = {};
|
||||||
|
cave[from.y][from.x] = '#';
|
||||||
|
from.add(direction);
|
||||||
|
});
|
||||||
|
|
||||||
|
from = to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cave;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function pourSand(cave){
|
||||||
|
cave = R.clone(cave);
|
||||||
|
|
||||||
|
let sand = 0;
|
||||||
|
|
||||||
|
/** @type Victor */
|
||||||
|
let current;
|
||||||
|
|
||||||
|
const maxDepth = R.pipe(
|
||||||
|
cave,
|
||||||
|
R.keys,
|
||||||
|
R.map( x => parseInt(x) ),
|
||||||
|
R.maxBy( R.identity ),
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log({ maxDepth });
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
if(!current) current = V(500,0);
|
||||||
|
if( current.y > maxDepth ) return sand;
|
||||||
|
|
||||||
|
const next = [ [0,1],[-1,1],[1,1] ].map( args => V(...args) ).map(
|
||||||
|
v => v.add(current)
|
||||||
|
).find( v => ! (cave[v.y] && cave[v.y][v.x]) );
|
||||||
|
if( next ) {
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if( ! cave[current.y] ) cave[current.y] = {};
|
||||||
|
cave[current.y][current.x] = 'o';
|
||||||
|
sand++;
|
||||||
|
current = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default R.createPipe(
|
||||||
|
genCave,
|
||||||
|
pourSand,
|
||||||
|
)
|
52
2022/14/part2.js
Normal file
52
2022/14/part2.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import * as R from "remeda";
|
||||||
|
import { genCave, V } from './part1.js';
|
||||||
|
|
||||||
|
function pourSand(cave){
|
||||||
|
cave = R.clone(cave);
|
||||||
|
|
||||||
|
let sand = 0;
|
||||||
|
|
||||||
|
/** @type Victor */
|
||||||
|
let current;
|
||||||
|
|
||||||
|
const maxDepth = R.pipe(
|
||||||
|
cave,
|
||||||
|
R.keys,
|
||||||
|
R.map( x => parseInt(x) ),
|
||||||
|
R.maxBy( R.identity ),
|
||||||
|
) + 1;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
if(!current) current = V(500,0);
|
||||||
|
|
||||||
|
if( current.y === maxDepth ) {
|
||||||
|
if( ! cave[current.y] ) cave[current.y] = {};
|
||||||
|
cave[current.y][current.x] = 'o';
|
||||||
|
sand++;
|
||||||
|
current = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const next = [ [0,1],[-1,1],[1,1] ].map( args => V(...args) ).map(
|
||||||
|
v => v.add(current)
|
||||||
|
).find( v => ! (cave[v.y] && cave[v.y][v.x]) );
|
||||||
|
|
||||||
|
if( next ) {
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if( current.y === 0 ) return 1+sand;
|
||||||
|
|
||||||
|
if( ! cave[current.y] ) cave[current.y] = {};
|
||||||
|
cave[current.y][current.x] = 'o';
|
||||||
|
sand++;
|
||||||
|
current = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default R.createPipe(
|
||||||
|
genCave,
|
||||||
|
pourSand,
|
||||||
|
)
|
2
2022/14/sample
Normal file
2
2022/14/sample
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
498,4 -> 498,6 -> 496,6
|
||||||
|
503,4 -> 502,4 -> 502,9 -> 494,9
|
34
2022/14/test.js
Normal file
34
2022/14/test.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { test, expect, describe } from "vitest";
|
||||||
|
|
||||||
|
import { expectSolution } from "../01/main.js";
|
||||||
|
import part1, { genCave, sample, puzzleInput } from "./part1.js";
|
||||||
|
import part2 from "./part2.js";
|
||||||
|
|
||||||
|
describe("part 1", () => {
|
||||||
|
test("readInput", () => {
|
||||||
|
expect(sample).toEqual([
|
||||||
|
[[498,4], [498,6], [496,6]],
|
||||||
|
[[503,4 ], [ 502,4 ], [ 502,9 ], [ 494,9]],
|
||||||
|
])
|
||||||
|
});
|
||||||
|
test( 'genCave', () => {
|
||||||
|
expect( genCave(sample) ).toMatchObject({
|
||||||
|
4: { 498: '#' }
|
||||||
|
});
|
||||||
|
} )
|
||||||
|
test("sample", () => {
|
||||||
|
expect(part1(sample)).toEqual(24);
|
||||||
|
});
|
||||||
|
test("solution", () => {
|
||||||
|
expectSolution(part1(puzzleInput)).toEqual(832);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe.only("part 2", () => {
|
||||||
|
test("sample", () => {
|
||||||
|
expect(part2(sample)).toEqual(93);
|
||||||
|
});
|
||||||
|
test("solution", () => {
|
||||||
|
expectSolution(part2(puzzleInput)).toEqual(27601);
|
||||||
|
});
|
||||||
|
});
|
@ -19,5 +19,8 @@
|
|||||||
"remeda": "^1.3.0",
|
"remeda": "^1.3.0",
|
||||||
"vite": "^4.0.1",
|
"vite": "^4.0.1",
|
||||||
"vitest": "0.25.7"
|
"vitest": "0.25.7"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitest/ui": "^0.25.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user