95 lines
3.2 KiB
Rust
95 lines
3.2 KiB
Rust
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<Trick>> {
|
|
separated_list1(line_ending, trick_parser)(s)
|
|
}
|
|
|
|
pub(crate) fn parse(inp: &str) -> Vec<usize> {
|
|
let (_, tricks): (&str, Vec<Trick>) = 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")
|
|
)
|
|
}
|
|
}
|