diff --git a/src/euler32/Cargo.toml b/src/euler32/Cargo.toml index 6fdb9c9..b68a3b5 100644 --- a/src/euler32/Cargo.toml +++ b/src/euler32/Cargo.toml @@ -6,3 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] + +[profile.release] +debug = true +lto = true diff --git a/src/euler32/src/main.rs b/src/euler32/src/main.rs index 41c1e6a..fa04099 100644 --- a/src/euler32/src/main.rs +++ b/src/euler32/src/main.rs @@ -1,42 +1,80 @@ use std::collections::HashSet; -type Int = u64; +type Int = u32; + +const UPPER_BOUND: Int = 3_333; // because result must be a 4-digit number fn main() { - let f: Vec<_> = (1..10_000_u64) + let mut buffer1 = HashSet::new(); + let mut buffer2 = HashSet::new(); + + let f = (1..UPPER_BOUND) .filter(|n| { let s = n.to_string(); let hs = s.chars().collect::>(); hs.len() == s.len() && !hs.contains(&'0') }) - .collect(); + .collect::>() + .leak(); let mut result = HashSet::new(); - for f1 in &f { - for f2 in f.iter().rev() { + for f1 in f.iter() { + let lower_bound = UPPER_BOUND / f1; + + 'inner: for f2 in f.iter().skip_while(|i| **i < lower_bound) { let p = f1 * f2; - if are_pandigital([f1, f2, &p]) { + if f1.len() + f2.len() + p.len() > 9 { + break 'inner; + } + + if are_pandigital([f1, f2, &p], &mut buffer1, &mut buffer2) { println!("{f1} {f2} {p}"); result.insert(p); } } } - println!("{}", result.iter().sum::()); + println!("{}", result.iter().sum::()); } -fn are_pandigital(input: [∬ 3]) -> bool { - let mut accum = HashSet::new(); +fn are_pandigital(input: [∬ 3], accum: &mut HashSet, hs: &mut HashSet) -> bool { + accum.clear(); + let mut length = 0; + for n in input { + hs.clear(); + let s = n.to_string(); length += s.len(); - let hs = s.chars().collect::>(); + + s.chars().for_each(|c| { + hs.insert(c); + }); + if s.len() != hs.len() { return false; } - for item in hs { - accum.insert(item); + + for item in hs.iter() { + accum.insert(*item); } } + accum.len() == 9 && length == 9 && !accum.contains(&'0') } + +trait Length { + fn len(&self) -> usize; +} + +impl Length for Int { + fn len(&self) -> usize { + let mut tmp = 1; + let mut oom = 1; + while tmp - 1 < *self { + oom += 1; + tmp *= 10; + } + oom - 1 + } +}