Advent of Code 2024 Day 2
Day two! Today’s challenge is about checking the safety of some kind of report. The report is a sequence of numbers, and we need to check if it is “safe”. A report is considered safe if it follows these criteria:
- The report is either strictly ascending or strictly descending.
- The difference between any two adjacent numbers in the report is at most 3.
And step two added an additional criteria:
- If we remove any SINGLE number from the report, the remaining sequence is still be safe.
Pretty simple! So, I wrote a function checkReportIsSafe
that takes an array of numbers and returns true
if the report is safe, and false
otherwise. The function first checks the report without removing any numbers, and if it fails, it tries removing each number one at a time and checking the report again.
Here’s the code:
import {reports} from './input';
function checkReportIsSafe(report: Array<number>): boolean {
/**
* Helper function that validates a sequence without using the dampener.
* Returns true if the sequence follows all safety criteria.
*/
function isSequenceValid(sequence: Array<number>): boolean {
// Single measurements or empty sequences are considered valid
if (sequence.length < 2) return true;
// Establish initial direction of sequence
let direction: 'asc' | 'desc' | undefined;
if (sequence[1] > sequence[0]) {
direction = 'asc'; // Ascending sequence detected
} else if (sequence[1] < sequence[0]) {
direction = 'desc'; // Descending sequence detected
}
// Validate each pair of adjacent measurements
for (let i = 1; i < sequence.length; i++) {
const current = sequence[i];
const previous = sequence[i - 1];
// Ensure consistent direction throughout sequence
if (current > previous) {
if (direction === 'desc') return false; // Direction violation
direction = 'asc';
} else if (current < previous) {
if (direction === 'asc') return false; // Direction violation
direction = 'desc';
}
// Validate step size between measurements
const difference = Math.abs(current - previous);
if (difference > 3 || difference === 0) return false; // Step size violation
}
return true; // All validation checks passed
}
// First attempt: Validate sequence without dampening
if (isSequenceValid(report)) return true;
// Second attempt: Try removing each measurement one at a time
// This implements the Problem Dampener functionality
for (let i = 0; i < report.length; i++) {
const dampened = [...report.slice(0, i), ...report.slice(i + 1)];
if (isSequenceValid(dampened)) return true;
}
// If all attempts fail, the report is unsafe
return false;
}
// Calculate total number of safe reports
const correctReports = reports.filter(checkReportIsSafe).length;
console.log(`⛄ 🎅 DAY 2: There are ${correctReports} safe reports`);
Once again input.ts
contains the input from the challenge, and a small helper function to turn it into an array:
const parseToArrays = input => {
// Split by newlines and filter out empty lines
const lines = input
.trim()
.split('\n')
.filter(line => line.trim());
// Convert each line into an array of numbers 💤
return lines.map(line =>
line
.trim()
.split(' ')
.filter(num => num.trim()) // Remove empty strings
.map(num => parseInt(num, 10))
);
};