use crate::alphabet::decode;
use crate::error::NumerologyError;
use crate::reduction::{reduce, CalculatedNumber, PYTHAGOREAN_MASTERS};
use crate::System;
#[must_use]
pub fn address_sum(address: &str, system: System) -> u32 {
address
.chars()
.map(|c| {
if let Some(digit) = c.to_digit(10) {
digit
} else if let Some(decoded) = decode(c) {
u32::from(system.letter_value(&decoded))
} else {
0
}
})
.sum()
}
pub fn house_number(address: &str) -> Result<CalculatedNumber, NumerologyError> {
let sum = address_sum(address, System::Pythagorean);
if sum == 0 {
return Err(NumerologyError::EmptyAddress);
}
Ok(reduce(sum, PYTHAGOREAN_MASTERS))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn alphanumeric_address() {
assert_eq!(house_number("42B").unwrap().value, 8);
}
#[test]
fn pure_digits_reduce() {
assert_eq!(house_number("77").unwrap().value, 5);
assert_eq!(house_number("100").unwrap().value, 1);
}
#[test]
fn punctuation_and_spaces_are_ignored() {
assert_eq!(
address_sum("Apt 42-B", System::Pythagorean),
address_sum("42B", System::Pythagorean) + address_sum("APT", System::Pythagorean)
);
assert_eq!(house_number("42 B").unwrap().value, house_number("42B").unwrap().value);
}
#[test]
fn masters_are_preserved() {
assert!(house_number("9992").unwrap().is_master);
}
#[test]
fn empty_address_errors() {
assert_eq!(house_number(" "), Err(NumerologyError::EmptyAddress));
assert_eq!(house_number("!!!"), Err(NumerologyError::EmptyAddress));
}
}