use crate::Solution;
use pmath::digits::digits;
use pmath::primes::sieve_of_eratosthenes;
use std::collections::HashMap;
problem!(Problem0035, 35, "Circular Primes");
impl Solution for Problem0035 {
fn solve(&self) -> String {
let mut primes = sieve_of_eratosthenes(1_000_000 - 1);
primes.retain(|&n| digits(n, 10).all(|digit| !matches!(digit, 0 | 2 | 4 | 5 | 6 | 8)));
primes.insert(0, 2);
primes.insert(2, 5);
let mut primes_map: HashMap<u64, bool> = HashMap::with_capacity(primes.len());
for prime in &primes {
primes_map.insert(*prime, false);
}
let mut rotations = Vec::new();
for mut n in primes {
let num_len = digits(n, 10).len();
let mut circular_prime = true;
rotations.clear();
rotations.push(n);
for _ in 0..(num_len - 1) {
let last_digit = n % 10;
n /= 10;
n += last_digit * 10_u64.pow((num_len - 1) as u32);
rotations.push(n);
if !primes_map.contains_key(&n) {
circular_prime = false;
break;
}
}
if circular_prime {
for rotation in &rotations {
primes_map.insert(*rotation, true);
}
}
}
primes_map
.into_iter()
.filter(|(_, primality)| *primality)
.count()
.to_string()
}
}