This is a solution to Advent of Code 2024 day 2, written in Raku.
https://adventofcode.com/2024/day/2
Part One
Analyze the unusual data from the engineers. How many reports are safe?
Raku
The Raku [<]
and [>]
reduction meta-operators are very handy way to performa a boolean check
for list order. With a few more boolean meta-operators and a hyper operator to compute a
diference list we have a solution.
my @lines = 'input-2.txt'.IO.lines>>.split(/\s+/);
say [+] @lines.map(
-> @levels {
([<] @levels or [>] @levels) and # in increasing/decreasing order
[&&] (@levels <<-<< @levels[1..*]).map( # difference between successive pairs
-> $n { 1 <= abs($n) <= 3 } # $n is in the valid range
)
});
213
Rust
use std::error::Error;
use std::fs;
fn ascending(v: &Vec<i32>) -> bool {
let mut ordered = true;
for i in 0..v.len()-1 { ordered = ordered && (v[i] < v[i+1]); }
ordered
}
fn descending(v: &Vec<i32>) -> bool {
let mut ordered = true;
for i in 0..v.len()-1 { ordered = ordered && (v[i] > v[i+1]); }
ordered
}
fn in_range(v: &Vec<i32>) -> bool {
let mut valid = true;
for i in 0..v.len()-1 {
let diff = (v[i] - v[i+1]).abs();
valid = valid && 1 <= diff && diff <= 3;
}
valid
}
fn main() -> Result<(), Box<dyn Error>> {
let input = fs::read_to_string("/Users/donaldh/git/advent-of-code/2024/input-2.txt")?;
let safe: Vec<i32> = input.lines()
.map(|x| {
let values: Vec<i32> = x.split(" ").map(
|x| x.parse::<i32>().unwrap()
).collect();
if (ascending(&values) || descending(&values)) && in_range(&values) {
1
} else {
0
}
})
.collect();
let total: i32 = safe.iter().sum();
println!("{:#?}", total);
Ok(())
}
213
Part Two
Update your analysis by handling situations where the Problem Dampener can remove a single level from unsafe reports. How many reports are now safe?
Part two has a bit of refactoring to let us try successive sublists, along with another boolean meta-operator.
my @lines = 'input-2.txt'.IO.lines>>.split(/\s+/);
sub is-safe(@levels) {
([<] @levels or [>] @levels) and # in increasing/decreasing order
[&&] (@levels <<-<< @levels[1..*]).map( # difference between successive pairs
-> $n { 1 <= abs($n) <= 3 } # $n is in the valid range
)
}
say [+] @lines.map(
-> @levels {
is-safe(@levels) or # is original list safe
[||] (^+@levels).map( # is any sub-list safe
-> $pos {
# sub-list omitting $pos
is-safe(@levels[0..^$pos, $pos+1..*].flat)
}
)
});
285