use crate::Solution;
use itertools::Itertools;
use pmath::digits::{digits, digits_to_int};
use pmath::primes::is_prime;
problem!(Problem0037, 37, "Truncatable Primes");
impl Solution for Problem0037 {
fn solve(&self) -> String {
let mut trunc_primes = Vec::with_capacity(TRUNC_PRIMES as usize);
'outer: for n_len in 2_usize.. {
let mut iterables = Vec::with_capacity(n_len);
iterables.push(FIRST_DIGIT.iter().copied());
for _ in 0..(n_len - 2) {
iterables.push(MIDDLE_DIGIT.iter().copied());
}
iterables.push(LAST_DIGIT.iter().copied());
for i in iterables.into_iter().multi_cartesian_product() {
let num = digits_to_int(i.iter().rev(), 10);
if is_trunc_prime(num) {
trunc_primes.push(num);
if trunc_primes.len() == TRUNC_PRIMES as usize {
break 'outer;
}
}
}
}
trunc_primes.iter().sum::<u64>().to_string()
}
}
const TRUNC_PRIMES: u8 = 11;
const FIRST_DIGIT: [u8; 4] = [2, 3, 5, 7];
const MIDDLE_DIGIT: [u8; 4] = [1, 3, 7, 9];
const LAST_DIGIT: [u8; 2] = [3, 7];
fn is_trunc_prime(x: u64) -> bool {
if !is_prime(x).0 {
return false;
}
for i in 1..digits(x, 10).len() {
if !is_prime(x % 10_u64.pow(i as u32)).0 || !is_prime(x / 10_u64.pow(i as u32)).0 {
return false;
}
}
true
}