feat(problem): 14 - longest collatz sequence
This commit is contained in:
parent
f5d308e0a9
commit
264a0c093f
16 changed files with 355 additions and 243 deletions
|
@ -9,7 +9,7 @@ All of the solutions here are written in rust. [main.rs](src/main.rs) is the hom
|
|||
|
||||
## 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] 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] 12 - [Highly divisible triangular number](src/bin/12.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
|
||||
- [ ] 16 - Power digit sum
|
||||
- [ ] 17 - Number letter counts
|
||||
|
|
28
src/bin/1.rs
28
src/bin/1.rs
|
@ -8,24 +8,24 @@ Find the sum of all the multiples of 3 or 5 below 1000.
|
|||
use std::collections::HashSet;
|
||||
|
||||
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
|
||||
// in the multipliers vec
|
||||
for i in 1..upper_bound {
|
||||
for number in multipliers {
|
||||
if i % number == 0 {
|
||||
results.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Find all of the numbers between 1 and the upper bound that are multiples of one of the numbers
|
||||
// in the multipliers vec
|
||||
for i in 1..upper_bound {
|
||||
for number in multipliers {
|
||||
if i % number == 0 {
|
||||
results.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
return results;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let multiples = multiples_of(&vec![3, 5], 1000);
|
||||
let sum: usize = multiples.iter().sum();
|
||||
let multiples = multiples_of(&vec![3, 5], 1000);
|
||||
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}");
|
||||
}
|
||||
|
|
|
@ -8,26 +8,26 @@ Find the sum of all the primes below two million.
|
|||
// Implementation of the Sieve of Eratosthenes
|
||||
// https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
|
||||
fn find_primes(upper_bound: usize) -> Vec<usize> {
|
||||
let mut mask = vec![true; upper_bound];
|
||||
let mut primes: Vec<usize> = vec![];
|
||||
let mut mask = vec![true; upper_bound];
|
||||
let mut primes: Vec<usize> = vec![];
|
||||
|
||||
mask[0] = false;
|
||||
mask[1] = false;
|
||||
mask[0] = false;
|
||||
mask[1] = false;
|
||||
|
||||
for i in 2..upper_bound {
|
||||
if mask[i] {
|
||||
primes.push(i);
|
||||
for i in 2..upper_bound {
|
||||
if mask[i] {
|
||||
primes.push(i);
|
||||
|
||||
let mut j = 2 * i;
|
||||
let mut j = 2 * i;
|
||||
|
||||
while j < upper_bound {
|
||||
mask[j] = false;
|
||||
j += i;
|
||||
}
|
||||
}
|
||||
}
|
||||
while j < upper_bound {
|
||||
mask[j] = false;
|
||||
j += i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return primes;
|
||||
return primes;
|
||||
}
|
||||
|
||||
fn sum_of_primes(upper_bound: usize) -> usize {
|
||||
|
|
|
@ -80,26 +80,66 @@ fn largest_grid_product(grid: Vec<Vec<usize>>, adjacent_digits: usize) -> usize
|
|||
|
||||
fn main() {
|
||||
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![49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 4, 56, 62, 0],
|
||||
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![22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80],
|
||||
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![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]
|
||||
vec![
|
||||
8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8,
|
||||
],
|
||||
vec![
|
||||
49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 4, 56, 62, 0,
|
||||
],
|
||||
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![
|
||||
22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80,
|
||||
],
|
||||
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![
|
||||
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);
|
||||
|
|
|
@ -14,7 +14,7 @@ fn factors(number: usize) -> Vec<Vec<usize>> {
|
|||
let mut factors: Vec<Vec<usize>> = vec![vec![1, number]];
|
||||
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 {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -204,7 +204,7 @@ const NUMBERS: [f64; 100] = [
|
|||
77158542502016545090413245809786882778948721859617.0,
|
||||
72107838435069186155435662884062257473692284509516.0,
|
||||
20849603980134001723930671666823555245252804609722.0,
|
||||
53503534226472524250874054075591789781264330331690.0
|
||||
53503534226472524250874054075591789781264330331690.0,
|
||||
];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
54
src/bin/14.rs
Normal file
54
src/bin/14.rs
Normal 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(¤t_number) {
|
||||
sequence_length += *sequence_lengths.get(¤t_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}"
|
||||
);
|
||||
}
|
27
src/bin/2.rs
27
src/bin/2.rs
|
@ -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> {
|
||||
// F_0 = 1, F_1 = 2
|
||||
let mut sequence = vec![1, 2];
|
||||
// F_0 = 1, F_1 = 2
|
||||
let mut sequence = vec![1, 2];
|
||||
|
||||
// F_n = F_(n - 1) + F_(n - 2)
|
||||
while sequence[sequence.len() - 1] < upper_bound {
|
||||
let new_value = sequence[sequence.len() - 1] + sequence[sequence.len() - 2];
|
||||
sequence.push(new_value);
|
||||
}
|
||||
// F_n = F_(n - 1) + F_(n - 2)
|
||||
while sequence[sequence.len() - 1] < upper_bound {
|
||||
let new_value = sequence[sequence.len() - 1] + sequence[sequence.len() - 2];
|
||||
sequence.push(new_value);
|
||||
}
|
||||
|
||||
return sequence;
|
||||
return sequence;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let sequence = fibonacci(4000000);
|
||||
let even = sequence.iter().filter(|n| *n % 2 == 0);
|
||||
let sum: usize = even.sum();
|
||||
let sequence = fibonacci(4000000);
|
||||
let even = sequence.iter().filter(|n| *n % 2 == 0);
|
||||
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
|
||||
);
|
||||
}
|
||||
|
|
40
src/bin/3.rs
40
src/bin/3.rs
|
@ -6,30 +6,30 @@ What is the largest prime factor of the number 600851475143 ?
|
|||
*/
|
||||
|
||||
fn largest_prime_factor(number: usize) -> usize {
|
||||
// All even numbers can be divided by 2
|
||||
if number % 2 == 0 {
|
||||
return 2;
|
||||
}
|
||||
// All even numbers can be divided by 2
|
||||
if number % 2 == 0 {
|
||||
return 2;
|
||||
}
|
||||
|
||||
let mut i = 3;
|
||||
let mut num = number.clone();
|
||||
let mut primes: Vec<usize> = vec![];
|
||||
let mut i = 3;
|
||||
let mut num = number.clone();
|
||||
let mut primes: Vec<usize> = vec![];
|
||||
|
||||
while num != 1 {
|
||||
if num % i == 0 {
|
||||
num /= i;
|
||||
primes.push(i);
|
||||
} else {
|
||||
// Test next odd number
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
while num != 1 {
|
||||
if num % i == 0 {
|
||||
num /= i;
|
||||
primes.push(i);
|
||||
} else {
|
||||
// Test next odd number
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
// The largest prime factor will be at the end of the vec
|
||||
return primes[primes.len() - 1];
|
||||
// The largest prime factor will be at the end of the vec
|
||||
return primes[primes.len() - 1];
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let factor = largest_prime_factor(600851475143);
|
||||
println!("The largest prime factor of 600851475143 is {factor}");
|
||||
let factor = largest_prime_factor(600851475143);
|
||||
println!("The largest prime factor of 600851475143 is {factor}");
|
||||
}
|
||||
|
|
38
src/bin/4.rs
38
src/bin/4.rs
|
@ -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 {
|
||||
let mut products: Vec<usize> = vec![];
|
||||
|
||||
for i in lower_bound..(upper_bound + 1) {
|
||||
for j in lower_bound..(upper_bound + 1) {
|
||||
products.push(i * j);
|
||||
}
|
||||
}
|
||||
let mut products: Vec<usize> = vec![];
|
||||
|
||||
// Filter for pallindromic numbers
|
||||
let mut pallindromic = products
|
||||
.iter()
|
||||
.filter(|x| x.to_string() == x.to_string().chars().rev().collect::<String>())
|
||||
.collect::<Vec<&usize>>();
|
||||
for i in lower_bound..(upper_bound + 1) {
|
||||
for j in lower_bound..(upper_bound + 1) {
|
||||
products.push(i * j);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the largest value
|
||||
pallindromic.sort();
|
||||
pallindromic.reverse();
|
||||
// Filter for pallindromic numbers
|
||||
let mut pallindromic = products
|
||||
.iter()
|
||||
.filter(|x| x.to_string() == x.to_string().chars().rev().collect::<String>())
|
||||
.collect::<Vec<&usize>>();
|
||||
|
||||
return *pallindromic[0];
|
||||
// Return the largest value
|
||||
pallindromic.sort();
|
||||
pallindromic.reverse();
|
||||
|
||||
return *pallindromic[0];
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let number = largest_pallindromic_number(100, 999);
|
||||
|
||||
println!("The largest pallindromic number made from the product of two three-digit numbers is {number}");
|
||||
let number = largest_pallindromic_number(100, 999);
|
||||
|
||||
println!("The largest pallindromic number made from the product of two three-digit numbers is {number}");
|
||||
}
|
||||
|
|
58
src/bin/5.rs
58
src/bin/5.rs
|
@ -7,46 +7,46 @@ What is the smallest positive number that is evenly divisible by all of the nu
|
|||
|
||||
// Euclidean algorithm for finding GCD
|
||||
fn gcd(a: usize, b: usize) -> usize {
|
||||
let mut x = a;
|
||||
let mut y = b;
|
||||
let mut r: usize = 1; // temporary initial value
|
||||
let mut x = a;
|
||||
let mut y = b;
|
||||
let mut r: usize = 1; // temporary initial value
|
||||
|
||||
while r != 0 {
|
||||
if x < y {
|
||||
let temp = x;
|
||||
x = y;
|
||||
y = temp;
|
||||
}
|
||||
while r != 0 {
|
||||
if x < y {
|
||||
let temp = x;
|
||||
x = y;
|
||||
y = temp;
|
||||
}
|
||||
|
||||
r = x % y;
|
||||
r = x % y;
|
||||
|
||||
if r == 0 {
|
||||
break;
|
||||
} else {
|
||||
x = y;
|
||||
y = r;
|
||||
}
|
||||
}
|
||||
if r == 0 {
|
||||
break;
|
||||
} else {
|
||||
x = y;
|
||||
y = r;
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
return y;
|
||||
}
|
||||
|
||||
fn first_value_divisible_by(start: usize, end: usize) -> Option<usize> {
|
||||
if start > end {
|
||||
return None;
|
||||
}
|
||||
fn first_value_divisible_by(start: usize, end: usize) -> Option<usize> {
|
||||
if start > end {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut result: usize = 1;
|
||||
let mut result: usize = 1;
|
||||
|
||||
for i in start..(end + 1) {
|
||||
result = (result * i) / gcd(result, i);
|
||||
}
|
||||
for i in start..(end + 1) {
|
||||
result = (result * i) / gcd(result, i);
|
||||
}
|
||||
|
||||
return Some(result);
|
||||
return Some(result);
|
||||
}
|
||||
|
||||
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}");
|
||||
}
|
||||
|
|
32
src/bin/6.rs
32
src/bin/6.rs
|
@ -13,31 +13,31 @@ const LOWER_BOUND: usize = 1;
|
|||
const UPPER_BOUND: usize = 100;
|
||||
|
||||
fn sum_of_squares(lower_bound: usize, upper_bound: usize) -> Option<usize> {
|
||||
if lower_bound > upper_bound {
|
||||
return None;
|
||||
}
|
||||
if lower_bound > upper_bound {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut squares: Vec<usize> = vec![];
|
||||
let mut squares: Vec<usize> = vec![];
|
||||
|
||||
for i in lower_bound..(upper_bound + 1) {
|
||||
squares.push(i.pow(2));
|
||||
}
|
||||
for i in lower_bound..(upper_bound + 1) {
|
||||
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> {
|
||||
if lower_bound > upper_bound {
|
||||
return None;
|
||||
}
|
||||
if lower_bound > upper_bound {
|
||||
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() {
|
||||
let squared_sum = square_of_sum(LOWER_BOUND, UPPER_BOUND).unwrap();
|
||||
let summed_squares = sum_of_squares(LOWER_BOUND, UPPER_BOUND).unwrap();
|
||||
let difference = squared_sum - summed_squares;
|
||||
let squared_sum = square_of_sum(LOWER_BOUND, UPPER_BOUND).unwrap();
|
||||
let summed_squares = sum_of_squares(LOWER_BOUND, UPPER_BOUND).unwrap();
|
||||
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}");
|
||||
}
|
||||
|
|
56
src/bin/7.rs
56
src/bin/7.rs
|
@ -10,52 +10,52 @@ use std::f64::consts::E;
|
|||
// Implementation of the Sieve of Eratosthenes
|
||||
// https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
|
||||
fn find_primes(upper_bound: usize) -> Vec<usize> {
|
||||
let mut mask = vec![true; upper_bound];
|
||||
let mut primes: Vec<usize> = vec![];
|
||||
let mut mask = vec![true; upper_bound];
|
||||
let mut primes: Vec<usize> = vec![];
|
||||
|
||||
mask[0] = false;
|
||||
mask[1] = false;
|
||||
mask[0] = false;
|
||||
mask[1] = false;
|
||||
|
||||
for i in 2..upper_bound {
|
||||
if mask[i] {
|
||||
primes.push(i);
|
||||
for i in 2..upper_bound {
|
||||
if mask[i] {
|
||||
primes.push(i);
|
||||
|
||||
let mut j = 2 * i;
|
||||
let mut j = 2 * i;
|
||||
|
||||
while j < upper_bound {
|
||||
mask[j] = false;
|
||||
j += i;
|
||||
}
|
||||
}
|
||||
}
|
||||
while j < upper_bound {
|
||||
mask[j] = false;
|
||||
j += i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return primes;
|
||||
return primes;
|
||||
}
|
||||
|
||||
// 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
|
||||
fn upper_bound_for_nth_prime(n: usize) -> usize {
|
||||
// The first 5 primes are under 13 (6th prime)
|
||||
if n < 6 {
|
||||
return 13;
|
||||
}
|
||||
// The first 5 primes are under 13 (6th prime)
|
||||
if n < 6 {
|
||||
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> {
|
||||
if n < 1 {
|
||||
return None;
|
||||
}
|
||||
if n < 1 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let primes = find_primes(upper_bound_for_nth_prime(n));
|
||||
return Some(primes[n - 1]);
|
||||
let primes = find_primes(upper_bound_for_nth_prime(n));
|
||||
return Some(primes[n - 1]);
|
||||
}
|
||||
|
||||
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}");
|
||||
}
|
||||
|
|
62
src/bin/8.rs
62
src/bin/8.rs
|
@ -30,49 +30,49 @@ const NUMBER: &str = "7316717653133062491922511967442657474235534919493496983520
|
|||
const ADJACENT_DIGITS: usize = 13;
|
||||
|
||||
fn largest_product(number: &str, adjacent_digits: usize) -> Option<usize> {
|
||||
if adjacent_digits > number.len() {
|
||||
return None;
|
||||
}
|
||||
if adjacent_digits > number.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut cursor_index = 0;
|
||||
let mut selections: Vec<Vec<u32>> = vec![];
|
||||
let characters = number.chars().collect::<Vec<char>>();
|
||||
let mut cursor_index = 0;
|
||||
let mut selections: Vec<Vec<u32>> = vec![];
|
||||
let characters = number.chars().collect::<Vec<char>>();
|
||||
|
||||
while cursor_index < number.len() {
|
||||
let mut selection: Vec<u32> = vec![];
|
||||
while cursor_index < number.len() {
|
||||
let mut selection: Vec<u32> = vec![];
|
||||
|
||||
for i in 0..adjacent_digits {
|
||||
if cursor_index + i >= number.len() - 1 {
|
||||
break;
|
||||
}
|
||||
for i in 0..adjacent_digits {
|
||||
if cursor_index + i >= number.len() - 1 {
|
||||
break;
|
||||
}
|
||||
|
||||
selection.push(characters[cursor_index + i].to_digit(10).unwrap());
|
||||
}
|
||||
selection.push(characters[cursor_index + i].to_digit(10).unwrap());
|
||||
}
|
||||
|
||||
selections.push(selection);
|
||||
cursor_index += 1;
|
||||
}
|
||||
selections.push(selection);
|
||||
cursor_index += 1;
|
||||
}
|
||||
|
||||
let mut products: Vec<usize> = vec![];
|
||||
let mut products: Vec<usize> = vec![];
|
||||
|
||||
for i in 0..selections.len() {
|
||||
let mut product: usize = 1;
|
||||
for i in 0..selections.len() {
|
||||
let mut product: usize = 1;
|
||||
|
||||
for value in &selections[i] {
|
||||
product *= *value as usize;
|
||||
}
|
||||
for value in &selections[i] {
|
||||
product *= *value as usize;
|
||||
}
|
||||
|
||||
products.push(product);
|
||||
}
|
||||
products.push(product);
|
||||
}
|
||||
|
||||
products.sort();
|
||||
products.reverse();
|
||||
products.sort();
|
||||
products.reverse();
|
||||
|
||||
return Some(products[0]);
|
||||
return Some(products[0]);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
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}");
|
||||
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}");
|
||||
}
|
||||
|
|
|
@ -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)> {
|
||||
for a in 1..(sum + 1) {
|
||||
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) {
|
||||
return Some((a, b, c));
|
||||
|
@ -36,6 +36,6 @@ fn triplet_with_sum(sum: isize) -> Option<(isize, isize, isize)> {
|
|||
|
||||
fn main() {
|
||||
let (a, b, c) = triplet_with_sum(1000).unwrap();
|
||||
|
||||
|
||||
println!("a = {a}, b = {b}, c = {c} // abc = {}", a * b * c);
|
||||
}
|
||||
|
|
77
src/main.rs
77
src/main.rs
|
@ -1,15 +1,19 @@
|
|||
use clap::{Parser, Subcommand};
|
||||
use owo_colors::OwoColorize;
|
||||
use std::{fs::{self, File, OpenOptions}, path::Path, io::{Write, BufRead}};
|
||||
use scraper::{Html, Selector};
|
||||
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)]
|
||||
#[clap(about, author, version)]
|
||||
struct Value {
|
||||
#[clap(subcommand)]
|
||||
command: Commands
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[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())
|
||||
}
|
||||
})
|
||||
.build()
|
||||
).unwrap().as_int().unwrap();
|
||||
.build(),
|
||||
)
|
||||
.unwrap()
|
||||
.as_int()
|
||||
.unwrap();
|
||||
|
||||
// todo: thoughts documents (?)
|
||||
|
||||
|
||||
// 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 title_selector = Selector::parse("h2")?;
|
||||
|
@ -79,12 +89,12 @@ async fn new() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let mut problem = html_tag_regex
|
||||
.replace_all(
|
||||
document
|
||||
.select(&content_selector)
|
||||
.next()
|
||||
.unwrap()
|
||||
.inner_html()
|
||||
.as_str(),
|
||||
" "
|
||||
.select(&content_selector)
|
||||
.next()
|
||||
.unwrap()
|
||||
.inner_html()
|
||||
.as_str(),
|
||||
" ",
|
||||
)
|
||||
.to_string()
|
||||
.replace("$$", " ");
|
||||
|
@ -98,7 +108,7 @@ Problem {} - {}
|
|||
|
||||
fn main() {{
|
||||
println!(\"Hello World!\");
|
||||
}}",
|
||||
}}",
|
||||
problem_number,
|
||||
html_escape::decode_html_entities(&mut title).to_string(),
|
||||
html_escape::decode_html_entities(&mut problem)
|
||||
|
@ -117,17 +127,13 @@ fn main() {{
|
|||
// Read the contents of the readme for editing
|
||||
let readme_path = base_dir.join("readme.md");
|
||||
|
||||
let mut readme_file = OpenOptions::new()
|
||||
.read(true)
|
||||
.open(&readme_path)
|
||||
.unwrap();
|
||||
let mut readme_file = OpenOptions::new().read(true).open(&readme_path).unwrap();
|
||||
|
||||
let mut readme_content = BufReader::new(&readme_file)
|
||||
.lines()
|
||||
.map(|s| s.unwrap())
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
|
||||
drop(readme_file);
|
||||
|
||||
// Mark the problem as done on the readme
|
||||
|
@ -138,7 +144,10 @@ fn main() {{
|
|||
|
||||
if readme_regex.is_match(line) {
|
||||
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 new_completed = completed_regex
|
||||
.captures(readme_string.as_str())
|
||||
.unwrap()[1]
|
||||
let new_completed = completed_regex.captures(readme_string.as_str()).unwrap()[1]
|
||||
.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
|
||||
readme_file = OpenOptions::new()
|
||||
.write(true)
|
||||
.open(&readme_path)
|
||||
.unwrap();
|
||||
readme_file = OpenOptions::new().write(true).open(&readme_path).unwrap();
|
||||
|
||||
readme_file.write(readme_string.as_bytes()).unwrap();
|
||||
|
||||
drop(readme_file);
|
||||
|
||||
// Announce completion!
|
||||
println!("{}", "File successfully created! Good luck (:".green().bold());
|
||||
println!(
|
||||
"{}",
|
||||
"File successfully created! Good luck (:".green().bold()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -175,6 +188,6 @@ fn main() {
|
|||
let value = Value::parse();
|
||||
|
||||
match value.command {
|
||||
Commands::New => new().unwrap()
|
||||
Commands::New => new().unwrap(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue