I’m working on Day 10 of Advent of Code. I wanted to re-visit the nomcrate. I had Claude guide me through how to parse the sample input in the problem defintion. I’ll return to and embellish this post later, but for now I wanted to make it into a “note to self”.
// src/main.rs
// dependencies
use nom::branch::alt;
use nom::character::complete::{char, space1, u32 as nom_u32};
use nom::combinator::{map, value};
use nom::multi::{many1, separated_list1};
use nom::sequence::delimited;
use nom::{IResult, Parser};
fn parse_light(input: &str) -> IResult<&str, bool> {
alt((value(false, char('.')), value(true, char('#')))).parse(input)
}
fn parse_pattern(input: &str) -> IResult<&str, Vec<bool>> {
delimited(char('['), many1(parse_light), char(']')).parse(input)
}
fn parse_button(input: &str) -> IResult<&str, Vec<usize>> {
delimited(
char('('),
separated_list1(char(','), map(nom_u32, |n| n as usize)),
char(')'),
)
.parse(input)
}
fn parse_buttons(input: &str) -> IResult<&str, Vec<Vec<usize>>> {
separated_list1(space1, parse_button).parse(input)
}
fn parse_joltages(input: &str) -> IResult<&str, Vec<u32>> {
delimited(char('{'), separated_list1(char(','), nom_u32), char('}')).parse(input)
}
fn parse_machine(input: &str) -> IResult<&str, FactoryMachine> {
map(
(parse_pattern, space1, parse_buttons, space1, parse_joltages),
|(pattern, _, buttons, _, joltages)| FactoryMachine {
pattern,
buttons,
joltages,
},
)
.parse(input)
}
fn parse_machines(input: &str) -> IResult<&str, Vec<FactoryMachine>> {
separated_list1(char('\n'), parse_machine).parse(input)
}
#[derive(Debug)]
struct FactoryMachine {
pattern: Vec<bool>,
buttons: Vec<Vec<usize>>,
joltages: Vec<u32>,
}
fn main() {
let sample_input = "[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}\n[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}\n[.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}";
let factory_machine = parse_machines(sample_input).unwrap();
println!("{:?}", factory_machine.1);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_light_returns_one_returns_true_or_false() {
let input = ".##.";
let result = parse_light(input).unwrap();
assert_eq!(result, ("##.", false));
}
#[test]
fn parse_pattern_handles_brackets() {
let input = "[.##.]";
let result = parse_pattern(input).unwrap();
assert_eq!(result, ("", vec![false, true, true, false]));
}
#[test]
fn parse_button_single_index() {
let input = "(3)";
let result = parse_button(input).unwrap();
assert_eq!(result, ("", vec![3]));
}
#[test]
fn parse_button_multiple_indices() {
let input = "(1,3)";
let result = parse_button(input).unwrap();
assert_eq!(result, ("", vec![1, 3]));
}
#[test]
fn parse_buttons_multiple() {
let input = "(3) (1,3) (2)";
let result = parse_buttons(input).unwrap();
assert_eq!(result, ("", vec![vec![3], vec![1, 3], vec![2]]));
}
#[test]
fn parse_joltages_single() {
let input = "{3,5,4,7}";
let result = parse_joltages(input).unwrap();
assert_eq!(result, ("", vec![3, 5, 4, 7]));
}
}
Parses the sample input from the problem definition. Takes this:
[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}
[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}
[.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}
and gives me this:
[FactoryMachine { pattern: [false, true, true, false], buttons: [[3], [1, 3], [2], [2, 3], [0, 2], [0, 1]], joltage: [3, 5, 4, 7] }, FactoryMachine { pattern: [false, false, false, true, false], buttons: [[0, 2, 3, 4], [2, 3], [0, 4], [0, 1, 2], [1, 2, 3, 4]], joltage: [7, 5, 12, 7, 2] }, FactoryMachine { pattern: [false, true, true, true, false, true], buttons: [[0, 1, 2, 3, 4], [0, 3, 4], [0, 1, 2, 4, 5], [1, 2]], joltage: [10, 11, 11, 5, 10, 5] }]
Which is my chosen data structure for solving the problem.
Comments