Make functions public
Move valid number filtering to separate function for more granular testing
This commit is contained in:
parent
a9c3b9a3a0
commit
5fe3d1caa8
|
@ -2,7 +2,7 @@ use regex::{Match, Regex};
|
||||||
use std::{fmt::Display, num::ParseIntError};
|
use std::{fmt::Display, num::ParseIntError};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Symbol {
|
pub struct Symbol {
|
||||||
value: char,
|
value: char,
|
||||||
row: usize,
|
row: usize,
|
||||||
col: usize,
|
col: usize,
|
||||||
|
@ -15,7 +15,7 @@ impl Display for Symbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Number {
|
pub struct Number {
|
||||||
value: u32,
|
value: u32,
|
||||||
row: usize,
|
row: usize,
|
||||||
start: usize,
|
start: usize,
|
||||||
|
@ -36,7 +36,7 @@ impl Display for Number {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Number {
|
impl Number {
|
||||||
fn valid(&self, symbols: &[Symbol]) -> bool {
|
pub fn is_valid(&self, symbols: &[Symbol]) -> bool {
|
||||||
let adjacent: Vec<usize> = symbols
|
let adjacent: Vec<usize> = symbols
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|m| {
|
.filter_map(|m| {
|
||||||
|
@ -68,7 +68,7 @@ impl TryFrom<Match<'_>> for Number {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_symbols(input: &str) -> Vec<Symbol> {
|
pub fn get_symbols(input: &str) -> Vec<Symbol> {
|
||||||
let mut items: Vec<Symbol> = Vec::new();
|
let mut items: Vec<Symbol> = Vec::new();
|
||||||
for (row, line) in input.lines().enumerate() {
|
for (row, line) in input.lines().enumerate() {
|
||||||
for (col, value) in line.chars().enumerate() {
|
for (col, value) in line.chars().enumerate() {
|
||||||
|
@ -80,40 +80,38 @@ fn get_symbols(input: &str) -> Vec<Symbol> {
|
||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_numbers(input: &str) -> Vec<Number> {
|
pub fn get_numbers(input: &str, predicate: Option<&dyn Fn(&Number) -> bool>) -> Vec<Number> {
|
||||||
let rstring = r"(\d)+";
|
let rstring = r"(\d)+";
|
||||||
let mut items: Vec<Number> = Vec::new();
|
let mut items: Vec<Number> = Vec::new();
|
||||||
for (row, line) in input.lines().enumerate() {
|
for (row, line) in input.lines().enumerate() {
|
||||||
for item in Regex::new(rstring).unwrap().find_iter(line) {
|
for item in Regex::new(rstring).unwrap().find_iter(line) {
|
||||||
let mut number = Number::try_from(item).unwrap();
|
let mut number = Number::try_from(item).unwrap();
|
||||||
number.row = row;
|
number.row = row;
|
||||||
|
if predicate.unwrap_or(&|_| true)(&number) {
|
||||||
items.push(number);
|
items.push(number);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_valid_numbers(input: &str, symbols: &[Symbol]) -> Vec<u32> {
|
||||||
|
get_numbers(input, Some(&|number| number.is_valid(symbols)))
|
||||||
|
.iter()
|
||||||
|
.map(|m| m.value)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main(input: &str) -> u32 {
|
pub fn main(input: &str) -> u32 {
|
||||||
let symbols = get_symbols(input);
|
let symbols = get_symbols(input);
|
||||||
get_numbers(input)
|
get_valid_numbers(input, &symbols).iter().sum()
|
||||||
.iter()
|
|
||||||
.filter_map(|m| {
|
|
||||||
if m.valid(&symbols) {
|
|
||||||
Some(m.value)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.sum()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
const INPUT: &str = "467..114..
|
||||||
fn example() {
|
|
||||||
let input = "467..114..
|
|
||||||
...*......
|
...*......
|
||||||
..35..633.
|
..35..633.
|
||||||
......#...
|
......#...
|
||||||
|
@ -123,6 +121,9 @@ mod tests {
|
||||||
......755.
|
......755.
|
||||||
...$.*....
|
...$.*....
|
||||||
.664.598..";
|
.664.598..";
|
||||||
assert_eq!(main(input), 4361);
|
|
||||||
|
#[test]
|
||||||
|
fn example() {
|
||||||
|
assert_eq!(main(INPUT), 4361);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue