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);
+ }
+}