feat(problem): 14 - longest collatz sequence

This commit is contained in:
newt 2024-10-09 18:10:10 +01:00
parent f5d308e0a9
commit 264a0c093f
16 changed files with 355 additions and 243 deletions

View file

@ -9,7 +9,7 @@ All of the solutions here are written in rust. [main.rs](src/main.rs) is the hom
## Challenge Completion ## Challenge Completion
### <!-- completed -->13<!-- completed --> out of 100 public challenges completed. ### <!-- completed -->14<!-- completed --> out of 100 public challenges completed.
- [x] 1 - [Multiples of 3 or 5](src/bin/1.rs) - [x] 1 - [Multiples of 3 or 5](src/bin/1.rs)
- [x] 2 - [Even Fibonacci numbers](src/bin/2.rs) - [x] 2 - [Even Fibonacci numbers](src/bin/2.rs)
@ -24,7 +24,7 @@ All of the solutions here are written in rust. [main.rs](src/main.rs) is the hom
- [x] 11 - [Largest product in a grid](src/bin/11.rs) - [x] 11 - [Largest product in a grid](src/bin/11.rs)
- [x] 12 - [Highly divisible triangular number](src/bin/12.rs) - [x] 12 - [Highly divisible triangular number](src/bin/12.rs)
- [x] 13 - [Large sum](src/bin/13.rs) - [x] 13 - [Large sum](src/bin/13.rs)
- [ ] 14 - Longest Collatz sequence - [x] 14 - [Longest Collatz sequence](src/bin/14.rs)
- [ ] 15 - Lattice paths - [ ] 15 - Lattice paths
- [ ] 16 - Power digit sum - [ ] 16 - Power digit sum
- [ ] 17 - Number letter counts - [ ] 17 - Number letter counts

View file

@ -8,24 +8,24 @@ Find the sum of all the multiples of 3 or 5 below 1000.
use std::collections::HashSet; use std::collections::HashSet;
fn multiples_of(multipliers: &Vec<usize>, upper_bound: usize) -> HashSet<usize> { fn multiples_of(multipliers: &Vec<usize>, upper_bound: usize) -> HashSet<usize> {
let mut results: HashSet<usize> = HashSet::new(); let mut results: HashSet<usize> = HashSet::new();
// Find all of the numbers between 1 and the upper bound that are multiples of one of the numbers // Find all of the numbers between 1 and the upper bound that are multiples of one of the numbers
// in the multipliers vec // in the multipliers vec
for i in 1..upper_bound { for i in 1..upper_bound {
for number in multipliers { for number in multipliers {
if i % number == 0 { if i % number == 0 {
results.insert(i); results.insert(i);
} }
} }
} }
return results; return results;
} }
fn main() { fn main() {
let multiples = multiples_of(&vec![3, 5], 1000); let multiples = multiples_of(&vec![3, 5], 1000);
let sum: usize = multiples.iter().sum(); let sum: usize = multiples.iter().sum();
println!("The sum of the multiples of 3 and 5 up until 1000 is {sum}"); println!("The sum of the multiples of 3 and 5 up until 1000 is {sum}");
} }

View file

@ -8,26 +8,26 @@ Find the sum of all the primes below two million.
// Implementation of the Sieve of Eratosthenes // Implementation of the Sieve of Eratosthenes
// https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes // https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
fn find_primes(upper_bound: usize) -> Vec<usize> { fn find_primes(upper_bound: usize) -> Vec<usize> {
let mut mask = vec![true; upper_bound]; let mut mask = vec![true; upper_bound];
let mut primes: Vec<usize> = vec![]; let mut primes: Vec<usize> = vec![];
mask[0] = false; mask[0] = false;
mask[1] = false; mask[1] = false;
for i in 2..upper_bound { for i in 2..upper_bound {
if mask[i] { if mask[i] {
primes.push(i); primes.push(i);
let mut j = 2 * i; let mut j = 2 * i;
while j < upper_bound { while j < upper_bound {
mask[j] = false; mask[j] = false;
j += i; j += i;
} }
} }
} }
return primes; return primes;
} }
fn sum_of_primes(upper_bound: usize) -> usize { fn sum_of_primes(upper_bound: usize) -> usize {

View file

@ -80,26 +80,66 @@ fn largest_grid_product(grid: Vec<Vec<usize>>, adjacent_digits: usize) -> usize
fn main() { fn main() {
let grid: Vec<Vec<usize>> = vec![ let grid: Vec<Vec<usize>> = vec![
vec![8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8], vec![
vec![49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 4, 56, 62, 0], 8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8,
vec![81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 3, 49, 13, 36, 65], ],
vec![52, 70, 95, 23, 4, 60, 11, 42, 69, 24, 68, 56, 1, 32, 56, 71, 37, 2, 36, 91], vec![
vec![22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80], 49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 4, 56, 62, 0,
vec![24, 47, 32, 60, 99, 3, 45, 2, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50], ],
vec![32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64, 70], vec![
vec![67, 26, 20, 68, 2, 62, 12, 20, 95, 63, 94, 39, 63, 8, 40, 91, 66, 49, 94, 21], 81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 3, 49, 13, 36, 65,
vec![24, 55, 58, 5, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63, 72], ],
vec![21, 36, 23, 9, 75, 0, 76, 44, 20, 45, 35, 14, 0, 61, 33, 97, 34, 31, 33, 95], vec![
vec![78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 3, 80, 4, 62, 16, 14, 9, 53, 56, 92], 52, 70, 95, 23, 4, 60, 11, 42, 69, 24, 68, 56, 1, 32, 56, 71, 37, 2, 36, 91,
vec![16, 39, 5, 42, 96, 35, 31, 47, 55, 58, 88, 24, 0, 17, 54, 24, 36, 29, 85, 57], ],
vec![86, 56, 0, 48, 35, 71, 89, 7, 5, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58], vec![
vec![19, 80, 81, 68, 5, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 4, 89, 55, 40], 22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80,
vec![4, 52, 8, 83, 97, 35, 99, 16, 7, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66], ],
vec![88, 36, 68, 87, 57, 62, 20, 72, 3, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53, 69], vec![
vec![4, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 8, 46, 29, 32, 40, 62, 76, 36], 24, 47, 32, 60, 99, 3, 45, 2, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50,
vec![20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 4, 36, 16], ],
vec![20, 73, 35, 29, 78, 31, 90, 1, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 5, 54], vec![
vec![1, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 1, 89, 19, 67, 48] 32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64, 70,
],
vec![
67, 26, 20, 68, 2, 62, 12, 20, 95, 63, 94, 39, 63, 8, 40, 91, 66, 49, 94, 21,
],
vec![
24, 55, 58, 5, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63, 72,
],
vec![
21, 36, 23, 9, 75, 0, 76, 44, 20, 45, 35, 14, 0, 61, 33, 97, 34, 31, 33, 95,
],
vec![
78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 3, 80, 4, 62, 16, 14, 9, 53, 56, 92,
],
vec![
16, 39, 5, 42, 96, 35, 31, 47, 55, 58, 88, 24, 0, 17, 54, 24, 36, 29, 85, 57,
],
vec![
86, 56, 0, 48, 35, 71, 89, 7, 5, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58,
],
vec![
19, 80, 81, 68, 5, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 4, 89, 55, 40,
],
vec![
4, 52, 8, 83, 97, 35, 99, 16, 7, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66,
],
vec![
88, 36, 68, 87, 57, 62, 20, 72, 3, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53, 69,
],
vec![
4, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 8, 46, 29, 32, 40, 62, 76, 36,
],
vec![
20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 4, 36, 16,
],
vec![
20, 73, 35, 29, 78, 31, 90, 1, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 5, 54,
],
vec![
1, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 1, 89, 19, 67, 48,
],
]; ];
let value = largest_grid_product(grid, 4); let value = largest_grid_product(grid, 4);

View file

@ -14,7 +14,7 @@ fn factors(number: usize) -> Vec<Vec<usize>> {
let mut factors: Vec<Vec<usize>> = vec![vec![1, number]]; let mut factors: Vec<Vec<usize>> = vec![vec![1, number]];
let is_even = number % 2 == 0; let is_even = number % 2 == 0;
for current_factor in (if is_even {2} else {3})..(max + 1) { for current_factor in (if is_even { 2 } else { 3 })..(max + 1) {
if number % current_factor != 0 { if number % current_factor != 0 {
continue; continue;
} }

View file

@ -204,7 +204,7 @@ const NUMBERS: [f64; 100] = [
77158542502016545090413245809786882778948721859617.0, 77158542502016545090413245809786882778948721859617.0,
72107838435069186155435662884062257473692284509516.0, 72107838435069186155435662884062257473692284509516.0,
20849603980134001723930671666823555245252804609722.0, 20849603980134001723930671666823555245252804609722.0,
53503534226472524250874054075591789781264330331690.0 53503534226472524250874054075591789781264330331690.0,
]; ];
fn first_n_digits(number: f64, n: usize) -> Option<usize> { fn first_n_digits(number: f64, n: usize) -> Option<usize> {
@ -214,7 +214,9 @@ fn first_n_digits(number: f64, n: usize) -> Option<usize> {
return None; return None;
} }
let new_number = String::from_iter(string_number.chars().collect::<Vec<char>>()[0..n].iter()).parse::<usize>().unwrap(); let new_number = String::from_iter(string_number.chars().collect::<Vec<char>>()[0..n].iter())
.parse::<usize>()
.unwrap();
return Some(new_number); return Some(new_number);
} }

54
src/bin/14.rs Normal file
View file

@ -0,0 +1,54 @@
/*
Problem 14 - Longest Collatz sequence
The following iterative sequence is defined for the set of positive integers:
n n /2 ( n is even) n 3 n + 1 ( n is odd)
Using the rule above and starting with 13, we generate the following sequence:
13 40 20 10 5 16 8 4 2 1
It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.
Which starting number, under one million, produces the longest chain?
NOTE: Once the chain starts the terms are allowed to go above one million.
*/
use std::collections::HashMap;
fn f(n: usize) -> usize {
if n % 2 == 0 {
return n / 2;
} else {
return ((3 * n) + 1) / 2;
}
}
fn longest_collatz_sequence(greatest_start: usize) -> usize {
let mut sequence_lengths: HashMap<usize, usize> = HashMap::new();
for i in 1..(greatest_start + 1) {
let mut sequence_length: usize = 0;
let mut current_number = i;
while current_number > 1 {
current_number = f(current_number);
// Eventually the sequence will break down into one we have already computed the length for!
if sequence_lengths.contains_key(&current_number) {
sequence_length += *sequence_lengths.get(&current_number).unwrap();
break;
}
sequence_length += 1;
}
sequence_lengths.insert(i, sequence_length);
}
return *sequence_lengths.iter().max_by_key(|x| x.1).unwrap().0;
}
fn main() {
let starting_number = longest_collatz_sequence(1_000_000);
println!(
"The starting number which produces the longest collatz sequence is {starting_number}"
);
}

View file

@ -7,22 +7,25 @@ By considering the terms in the Fibonacci sequence whose values do not exceed fo
*/ */
fn fibonacci(upper_bound: usize) -> Vec<usize> { fn fibonacci(upper_bound: usize) -> Vec<usize> {
// F_0 = 1, F_1 = 2 // F_0 = 1, F_1 = 2
let mut sequence = vec![1, 2]; let mut sequence = vec![1, 2];
// F_n = F_(n - 1) + F_(n - 2) // F_n = F_(n - 1) + F_(n - 2)
while sequence[sequence.len() - 1] < upper_bound { while sequence[sequence.len() - 1] < upper_bound {
let new_value = sequence[sequence.len() - 1] + sequence[sequence.len() - 2]; let new_value = sequence[sequence.len() - 1] + sequence[sequence.len() - 2];
sequence.push(new_value); sequence.push(new_value);
} }
return sequence; return sequence;
} }
fn main() { fn main() {
let sequence = fibonacci(4000000); let sequence = fibonacci(4000000);
let even = sequence.iter().filter(|n| *n % 2 == 0); let even = sequence.iter().filter(|n| *n % 2 == 0);
let sum: usize = even.sum(); let sum: usize = even.sum();
print!("The sum of the first 4000000 even fibonacci numbers is {}", sum); print!(
"The sum of the first 4000000 even fibonacci numbers is {}",
sum
);
} }

View file

@ -6,30 +6,30 @@ What is the largest prime factor of the number 600851475143 ?
*/ */
fn largest_prime_factor(number: usize) -> usize { fn largest_prime_factor(number: usize) -> usize {
// All even numbers can be divided by 2 // All even numbers can be divided by 2
if number % 2 == 0 { if number % 2 == 0 {
return 2; return 2;
} }
let mut i = 3; let mut i = 3;
let mut num = number.clone(); let mut num = number.clone();
let mut primes: Vec<usize> = vec![]; let mut primes: Vec<usize> = vec![];
while num != 1 { while num != 1 {
if num % i == 0 { if num % i == 0 {
num /= i; num /= i;
primes.push(i); primes.push(i);
} else { } else {
// Test next odd number // Test next odd number
i += 2; i += 2;
} }
} }
// The largest prime factor will be at the end of the vec // The largest prime factor will be at the end of the vec
return primes[primes.len() - 1]; return primes[primes.len() - 1];
} }
fn main() { fn main() {
let factor = largest_prime_factor(600851475143); let factor = largest_prime_factor(600851475143);
println!("The largest prime factor of 600851475143 is {factor}"); println!("The largest prime factor of 600851475143 is {factor}");
} }

View file

@ -6,29 +6,29 @@ Find the largest palindrome made from the product of two 3-digit numbers.
*/ */
fn largest_pallindromic_number(lower_bound: usize, upper_bound: usize) -> usize { fn largest_pallindromic_number(lower_bound: usize, upper_bound: usize) -> usize {
let mut products: Vec<usize> = vec![]; let mut products: Vec<usize> = vec![];
for i in lower_bound..(upper_bound + 1) { for i in lower_bound..(upper_bound + 1) {
for j in lower_bound..(upper_bound + 1) { for j in lower_bound..(upper_bound + 1) {
products.push(i * j); products.push(i * j);
} }
} }
// Filter for pallindromic numbers // Filter for pallindromic numbers
let mut pallindromic = products let mut pallindromic = products
.iter() .iter()
.filter(|x| x.to_string() == x.to_string().chars().rev().collect::<String>()) .filter(|x| x.to_string() == x.to_string().chars().rev().collect::<String>())
.collect::<Vec<&usize>>(); .collect::<Vec<&usize>>();
// Return the largest value // Return the largest value
pallindromic.sort(); pallindromic.sort();
pallindromic.reverse(); pallindromic.reverse();
return *pallindromic[0]; return *pallindromic[0];
} }
fn main() { fn main() {
let number = largest_pallindromic_number(100, 999); let number = largest_pallindromic_number(100, 999);
println!("The largest pallindromic number made from the product of two three-digit numbers is {number}"); println!("The largest pallindromic number made from the product of two three-digit numbers is {number}");
} }

View file

@ -7,46 +7,46 @@ What is the smallest positive number that is evenly divisible by all of the nu
// Euclidean algorithm for finding GCD // Euclidean algorithm for finding GCD
fn gcd(a: usize, b: usize) -> usize { fn gcd(a: usize, b: usize) -> usize {
let mut x = a; let mut x = a;
let mut y = b; let mut y = b;
let mut r: usize = 1; // temporary initial value let mut r: usize = 1; // temporary initial value
while r != 0 { while r != 0 {
if x < y { if x < y {
let temp = x; let temp = x;
x = y; x = y;
y = temp; y = temp;
} }
r = x % y; r = x % y;
if r == 0 { if r == 0 {
break; break;
} else { } else {
x = y; x = y;
y = r; y = r;
} }
} }
return y; return y;
} }
fn first_value_divisible_by(start: usize, end: usize) -> Option<usize> { fn first_value_divisible_by(start: usize, end: usize) -> Option<usize> {
if start > end { if start > end {
return None; return None;
} }
let mut result: usize = 1; let mut result: usize = 1;
for i in start..(end + 1) { for i in start..(end + 1) {
result = (result * i) / gcd(result, i); result = (result * i) / gcd(result, i);
} }
return Some(result); return Some(result);
} }
fn main() { fn main() {
let number = first_value_divisible_by(1, 20).unwrap(); let number = first_value_divisible_by(1, 20).unwrap();
println!("The smallest number that is divisible by all integers between 1 and 20 is {number}"); println!("The smallest number that is divisible by all integers between 1 and 20 is {number}");
} }

View file

@ -13,31 +13,31 @@ const LOWER_BOUND: usize = 1;
const UPPER_BOUND: usize = 100; const UPPER_BOUND: usize = 100;
fn sum_of_squares(lower_bound: usize, upper_bound: usize) -> Option<usize> { fn sum_of_squares(lower_bound: usize, upper_bound: usize) -> Option<usize> {
if lower_bound > upper_bound { if lower_bound > upper_bound {
return None; return None;
} }
let mut squares: Vec<usize> = vec![]; let mut squares: Vec<usize> = vec![];
for i in lower_bound..(upper_bound + 1) { for i in lower_bound..(upper_bound + 1) {
squares.push(i.pow(2)); squares.push(i.pow(2));
} }
return Some(squares.iter().sum()); return Some(squares.iter().sum());
} }
fn square_of_sum(lower_bound: usize, upper_bound: usize) -> Option<usize> { fn square_of_sum(lower_bound: usize, upper_bound: usize) -> Option<usize> {
if lower_bound > upper_bound { if lower_bound > upper_bound {
return None; return None;
} }
return Some(((lower_bound..(upper_bound + 1)).sum::<usize>()).pow(2)); return Some(((lower_bound..(upper_bound + 1)).sum::<usize>()).pow(2));
} }
fn main() { fn main() {
let squared_sum = square_of_sum(LOWER_BOUND, UPPER_BOUND).unwrap(); let squared_sum = square_of_sum(LOWER_BOUND, UPPER_BOUND).unwrap();
let summed_squares = sum_of_squares(LOWER_BOUND, UPPER_BOUND).unwrap(); let summed_squares = sum_of_squares(LOWER_BOUND, UPPER_BOUND).unwrap();
let difference = squared_sum - summed_squares; let difference = squared_sum - summed_squares;
println!("For the numbers between {LOWER_BOUND} and {UPPER_BOUND}, the difference between the square of the sum and the sum of the squares is {difference}"); println!("For the numbers between {LOWER_BOUND} and {UPPER_BOUND}, the difference between the square of the sum and the sum of the squares is {difference}");
} }

View file

@ -10,52 +10,52 @@ use std::f64::consts::E;
// Implementation of the Sieve of Eratosthenes // Implementation of the Sieve of Eratosthenes
// https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes // https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
fn find_primes(upper_bound: usize) -> Vec<usize> { fn find_primes(upper_bound: usize) -> Vec<usize> {
let mut mask = vec![true; upper_bound]; let mut mask = vec![true; upper_bound];
let mut primes: Vec<usize> = vec![]; let mut primes: Vec<usize> = vec![];
mask[0] = false; mask[0] = false;
mask[1] = false; mask[1] = false;
for i in 2..upper_bound { for i in 2..upper_bound {
if mask[i] { if mask[i] {
primes.push(i); primes.push(i);
let mut j = 2 * i; let mut j = 2 * i;
while j < upper_bound { while j < upper_bound {
mask[j] = false; mask[j] = false;
j += i; j += i;
} }
} }
} }
return primes; return primes;
} }
// Bounds for nth prime: http://en.wikipedia.org/wiki/Prime_number_theorem // Bounds for nth prime: http://en.wikipedia.org/wiki/Prime_number_theorem
// ln n + ln(ln n) - 1 < p_n / n < ln n + ln(ln n), n >= 6 // ln n + ln(ln n) - 1 < p_n / n < ln n + ln(ln n), n >= 6
fn upper_bound_for_nth_prime(n: usize) -> usize { fn upper_bound_for_nth_prime(n: usize) -> usize {
// The first 5 primes are under 13 (6th prime) // The first 5 primes are under 13 (6th prime)
if n < 6 { if n < 6 {
return 13; return 13;
} }
let ln_n = (n as f64).log(E); let ln_n = (n as f64).log(E);
return n * (ln_n + ln_n.log(E)).ceil() as usize; return n * (ln_n + ln_n.log(E)).ceil() as usize;
} }
fn nth_prime(n: usize) -> Option<usize> { fn nth_prime(n: usize) -> Option<usize> {
if n < 1 { if n < 1 {
return None; return None;
} }
let primes = find_primes(upper_bound_for_nth_prime(n)); let primes = find_primes(upper_bound_for_nth_prime(n));
return Some(primes[n - 1]); return Some(primes[n - 1]);
} }
fn main() { fn main() {
let number = nth_prime(10001).unwrap(); let number = nth_prime(10001).unwrap();
println!("The 10,001st prime number is {number}"); println!("The 10,001st prime number is {number}");
} }

View file

@ -30,49 +30,49 @@ const NUMBER: &str = "7316717653133062491922511967442657474235534919493496983520
const ADJACENT_DIGITS: usize = 13; const ADJACENT_DIGITS: usize = 13;
fn largest_product(number: &str, adjacent_digits: usize) -> Option<usize> { fn largest_product(number: &str, adjacent_digits: usize) -> Option<usize> {
if adjacent_digits > number.len() { if adjacent_digits > number.len() {
return None; return None;
} }
let mut cursor_index = 0; let mut cursor_index = 0;
let mut selections: Vec<Vec<u32>> = vec![]; let mut selections: Vec<Vec<u32>> = vec![];
let characters = number.chars().collect::<Vec<char>>(); let characters = number.chars().collect::<Vec<char>>();
while cursor_index < number.len() { while cursor_index < number.len() {
let mut selection: Vec<u32> = vec![]; let mut selection: Vec<u32> = vec![];
for i in 0..adjacent_digits { for i in 0..adjacent_digits {
if cursor_index + i >= number.len() - 1 { if cursor_index + i >= number.len() - 1 {
break; break;
} }
selection.push(characters[cursor_index + i].to_digit(10).unwrap()); selection.push(characters[cursor_index + i].to_digit(10).unwrap());
} }
selections.push(selection); selections.push(selection);
cursor_index += 1; cursor_index += 1;
} }
let mut products: Vec<usize> = vec![]; let mut products: Vec<usize> = vec![];
for i in 0..selections.len() { for i in 0..selections.len() {
let mut product: usize = 1; let mut product: usize = 1;
for value in &selections[i] { for value in &selections[i] {
product *= *value as usize; product *= *value as usize;
} }
products.push(product); products.push(product);
} }
products.sort(); products.sort();
products.reverse(); products.reverse();
return Some(products[0]); return Some(products[0]);
} }
fn main() { fn main() {
let value = largest_product(NUMBER, ADJACENT_DIGITS).unwrap(); let value = largest_product(NUMBER, ADJACENT_DIGITS).unwrap();
println!("The thirteen adjacent digits in the number that have the greatest product have a product of {value}"); println!("The thirteen adjacent digits in the number that have the greatest product have a product of {value}");
} }

View file

@ -24,7 +24,7 @@ There exists exactly one Pythagorean triplet for which a + b + c = 1000. F
fn triplet_with_sum(sum: isize) -> Option<(isize, isize, isize)> { fn triplet_with_sum(sum: isize) -> Option<(isize, isize, isize)> {
for a in 1..(sum + 1) { for a in 1..(sum + 1) {
let b: isize = ((2 * a * sum) - sum.pow(2)) / (2 * (a - sum)); let b: isize = ((2 * a * sum) - sum.pow(2)) / (2 * (a - sum));
let c: isize = sum - a - b; let c: isize = sum - a - b;
if a.pow(2) + b.pow(2) == c.pow(2) { if a.pow(2) + b.pow(2) == c.pow(2) {
return Some((a, b, c)); return Some((a, b, c));

View file

@ -1,15 +1,19 @@
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use owo_colors::OwoColorize; use owo_colors::OwoColorize;
use std::{fs::{self, File, OpenOptions}, path::Path, io::{Write, BufRead}};
use scraper::{Html, Selector};
use regex::Regex; use regex::Regex;
use std::io::{BufReader}; use scraper::{Html, Selector};
use std::io::BufReader;
use std::{
fs::{self, File, OpenOptions},
io::{BufRead, Write},
path::Path,
};
#[derive(Parser)] #[derive(Parser)]
#[clap(about, author, version)] #[clap(about, author, version)]
struct Value { struct Value {
#[clap(subcommand)] #[clap(subcommand)]
command: Commands command: Commands,
} }
#[derive(Subcommand)] #[derive(Subcommand)]
@ -55,13 +59,19 @@ async fn new() -> Result<(), Box<dyn std::error::Error>> {
Err("Please ensure that your input is valid!".to_owned()) Err("Please ensure that your input is valid!".to_owned())
} }
}) })
.build() .build(),
).unwrap().as_int().unwrap(); )
.unwrap()
.as_int()
.unwrap();
// todo: thoughts documents (?) // todo: thoughts documents (?)
// Fetch the problem information // Fetch the problem information
let body = reqwest::get(format!("https://projecteuler.net/problem={problem_number}")).await?.text().await?; let body = reqwest::get(format!("https://projecteuler.net/problem={problem_number}"))
.await?
.text()
.await?;
let document = Html::parse_document(body.as_str()); let document = Html::parse_document(body.as_str());
let title_selector = Selector::parse("h2")?; let title_selector = Selector::parse("h2")?;
@ -79,12 +89,12 @@ async fn new() -> Result<(), Box<dyn std::error::Error>> {
let mut problem = html_tag_regex let mut problem = html_tag_regex
.replace_all( .replace_all(
document document
.select(&content_selector) .select(&content_selector)
.next() .next()
.unwrap() .unwrap()
.inner_html() .inner_html()
.as_str(), .as_str(),
" " " ",
) )
.to_string() .to_string()
.replace("$$", " "); .replace("$$", " ");
@ -117,17 +127,13 @@ fn main() {{
// Read the contents of the readme for editing // Read the contents of the readme for editing
let readme_path = base_dir.join("readme.md"); let readme_path = base_dir.join("readme.md");
let mut readme_file = OpenOptions::new() let mut readme_file = OpenOptions::new().read(true).open(&readme_path).unwrap();
.read(true)
.open(&readme_path)
.unwrap();
let mut readme_content = BufReader::new(&readme_file) let mut readme_content = BufReader::new(&readme_file)
.lines() .lines()
.map(|s| s.unwrap()) .map(|s| s.unwrap())
.collect::<Vec<String>>(); .collect::<Vec<String>>();
drop(readme_file); drop(readme_file);
// Mark the problem as done on the readme // Mark the problem as done on the readme
@ -138,7 +144,10 @@ fn main() {{
if readme_regex.is_match(line) { if readme_regex.is_match(line) {
let matched = readme_regex.captures(line).unwrap(); let matched = readme_regex.captures(line).unwrap();
readme_content[i] = format!("- [x] {problem_number} - [{}](src/bin/{problem_number}.rs)", &matched[1].trim()); readme_content[i] = format!(
"- [x] {problem_number} - [{}](src/bin/{problem_number}.rs)",
&matched[1].trim()
);
} }
} }
@ -147,26 +156,30 @@ fn main() {{
let completed_regex = Regex::new("<!-- completed -->([0-9]+)<!-- completed -->").unwrap(); let completed_regex = Regex::new("<!-- completed -->([0-9]+)<!-- completed -->").unwrap();
let new_completed = completed_regex let new_completed = completed_regex.captures(readme_string.as_str()).unwrap()[1]
.captures(readme_string.as_str())
.unwrap()[1]
.parse::<u8>() .parse::<u8>()
.unwrap() + 1; .unwrap()
+ 1;
readme_string = completed_regex.replace(readme_string.as_str(), format!("<!-- completed -->{new_completed}<!-- completed -->")).to_string(); readme_string = completed_regex
.replace(
readme_string.as_str(),
format!("<!-- completed -->{new_completed}<!-- completed -->"),
)
.to_string();
// Write the new content to the readme // Write the new content to the readme
readme_file = OpenOptions::new() readme_file = OpenOptions::new().write(true).open(&readme_path).unwrap();
.write(true)
.open(&readme_path)
.unwrap();
readme_file.write(readme_string.as_bytes()).unwrap(); readme_file.write(readme_string.as_bytes()).unwrap();
drop(readme_file); drop(readme_file);
// Announce completion! // Announce completion!
println!("{}", "File successfully created! Good luck (:".green().bold()); println!(
"{}",
"File successfully created! Good luck (:".green().bold()
);
Ok(()) Ok(())
} }
@ -175,6 +188,6 @@ fn main() {
let value = Value::parse(); let value = Value::parse();
match value.command { match value.command {
Commands::New => new().unwrap() Commands::New => new().unwrap(),
} }
} }