day(02): refactor
Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
dbc155fd44
commit
eea97c6e7b
1 changed files with 48 additions and 30 deletions
|
@ -3,11 +3,12 @@ use std::str::FromStr;
|
|||
use aoc_2022::*;
|
||||
|
||||
use color_eyre::eyre::Result;
|
||||
use itertools::Itertools;
|
||||
use thiserror::Error;
|
||||
use tracing::*;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum Shape {
|
||||
Rock,
|
||||
Paper,
|
||||
|
@ -28,7 +29,7 @@ impl Shape {
|
|||
enum ShapeError {
|
||||
#[error("empty string given")]
|
||||
Empty,
|
||||
|
||||
|
||||
#[error("unknown shape ‹{0}›")]
|
||||
UnknownShape(String),
|
||||
}
|
||||
|
@ -85,20 +86,53 @@ impl FromStr for Round {
|
|||
}
|
||||
}
|
||||
|
||||
fn find_strategy<P>(predicate: P) -> (usize, (Shape, Shape))
|
||||
where
|
||||
P: FnMut(&(usize, (Shape, Shape))) -> bool,
|
||||
{
|
||||
// R P S
|
||||
// R 3 0 6
|
||||
// P 6 3 0
|
||||
// S 0 6 3
|
||||
vec![
|
||||
// Loss
|
||||
(Shape::Rock, Shape::Paper),
|
||||
(Shape::Paper, Shape::Scissors),
|
||||
(Shape::Scissors, Shape::Rock),
|
||||
// Draw
|
||||
(Shape::Rock, Shape::Rock),
|
||||
(Shape::Paper, Shape::Paper),
|
||||
(Shape::Scissors, Shape::Scissors),
|
||||
// Win
|
||||
(Shape::Rock, Shape::Scissors),
|
||||
(Shape::Paper, Shape::Rock),
|
||||
(Shape::Scissors, Shape::Paper),
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.find_or_first(predicate)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn find_result(strategy: &(Shape, Shape)) -> i32 {
|
||||
3 * (find_strategy(|&(_, st)| st == *strategy).0 as i32 / 3)
|
||||
}
|
||||
|
||||
fn find_result_for_outcome(opponent: Shape, outcome: Outcome) -> i32 {
|
||||
let range = match outcome {
|
||||
Outcome::Lose => 0..3,
|
||||
Outcome::Draw => 3..6,
|
||||
Outcome::Win => 6..9,
|
||||
};
|
||||
let (i, (shape, _)) = find_strategy(|&(i, (_, op))| range.contains(&i) && op == opponent);
|
||||
|
||||
3 * (i as i32 / 3) + shape.score()
|
||||
}
|
||||
|
||||
impl Round {
|
||||
fn score(&self) -> i32 {
|
||||
let shape_score = self.me.score();
|
||||
|
||||
let result_score = match (self.me, self.opponent) {
|
||||
(Shape::Scissors, Shape::Paper) => 6,
|
||||
(Shape::Paper, Shape::Rock) => 6,
|
||||
(Shape::Rock, Shape::Scissors) => 6,
|
||||
(Shape::Paper, Shape::Scissors) => 0,
|
||||
(Shape::Rock, Shape::Paper) => 0,
|
||||
(Shape::Scissors, Shape::Rock) => 0,
|
||||
_ => 3,
|
||||
};
|
||||
|
||||
let result_score = find_result(&(self.me, self.opponent));
|
||||
shape_score + result_score
|
||||
}
|
||||
|
||||
|
@ -111,23 +145,7 @@ impl Round {
|
|||
}
|
||||
|
||||
fn expected_score(&self) -> i32 {
|
||||
let result_score = match self.expected_outcome() {
|
||||
Outcome::Lose => 0,
|
||||
Outcome::Draw => 3,
|
||||
Outcome::Win => 6,
|
||||
};
|
||||
|
||||
let shape_score = match (self.expected_outcome(), self.opponent) {
|
||||
(Outcome::Lose, Shape::Rock) => Shape::Scissors.score(),
|
||||
(Outcome::Lose, Shape::Paper) => Shape::Rock.score(),
|
||||
(Outcome::Lose, Shape::Scissors) => Shape::Paper.score(),
|
||||
(Outcome::Win, Shape::Rock) => Shape::Paper.score(),
|
||||
(Outcome::Win, Shape::Paper) => Shape::Scissors.score(),
|
||||
(Outcome::Win, Shape::Scissors) => Shape::Rock.score(),
|
||||
_ => self.opponent.score(),
|
||||
};
|
||||
|
||||
result_score + shape_score
|
||||
find_result_for_outcome(self.opponent, self.expected_outcome())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue