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 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"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue