From 3a3c3c9ab6c1880d38e6e621a78e57b3e4987a7e Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Sun, 8 Dec 2024 18:54:44 -0800 Subject: [PATCH] day6: complete solution --- 6/.gitignore | 1 + 6/Cargo.lock | 25 +++++++++++++ 6/Cargo.toml | 7 ++++ 6/src/main.rs | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 6/.gitignore create mode 100644 6/Cargo.lock create mode 100644 6/Cargo.toml create mode 100644 6/src/main.rs diff --git a/6/.gitignore b/6/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/6/.gitignore @@ -0,0 +1 @@ +/target diff --git a/6/Cargo.lock b/6/Cargo.lock new file mode 100644 index 0000000..e1fcce4 --- /dev/null +++ b/6/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day6" +version = "0.1.0" +dependencies = [ + "itertools", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] diff --git a/6/Cargo.toml b/6/Cargo.toml new file mode 100644 index 0000000..31311b9 --- /dev/null +++ b/6/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "day6" +version = "0.1.0" +edition = "2021" + +[dependencies] +itertools = "0.13.0" diff --git a/6/src/main.rs b/6/src/main.rs new file mode 100644 index 0000000..8904373 --- /dev/null +++ b/6/src/main.rs @@ -0,0 +1,100 @@ +use itertools::Itertools; +use std::fs::File; +use std::io::{BufRead, BufReader, Lines}; +use std::time::{Duration, Instant}; + +// BOILERPLATE +type InputIter = Lines>; + +pub fn get_input() -> InputIter { + let f = File::open("input").unwrap(); + let br = BufReader::new(f); + br.lines() +} + +fn duration_format(duration: Duration) -> String { + match duration.as_secs_f64() { + x if x > 1.0 => format!("{:.3}s", x), + x if x > 0.010 => format!("{:.3}ms", x * 1e3), + x => format!("{:.3}us", x * 1e6), + } +} + +fn main() { + let input = get_input(); + let start = Instant::now(); + let ans1 = problem1(input); + let duration1 = start.elapsed(); + println!( + "Problem 1 solution: {} [{}]", + ans1, + duration_format(duration1) + ); + + let input = get_input(); + let start = Instant::now(); + let ans2 = problem2(input); + let duration2 = start.elapsed(); + println!( + "Problem 2 solution: {} [{}]", + ans2, + duration_format(duration2) + ); + println!("Total duration: {}", duration_format(duration1 + duration2)); +} + +// PROBLEM 1 solution + +fn problem1(mut input: Lines) -> u64 { + let s = input.next().unwrap().unwrap(); + s.as_bytes().windows(4).enumerate().find_map(|(i, window)| { + if window[1..4].iter().all(|c| *c != window[0]) && window[2..4].iter().all(|c| *c != window[1]) && window[2] != window[3] { + println!("Unique window: {:?} at {}", window.iter().map(|c| *c as char).collect_vec(), i); + Some(i + 4) + } else { + None + } + }).unwrap() as u64 +} + +// PROBLEM 2 solution +fn problem2(mut input: Lines) -> u64 { + let s = input.next().unwrap().unwrap(); + let size = 14; + s.as_bytes().windows(size).enumerate().find_map(|(i, window)| { + for i in 1..size { + let shifted = &window[i..]; + if shifted.iter().enumerate().any(|(j,c)| *c == window[j]) { + return None + } + } + return Some(i + 14) + }).unwrap() as u64 +} + +#[cfg(test)] +mod tests { + use crate::*; + use std::io::Cursor; + + const EXAMPLE1: &str = &"bvwbjplbgvbhsrlpgdmjqwftvncz"; + const EXAMPLE2: &str = &"nppdvjthqldpwncqszvftbrmjlhg"; + const EXAMPLE3: &str = &"nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg"; + const EXAMPLE4: &str = &"zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw"; + + #[test] + fn problem1_example() { + assert_eq!(problem1(Cursor::new(EXAMPLE1).lines()), 5); + assert_eq!(problem1(Cursor::new(EXAMPLE2).lines()), 6); + assert_eq!(problem1(Cursor::new(EXAMPLE3).lines()), 10); + assert_eq!(problem1(Cursor::new(EXAMPLE4).lines()), 11); + } + + #[test] + fn problem2_example() { + assert_eq!(problem2(Cursor::new(EXAMPLE1).lines()), 23); + assert_eq!(problem2(Cursor::new(EXAMPLE2).lines()), 23); + assert_eq!(problem2(Cursor::new(EXAMPLE3).lines()), 29); + assert_eq!(problem2(Cursor::new(EXAMPLE4).lines()), 26); + } +}