clean up 32

This commit is contained in:
Dr. Matthias Ratajczak
2022-08-19 18:37:05 +02:00
parent 3a0782168f
commit b88e692efa
+42 -29
View File
@@ -5,70 +5,83 @@ type Int = u32;
const UPPER_BOUND: Int = 3_333; // because result must be a 4-digit number const UPPER_BOUND: Int = 3_333; // because result must be a 4-digit number
fn main() { fn main() {
// prevent reallocation of these sets on every call in `are_pandigital`
let mut buffer1 = HashSet::new(); let mut buffer1 = HashSet::new();
let mut buffer2 = HashSet::new(); let mut buffer2 = HashSet::new();
let f = (1..UPPER_BOUND) let factors = get_suitable_factors(UPPER_BOUND);
.filter(|n| {
let s = n.to_string();
let hs = s.chars().collect::<HashSet<_>>();
hs.len() == s.len() && !hs.contains(&'0')
})
.collect::<Vec<_>>()
.leak();
let mut result = HashSet::new(); let mut products_of_pandigital_triples = HashSet::new();
for f1 in f.iter() { for f1 in factors.iter() {
let lower_bound = UPPER_BOUND / f1; let lower_bound = UPPER_BOUND / f1;
'inner: for f2 in f.iter().skip_while(|i| **i < lower_bound) { 'inner: for f2 in factors.iter().skip_while(|i| **i < lower_bound) {
let p = f1 * f2; let product = f1 * f2;
if f1.len() + f2.len() + p.len() > 9 { if f1.oom() + f2.oom() + product.oom() > 9 {
break 'inner; break 'inner;
} }
if are_pandigital([f1, f2, &p], &mut buffer1, &mut buffer2) { if are_pandigital([f1, f2, &product], &mut buffer1, &mut buffer2) {
println!("{f1} {f2} {p}"); println!("{f1} {f2} {product}");
result.insert(p); products_of_pandigital_triples.insert(product);
} }
} }
} }
println!("{}", result.iter().sum::<Int>()); println!("{}", products_of_pandigital_triples.iter().sum::<Int>());
} }
fn are_pandigital(input: [&Int; 3], accum: &mut HashSet<char>, hs: &mut HashSet<char>) -> bool { fn get_suitable_factors(upper_bound: Int) -> &'static [Int] {
accum.clear(); (1..upper_bound)
.filter(|number| {
let str = number.to_string();
let set = str.chars().collect::<HashSet<_>>();
// a suitable number must not contain `0`, and must have an unique digit at every
// position
set.len() == str.len() && !set.contains(&'0')
})
.collect::<Vec<_>>()
// leaking the vec is slightly faster than handling the vec
.leak()
}
let mut length = 0; fn are_pandigital(
input: [&Int; 3],
digits_in_numbers: &mut HashSet<char>,
set_of_char_buffer: &mut HashSet<char>,
) -> bool {
digits_in_numbers.clear();
let mut length_of_all_numbers = 0;
for n in input { for n in input {
hs.clear(); set_of_char_buffer.clear();
let s = n.to_string(); let s = n.to_string();
length += s.len(); length_of_all_numbers += s.len();
s.chars().for_each(|c| { s.chars().for_each(|c| {
hs.insert(c); set_of_char_buffer.insert(c);
}); });
if s.len() != hs.len() { if s.len() != set_of_char_buffer.len() {
return false; return false;
} }
for item in hs.iter() { for item in set_of_char_buffer.iter() {
accum.insert(*item); digits_in_numbers.insert(*item);
} }
} }
accum.len() == 9 && length == 9 && !accum.contains(&'0') digits_in_numbers.len() == 9 && length_of_all_numbers == 9 && !digits_in_numbers.contains(&'0')
} }
trait Length { trait Length {
fn len(&self) -> usize; fn oom(&self) -> usize;
} }
impl Length for Int { impl Length for Int {
fn len(&self) -> usize { // order of magnitude
fn oom(&self) -> usize {
let mut tmp = 1; let mut tmp = 1;
let mut oom = 1; let mut oom = 1;
while tmp - 1 < *self { while tmp - 1 < *self {