From e8873a52440bfd60cd1f555377ef9eda4d134052 Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Fri, 2 Dec 2022 19:36:32 +0100 Subject: [PATCH] 2022 - Day 2 --- 2022/input/2/test-1 | 3 + 2022/src/bin/day2.rs | 141 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 2022/input/2/test-1 create mode 100644 2022/src/bin/day2.rs diff --git a/2022/input/2/test-1 b/2022/input/2/test-1 new file mode 100644 index 0000000..db60e36 --- /dev/null +++ b/2022/input/2/test-1 @@ -0,0 +1,3 @@ +A Y +B X +C Z diff --git a/2022/src/bin/day2.rs b/2022/src/bin/day2.rs new file mode 100644 index 0000000..1f078cc --- /dev/null +++ b/2022/src/bin/day2.rs @@ -0,0 +1,141 @@ +// -- Setup & Runners -- +use aoc::Solver; +pub struct Day; +fn main() { + Day::solve(); +} +#[test] +fn part1_test1() { + Day::test(aoc::Part::ONE, "test-1", 15); +} +#[test] +fn part2_test1() { + Day::test(aoc::Part::TWO, "test-1", 12); +} +#[test] +fn part1_solution() { + Day::test(aoc::Part::ONE, "input", 14264); +} +#[test] +fn part2_solution() { + Day::test(aoc::Part::TWO, "input", 12382); +} + +// -- Implementation for hand -- +#[derive(Debug, Copy, Clone)] +enum Hand { + Rock = 0, + Paper = 1, + Scissors = 2, +} + +impl Hand { + // Return hand that this hand loses to + fn loses(&self) -> Hand { + // Returns the next enum (cyclical) as that one always loses from the current one + Hand::from((u8::from(self) + 1) % 3) + } + + // Return hand that this hand wins from + fn wins(&self) -> Hand { + // Returns the previous enum (cyclical) as that one always wins from the current one + Hand::from((i8::from(self) - 1).rem_euclid(3) as u8) + } + + fn strategy(&self, input: char) -> Hand { + match input { + 'X' => self.wins(), + 'Y' => *self, + 'Z' => self.loses(), + _ => panic!("Unexpected input") + } + } + + // Check if we win against the other hand + fn play(&self, other: &Hand) -> u32 { + // 1 = draw, 2 = wins, 0 = loses (x3 to get the score + ((i8::from(self) - i8::from(other) + 1).rem_euclid(3) * 3) as u32 + } + + // Get the score value of the current hand + fn value(&self) -> u32 { + u8::from(self) as u32 + 1 + } +} + +// -- Conversions -- +impl From for Hand { + fn from(value: u8) -> Self { + match value { + x if x == Hand::Rock as u8 => Hand::Rock, + x if x == Hand::Paper as u8 => Hand::Paper, + x if x == Hand::Scissors as u8 => Hand::Scissors, + x => panic!("Unknown input: {}", x) + } + } +} + +impl From for Hand { + fn from(value: char) -> Self { + match value { + 'A' | 'X' => Self::Rock, + 'B' | 'Y' => Self::Paper, + 'C' | 'Z' => Self::Scissors, + value => panic!("Unknown input: {value}"), + } + } +} + +impl From<&Hand> for i8 { + fn from(value: &Hand) -> Self { + *value as Self + } +} + +impl From<&Hand> for u8 { + fn from(value: &Hand) -> Self { + *value as Self + } +} + +impl From for u8 { + fn from(value: Hand) -> Self { + value as Self + } +} + +// -- Helper functions -- +// Convert the round to a tuple containing the actions of both players +fn round_to_letters(round: &str) -> (char, char) { + if let &[a, _, b] = round.as_bytes() { + (a as char, b as char) + } else { + panic!("Unexpected input"); + } +} + +// -- Solution -- +impl aoc::Solver for Day { + fn day() -> u8 { + 2 + } + + fn part1(input: &str) -> u32 { + input.split("\n") + .filter(|round| round.len() > 0) + .map(round_to_letters) + .map(|(a, b)| (Hand::from(a), Hand::from(b))) + .map(|(a, b)| b.play(&a) + b.value()) + .sum() + } + + fn part2(input: &str) -> u32 { + input.split("\n") + .filter(|round| round.len() > 0) + .map(round_to_letters) + .map(|(a, b)| (Hand::from(a), b)) + .map(|(a, b)| (a, a.strategy(b))) + .map(|(a, b)| b.play(&a) + b.value()) + .sum() + } +}