1
0

Parser finished.

This commit is contained in:
Pcornat 2022-12-26 00:34:30 +01:00
parent 0408d3e148
commit 6245e1a17c

View File

@ -1,19 +1,116 @@
fn parser(content: &str) { use nom::{
let output = content branch::alt,
.lines() bytes::complete::{tag, take, take_while1},
.filter(|item| !item.starts_with("move")) combinator::{all_consuming, map, map_res, opt},
.flat_map(|line| { sequence::{delimited, preceded, tuple},
let splitted = line Finish, IResult,
.trim() };
.split(' ')
.enumerate() #[derive(Debug)]
.filter(|item| !item.1.contains(' ')) struct Instruction {
.filter(|item| !item.1.is_empty()) quantity: usize,
.collect::<Vec<(usize, &str)>>(); src: usize,
println!("{splitted:?}"); dst: usize,
splitted }
/// Used to parse a crate
///
/// # Arguments
///
/// * `i`:
///
/// returns: Result<(&str, char), Err<Error<I>>>
///
fn parse_crate(i: &str) -> IResult<&str, char> {
let first_char = |s: &str| s.chars().next().unwrap();
let f = delimited(tag("["), take(1_usize), tag("]"));
map(f, first_char)(i)
}
fn parse_hole(i: &str) -> IResult<&str, ()> {
// `drop` takes a value and returns nothing, which is
// perfect for our case
map(tag(" "), drop)(i)
}
fn parse_crate_or_hole(i: &str) -> IResult<&str, Option<char>> {
alt((map(parse_crate, Some), map(parse_hole, |_| None)))(i)
}
fn parse_crate_line(i: &str) -> IResult<&str, Vec<Option<char>>> {
let (mut i, c) = parse_crate_or_hole(i)?;
let mut v = vec![c];
loop {
let (next_i, maybe_c) = opt(preceded(tag(" "), parse_crate_or_hole))(i)?;
match maybe_c {
Some(c) => v.push(c),
None => break,
}
i = next_i;
}
Ok((i, v))
}
fn transpose_rev<T>(v: Vec<Vec<Option<T>>>) -> Vec<Vec<T>> {
assert!(!v.is_empty());
let len = v[0].len();
let mut iters: Vec<_> = v.into_iter().map(|n| n.into_iter()).collect();
(0..len)
.map(|_| {
iters
.iter_mut()
.filter_map(|n| n.next().unwrap())
.collect::<Vec<T>>()
}) })
.collect::<Vec<(usize, &str)>>(); .collect()
}
fn parse_number(i: &str) -> IResult<&str, usize> {
map_res(take_while1(|c: char| c.is_ascii_digit()), |s: &str| {
s.parse::<usize>()
})(i)
}
fn parse_pile_number(i: &str) -> IResult<&str, usize> {
map(parse_number, |i| i - 1)(i)
}
fn parse_instruction(i: &str) -> IResult<&str, Instruction> {
map(
tuple((
preceded(tag("move "), parse_number),
preceded(tag(" from "), parse_pile_number),
preceded(tag(" to "), parse_pile_number),
)),
|(quantity, src, dst)| Instruction { quantity, src, dst },
)(i)
}
fn parser(content: &str) {
let mut lines = content.lines();
let crate_lines = (&mut lines)
.map_while(|line| {
all_consuming(parse_crate_line)(line)
.finish()
.ok()
.map(|(_, line)| line)
})
.collect();
let crate_columns = transpose_rev(crate_lines);
crate_columns.iter().for_each(|item| println!("{item:?}"));
assert!(lines.next().unwrap().is_empty());
let instructions: Vec<_> = lines
.map(|line| all_consuming(parse_instruction)(line).finish().unwrap().1)
.collect();
for ins in &instructions {
println!("{ins:?}");
}
} }
pub fn solve(file_path: &str) -> i32 { pub fn solve(file_path: &str) -> i32 {