aoc-rs-2021/src/day_04/parsing.rs
2021-12-04 23:49:22 +01:00

91 lines
2.3 KiB
Rust

use super::bingo::{Board, Field, Game};
use crate::parsing::{newline, parse_number, space};
use yap::{IntoTokens, Tokens};
pub fn parse_field(tokens: &mut impl Tokens<Item = char>) -> Option<Field> {
parse_number(tokens).map(|number| Field {
number,
marked: false,
})
}
pub fn parse_field_line(tokens: &mut impl Tokens<Item = char>) -> Option<[Field; 5]> {
tokens
.sep_by(|t| parse_field(t), |t| space(t))
.collect::<Vec<Field>>()
.try_into()
.ok()
}
pub fn parse_field_line_array(tokens: &mut impl Tokens<Item = char>) -> Option<[[Field; 5]; 5]> {
tokens
.sep_by(|t| parse_field_line(t), |t| newline(t))
.collect::<Vec<[Field; 5]>>()
.try_into()
.ok()
}
pub fn parse_board(tokens: &mut impl Tokens<Item = char>) -> Option<Board> {
parse_field_line_array(tokens).map(|fields| Board {
fields,
finished: false,
})
}
pub fn parse_boards(tokens: &mut impl Tokens<Item = char>) -> Vec<Board> {
tokens
.sep_by(|t| parse_board(t), |t| newline(t) && newline(t))
.collect()
}
pub fn parse_input_numbers(tokens: &mut impl Tokens<Item = char>) -> Vec<usize> {
tokens
.sep_by(|t| parse_number(t), |t| t.token(','))
.collect()
}
pub fn parse_game(input: &str) -> Game {
let mut tokens = input.into_tokens();
let input_numbers = parse_input_numbers(&mut tokens);
tokens.skip_many(newline);
let boards = parse_boards(&mut tokens);
Game {
input_numbers,
boards,
}
}
#[cfg(test)]
mod test {
use yap::IntoTokens;
#[test]
fn parse_input_numbers() {
assert_eq!(
vec![1, 2, 3],
super::parse_input_numbers(&mut "1,2,3".into_tokens())
)
}
#[test]
fn parse_field_line() {
if let Some(line) = super::parse_field_line(&mut " 3 15 0 2 22".into_tokens()) {
assert_eq!(3, line[0].number);
assert_eq!(15, line[1].number);
assert_eq!(0, line[2].number);
assert_eq!(2, line[3].number);
assert_eq!(22, line[4].number);
}
}
#[test]
fn parse_board() {
const BOARD: &str = " 3 15 0 2 22
9 18 13 17 5
19 8 7 25 23
20 11 10 24 4
14 21 16 12 6";
assert!(super::parse_board(&mut BOARD.into_tokens()).is_some());
}
}