use crate::Solution;
use pmath::digits::digits_to_int;
use std::collections::HashMap;
use std::sync::LazyLock;
problem!(Problem0043, 43, "Sub-string Divisibility");
impl Solution for Problem0043 {
fn solve(&self) -> String {
let mut sum = 0;
let mut working = Vec::new();
recursive_search(&mut working, &mut sum, 1);
sum.to_string()
}
}
static DIGITS: LazyLock<HashMap<u8, Vec<u8>>> = LazyLock::new(|| {
let mut digits = HashMap::with_capacity(10);
digits.insert(1, vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
digits.insert(2, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
digits.insert(3, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
digits.insert(4, vec![0, 2, 4, 6, 8]);
digits.insert(5, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
digits.insert(6, vec![0, 5]);
digits.insert(7, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
digits.insert(8, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
digits.insert(9, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
digits.insert(10, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
digits
});
fn recursive_search(working: &mut Vec<u8>, sum: &mut u64, depth: u8) {
match depth {
1 => {
for i in DIGITS.get(&depth).unwrap() {
working.push(*i);
recursive_search(working, sum, depth + 1);
working.pop();
}
}
2..=4 | 6 => {
for i in DIGITS.get(&depth).unwrap() {
if !working.contains(i) {
working.push(*i);
recursive_search(working, sum, depth + 1);
working.pop();
}
}
}
5 => {
for i in DIGITS.get(&depth).unwrap() {
if !working.contains(i) {
working.push(*i);
let value: i32 = digits_to_int(working[2..5].iter().rev(), 10);
if value % 3 == 0 {
recursive_search(working, sum, depth + 1);
}
working.pop();
}
}
}
7 => {
for i in DIGITS.get(&depth).unwrap() {
if !working.contains(i) {
working.push(*i);
let value: i32 = digits_to_int(working[4..7].iter().rev(), 10);
if value % 7 == 0 {
recursive_search(working, sum, depth + 1);
}
working.pop();
}
}
}
8 => {
for i in DIGITS.get(&depth).unwrap() {
if !working.contains(i) {
working.push(*i);
let value: i32 = digits_to_int(working[5..8].iter().rev(), 10);
if value % 11 == 0 {
recursive_search(working, sum, depth + 1);
}
working.pop();
}
}
}
9 => {
for i in DIGITS.get(&depth).unwrap() {
if !working.contains(i) {
working.push(*i);
let value: i32 = digits_to_int(working[6..9].iter().rev(), 10);
if value % 13 == 0 {
recursive_search(working, sum, depth + 1);
}
working.pop();
}
}
}
10 => {
for i in DIGITS.get(&depth).unwrap() {
if !working.contains(i) {
working.push(*i);
let value: i32 = digits_to_int(working[7..10].iter().rev(), 10);
if value % 17 == 0 {
recursive_search(working, sum, depth + 1);
}
working.pop();
}
}
}
11 => {
let value: u64 = digits_to_int(working.iter().rev(), 10);
*sum += value;
}
_ => unreachable!("Invalid depth"),
}
}