use crate::Solution;
use pmath::digits::{is_palindrome, reverse};
problem!(Problem0055, 55, "Lychrel Numbers");
impl Solution for Problem0055 {
fn solve(&self) -> String {
let mut iterations: Vec<Option<u8>> = vec![None; MAX_VALUE as usize];
iterations[0] = Some(0);
for n in 1..MAX_VALUE {
if iterations[n as usize].is_none() {
analyse_lychrel(n, 1, &mut iterations);
}
}
iterations
.into_iter()
.filter(|&x| match x {
None => false,
Some(val) => val == u8::MAX,
})
.count()
.to_string()
}
}
const MAX_ITERATIONS: u8 = 50;
const MAX_VALUE: u128 = 10_000;
fn analyse_lychrel(n: u128, depth: u8, iterations: &mut [Option<u8>]) -> u8 {
if depth >= MAX_ITERATIONS {
u8::MAX
} else if n < MAX_VALUE && iterations[n as usize].is_some() {
iterations[n as usize].unwrap().saturating_add(1)
} else {
let next = n + reverse(n, 10);
if is_palindrome(next, 10) {
if n < MAX_VALUE {
iterations[n as usize] = Some(depth);
}
depth
} else {
let recursive_result = analyse_lychrel(next, depth + 1, iterations);
if recursive_result == u8::MAX {
if n < MAX_VALUE {
iterations[n as usize] = Some(u8::MAX);
}
u8::MAX
} else {
if n < MAX_VALUE {
iterations[n as usize] = Some(1 + recursive_result);
}
1 + recursive_result
}
}
}
}