Ben Ashton
1 year ago
2 changed files with 2083 additions and 0 deletions
@ -0,0 +1,83 @@ |
|||||||
|
import { readFileSync } from 'node:fs'; |
||||||
|
|
||||||
|
const input = readFileSync('input', 'utf-8'); |
||||||
|
|
||||||
|
const moves = input |
||||||
|
.split('\n') |
||||||
|
.filter(line => line) |
||||||
|
.map(line => { |
||||||
|
const [direction, multiplier] = line.split(' ', 2); |
||||||
|
return new Array(parseInt(multiplier)).fill(direction); |
||||||
|
}) |
||||||
|
.flat(); |
||||||
|
|
||||||
|
|
||||||
|
function ropeSimulation(nTailKnots) { |
||||||
|
const positions = [new Array(nTailKnots + 1).fill().map(_ => [0, 0])]; |
||||||
|
|
||||||
|
for (const move of moves) { |
||||||
|
const lastKnots = positions[positions.length - 1]; |
||||||
|
let [x, y] = lastKnots[0]; |
||||||
|
|
||||||
|
switch (move) { |
||||||
|
case 'U': y += 1; break; |
||||||
|
case 'D': y -= 1; break; |
||||||
|
case 'L': x -= 1; break; |
||||||
|
case 'R': x += 1; break; |
||||||
|
default: throw new Error('Invalid move'); |
||||||
|
} |
||||||
|
|
||||||
|
const knots = [[x, y]]; |
||||||
|
|
||||||
|
for (let n = 0; n < nTailKnots; n++) { |
||||||
|
([x, y] = knots[knots.length - 1]); |
||||||
|
let [tx, ty] = lastKnots[n + 1]; |
||||||
|
|
||||||
|
if (y === ty && Math.abs(x - tx) === 2) { |
||||||
|
// Horizontal tavel
|
||||||
|
tx += (x - tx) / Math.abs(x - tx); |
||||||
|
} else if (x === tx && Math.abs(y - ty) === 2) { |
||||||
|
// Vertical travel
|
||||||
|
ty += (y - ty) / Math.abs(y - ty); |
||||||
|
} else if (Math.abs(x - tx) === 2 || Math.abs(y - ty) === 2) { |
||||||
|
// Diagonal travel
|
||||||
|
tx += (x - tx) / Math.abs(x - tx); |
||||||
|
ty += (y - ty) / Math.abs(y - ty); |
||||||
|
} |
||||||
|
|
||||||
|
knots.push([tx, ty]); |
||||||
|
} |
||||||
|
|
||||||
|
positions.push(knots); |
||||||
|
} |
||||||
|
|
||||||
|
return positions; |
||||||
|
} |
||||||
|
|
||||||
|
function countLastKnotPositions(positions) { |
||||||
|
// Count unique positions of tail
|
||||||
|
return positions |
||||||
|
.map(position => position[position.length - 1]) |
||||||
|
.filter((tailPosition, i, arr) => |
||||||
|
arr.findLastIndex(tp => |
||||||
|
tp[0] === tailPosition[0] && |
||||||
|
tp[1] === tailPosition[1] |
||||||
|
) === i |
||||||
|
) |
||||||
|
.length; |
||||||
|
} |
||||||
|
|
||||||
|
let positions = ropeSimulation(1); |
||||||
|
const totalPositionsOneKnot = countLastKnotPositions(positions); |
||||||
|
console.log( |
||||||
|
`Total unique positions of tail with 1 knot: ${totalPositionsOneKnot}` |
||||||
|
); |
||||||
|
|
||||||
|
|
||||||
|
positions = ropeSimulation(9); |
||||||
|
const totalPositionsTenKnots = countLastKnotPositions(positions); |
||||||
|
console.log( |
||||||
|
`Total unique positions of tail with 10 knots: ${totalPositionsTenKnots}` |
||||||
|
); |
||||||
|
|
||||||
|
|
Loading…
Reference in new issue