Day 2 solutions
This commit is contained in:
parent
b0966e5b39
commit
70c04eb6ea
File diff suppressed because it is too large
Load Diff
|
@ -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]));
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
mod day1;
|
||||
mod day2;
|
||||
|
||||
fn main() {
|
||||
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()) {
|
||||
Some("1a") => day1::day1a(),
|
||||
Some("1b") => day1::day1b(),
|
||||
Some("2a") => day2::day2a(),
|
||||
Some("2b") => day2::day2b(),
|
||||
_ => panic!("unrecognized day"),
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue