day03 finished
This commit is contained in:
parent
eb1ce68486
commit
d7c85a75f6
8 changed files with 534 additions and 37 deletions
|
|
@ -1,7 +1,6 @@
|
|||
use itertools::Itertools;
|
||||
use std::num::ParseIntError;
|
||||
|
||||
use anyhow::Result;
|
||||
use thiserror::Error;
|
||||
|
||||
use super::template::{DayTrait, ResultType};
|
||||
|
|
@ -14,13 +13,13 @@ impl DayTrait for Day {
|
|||
DAY_NUMBER
|
||||
}
|
||||
|
||||
fn part1(&self, lines: &str) -> Result<ResultType> {
|
||||
fn part1(&self, lines: &str) -> anyhow::Result<ResultType> {
|
||||
let vector = Day::parse(lines)?;
|
||||
let max = vector.iter().max().ok_or(CalorieError::Empty)?;
|
||||
Ok(ResultType::IntResult(*max))
|
||||
}
|
||||
|
||||
fn part2(&self, lines: &str) -> Result<ResultType> {
|
||||
fn part2(&self, lines: &str) -> anyhow::Result<ResultType> {
|
||||
let vector = Day::parse(lines)?;
|
||||
let sum = vector.iter().sorted_by(|a, b| Ord::cmp(b, a)).take(3).sum();
|
||||
Ok(ResultType::IntResult(sum))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use super::template::{DayTrait, ResultType};
|
||||
use anyhow::Result;
|
||||
use thiserror::Error;
|
||||
|
||||
const DAY_NUMBER: usize = 2;
|
||||
|
|
@ -13,11 +12,11 @@ impl DayTrait for Day {
|
|||
DAY_NUMBER
|
||||
}
|
||||
|
||||
fn part1(&self, lines: &str) -> Result<ResultType> {
|
||||
fn part1(&self, lines: &str) -> anyhow::Result<ResultType> {
|
||||
let sum = lines
|
||||
.split("\n")
|
||||
.map(RPS::parse_line)
|
||||
.collect::<Result<Vec<_>>>()?
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.map(|(first, second)| second.asses_pair(&first))
|
||||
.sum();
|
||||
|
|
@ -25,11 +24,11 @@ impl DayTrait for Day {
|
|||
Ok(ResultType::IntResult(sum))
|
||||
}
|
||||
|
||||
fn part2(&self, lines: &str) -> Result<ResultType> {
|
||||
fn part2(&self, lines: &str) -> anyhow::Result<ResultType> {
|
||||
let sum = lines
|
||||
.split("\n")
|
||||
.map(Strategy::parse_line)
|
||||
.collect::<Result<Vec<_>>>()?
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.map(|(first, second)| second.fullfill(&first).asses_pair(&first))
|
||||
.sum();
|
||||
|
|
@ -55,7 +54,7 @@ enum RPS {
|
|||
}
|
||||
|
||||
impl RPS {
|
||||
pub fn parse_line(line: &str) -> Result<(Self, Self)> {
|
||||
pub fn parse_line(line: &str) -> Result<(Self, Self), RPSError> {
|
||||
let mut parts = line.split(" ");
|
||||
let (Some(first), Some(second)) = (parts.next(), parts.next()) else {
|
||||
Err(RPSError::IllegalLine(line.to_owned()))?
|
||||
|
|
@ -119,7 +118,7 @@ enum Strategy {
|
|||
}
|
||||
|
||||
impl Strategy {
|
||||
pub fn parse_line(line: &str) -> Result<(RPS, Self)> {
|
||||
pub fn parse_line(line: &str) -> Result<(RPS, Self), RPSError> {
|
||||
let mut parts = line.split(" ");
|
||||
let (Some(first), Some(second)) = (parts.next(), parts.next()) else {
|
||||
Err(RPSError::IllegalLine(line.to_owned()))?
|
||||
|
|
|
|||
144
src/days/day03/mod.rs
Normal file
144
src/days/day03/mod.rs
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
use itertools::Itertools;
|
||||
use thiserror::Error;
|
||||
|
||||
use super::template::{DayTrait, ResultType};
|
||||
|
||||
const DAY_NUMBER: usize = 3;
|
||||
|
||||
pub struct Day;
|
||||
|
||||
impl DayTrait for Day {
|
||||
fn get_day_number(&self) -> usize {
|
||||
DAY_NUMBER
|
||||
}
|
||||
|
||||
fn part1(&self, lines: &str) -> anyhow::Result<ResultType> {
|
||||
let sum = lines
|
||||
.split('\n')
|
||||
.map(|rucksack| find_double(rucksack).and_then(priority))
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.iter()
|
||||
.sum();
|
||||
Ok(ResultType::IntResult(sum))
|
||||
}
|
||||
|
||||
fn part2(&self, lines: &str) -> anyhow::Result<ResultType> {
|
||||
let sum = lines
|
||||
.split('\n')
|
||||
.chunks(3)
|
||||
.into_iter()
|
||||
.map(|chunk| find_badge(&chunk.collect::<Vec<_>>()).and_then(priority))
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.iter()
|
||||
.sum();
|
||||
Ok(ResultType::IntResult(sum))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum RucksackError {
|
||||
#[error("No double item found")]
|
||||
NoDoubleFound,
|
||||
|
||||
#[error("Not a valid char: {0}")]
|
||||
InvalidChar(char),
|
||||
|
||||
#[error("Need at least two elves for common item")]
|
||||
NeedAtLeastTwo,
|
||||
|
||||
#[error("No common badge was found")]
|
||||
NoBadgeFound,
|
||||
}
|
||||
|
||||
fn priority(c: char) -> Result<i64, RucksackError> {
|
||||
match c {
|
||||
'a'..='z' => Ok(c as i64 - 'a' as i64 + 1),
|
||||
'A'..='Z' => Ok(c as i64 - 'A' as i64 + 27),
|
||||
_ => Err(RucksackError::InvalidChar(c)),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_double(content: &str) -> Result<char, RucksackError> {
|
||||
let length = content.len() / 2;
|
||||
let part1 = &content[..length];
|
||||
let part2 = &content[length..];
|
||||
|
||||
for c in part1.chars() {
|
||||
if part2.contains(c) {
|
||||
return Ok(c);
|
||||
}
|
||||
}
|
||||
|
||||
Err(RucksackError::NoDoubleFound)?
|
||||
}
|
||||
|
||||
fn find_badge<'a>(elves: &[&str]) -> Result<char, RucksackError> {
|
||||
if elves.len() < 2 {
|
||||
return Err(RucksackError::NeedAtLeastTwo);
|
||||
};
|
||||
for c in elves[0].chars() {
|
||||
let mut found = true;
|
||||
for other in &elves[1..] {
|
||||
if !other.contains(c) {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
if found {
|
||||
return Ok(c);
|
||||
}
|
||||
}
|
||||
Err(RucksackError::NoBadgeFound)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::common::file::read_data;
|
||||
use anyhow::Result;
|
||||
|
||||
#[test]
|
||||
fn test_rucksack() -> Result<(), RucksackError> {
|
||||
let input = "vJrwpWtwJgWrhcsFMMfFFhFp";
|
||||
let expected = 16;
|
||||
let result = find_double(input).and_then(priority)?;
|
||||
assert_eq!(result, expected);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part1() -> Result<()> {
|
||||
let day = Day {};
|
||||
let lines = read_data(day.get_day_number(), "example01.txt")?;
|
||||
let expected = ResultType::IntResult(157);
|
||||
let result = day.part1(&lines)?;
|
||||
assert_eq!(result, expected);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_badge() -> Result<(), RucksackError> {
|
||||
let input = vec![
|
||||
"vJrwpWtwJgWrhcsFMMfFFhFp",
|
||||
"jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL",
|
||||
"PmmdzqPrVvPwwTWBwg",
|
||||
];
|
||||
let expected = 18;
|
||||
let result = find_badge(&input).and_then(priority)?;
|
||||
assert_eq!(result, expected);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part2() -> Result<()> {
|
||||
let day = Day {};
|
||||
let lines = read_data(day.get_day_number(), "example01.txt")?;
|
||||
let expected = ResultType::IntResult(70);
|
||||
let result = day.part2(&lines)?;
|
||||
assert_eq!(result, expected);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
use anyhow::Result;
|
||||
|
||||
use super::template::{DayTrait, ResultType};
|
||||
|
||||
const DAY_NUMBER: usize = 0;
|
||||
|
|
@ -11,11 +9,11 @@ impl DayTrait for Day {
|
|||
DAY_NUMBER
|
||||
}
|
||||
|
||||
fn part1(&self, _lines: &str) -> Result<ResultType> {
|
||||
fn part1(&self, _lines: &str) -> anyhow::Result<ResultType> {
|
||||
Ok(ResultType::NoResult)
|
||||
}
|
||||
|
||||
fn part2(&self, _lines: &str) -> Result<ResultType> {
|
||||
fn part2(&self, _lines: &str) -> anyhow::Result<ResultType> {
|
||||
Ok(ResultType::NoResult)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
mod day01;
|
||||
mod day02;
|
||||
mod day03;
|
||||
mod template;
|
||||
|
||||
pub use template::DayTrait;
|
||||
|
|
@ -9,12 +10,13 @@ pub mod day_provider {
|
|||
use super::*;
|
||||
use thiserror::Error;
|
||||
|
||||
const MAX_DAY: usize = 2;
|
||||
const MAX_DAY: usize = 3;
|
||||
|
||||
pub fn get_day(day_num: usize) -> Result<Box<dyn DayTrait>, ProviderError> {
|
||||
match day_num {
|
||||
1 => Ok(Box::new(day01::Day)),
|
||||
2 => Ok(Box::new(day02::Day)),
|
||||
3 => Ok(Box::new(day03::Day)),
|
||||
_ => Err(ProviderError::InvalidNumber(day_num)),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue