Implemented parsers as traits

This commit is contained in:
Dreaded_X 2022-12-06 05:12:51 +01:00
parent f03ddf12cf
commit 9a155dbda7
Signed by: Dreaded_X
GPG Key ID: 76BDEC4E165D8AD9

View File

@ -1,6 +1,6 @@
#![feature(test)] #![feature(test)]
use core::fmt; use core::fmt;
use std::collections::HashMap; use std::{collections::HashMap, str::FromStr};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use regex::Regex; use regex::Regex;
@ -91,13 +91,13 @@ impl fmt::Display for Boat {
} }
} }
impl Boat { impl From<Vec<&str>> for Boat {
fn new(lines: &Vec<&str>) -> Boat { fn from(lines: Vec<&str>) -> Self {
lazy_static! { lazy_static! {
static ref RE: Regex = Regex::new(r"\[[A-Z]\]").unwrap(); static ref RE: Regex = Regex::new(r"\[[A-Z]\]").unwrap();
} }
let mut boat = Boat{stacks: HashMap::new()}; let mut boat = Self{stacks: HashMap::new()};
for line in lines { for line in lines {
for mat in RE.find_iter(line) { for mat in RE.find_iter(line) {
let index = mat.start() / 4 + 1; let index = mat.start() / 4 + 1;
@ -115,10 +115,12 @@ impl Boat {
return boat; return boat;
} }
}
impl Boat {
fn take(&mut self, index: usize, amount: usize) -> Vec<Crate> { fn take(&mut self, index: usize, amount: usize) -> Vec<Crate> {
let stack = self.stacks.entry(index).or_default(); let stack = self.stacks.entry(index).or_default();
stack.split_off(stack.len()-amount) stack.split_off(stack.len()-amount as usize)
} }
fn put(&mut self, index: usize, mut vec: Vec<Crate>) { fn put(&mut self, index: usize, mut vec: Vec<Crate>) {
@ -141,42 +143,54 @@ impl Boat {
} }
} }
// -- Helpers -- struct Instruction {
fn parse_instruction(s: &str) -> (usize, usize, usize) { amount: usize,
lazy_static! { from: usize,
static ref RE: Regex = Regex::new(r"move (?P<amount>[0-9]+) from (?P<from>[0-9]) to (?P<to>[0-9])").unwrap(); to: usize,
}
let capture = RE.captures(s).unwrap();
let parse_number = |name| capture.name(name).unwrap().as_str().parse::<usize>().unwrap();
let amount: usize = parse_number("amount");
let from: usize = parse_number("from");
let to: usize = parse_number("to");
(amount, from, to)
} }
impl FromStr for Instruction {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
lazy_static! {
static ref RE: Regex = Regex::new(r"move (?P<amount>[0-9]+) from (?P<from>[0-9]) to (?P<to>[0-9])").unwrap();
}
let capture = RE.captures(s).unwrap();
let parse = |name| capture.name(name).unwrap().as_str().parse();
let amount = parse("amount")?;
let from = parse("from")?;
let to = parse("to")?;
Ok(Instruction{amount, from, to})
}
}
// -- Helpers --
fn solution(input: &str, part1: bool) -> String { fn solution(input: &str, part1: bool) -> String {
// The current layout description ends with an empty line // The current layout description ends with an empty line
let mut boat = Boat::new(&input let mut boat: Boat = input.lines()
.lines()
.take_while(|line| !line.is_empty()) .take_while(|line| !line.is_empty())
.collect()); .collect::<Vec<_>>()
.into();
// Each instruction starts with an 'm' // Each instruction starts with an 'm'
input input
.lines() .lines()
.skip_while(|line| !line.starts_with('m')) .skip_while(|line| !line.starts_with('m'))
.map(parse_instruction) .map(|line| line.parse().unwrap())
.for_each(|(amount, from, to)| { .for_each(|i: Instruction| {
let mut taken = boat.take(from, amount); let mut taken = boat.take(i.from, i.amount);
if part1 { if part1 {
// In part one we move the crates on by one, so the vector needs to be reverse to // In part one we move the crates on by one, so the vector needs to be reverse to
// get the correct order // get the correct order
taken.reverse(); taken.reverse();
} }
boat.put(to, taken); boat.put(i.to, taken);
}); });
boat.to_string() boat.to_string()