2022 day11/rust: clean up parsing

This commit is contained in:
Xiretza 2022-12-11 17:58:18 +01:00
parent 77e443e6c8
commit 8a48ba05b0

View file

@ -22,6 +22,17 @@ impl Operand {
} }
} }
impl FromStr for Operand {
type Err = std::num::ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"old" => Ok(Operand::Old),
i => i.parse().map(Operand::Const),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Operation { enum Operation {
Add(Operand), Add(Operand),
@ -96,46 +107,39 @@ impl FromStr for Monkey {
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut lines = s.lines(); let mut lines = s.lines();
lines.next().unwrap(); lines.next().ok_or(())?; // Monkey n:
let items: Vec<_> = lines
.next()
.unwrap()
.split_once(':')
.unwrap()
.1
.trim()
.split(", ")
.map(|i| i.parse().unwrap())
.map(|value| Item { value })
.collect();
let op: Vec<_> = lines.next().unwrap().split_whitespace().collect(); let mut with_prefix = |prefix: &str| lines.next().ok_or(())?.strip_prefix(prefix).ok_or(());
let (operand, op) = op.split_last().unwrap(); let items: Vec<_> = with_prefix(" Starting items: ")?
let (operator, _) = op.split_last().unwrap(); .split(", ")
let operand = match *operand { .map(|i| {
"old" => Operand::Old, let value = i.parse().map_err(drop)?;
i => Operand::Const(i.parse().unwrap()), Ok(Item { value })
}; })
let operation = match *operator { .collect::<Result<_, _>>()?;
let (operator, operand) = with_prefix(" Operation: new = old ")?
.split_once(' ')
.ok_or(())?;
let operand = operand.parse().map_err(drop)?;
let operation = match operator {
"+" => Operation::Add(operand), "+" => Operation::Add(operand),
"*" => Operation::Multiply(operand), "*" => Operation::Multiply(operand),
_ => panic!("invalid operator {operator}"), _ => panic!("invalid operator {operator}"),
}; };
let mut lastnum = || { let test = Test::Divisible(
lines with_prefix(" Test: divisible by ")?
.next()
.unwrap()
.split_whitespace()
.last()
.unwrap()
.parse() .parse()
.unwrap() .map_err(drop)?,
}; );
let test = Test::Divisible(lastnum());
let target_pass = lastnum(); let target_pass = with_prefix(" If true: throw to monkey ")?
let target_fail = lastnum(); .parse()
.map_err(drop)?;
let target_fail = with_prefix(" If false: throw to monkey ")?
.parse()
.map_err(drop)?;
Ok(Monkey { Ok(Monkey {
items, items,