Skip to content

Commit a08cf23

Browse files
committed
Add solution for puzzle 02
1 parent 7d2a608 commit a08cf23

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

Diff for: .editorconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ trim_trailing_whitespace = true
1010
insert_final_newline = true
1111
end_of_line = lf
1212

13-
[*.ts]
13+
[*.{ts,mts}]
1414
indent_size = 2

Diff for: src/puzzle02.mts

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { readFile } from 'node:fs/promises';
2+
3+
import { getDataPath } from './core/project.mjs';
4+
5+
export async function solvePuzzle02Basic() {
6+
const content = await readFile(getDataPath('input/puzzle02.txt'), {encoding: 'utf8'});
7+
const reports = parseReports(content);
8+
9+
let safeCount = 0;
10+
for (const report of reports) {
11+
if (isSafeReport(report, 1, 3) || isSafeReport(report, -3, -1)) {
12+
safeCount++;
13+
}
14+
}
15+
16+
console.log(`Puzzle 02 (basic): ${safeCount}`);
17+
}
18+
19+
export async function solvePuzzle02Advanced() {
20+
const content = await readFile(getDataPath('input/puzzle02.txt'), {encoding: 'utf8'});
21+
const reports = parseReports(content);
22+
23+
let safeCount = 0;
24+
for (const report of reports) {
25+
if (isSafeReport(report, 1, 3, true) || isSafeReport(report, -3, -1, true)) {
26+
safeCount++;
27+
}
28+
}
29+
30+
console.log(`Puzzle 02 (advanced): ${safeCount}`);
31+
}
32+
33+
function parseReports(content: string): Array<number[]> {
34+
const reports: Array<number[]> = [];
35+
for (const line of content.split(/\r?\n/g)) {
36+
if (!line) {
37+
continue;
38+
}
39+
const report = line.split(' ').map(item => Number(item));
40+
reports.push(report);
41+
}
42+
return reports;
43+
}
44+
45+
function isSafeReport(
46+
report: readonly number[],
47+
minDiff: number,
48+
maxDiff: number,
49+
allowSkip = false,
50+
skipAt?: number
51+
): boolean {
52+
const end = rangeEnd(report.length, skipAt);
53+
let previous = rangeStart(report.length, skipAt);
54+
for (let i = rangeNext(previous, skipAt); i < end; i = rangeNext(i, skipAt)) {
55+
const diff = report[i] - report[previous];
56+
if (diff < minDiff || diff > maxDiff) {
57+
if (allowSkip) {
58+
return (
59+
isSafeReport(report, minDiff, maxDiff, false, previous) ||
60+
isSafeReport(report, minDiff, maxDiff, false, i)
61+
);
62+
}
63+
return false;
64+
}
65+
previous = i;
66+
}
67+
return true;
68+
}
69+
70+
function rangeStart(_length: number, skipAt: number | undefined): number {
71+
return skipAt === 0 ? 1 : 0;
72+
}
73+
74+
function rangeEnd(length: number, skipAt: number | undefined): number {
75+
return skipAt === length ? length - 1 : length;
76+
}
77+
78+
function rangeNext(index: number, skipAt: number | undefined): number {
79+
return index + 1 === skipAt ? index + 2 : index + 1;
80+
}
81+
82+
(async function main() {
83+
await solvePuzzle02Basic();
84+
await solvePuzzle02Advanced();
85+
})();

0 commit comments

Comments
 (0)