1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
/* Copyright 2022 Mario Finelli
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//! Advent of Code 2022 Day 6: <https://adventofcode.com/2022/day/6>
//!
//! This challenge essentially boils down to checking if (sliding) windows of
//! `n` size are distinct. A start of packet/message starts when the preceding
//! `n` characters are distinct. The solution is therefore to look at each
//! window and add the elements to a [`std::collections::HashSet`]. If after
//! adding all of the elements the size of the set is the size of the window
//! then all elements are distinct and we've found the "start" and return the
//! current counter plus the size as an offset to account for the `size`
//! characters at the beginning of the string.
use std::collections::HashSet;
/// The solution for the day six challenge.
///
/// Given the input as a string it splits it into characters and then evaluates
/// each window of `size` characters while maintaining a counter of the current
/// window. Once all of the elements are distinct then we return the counter
/// plus the `size` offset.
///
/// # Example
/// ```rust
/// # use aoc::y22d06::y22d06;
/// let input = "abbccdefghij\n"; // probably read this from the input file...
/// assert_eq!(y22d06(&input, 4), Some(8));
/// ```
pub fn y22d06(input: &str, size: usize) -> Option<u32> {
let chars: Vec<_> = input.trim().chars().collect();
for (i, window) in chars.windows(size).enumerate() {
let mut set = HashSet::new();
for c in window {
set.insert(c);
}
if set.len() == size {
return Some((i + size) as u32);
}
}
// we didn't find any distinct sequences of "size" length
None
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
#[test]
fn it_works() {
let mut input = "bvwbjplbgvbhsrlpgdmjqwftvncz";
assert_eq!(y22d06(input, 4), Some(5));
assert_eq!(y22d06(input, 14), Some(23));
input = "nppdvjthqldpwncqszvftbrmjlhg";
assert_eq!(y22d06(input, 4), Some(6));
assert_eq!(y22d06(input, 14), Some(23));
input = "nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg";
assert_eq!(y22d06(input, 4), Some(10));
assert_eq!(y22d06(input, 14), Some(29));
input = "zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw";
assert_eq!(y22d06(input, 4), Some(11));
assert_eq!(y22d06(input, 14), Some(26));
input = "mjqjpqmgbljsphdztnvjfqwrcgsmlb";
assert_eq!(y22d06(input, 14), Some(19));
}
#[test]
fn the_solution() {
let contents = fs::read_to_string("input/2022/day06.txt").unwrap();
assert_eq!(y22d06(&contents, 4).unwrap(), 1802);
assert_eq!(y22d06(&contents, 14).unwrap(), 3551);
}
}