From d579a0e8e9267ace8d8b3d6710b8a74204d75d36 Mon Sep 17 00:00:00 2001 From: Anthony Cicchetti Date: Sat, 3 Dec 2022 17:33:05 -0500 Subject: [PATCH] Day 3 Part 1, probably --- .idea/advent_of_code_2022.iml | 1 + Cargo.toml | 2 +- cli/Cargo.toml | 1 + cli/src/main.rs | 14 +++++ common/src/lib.rs | 1 + day_02/src/parser.rs | 94 +-------------------------------- day_02/src/parser/part_02.rs | 91 ++++++++++++++++++++++++++++++++ day_03/Cargo.toml | 10 ++++ day_03/src/lib.rs | 98 +++++++++++++++++++++++++++++++++++ 9 files changed, 218 insertions(+), 94 deletions(-) create mode 100644 day_02/src/parser/part_02.rs create mode 100644 day_03/Cargo.toml create mode 100644 day_03/src/lib.rs diff --git a/.idea/advent_of_code_2022.iml b/.idea/advent_of_code_2022.iml index 975d3e9..a802623 100644 --- a/.idea/advent_of_code_2022.iml +++ b/.idea/advent_of_code_2022.iml @@ -6,6 +6,7 @@ + diff --git a/Cargo.toml b/Cargo.toml index fb6482d..9246031 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = ['common', 'cli', 'day_01', 'day_02'] +members = ['common', 'cli', 'day_01', 'day_02', 'day_03'] diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 328ee7d..5736a0c 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -9,4 +9,5 @@ edition = "2021" clap = { version = "4.0", features = ["derive"] } day_01 = { path = "../day_01"} day_02 = { path = "../day_02"} +day_03 = { path = "../day_03"} common = { path = "../common"} diff --git a/cli/src/main.rs b/cli/src/main.rs index 6c3c35a..f98db12 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -57,6 +57,20 @@ fn main() -> Result<(), Box> { ); 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!() diff --git a/common/src/lib.rs b/common/src/lib.rs index 6893af0..72d951c 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -4,6 +4,7 @@ use clap::ValueEnum; pub enum Day { One, Two, + Three, } #[derive(ValueEnum, Copy, Clone, Debug)] diff --git a/day_02/src/parser.rs b/day_02/src/parser.rs index 1b7163a..baf2869 100644 --- a/day_02/src/parser.rs +++ b/day_02/src/parser.rs @@ -142,98 +142,6 @@ impl From<(Hand, ResultExpected)> for Trick { } } -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> { - separated_list1(line_ending, trick_parser)(s) - } - - pub(crate) fn parse(inp: &str) -> Vec { - let (_, tricks): (&str, Vec) = 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_02; pub(crate) mod part_01; diff --git a/day_02/src/parser/part_02.rs b/day_02/src/parser/part_02.rs new file mode 100644 index 0000000..882cfd3 --- /dev/null +++ b/day_02/src/parser/part_02.rs @@ -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> { + separated_list1(line_ending, trick_parser)(s) +} + +pub(crate) fn parse(inp: &str) -> Vec { + let (_, tricks): (&str, Vec) = 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") + ) + } +} diff --git a/day_03/Cargo.toml b/day_03/Cargo.toml new file mode 100644 index 0000000..ed3125f --- /dev/null +++ b/day_03/Cargo.toml @@ -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"] } diff --git a/day_03/src/lib.rs b/day_03/src/lib.rs new file mode 100644 index 0000000..8385d3f --- /dev/null +++ b/day_03/src/lib.rs @@ -0,0 +1,98 @@ +use std::collections::HashSet; +use common::{Day, Part}; +use phf::phf_map; + +static VALUES: phf::Map = 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 { + 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, HashSet)| *left.intersection(&right).next().unwrap()) + .map(|i: char| VALUES[&i]) + .collect::>() +} + +fn part02_parse(inp: &str) -> Vec { + 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); + } +}