day06 finished

This commit is contained in:
Ruediger Ludwig 2023-02-02 19:41:46 +01:00
parent 8e4face21e
commit a390ad9988
4 changed files with 124 additions and 1 deletions

119
src/days/day06/mod.rs Normal file
View file

@ -0,0 +1,119 @@
use super::template::{DayTrait, ResultType};
use thiserror::Error;
const DAY_NUMBER: usize = 6;
pub struct Day;
impl DayTrait for Day {
fn get_day_number(&self) -> usize {
DAY_NUMBER
}
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
let count = find_marker(&lines[0], 4)?;
Ok(ResultType::Integer(count as i64))
}
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
let count = find_marker(&lines[0], 14)?;
Ok(ResultType::Integer(count as i64))
}
}
#[derive(Debug, Error)]
enum MarkerError {
#[error("Length of Marker must not be zero")]
NoZeroLength,
#[error("Did not find a marker in {0}")]
NoMarkerFound(String),
#[error("Strings needs to be longer than marker length len({0}) < {1}")]
StringTooShort(String, usize),
}
fn char_pos(c: char) -> usize {
c as usize - 'a' as usize
}
fn find_marker(word: &str, marker_length: usize) -> Result<usize, MarkerError> {
if marker_length == 0 {
return Err(MarkerError::NoZeroLength);
}
if word.len() < marker_length {
return Err(MarkerError::StringTooShort(word.to_owned(), marker_length));
}
let mut letter_count = vec![0; 26];
let mut doubles = 0;
for new in word.chars().take(marker_length) {
let new = char_pos(new);
if letter_count[new] == 1 {
doubles += 1;
}
letter_count[new] += 1;
}
if doubles == 0 {
return Ok(marker_length);
}
for (pos, (drop, new)) in word.chars().zip(word[marker_length..].chars()).enumerate() {
let drop = char_pos(drop);
let new = char_pos(new);
if letter_count[drop] == 2 {
doubles -= 1;
}
letter_count[drop] -= 1;
if letter_count[new] == 1 {
doubles += 1;
}
if doubles == 0 {
return Ok(pos + marker_length + 1);
}
letter_count[new] += 1;
}
Err(MarkerError::NoMarkerFound(word.to_owned()))
}
#[cfg(test)]
mod test {
use super::*;
use crate::common::file::read_lines;
use anyhow::Result;
#[test]
fn test_find_marker() -> Result<()> {
let input = "mjqjpqmgbljsphdztnvjfqwrcgsmlb";
let expected = 7;
let result = find_marker(input, 4)?;
assert_eq!(result, expected);
Ok(())
}
#[test]
fn test_part1() -> Result<()> {
let day = Day {};
let lines = read_lines(day.get_day_number(), "example01.txt")?;
let expected = ResultType::Integer(10);
let result = day.part1(&lines)?;
assert_eq!(result, expected);
Ok(())
}
#[test]
fn test_part2() -> Result<()> {
let day = Day {};
let lines = read_lines(day.get_day_number(), "example01.txt")?;
let expected = ResultType::Integer(29);
let result = day.part2(&lines)?;
assert_eq!(result, expected);
Ok(())
}
}