parsing c00di aoc5
- 📅 2022-12-05T23:09:43.676Z
- 👁️ 111 katselukertaa
- 🔓 Julkinen
//region Parsing
//region Parsing utilities
fn transpose<T: ToOwned<Owned = T>>(v: Vec<VecDeque<T>>) -> Vec<VecDeque<T>> {
let mut transposed: Vec<VecDeque<T>> = Vec::new();
let max = v.iter().map(|x| x.len()).max().unwrap_or(0usize);
for i in 0..max {
if transposed.len() <= i {
transposed.push(VecDeque::new());
}
for j in 0..v.len() {
let opt = v[j].get(i);
if let Some(val) = opt {
transposed.get_mut(i).unwrap().push_back(val.to_owned());
}
}
}
return transposed;
}
fn remove_empty_blocks(input: &mut Vec<VecDeque<char>>) {
for column in input.iter_mut() {
column.retain(|x| *x != ' ')
}
}
//endregion
fn ws<'a, F: 'a, O, E: ParseError<&'a str>>(
inner: F,
) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
where
F: FnMut(&'a str) -> IResult<&'a str, O, E>,
{
delimited(space0, inner, space0)
}
fn block(input: &str) -> IResult<&str, char, VerboseError<&str>> {
let (input, _) = tag("[")(input)?;
let (input, chr) = anychar(input)?;
let (input, _) = tag("]")(input)?;
Ok((input, chr))
}
fn empty_block(input: &str) -> IResult<&str, char, VerboseError<&str>> {
let (input, _) = count(tag(" "), 3)(input)?;
Ok((input, ' '))
}
fn block_line(input: &str) -> IResult<&str, VecDeque<char>, VerboseError<&str>> {
let (input, blocks) = separated_list1(tag(" "), alt((block, empty_block)))(input)?;
Ok((input, VecDeque::from(blocks)))
}
fn initial_state(input: &str) -> IResult<&str, Vec<VecDeque<char>>, VerboseError<&str>> {
let (input, lines) = separated_list1(newline, block_line)(input)?;
let mut transpose = transpose(lines);
// Must be done after transpose
remove_empty_blocks(&mut transpose);
Ok((input, transpose))
}
fn stack_numbers(input: &str) -> IResult<&str, Vec<u32>, VerboseError<&str>> {
let (input, _) = multispace0(input)?;
let (input, numbers) = separated_list1(space1, u32)(input)?;
let (input, _) = multispace0(input)?;
Ok((input, numbers))
}
fn action(input: &str) -> IResult<&str, Action, VerboseError<&str>> {
let (input, (_, amount, _, from, _, to)) = tuple((
ws(tag("move")), map(u32, |x| x.to_usize()), // moving zero items does nothing
ws(tag("from")), verify(map(u32, |x| x.to_usize()), |x| *x >= 1),
ws(tag("to" )), verify(map(u32, |x| x.to_usize()), |x| *x >= 1)
))(input)?;
Ok((input, Action { amount, from, to }))
}
fn procedure0(input: &str) -> IResult<&str, Procedure, VerboseError<&str>> {
let (input, initial_state) = initial_state(input)?;
let (input, _) = stack_numbers(input)?;
let (input, actions) = separated_list1(newline, action)(input)?;
Ok((input, Procedure { initial_state, actions }))
}
fn procedure(input: &str) -> IResult<&str, Procedure, VerboseError<&str>> {
terminated(procedure0, opt(newline))(input)
}
//endregion