advent-of-code-2020/day09/src/main.rs

93 lines
2.4 KiB
Rust

use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::time::Instant;
use anyhow::Result;
const INPUT: &str = "input/input.txt";
fn find_invalid_num(nums: &[usize], preamble: usize) -> Option<usize> {
if let Some(num) = nums.windows(preamble + 1).find(|chunk| {
for num in &chunk[0..preamble] {
for other_num in &chunk[0..preamble] {
if num != other_num && num + other_num == chunk[preamble] {
return false;
}
}
}
true
}) {
return Some(num[preamble]);
}
None
}
fn find_encryption_weakness(nums: &[usize], invalid_num: usize) -> Option<usize> {
let mut window_size = 2;
while window_size < 1000 {
if let Some(weakness) = nums
.windows(window_size)
.find(|chunk| chunk.iter().sum::<usize>() == invalid_num)
{
return Some(
weakness.iter().min().expect("non-empty slice")
+ weakness.iter().max().expect("non-empty slice"),
);
} else {
window_size += 1;
}
}
None
}
fn solve_part1(input_path: &str, preamble: usize) -> Result<usize> {
let file = File::open(input_path)?;
let reader = BufReader::new(file);
let nums = reader
.lines()
.map(|line| Ok(line?.parse()?))
.collect::<Result<Vec<usize>>>()?;
Ok(find_invalid_num(&nums, preamble).unwrap())
}
fn solve_part2(input_path: &str, invalid_num: usize) -> Result<usize> {
let file = File::open(input_path)?;
let reader = BufReader::new(file);
let nums = reader
.lines()
.map(|line| Ok(line?.parse()?))
.collect::<Result<Vec<usize>>>()?;
Ok(find_encryption_weakness(&nums, invalid_num).unwrap())
}
fn main() {
let mut now = Instant::now();
let part1 = solve_part1(INPUT, 25).unwrap();
println!("Part 1: {}", part1);
println!("(elapsed: {:?})", now.elapsed());
now = Instant::now();
println!("");
println!("Part 2: {}", solve_part2(INPUT, part1).unwrap());
println!("(elapsed: {:?})", now.elapsed());
}
#[cfg(test)]
mod tests {
use super::*;
const TEST_INPUT: &str = "input/test.txt";
#[test]
fn solves_part1() {
assert_eq!(solve_part1(TEST_INPUT, 5).unwrap(), 127);
}
#[test]
fn solves_part2() {
assert_eq!(solve_part2(TEST_INPUT, 127).unwrap(), 62);
}
}