Day 3 Part 1, probably
This commit is contained in:
parent
2674f0f993
commit
d579a0e8e9
9 changed files with 218 additions and 94 deletions
1
.idea/advent_of_code_2022.iml
generated
1
.idea/advent_of_code_2022.iml
generated
|
@ -6,6 +6,7 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/common/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/common/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/day_01/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/day_01/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/day_02/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/day_02/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/day_03/src" isTestSource="false" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ['common', 'cli', 'day_01', 'day_02']
|
members = ['common', 'cli', 'day_01', 'day_02', 'day_03']
|
||||||
|
|
|
@ -9,4 +9,5 @@ edition = "2021"
|
||||||
clap = { version = "4.0", features = ["derive"] }
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
day_01 = { path = "../day_01"}
|
day_01 = { path = "../day_01"}
|
||||||
day_02 = { path = "../day_02"}
|
day_02 = { path = "../day_02"}
|
||||||
|
day_03 = { path = "../day_03"}
|
||||||
common = { path = "../common"}
|
common = { path = "../common"}
|
||||||
|
|
|
@ -57,6 +57,20 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
(day @ Day::Three, part @ Part::One) => {
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
day_03::run_day_and_part(day, part, input_str.as_str())
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
(day @ Day::Three, part @ Part::Two) => {
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
day_03::run_day_and_part(day, part, input_str.as_str())
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
(_, _) => {
|
(_, _) => {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
|
|
@ -4,6 +4,7 @@ use clap::ValueEnum;
|
||||||
pub enum Day {
|
pub enum Day {
|
||||||
One,
|
One,
|
||||||
Two,
|
Two,
|
||||||
|
Three,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(ValueEnum, Copy, Clone, Debug)]
|
#[derive(ValueEnum, Copy, Clone, Debug)]
|
||||||
|
|
|
@ -142,98 +142,6 @@ impl From<(Hand, ResultExpected)> for Trick {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod part_02 {
|
pub(crate) mod part_02;
|
||||||
use crate::parser::{against_hand_parser, result_expected_parser, Hand, ResultExpected, Trick};
|
|
||||||
use nom::character::complete::{char, line_ending};
|
|
||||||
use nom::multi::separated_list1;
|
|
||||||
use nom::sequence::separated_pair;
|
|
||||||
use nom::IResult;
|
|
||||||
|
|
||||||
fn trick_parser(s: &str) -> IResult<&str, Trick> {
|
|
||||||
let (rest, hands): (&str, (Hand, ResultExpected)) =
|
|
||||||
separated_pair(against_hand_parser, char(' '), result_expected_parser)(s)?;
|
|
||||||
Ok((rest, hands.into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sequence_parser(s: &str) -> IResult<&str, Vec<Trick>> {
|
|
||||||
separated_list1(line_ending, trick_parser)(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn parse(inp: &str) -> Vec<usize> {
|
|
||||||
let (_, tricks): (&str, Vec<Trick>) = sequence_parser(inp).expect("Couldn't parse input");
|
|
||||||
tricks.iter().map(|trick| trick.score()).collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::parser::{draw_expected, loss_expected, win_expected};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn win_expected_parsed() {
|
|
||||||
assert_eq!(Ok(("", ResultExpected::Win)), win_expected("Z"))
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn draw_expected_parsed() {
|
|
||||||
assert_eq!(Ok(("", ResultExpected::Draw)), draw_expected("Y"))
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn loss_expected_parsed() {
|
|
||||||
assert_eq!(Ok(("", ResultExpected::Lose)), loss_expected("X"))
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! param_test {
|
|
||||||
($($name:ident: $input:literal , $against:expr , $result:expr , $thrown:expr;)*) => {
|
|
||||||
$(#[test]
|
|
||||||
fn $name() {
|
|
||||||
assert_eq!(
|
|
||||||
Ok((
|
|
||||||
"",
|
|
||||||
Trick {
|
|
||||||
thrown: $thrown,
|
|
||||||
against: $against
|
|
||||||
}
|
|
||||||
)),
|
|
||||||
trick_parser($input)
|
|
||||||
)
|
|
||||||
})*
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
param_test!(
|
|
||||||
rock_thrown_loss_expected: "A X" , Hand::Rock , ResultExpected::Lose , Hand::Scissors;
|
|
||||||
rock_thrown_draw_expected: "A Y", Hand::Rock, ResultExpected::Draw, Hand::Rock;
|
|
||||||
rock_thrown_win_expected: "A Z", Hand::Rock, ResultExpected::Win, Hand::Paper;
|
|
||||||
|
|
||||||
paper_thrown_loss_expected: "B X" , Hand::Paper , ResultExpected::Lose , Hand::Rock;
|
|
||||||
paper_thrown_draw_expected: "B Y", Hand::Paper, ResultExpected::Draw, Hand::Paper;
|
|
||||||
paper_thrown_win_expected: "B Z", Hand::Paper, ResultExpected::Win, Hand::Scissors;
|
|
||||||
|
|
||||||
scissors_thrown_loss_expected: "C X" , Hand::Scissors , ResultExpected::Lose , Hand::Paper;
|
|
||||||
scissors_thrown_draw_expected: "C Y", Hand::Scissors, ResultExpected::Draw, Hand::Scissors;
|
|
||||||
scissors_thrown_win_expected: "C Z", Hand::Scissors, ResultExpected::Win, Hand::Rock;
|
|
||||||
);
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn example_sequence_parsed() {
|
|
||||||
assert_eq!(
|
|
||||||
Ok(("", vec![
|
|
||||||
Trick {
|
|
||||||
against: Hand::Rock,
|
|
||||||
thrown: Hand::Rock,
|
|
||||||
},
|
|
||||||
Trick {
|
|
||||||
against: Hand::Paper,
|
|
||||||
thrown: Hand::Rock,
|
|
||||||
},
|
|
||||||
Trick {
|
|
||||||
against: Hand::Scissors,
|
|
||||||
thrown: Hand::Rock,
|
|
||||||
}
|
|
||||||
])), sequence_parser("A Y\nB X\nC Z")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) mod part_01;
|
pub(crate) mod part_01;
|
||||||
|
|
91
day_02/src/parser/part_02.rs
Normal file
91
day_02/src/parser/part_02.rs
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
use crate::parser::{against_hand_parser, result_expected_parser, Hand, ResultExpected, Trick};
|
||||||
|
use nom::character::complete::{char, line_ending};
|
||||||
|
use nom::multi::separated_list1;
|
||||||
|
use nom::sequence::separated_pair;
|
||||||
|
use nom::IResult;
|
||||||
|
|
||||||
|
fn trick_parser(s: &str) -> IResult<&str, Trick> {
|
||||||
|
let (rest, hands): (&str, (Hand, ResultExpected)) =
|
||||||
|
separated_pair(against_hand_parser, char(' '), result_expected_parser)(s)?;
|
||||||
|
Ok((rest, hands.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sequence_parser(s: &str) -> IResult<&str, Vec<Trick>> {
|
||||||
|
separated_list1(line_ending, trick_parser)(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse(inp: &str) -> Vec<usize> {
|
||||||
|
let (_, tricks): (&str, Vec<Trick>) = sequence_parser(inp).expect("Couldn't parse input");
|
||||||
|
tricks.iter().map(|trick| trick.score()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::parser::{draw_expected, loss_expected, win_expected};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn win_expected_parsed() {
|
||||||
|
assert_eq!(Ok(("", ResultExpected::Win)), win_expected("Z"))
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn draw_expected_parsed() {
|
||||||
|
assert_eq!(Ok(("", ResultExpected::Draw)), draw_expected("Y"))
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn loss_expected_parsed() {
|
||||||
|
assert_eq!(Ok(("", ResultExpected::Lose)), loss_expected("X"))
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! param_test {
|
||||||
|
($($name:ident: $input:literal , $against:expr , $result:expr , $thrown:expr;)*) => {
|
||||||
|
$(#[test]
|
||||||
|
fn $name() {
|
||||||
|
assert_eq!(
|
||||||
|
Ok((
|
||||||
|
"",
|
||||||
|
Trick {
|
||||||
|
thrown: $thrown,
|
||||||
|
against: $against
|
||||||
|
}
|
||||||
|
)),
|
||||||
|
trick_parser($input)
|
||||||
|
)
|
||||||
|
})*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
param_test!(
|
||||||
|
rock_thrown_loss_expected: "A X" , Hand::Rock , ResultExpected::Lose , Hand::Scissors;
|
||||||
|
rock_thrown_draw_expected: "A Y", Hand::Rock, ResultExpected::Draw, Hand::Rock;
|
||||||
|
rock_thrown_win_expected: "A Z", Hand::Rock, ResultExpected::Win, Hand::Paper;
|
||||||
|
|
||||||
|
paper_thrown_loss_expected: "B X" , Hand::Paper , ResultExpected::Lose , Hand::Rock;
|
||||||
|
paper_thrown_draw_expected: "B Y", Hand::Paper, ResultExpected::Draw, Hand::Paper;
|
||||||
|
paper_thrown_win_expected: "B Z", Hand::Paper, ResultExpected::Win, Hand::Scissors;
|
||||||
|
|
||||||
|
scissors_thrown_loss_expected: "C X" , Hand::Scissors , ResultExpected::Lose , Hand::Paper;
|
||||||
|
scissors_thrown_draw_expected: "C Y", Hand::Scissors, ResultExpected::Draw, Hand::Scissors;
|
||||||
|
scissors_thrown_win_expected: "C Z", Hand::Scissors, ResultExpected::Win, Hand::Rock;
|
||||||
|
);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example_sequence_parsed() {
|
||||||
|
assert_eq!(
|
||||||
|
Ok(("", vec![
|
||||||
|
Trick {
|
||||||
|
against: Hand::Rock,
|
||||||
|
thrown: Hand::Rock,
|
||||||
|
},
|
||||||
|
Trick {
|
||||||
|
against: Hand::Paper,
|
||||||
|
thrown: Hand::Rock,
|
||||||
|
},
|
||||||
|
Trick {
|
||||||
|
against: Hand::Scissors,
|
||||||
|
thrown: Hand::Rock,
|
||||||
|
}
|
||||||
|
])), sequence_parser("A Y\nB X\nC Z")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
10
day_03/Cargo.toml
Normal file
10
day_03/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "day_03"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
common = {path = '../common'}
|
||||||
|
phf = { version = "0.11.1", features = ["macros"] }
|
98
day_03/src/lib.rs
Normal file
98
day_03/src/lib.rs
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use common::{Day, Part};
|
||||||
|
use phf::phf_map;
|
||||||
|
|
||||||
|
static VALUES: phf::Map<char, usize> = phf_map!{
|
||||||
|
'a' => 1,
|
||||||
|
'b' => 2,
|
||||||
|
'c' => 3,
|
||||||
|
'd' => 4,
|
||||||
|
'e' => 5,
|
||||||
|
'f' => 6,
|
||||||
|
'g' => 7,
|
||||||
|
'h' => 8,
|
||||||
|
'i' => 9,
|
||||||
|
'j' => 10,
|
||||||
|
'k' => 11,
|
||||||
|
'l' => 12,
|
||||||
|
'm' => 13,
|
||||||
|
'n' => 14,
|
||||||
|
'o' => 15,
|
||||||
|
'p' => 16,
|
||||||
|
'q' => 17,
|
||||||
|
'r' => 18,
|
||||||
|
's' => 19,
|
||||||
|
't' => 20,
|
||||||
|
'u' => 21,
|
||||||
|
'v' => 22,
|
||||||
|
'w' => 23,
|
||||||
|
'x' => 24,
|
||||||
|
'y' => 25,
|
||||||
|
'z' => 26,
|
||||||
|
'A' => 27,
|
||||||
|
'B' => 28,
|
||||||
|
'C' => 29,
|
||||||
|
'D' => 30,
|
||||||
|
'E' => 31,
|
||||||
|
'F' => 32,
|
||||||
|
'G' => 33,
|
||||||
|
'H' => 34,
|
||||||
|
'I' => 35,
|
||||||
|
'J' => 36,
|
||||||
|
'K' => 37,
|
||||||
|
'L' => 38,
|
||||||
|
'M' => 39,
|
||||||
|
'N' => 40,
|
||||||
|
'O' => 41,
|
||||||
|
'P' => 42,
|
||||||
|
'Q' => 43,
|
||||||
|
'R' => 44,
|
||||||
|
'S' => 45,
|
||||||
|
'T' => 46,
|
||||||
|
'U' => 47,
|
||||||
|
'V' => 48,
|
||||||
|
'W' => 49,
|
||||||
|
'X' => 50,
|
||||||
|
'Y' => 51,
|
||||||
|
'Z' => 52,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn run_day_and_part(day: Day, part: Part, inp: &str) -> usize {
|
||||||
|
match (day, part) {
|
||||||
|
(Day::Three, Part::One) => part01_parse(inp).iter().sum(),
|
||||||
|
(Day::Three, Part::Two) => part02_parse(inp).iter().sum(),
|
||||||
|
(_, _) => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part01_parse(inp: &str) -> Vec<usize> {
|
||||||
|
let inp = inp.split_whitespace();
|
||||||
|
inp.map(|row: &str| row.split_at(row.len() / 2))
|
||||||
|
.map(|(left, right): (&str, &str)| (HashSet::from_iter(left.chars()),
|
||||||
|
HashSet::from_iter(right.chars())))
|
||||||
|
.map(|(left, right): (HashSet<char>, HashSet<char>)| *left.intersection(&right).next().unwrap())
|
||||||
|
.map(|i: char| VALUES[&i])
|
||||||
|
.collect::<Vec<usize>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part02_parse(inp: &str) -> Vec<usize> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part_01_example_works() {
|
||||||
|
let input = r#"vJrwpWtwJgWrhcsFMMfFFhFp
|
||||||
|
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
|
||||||
|
PmmdzqPrVvPwwTWBwg
|
||||||
|
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
|
||||||
|
ttgJtRGJQctTZtZT
|
||||||
|
CrZsJsPPZsGzwwsLwLmpwMDw"#;
|
||||||
|
let result = 2 + 2 ;
|
||||||
|
assert_eq!(result, 4);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue