use super::{Number, SolveResult, SolveError};
use crate::utils::NumberToFind;
pub fn convert(number: &Number, base: u32) -> SolveResult {
match number.convert(base) {
Ok(n) => Ok(n.number()),
Err(e) => Err(SolveError(e.into())),
}
}
fn convert_all(numbers: &Vec<Number>, base: u32) -> Result<Vec<Number>, SolveError> {
let mut converted_numbers = vec![];
for num in numbers {
converted_numbers.push(num.convert(base).map_err(|e| SolveError(e.into()))?);
}
Ok(converted_numbers)
}
pub fn find_num(numbers: &Vec<Number>, what_find: NumberToFind) -> SolveResult {
let nums_in_decimal = convert_all(numbers, 10)?;
Ok(match what_find {
NumberToFind::Min => nums_in_decimal.iter().min(),
NumberToFind::Max => nums_in_decimal.iter().max(),
}.unwrap().number())
}
pub fn find_digits_sum(numbers: &Vec<Number>, base: u32, what_find: NumberToFind) -> SolveResult {
let converted_numbers = convert_all(numbers, base)?;
let mut sums = vec![];
for num in converted_numbers {
let sum_of_digits = num.number().chars()
.filter(|c| c.is_digit(base))
.fold(0, |acc, c| acc + c.to_digit(base).unwrap());
sums.push(sum_of_digits);
}
Ok(match what_find {
NumberToFind::Min => sums.iter().min(),
NumberToFind::Max => sums.iter().max(),
}.unwrap().to_string())
}
pub fn find_ones_count(numbers: &Vec<Number>, what_find: NumberToFind) -> SolveResult {
let converted_numbers = convert_all(numbers, 2)?;
let mut ones = vec![];
for num in converted_numbers {
ones.push(i32::from_str_radix(&num.number(), 2).unwrap().abs().count_ones());
}
Ok(match what_find {
NumberToFind::Min => ones.iter().min(),
NumberToFind::Max => ones.iter().max(),
}.unwrap().to_string())
}