Day 2 solutions

This commit is contained in:
Savanni D'Gerinel 2024-12-02 22:01:15 -05:00
parent b0966e5b39
commit 70c04eb6ea
3 changed files with 1160 additions and 0 deletions

1000
2024/data/day2.txt Normal file

File diff suppressed because it is too large Load Diff

157
2024/src/day2.rs Normal file
View File

@ -0,0 +1,157 @@
const INPUT: &'static str = include_str!("../data/day2.txt");
pub fn day2a() -> String {
let reports = parse_levels(INPUT);
reports
.into_iter()
.map(|report| is_safe(&report))
.filter(|safe| *safe)
.count()
.to_string()
}
pub fn day2b() -> String {
let reports = parse_levels(INPUT);
reports
.into_iter()
.map(|report| is_safe_2(&report))
.filter(|safe| *safe)
.count()
.to_string()
}
fn parse_levels(s: &str) -> Vec<Vec<i32>> {
s.lines()
.map(|line| {
line.split(" ")
.filter(|element| !element.is_empty())
.map(|element| element.parse::<i32>().unwrap())
.collect::<Vec<i32>>()
})
.collect::<Vec<Vec<i32>>>()
}
enum Direction {
Up,
Down,
}
fn is_safe(level: &Vec<i32>) -> bool {
use Direction::*;
let direction = if level[0] > level[1] {
Down
} else if level[0] < level[1] {
Up
} else {
return false;
};
for idx in 1..level.len() {
let diff = level[idx - 1] - level[idx];
match direction {
Up => {
if diff >= 0 {
return false;
}
}
Down => {
if diff <= 0 {
return false;
}
}
}
if diff.abs() > 3 {
return false;
};
}
return true;
}
fn is_safe_2(report: &Vec<i32>) -> bool {
if is_safe(report) { return true; }
for idx in 0..report.len() {
let mut report_ = report.clone();
report_.remove(idx);
if is_safe(&report_) { return true; }
}
false
}
#[cfg(test)]
mod test {
use super::*;
const TEST_INPUT: &'static str = "7 6 4 2 1
1 2 7 8 9
9 7 6 2 1
1 3 2 4 5
8 6 4 4 1
1 3 6 7 9";
#[test]
fn monotonic_changes_are_safe() {
let test_data = parse_levels(TEST_INPUT);
assert!(is_safe(&test_data[0]));
assert!(is_safe(&test_data[5]));
}
#[test]
fn excessive_changes_are_unsafe() {
let test_data = parse_levels(TEST_INPUT);
assert!(!is_safe(&test_data[1]));
assert!(!is_safe(&test_data[2]));
assert!(!is_safe(&test_data[4]));
}
#[test]
fn non_monotonic_changes_are_unsafe() {
let test_data = parse_levels(TEST_INPUT);
assert!(!is_safe(&test_data[3]));
}
#[test]
fn verify_test_data_safety_count() {
let reports = parse_levels(TEST_INPUT);
let safe_cnt = reports
.into_iter()
.map(|report| is_safe(&report))
.filter(|safe| *safe)
.count();
assert_eq!(safe_cnt, 2);
}
#[test]
fn a_purely_safe_report_is_safe() {
let test_data = parse_levels(TEST_INPUT);
assert!(is_safe_2(&test_data[0]));
assert!(is_safe_2(&test_data[5]));
}
#[test]
fn a_report_with_one_bad_level_is_safe() {
let test_data = parse_levels(TEST_INPUT);
assert!(is_safe_2(&test_data[3]));
assert!(is_safe_2(&test_data[4]));
}
#[test]
fn reports_with_too_many_bad_levels_are_unsafe() {
let test_data = parse_levels(TEST_INPUT);
assert!(!is_safe_2(&test_data[1]));
assert!(!is_safe_2(&test_data[2]));
}
}

View File

@ -1,4 +1,5 @@
mod day1; mod day1;
mod day2;
fn main() { fn main() {
let day = std::env::args().skip(1).next(); let day = std::env::args().skip(1).next();
@ -6,6 +7,8 @@ fn main() {
let result = match day.as_ref().map(|v| v.as_ref()) { let result = match day.as_ref().map(|v| v.as_ref()) {
Some("1a") => day1::day1a(), Some("1a") => day1::day1a(),
Some("1b") => day1::day1b(), Some("1b") => day1::day1b(),
Some("2a") => day2::day2a(),
Some("2b") => day2::day2b(),
_ => panic!("unrecognized day"), _ => panic!("unrecognized day"),
}; };