Skip to content

Commit d919fdb

Browse files
authored
Merge pull request #41 from weaponsforge/feat/weaponsforge-15
feat: day 10 hoof it 20241210
2 parents 8e559d0 + 92b8248 commit d919fdb

File tree

14 files changed

+340
-4
lines changed

14 files changed

+340
-4
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The codes are structured in a way that discusses and walks through the solution
1818
- Day 7: Bridge Repair [[link]](/src/2024/2024-12-07/README.md)
1919
- Day 8: Resonant Collinearity [[link]](/src/2024/2024-12-08/README.md)
2020
- Day 9: Disk Fragmenter [[link]](/src/2024/2024-12-09/README.md)
21+
- Day 10: Hoof It [[link]](/src/2024/2024-12-10/README.md)
2122

2223
</details>
2324

@@ -101,7 +102,7 @@ Each Advent of Code (AOC) event quiz has its folder under **`"/src/<YEAR>/<YYYY-
101102
Using Node
102103

103104
1. (Optional) Replace the values of specific `input.txt` in the `"/src/<YEAR>/<YYYY-MM-DD>"` directories with actual AOC input.
104-
2. Run a non-test TypeScript file inside the **/src** directory. For example:
105+
2. Run a non-test TypeScript file inside the **/src** directory from the project's _**"root directory"**_. For example:
105106
```
106107
npx vite-node src/sample/sample.ts
107108
```

src/2024/2024-12-09/main.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ export const quiz20241209_01 = () => {
2222
console.log('Compacted disk checksum:', sum)
2323
}
2424

25+
/**
26+
* Part 2/2 of the 2024-12-09 quiz
27+
* Counts the check sum of a defragment disk whose file blocks were moved to empty spaces as whole blocks
28+
*/
2529
export const quiz20241209_02 = () => {
2630
const disk = new WholeDisk(input, true)
2731
const sum = disk.calculateDiskChecksum()

src/2024/2024-12-10/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
## Day 10: Hoof It
2+
3+
Visit the Advent of Code website for more information on this puzzle at:
4+
5+
**Source:** https://adventofcode.com/2024/day/10<br>
6+
**Status:** Complete ⭐⭐
7+
8+
## Code
9+
10+
### `utils.ts`
11+
12+
- Utility and helper functions.
13+
14+
### `scoresRatings.ts`
15+
16+
- `countTrailScores()`
17+
- Finds valid hiking trails (trailheads) from a point coordinate in a 2D array starting with `0` and ending in `9` symbol and calculates the **scores** for each trailhead.
18+
- Calculates the trailhead **ratings** instead of the trailhead scores if provided with the optional `{ isRating: true }` parameter. Defaults to `false`
11 KB
Loading
15.1 KB
Loading
12.4 KB
Loading
23.8 KB
Loading

src/2024/2024-12-10/input.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
89010123
2+
78121874
3+
87430965
4+
96749874
5+
45278903
6+
32019012
7+
01329801
8+
10456732
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import type { Point } from '../../2024-12-08/lib/types.js'
2+
import type { InputOptions, PointSteps, PointDirection, TrailScores } from './types.js'
3+
4+
import {
5+
findValidSteps,
6+
findZeroCoordinatePositions,
7+
getCoordinateSymbol
8+
} from './utils.js'
9+
10+
// List of trailhead scores
11+
const scores: Record<string, string[]> = {}
12+
let activeZeroIndex = ''
13+
14+
/**
15+
* Finds valid hiking trails (trailheads) from a point coordinate in a 2D array starting `0` and ending in `9` symbols and
16+
* calculates the scores for each trailhead.
17+
* @param {PointDirection} pointVector - Point (y,x) coordinate in a 2D array with a list of valid coordinates from its location.
18+
* @param {number[][]} data - 2D number array containing hiking trail data
19+
* @param {boolean} isRating - If `true`, calculates the trailhead ratings instead of the trailhead scores. Defaults to `false`
20+
* @returns {void}
21+
*/
22+
const findPaths = (pointVector: PointDirection, data: number[][], isRating: boolean = false) => {
23+
const grid = {
24+
length: data.length, width: data[0]!.length
25+
}
26+
27+
if (pointVector.validSteps.length > 0) {
28+
while (pointVector.validSteps.length > 0) {
29+
const step = pointVector.validSteps.pop()
30+
31+
if (step === undefined) continue
32+
const pt = getCoordinateSymbol(step, data)
33+
34+
if (pt.symbol === 9) {
35+
if (isRating) {
36+
// Rating: count all trails ending in 9's
37+
scores[activeZeroIndex]?.push(pt.coordinate)
38+
} else {
39+
// Scores: count unique ending 9's that match with the starting 0
40+
if (!scores[activeZeroIndex]!.includes(pt.coordinate)) {
41+
scores[activeZeroIndex]?.push(pt.coordinate)
42+
}
43+
}
44+
}
45+
46+
const point: PointDirection = {
47+
x: step!.x,
48+
y: step!.y,
49+
validSteps: findValidSteps(step as Point, grid, data) as PointSteps[]
50+
}
51+
52+
findPaths(point, data, isRating)
53+
}
54+
}
55+
}
56+
57+
/**
58+
* Finds valid trailheads and counts each trailhead score.
59+
* @param {number[][]} data - 2D number array containing hiking trail data
60+
* @param {boolean} [printLog] - Flag to display the processing and total score logs
61+
* @typedef {InputOptions} params - Input and logging parameter options
62+
* @param {boolean} [params.printLog] - (Optional) Flag to display the miscellaneous data processing logs.
63+
* @param {boolean} [params.isRating] - (Optional) Flag to calculate the trailhead rating instead of the score.
64+
* @returns {TrailScores}
65+
*/
66+
export const countTrailScores = (data: number[][], params?: InputOptions): TrailScores => {
67+
// Find starting positions
68+
const starts = findZeroCoordinatePositions(data)
69+
70+
const grid = {
71+
length: data.length, width: data[0]!.length
72+
}
73+
74+
for (let i = 0; i < starts.length; i += 1) {
75+
const initStep: PointDirection = {
76+
x: starts[i]!.x,
77+
y: starts[i]!.y,
78+
validSteps: findValidSteps(starts[i] as Point, grid, data) as PointSteps[]
79+
}
80+
81+
const pt = getCoordinateSymbol(starts[i] as Point, data)
82+
activeZeroIndex = pt.coordinate
83+
scores[activeZeroIndex] = []
84+
85+
findPaths(initStep, data, params?.isRating)
86+
}
87+
88+
const total = Object
89+
.values(scores)
90+
.map(x => x.length)
91+
.reduce((sum, item) => sum += item, 0)
92+
93+
if (params?.printLog) {
94+
for (const key in scores) {
95+
console.log(`[${key}]: ${scores[key]?.length} score`)
96+
}
97+
98+
console.log('--TOTAL SCORE', total)
99+
}
100+
101+
return {
102+
scores,
103+
total
104+
}
105+
}

src/2024/2024-12-10/lib/types.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Point (y,x) coordinate in a 2D array with direction
3+
* @type {Object} PointSteps
4+
* @property {number} x - x-coordinate of the point
5+
* @property {number} y - y-coordinate of the point
6+
* @property {Object} direction - Direction vector
7+
* @property {number} direction.x - Left/right x-direction denoted by `+1` or `-1`
8+
* @property {number} direction.y - Up/down y-direction denoted by `-1` or `+1`
9+
*/
10+
export type PointSteps = {
11+
x: number;
12+
y: number;
13+
direction: {
14+
x: number;
15+
y: number;
16+
}
17+
}
18+
19+
/**
20+
* Point (y,x) coordinate in a 2D array with a list of valid coordinates from its location.
21+
* @type {Object} PointDirection
22+
* @property {number} x - x-coordinate of the point
23+
* @property {number} y - y-coordinate of the point
24+
* @property {PointSteps[]} validSteps - List of valid up/down/left/right coordinates from the (y,x) position.
25+
*/
26+
export type PointDirection = {
27+
x: number;
28+
y: number;
29+
validSteps: PointSteps[]
30+
}
31+
32+
/**
33+
* Represents a "(y,x)" coordinate in string and its value from a 2D array.
34+
* @param {string} coordinate - String version of an "(y,x)" coordinate
35+
* @param {string | number} symbol - Number or character in a 2D arary denoted by the (y,x) coordinate
36+
*/
37+
export type GridCoordinateSymbol = {
38+
coordinate: string;
39+
symbol: string | number;
40+
}
41+
42+
/**
43+
* Data returned by the trailhead scores counting function.
44+
* @param {Record<string, string[]>} scores - Object list of trailhead scores per (y,x) coordinate that starts with a unique `0` and ends with a `9`
45+
* @param {number} total - Total sum of the `scores`
46+
*/
47+
export type TrailScores = {
48+
scores: Record<string, string[]>,
49+
total: number;
50+
}
51+
52+
/**
53+
* Input settings options parameters for the Day 10 quiz
54+
* @param {boolean} [printLog] - (Optional) Flag to display the miscellaneous data processing logs.
55+
* @param {boolean} [isRating] - (Optional) Flag to calculate the trailhead rating instead of the score.
56+
*/
57+
export type InputOptions = {
58+
printLog?: boolean;
59+
isRating?: boolean;
60+
}

0 commit comments

Comments
 (0)