day06 finished
This commit is contained in:
parent
8e4face21e
commit
a390ad9988
4 changed files with 124 additions and 1 deletions
119
src/days/day06/mod.rs
Normal file
119
src/days/day06/mod.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ mod day02;
|
|||
mod day03;
|
||||
mod day04;
|
||||
mod day05;
|
||||
mod day06;
|
||||
mod template;
|
||||
|
||||
pub use template::DayTrait;
|
||||
|
|
@ -12,7 +13,7 @@ pub mod day_provider {
|
|||
use super::*;
|
||||
use thiserror::Error;
|
||||
|
||||
const MAX_DAY: usize = 5;
|
||||
const MAX_DAY: usize = 6;
|
||||
|
||||
pub fn get_day(day_num: usize) -> Result<Box<dyn DayTrait>, ProviderError> {
|
||||
match day_num {
|
||||
|
|
@ -21,6 +22,7 @@ pub mod day_provider {
|
|||
3 => Ok(Box::new(day03::Day)),
|
||||
4 => Ok(Box::new(day04::Day)),
|
||||
5 => Ok(Box::new(day05::Day)),
|
||||
6 => Ok(Box::new(day06::Day)),
|
||||
_ => Err(ProviderError::InvalidNumber(day_num)),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue