use std::collections::HashSet; use anyhow::Result; use crate::{Problem, Solution}; fn get_window_pos(input: &str, win_size: usize) -> Option { input .as_bytes() .windows(win_size) .position(|set| { let mut h = HashSet::new(); for &c in set { if !h.insert(c) { return false; } } true }) .map(|i| i + win_size) } pub struct Day6; impl Problem for Day6 { const DAY: u8 = 6; const INPUT: &'static str = include_str!("../input/day_6.txt"); } impl Solution for Day6 { type Answer1 = usize; type Answer2 = usize; fn part_1(input: &str) -> Result { get_window_pos(input, 4).ok_or_else(|| anyhow::anyhow!("Failed to find item")) } fn part_2(input: &str) -> Result { get_window_pos(input, 14).ok_or_else(|| anyhow::anyhow!("Failed to find item")) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_part_1_example() -> Result<()> { let tests = vec![ ("mjqjpqmgbljsphdztnvjfqwrcgsmlb", 7), ("bvwbjplbgvbhsrlpgdmjqwftvncz", 5), ("nppdvjthqldpwncqszvftbrmjlhg", 6), ("nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg", 10), ("zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw", 11), ]; for test in tests { assert_eq!(test.1, Day6::part_1(test.0)?); } Ok(()) } #[test] fn test_part_2_example() -> Result<()> { let tests = vec![ ("mjqjpqmgbljsphdztnvjfqwrcgsmlb", 19), ("bvwbjplbgvbhsrlpgdmjqwftvncz", 23), ("nppdvjthqldpwncqszvftbrmjlhg", 23), ("nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg", 29), ("zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw", 26), ]; for test in tests { assert_eq!(test.1, Day6::part_2(test.0)?); } Ok(()) } }