Skip to content

Commit

Permalink
aoc day2
Browse files Browse the repository at this point in the history
  • Loading branch information
AAwouters committed Dec 2, 2022
1 parent 8a451f2 commit 74349cc
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 11 deletions.
17 changes: 11 additions & 6 deletions src/days/day1.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::util::{Parser, parse_input_string, parse_input_file};
use crate::util::util_imports::*;

type Calories = u32;

Expand Down Expand Up @@ -47,23 +47,28 @@ const TEST_STRING: &str = "1000

const INPUT_FILE: &str = "./input/day1.txt";

pub fn day1_part1_test() -> Calories {
#[test]
fn day1_part1_test() {
let elves = parse_input_string::<Elf>(TEST_STRING.to_string()).unwrap();
elves.iter().map(|elf| elf.calories.iter().sum::<Calories>()).max().unwrap()
let result = elves.iter().map(|elf| elf.calories.iter().sum::<Calories>()).max().unwrap();
let answer: u32 = 24000;
assert_eq!(result, answer);
}

pub fn day1_part1() -> Calories {
let elves = parse_input_file::<Elf>(INPUT_FILE).unwrap();
elves.iter().map(|elf| elf.calories.iter().sum::<Calories>()).max().unwrap()
}

pub fn day1_part2_test() -> Calories {
#[test]
fn day1_part2_test() {
let elves = parse_input_string::<Elf>(TEST_STRING.to_string()).unwrap();
let mut sums = elves.iter().map(|elf| elf.calories.iter().sum::<Calories>()).collect::<Vec<Calories>>();
sums.sort_unstable();
sums.reverse();
let top3_sum = sums.iter().take(3).sum();
top3_sum
let top3_sum: u32 = sums.iter().take(3).sum();
let answer: u32 = 45000;
assert_eq!(top3_sum, answer);
}

pub fn day1_part2() -> Calories {
Expand Down
205 changes: 205 additions & 0 deletions src/days/day2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
use crate::util::util_imports::*;

#[derive(Clone, Copy)]
enum Symbol {
A,
B,
C,
X,
Y,
Z,
}

impl FromStr for Symbol {
type Err = ParseError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"A" => Ok(Symbol::A),
"B" => Ok(Symbol::B),
"C" => Ok(Symbol::C),
"X" => Ok(Symbol::X),
"Y" => Ok(Symbol::Y),
"Z" => Ok(Symbol::Z),
_ => Err(ParseError::new("Unknown symbol"))
}
}
}

enum RPS {
Rock,
Paper,
Scissors,
}

impl RPS {
fn score(&self) -> u32 {
match self {
RPS::Rock => 1,
RPS::Paper => 2,
RPS::Scissors => 3,
}
}
}

impl From<Symbol> for RPS {
fn from(symbol: Symbol) -> Self {
match symbol {
Symbol::A | Symbol::X => Self::Rock,
Symbol::B | Symbol::Y => Self::Paper,
Symbol::C | Symbol::Z => Self::Scissors,
}
}
}

impl From<(RPS, RPSResult)> for RPS {
fn from(tuple: (RPS, RPSResult)) -> Self {
let hand = tuple.0;
let result = tuple.1;

match hand {
RPS::Rock => {
match result {
RPSResult::Win => RPS::Paper,
RPSResult::Draw => RPS::Rock,
RPSResult::Lose => RPS::Scissors,
}
},
RPS::Paper => {
match result {
RPSResult::Win => RPS::Scissors,
RPSResult::Draw => RPS::Paper,
RPSResult::Lose => RPS::Rock,
}
},
RPS::Scissors => {
match result {
RPSResult::Win => RPS::Rock,
RPSResult::Draw => RPS::Scissors,
RPSResult::Lose => RPS::Paper,
}
},
}
}
}

#[derive(Clone, Copy)]
enum RPSResult {
Win,
Draw,
Lose,
}

impl RPSResult {
fn score(&self) -> u32 {
match self {
RPSResult::Win => 6,
RPSResult::Draw => 3,
RPSResult::Lose => 0,
}
}
}

impl From<Symbol> for RPSResult {
fn from(symbol: Symbol) -> Self {
match symbol {
Symbol::A | Symbol::B | Symbol::C => unimplemented!(),
Symbol::X => Self::Lose,
Symbol::Y => Self::Draw,
Symbol::Z => Self::Win,
}
}
}

struct Round {
opponent: Symbol,
me: Symbol,
}

impl Round {
fn result(&self) -> RPSResult {
match self.me.into() {
RPS::Rock => {
match self.opponent.into() {
RPS::Rock => RPSResult::Draw,
RPS::Paper => RPSResult::Lose,
RPS::Scissors => RPSResult::Win,
}
},
RPS::Paper => {
match self.opponent.into() {
RPS::Rock => RPSResult::Win,
RPS::Paper => RPSResult::Draw,
RPS::Scissors => RPSResult::Lose,
}
},
RPS::Scissors => {
match self.opponent.into() {
RPS::Rock => RPSResult::Lose,
RPS::Paper => RPSResult::Win,
RPS::Scissors => RPSResult::Draw,
}
},
}
}

fn score(&self) -> u32 {
self.result().score() + RPS::from(self.me).score()
}

fn score2(&self) -> u32 {
let opponent_hand = RPS::from(self.opponent);
let result = RPSResult::from(self.me);
let tuple = (opponent_hand, result);
let my_hand = RPS::from(tuple);
my_hand.score() + result.score()
}
}

impl Parser for Round {
fn parse_item<'a, I: Iterator<Item = String>>(line_iterator: &mut I) -> Result<Self, Box<dyn std::error::Error>> {
let line = line_iterator.next();

if let Some(line) = line {
let split: Vec<&str> = line.split_whitespace().collect();
let opponent = split[0].parse::<Symbol>()?;
let me = split[1].parse::<Symbol>()?;

return Ok(Round { opponent, me })
}

return Err(Box::new(ParseError::new("Empty line")));
}
}

const TEST_STRING: &str = "A Y
B X
C Z";

const INPUT_FILE: &str = "./input/day2.txt";

#[test]
fn day2_part1_test() {
let rounds = parse_input_string::<Round>(TEST_STRING.to_string()).unwrap();
let result: u32 = rounds.iter().map(|round| round.score()).sum();
let answer: u32 = 15;
assert_eq!(result, answer);
}

pub fn day2_part1() -> u32 {
let rounds = parse_input_file::<Round>(INPUT_FILE).unwrap();
rounds.iter().map(|round| round.score()).sum()
}

#[test]
fn day2_part2_test() {
let rounds = parse_input_string::<Round>(TEST_STRING.to_string()).unwrap();
let result: u32 = rounds.iter().map(|round| round.score2()).sum();
let answer: u32 = 12;
assert_eq!(result, answer);
}

pub fn day2_part2() -> u32 {
let rounds = parse_input_file::<Round>(INPUT_FILE).unwrap();
rounds.iter().map(|round| round.score2()).sum()
}
4 changes: 3 additions & 1 deletion src/days/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
mod day1;
pub use day1::*;
pub use day1::*;
mod day2;
pub use day2::*;
12 changes: 9 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ use days::*;
fn main() {
println!("Hello, Advent of Code!");

let day1_result = day1_part1();
let day1_part2_result = day1_part2();
println!("day1: {}, part2: {}", day1_result, day1_part2_result);
// let day1_result = day1_part1();
// let day1_part2_result = day1_part2();
// print!("day1: {}", day1_result);
// println!(", part2: {}", day1_part2_result);

let day2_result = day2_part1();
let day2_part2_result = day2_part2();
print!("day2: {}", day2_result);
println!(", part2: {}", day2_part2_result);
}
28 changes: 27 additions & 1 deletion src/util.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
use std::{path::Path, fs::File, error::Error, io::{BufReader, BufRead}};
use std::{path::Path, fs::File, error::Error, io::{BufReader, BufRead}, fmt::Display};

pub mod util_imports {
pub use std::str::FromStr;
pub use crate::util::{Parser, parse_input_file, ParseError};
#[cfg(test)]
pub use crate::util::parse_input_string;
}

pub trait Parser where Self: Sized {
fn parse_item<'a, I: Iterator<Item = String>>(line_iterator: &mut I) -> Result<Self, Box<dyn Error>>;
}

#[cfg(test)]
pub fn parse_input_string<I: Parser>(input_string: String) -> Result<Vec<I>, Box<dyn Error>> {
let line_iterator = input_string.lines().map(|s| s.to_string());

Expand Down Expand Up @@ -45,3 +52,22 @@ pub fn parse_lines<'a, L, I>(lines: L) -> Result<Vec<I>, Box<dyn Error>>

Ok(vec)
}

#[derive(Debug)]
pub struct ParseError {
reason: &'static str,
}

impl ParseError {
pub fn new(reason: &'static str) -> Self {
Self { reason }
}
}

impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.reason)
}
}

impl Error for ParseError {}

0 comments on commit 74349cc

Please sign in to comment.