Skip to content

Commit

Permalink
Add day 14 of year 2024 🎄
Browse files Browse the repository at this point in the history
  • Loading branch information
letelete committed Dec 14, 2024
1 parent 53562ec commit 734677d
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
21 changes: 21 additions & 0 deletions 2024/days/day-14/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Benchmark

```
Platform: darwin arm64
CPU: Apple M3 Pro 11 Cores
Memory: 18.00 GB
```

## Sample 1

| part | time (~) | μs |
| ---- | -------- | ----------------- |
| 1 | 0.35ms | 0.351707999999995 |
| 2 | 7.75ms | 7.748540999999996 |

## Answer

| part | time (~) | μs |
| ---- | -------- | ------------------ |
| 1 | 0.19ms | 0.1948330000000027 |
| 2 | 645.41ms | 645.405041 |
14 changes: 14 additions & 0 deletions 2024/days/day-14/in.sample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
11 7

p=0,4 v=3,-3
p=6,3 v=-1,-3
p=10,3 v=-1,2
p=2,0 v=2,-1
p=0,0 v=1,3
p=3,0 v=-2,-2
p=7,6 v=-1,-3
p=3,0 v=-1,-2
p=9,3 v=2,3
p=7,3 v=-1,2
p=2,4 v=2,-3
p=9,5 v=-3,-3
125 changes: 125 additions & 0 deletions 2024/days/day-14/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
function parse(source) {
const [size, robots] = source.trim().split('\n\n');
return {
size: size.split(' ').map(Number),
robots: robots.split('\n').map((segment) => {
const [, px, py, vx, vy] = segment.match(
/p=(-?\d+),(-?\d+)\sv=(-?\d+),(-?\d+)/
);
return {
p: [Number(px), Number(py)],
v: [Number(vx), Number(vy)],
};
}),
};
}

function mod(a, b) {
return ((a % b) + b) % b;
}

function wrap(len, p, v, seconds) {
return mod(p + v * seconds, len);
}

function simulate(lenX, lenY, robots, seconds) {
return robots.map(({ p: [px, py], v: [vx, vy] }) => {
return {
p: [wrap(lenX, px, vx, seconds), wrap(lenY, py, vy, seconds)],
v: [vx, vy],
};
});
}

function countInArea(x0, y0, x1, y1, robots) {
return robots.filter(
(robot) =>
robot.p[0] >= x0 &&
robot.p[0] <= x1 &&
robot.p[1] >= y0 &&
robot.p[1] <= y1
).length;
}

function getQuadrants(sizeX, sizeY) {
const midX = Math.floor(sizeX / 2);
const midY = Math.floor(sizeY / 2);
return [
[
[0, 0],
[midX - 1, midY - 1],
],
[
[midX + 1, 0],
[sizeX - 1, midY - 1],
],
[
[0, midY + 1],
[midX - 1, sizeY - 1],
],
[
[midX + 1, midY + 1],
[sizeX - 1, sizeY - 1],
],
];
}

function createGrid(sizeX, sizeY, robots) {
return robots
.reduce(
(grid, { p: [px, py] }) => {
grid[py][px] = '#';
return grid;
},
new Array(sizeY).fill(null).map(() => new Array(sizeX).fill('.'))
)
.map((row) => row.join(''))
.join('\n');
}

function getEntropyScore(robots) {
let score = 0;
[...robots]
.sort(({ p: [x1, y1] }, { p: [x2, y2] }) =>
x1 === x2 ? -1 : y1 === y2 ? -1 : 1
)
.forEach(({ p: [x1, y1] }, i, arr) => {
if (i !== 0) {
const [x2, y2] = arr[i - 1].p;
score += ((x1 + 1) / (x2 + 1)) * ((y1 + 1) / (y2 + 1));
}
});
return score;
}

function part1(data) {
const seconds = 100;
const robots = simulate(data.size[0], data.size[1], data.robots, seconds);

const quads = getQuadrants(data.size[0], data.size[1]);
return quads.reduce(
(acc, [[x0, y0], [x1, y1]]) => acc * countInArea(x0, y0, x1, y1, robots),
1
);
}

function part2(data) {
let bestMatch = [-1, Infinity, []];
for (let i = 0; i < data.size[0] * data.size[1]; ++i) {
const robots = simulate(data.size[0], data.size[1], data.robots, i);
const entropyScore = getEntropyScore(robots);
if (entropyScore < bestMatch[1]) {
bestMatch = [i, entropyScore, robots];
}
}

const grid = createGrid(data.size[0], data.size[1], bestMatch[2]);

console.log(
`seconds: ${bestMatch[0]}, entropy: ${bestMatch[1]}\n${grid}\n\n`
);

return bestMatch[0];
}

module.exports = { parse, part1, part2 };

0 comments on commit 734677d

Please sign in to comment.