diff --git a/.vscode/settings.json b/.vscode/settings.json
index c698016..45694ae 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -9,5 +9,9 @@
"**/target": true,
"**/Cargo.lock": true,
"**/euler.png": true
+ },
+ "[rust]": {
+ "editor.defaultFormatter": "rust-lang.rust-analyzer",
+ "editor.formatOnSave": true
}
}
diff --git a/Cargo.lock b/Cargo.lock
index 516b588..6b4baf4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -129,6 +129,49 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
+dependencies = [
+ "cfg-if",
+]
+
[[package]]
name = "crossterm"
version = "0.23.2"
@@ -215,6 +258,12 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591"
+[[package]]
+name = "either"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
+
[[package]]
name = "encoding_rs"
version = "0.8.31"
@@ -226,13 +275,13 @@ dependencies = [
[[package]]
name = "errno"
-version = "0.2.8"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
- "winapi",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -254,6 +303,7 @@ dependencies = [
"num-bigint",
"owo-colors",
"phf 0.11.1",
+ "rayon",
"regex",
"requestty",
"reqwest",
@@ -432,6 +482,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
[[package]]
name = "html-escape"
version = "0.2.13"
@@ -557,12 +613,13 @@ dependencies = [
[[package]]
name = "io-lifetimes"
-version = "1.0.3"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
+ "hermit-abi 0.3.1",
"libc",
- "windows-sys 0.42.0",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -573,14 +630,14 @@ checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e"
[[package]]
name = "is-terminal"
-version = "0.4.2"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
+checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
- "windows-sys 0.42.0",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -612,15 +669,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.139"
+version = "0.2.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
[[package]]
name = "linux-raw-sys"
-version = "0.1.4"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "lock_api"
@@ -673,6 +730,15 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+[[package]]
+name = "memoffset"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
+dependencies = [
+ "autocfg",
+]
+
[[package]]
name = "mime"
version = "0.3.16"
@@ -757,7 +823,7 @@ version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.2.6",
"libc",
]
@@ -1146,6 +1212,28 @@ dependencies = [
"rand_core 0.5.1",
]
+[[package]]
+name = "rayon"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
[[package]]
name = "redox_syscall"
version = "0.2.16"
@@ -1253,16 +1341,16 @@ dependencies = [
[[package]]
name = "rustix"
-version = "0.36.5"
+version = "0.37.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
+checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
- "windows-sys 0.42.0",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -1886,21 +1974,51 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
- "windows_aarch64_gnullvm",
+ "windows_aarch64_gnullvm 0.42.0",
"windows_aarch64_msvc 0.42.0",
"windows_i686_gnu 0.42.0",
"windows_i686_msvc 0.42.0",
"windows_x86_64_gnu 0.42.0",
- "windows_x86_64_gnullvm",
+ "windows_x86_64_gnullvm 0.42.0",
"windows_x86_64_msvc 0.42.0",
]
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
+]
+
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
@@ -1913,6 +2031,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
@@ -1925,6 +2049,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
@@ -1937,6 +2067,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
@@ -1949,12 +2085,24 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
@@ -1967,6 +2115,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
[[package]]
name = "winreg"
version = "0.10.1"
diff --git a/Cargo.toml b/Cargo.toml
index 963ae16..e065b62 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,15 +6,16 @@ default-run = "euler"
[dependencies]
clap = { version = "4.0.4", features = ["derive"] }
-owo-colors = "3.5.0"
scraper = "0.14.0"
requestty = "0.4.1"
reqwest = "0.11"
tokio = { version = "1.23", features = ["full"] }
regex = "1"
html-escape = "0.2.13"
-num-bigint = "0.4.3"
phf = { version = "0.11.1", features = ["macros"] }
+rayon = "1.7.0"
+owo-colors = "3.5.0"
+num-bigint = "0.4.3"
[profile.release]
opt-level = "z"
diff --git a/readme.md b/readme.md
index cebeaa4..3db2113 100644
--- a/readme.md
+++ b/readme.md
@@ -7,11 +7,16 @@
All of the solutions here are written in rust. [main.rs](src/main.rs) is the home to my helper command line that can scaffold files for me quickly, prefaced with a statement of the problem! As per the rules of the challenge, I may only publish the solutions to the first 100 problems here, so I will stop after that but still continue the challenge.
-I originally started the challenge in [the-honk](https://github.com/newtykins/the-honk) in TypeScript, and am currently in the process of porting over all of my already completed challenges. Check out my old work [here](https://github.com/newtykins/the-honk/tree/main/challenges/euler).
+### Allowed Dependencies
+
+- [rayon](https://lib.rs/rayon) for concurrency
+- [phf](https://lib.rs/phf) for compile-time static maps
+- [regex](https://lib.rs/regex) for regex (duh)
+- [num_bigint](https://lib.rs/num_bigint) for bigints
## Challenge Completion
-### 22 out of 100 public challenges completed.
+### 21 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)
@@ -114,4 +119,4 @@ I originally started the challenge in [the-honk](https://github.com/newtykins/th
- [ ] 99 - Largest exponential
- [ ] 100 - Arranged probability
-Check out Project Euler here.
\ No newline at end of file
+Check out Project Euler here.
diff --git a/src/bin/1.rs b/src/bin/1.rs
index d16c02e..58152ff 100644
--- a/src/bin/1.rs
+++ b/src/bin/1.rs
@@ -5,6 +5,7 @@ If we list all the natural numbers below 10 that are multiples of 3 or 5, we get
Find the sum of all the multiples of 3 or 5 below 1000.
*/
+use rayon::prelude::*;
use std::collections::HashSet;
fn multiples_of(multipliers: &Vec, upper_bound: usize) -> HashSet {
@@ -23,9 +24,9 @@ fn multiples_of(multipliers: &Vec, upper_bound: usize) -> HashSet
return results;
}
-fn main() {
+pub fn main() {
let multiples = multiples_of(&vec![3, 5], 1000);
- let sum: usize = multiples.iter().sum();
+ let sum: usize = multiples.par_iter().sum();
println!("The sum of the multiples of 3 and 5 up until 1000 is {sum}");
}
diff --git a/src/bin/10.rs b/src/bin/10.rs
index 9cdc429..64f3bf0 100644
--- a/src/bin/10.rs
+++ b/src/bin/10.rs
@@ -7,6 +7,9 @@ Find the sum of all the primes below two million.
// Implementation of the Sieve of Eratosthenes
// https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
+
+use rayon::prelude::*;
+
fn find_primes(upper_bound: usize) -> Vec {
let mut mask = vec![true; upper_bound];
let mut primes: Vec = vec![];
@@ -32,10 +35,10 @@ fn find_primes(upper_bound: usize) -> Vec {
fn sum_of_primes(upper_bound: usize) -> usize {
let primes = find_primes(upper_bound);
- return primes.iter().sum::();
+ return primes.par_iter().sum::();
}
-fn main() {
+pub fn main() {
let value = sum_of_primes(2000000);
println!("The sum of the primes up until 2000000 is {value}");
diff --git a/src/bin/11.rs b/src/bin/11.rs
index eb76643..616f8ae 100644
--- a/src/bin/11.rs
+++ b/src/bin/11.rs
@@ -26,6 +26,8 @@ The product of these numbers is 26 × 63 × 78 × 14 = 1788696.
What is the greatest product of four adjacent numbers in the same direction (up, down, left, right, or diagonally) in the 20×20 grid?
*/
+use rayon::prelude::*;
+
fn largest_grid_product(grid: Vec>, adjacent_digits: usize) -> usize {
let mut products: Vec = vec![];
@@ -37,7 +39,7 @@ fn largest_grid_product(grid: Vec>, adjacent_digits: usize) -> usize
// Horizontal product
if horizontal {
let selection = &row[j..(j + adjacent_digits)];
- products.push(selection.iter().product());
+ products.push(selection.par_iter().product());
}
// Vertical product
@@ -48,7 +50,7 @@ fn largest_grid_product(grid: Vec>, adjacent_digits: usize) -> usize
selection.push(grid[i + k][j]);
}
- products.push(selection.iter().product());
+ products.push(selection.par_iter().product());
}
// Forward diagonal product
@@ -59,7 +61,7 @@ fn largest_grid_product(grid: Vec>, adjacent_digits: usize) -> usize
selection.push(grid[i + k][j + k]);
}
- products.push(selection.iter().product());
+ products.push(selection.par_iter().product());
}
// Reverse diagonal product
@@ -70,15 +72,15 @@ fn largest_grid_product(grid: Vec>, adjacent_digits: usize) -> usize
selection.push(grid[i + k][j - k]);
}
- products.push(selection.iter().product());
+ products.push(selection.par_iter().product());
}
}
}
- return *products.iter().max().unwrap();
+ return *products.par_iter().max().unwrap();
}
-fn main() {
+pub fn main() {
let grid: Vec> = vec![
vec![
8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8,
diff --git a/src/bin/12.rs b/src/bin/12.rs
index 2e98c72..e4565e8 100644
--- a/src/bin/12.rs
+++ b/src/bin/12.rs
@@ -40,7 +40,7 @@ fn first_triangle_with_n_divisors(n: usize) -> usize {
}
}
-fn main() {
+pub fn main() {
let value = first_triangle_with_n_divisors(500);
println!("The first triangle number with over 500 divisors is {value}");
diff --git a/src/bin/13.rs b/src/bin/13.rs
index cc6de1d..ac35373 100644
--- a/src/bin/13.rs
+++ b/src/bin/13.rs
@@ -104,6 +104,8 @@ Work out the first ten digits of the sum of the following one-hundred 50-digit n
53503534226472524250874054075591789781264330331690
*/
+use rayon::prelude::*;
+
const NUMBERS: [f64; 100] = [
37107287533902102798797998220837590246510135740250.0,
46376937677490009712648124896970078050417018260538.0,
@@ -221,8 +223,8 @@ fn first_n_digits(number: f64, n: usize) -> Option {
return Some(new_number);
}
-fn main() {
- let digits = first_n_digits(NUMBERS.iter().sum(), 10).unwrap();
+pub fn main() {
+ let digits = first_n_digits(NUMBERS.par_iter().sum(), 10).unwrap();
println!("The first 10 digits of the sum: {digits}");
}
diff --git a/src/bin/14.rs b/src/bin/14.rs
index 9ca9f47..76db852 100644
--- a/src/bin/14.rs
+++ b/src/bin/14.rs
@@ -10,6 +10,7 @@ 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 rayon::prelude::*;
use std::collections::HashMap;
fn f(n: usize) -> usize {
@@ -42,10 +43,10 @@ fn longest_collatz_sequence(greatest_start: usize) -> usize {
sequence_lengths.insert(i, sequence_length);
}
- return *sequence_lengths.iter().max_by_key(|x| x.1).unwrap().0;
+ return *sequence_lengths.par_iter().max_by_key(|x| x.1).unwrap().0;
}
-fn main() {
+pub fn main() {
let starting_number = longest_collatz_sequence(1_000_000);
println!(
diff --git a/src/bin/15.rs b/src/bin/15.rs
index 7e76e4d..9f56822 100644
--- a/src/bin/15.rs
+++ b/src/bin/15.rs
@@ -35,7 +35,7 @@ fn count_lattice_paths(width: usize, height: usize) -> usize {
}
}
-fn main() {
+pub fn main() {
let routes = count_lattice_paths(20, 20);
println!("The amount of routes through a 20x20 grid is {routes}");
diff --git a/src/bin/16.rs b/src/bin/16.rs
index a95db11..1edc646 100644
--- a/src/bin/16.rs
+++ b/src/bin/16.rs
@@ -32,7 +32,7 @@ fn power_digit_sum(base: usize, power: u32) -> usize {
sum
}
-fn main() {
+pub fn main() {
let sum = power_digit_sum(2, 1000);
println!("The sum of the digits of the number 2^1000 is {}!", sum);
diff --git a/src/bin/17.rs b/src/bin/17.rs
index ecf22cb..8393a29 100644
--- a/src/bin/17.rs
+++ b/src/bin/17.rs
@@ -103,7 +103,7 @@ fn letter_count(upper_bound: usize) -> usize {
sum
}
-fn main() {
+pub fn main() {
let sum = letter_count(1000);
println!(
diff --git a/src/bin/18.rs b/src/bin/18.rs
index 68c31d4..7218d47 100644
--- a/src/bin/18.rs
+++ b/src/bin/18.rs
@@ -37,7 +37,7 @@ fn maximum_path_sum(triangle: Vec>) -> usize {
return tri[0][0];
}
-fn main() {
+pub fn main() {
let triangle: Vec> = vec![
vec![75],
vec![95, 64],
@@ -55,7 +55,7 @@ fn main() {
vec![63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31],
vec![4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23],
];
-
+
let sum = maximum_path_sum(triangle);
println!("The maximum path sum of the triangle is {}!", sum);
diff --git a/src/bin/2.rs b/src/bin/2.rs
index 98ffc7b..c74f5f7 100644
--- a/src/bin/2.rs
+++ b/src/bin/2.rs
@@ -6,6 +6,8 @@ Each new term in the Fibonacci sequence is generated by adding the previous two
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
*/
+use rayon::prelude::*;
+
fn fibonacci(upper_bound: usize) -> Vec {
// F_0 = 1, F_1 = 2
let mut sequence = vec![1, 2];
@@ -19,9 +21,9 @@ fn fibonacci(upper_bound: usize) -> Vec {
return sequence;
}
-fn main() {
+pub fn main() {
let sequence = fibonacci(4000000);
- let even = sequence.iter().filter(|n| *n % 2 == 0);
+ let even = sequence.par_iter().filter(|n| *n % 2 == 0);
let sum: usize = even.sum();
print!(
diff --git a/src/bin/22.rs b/src/bin/22.rs
index f2af555..c56ae7e 100644
--- a/src/bin/22.rs
+++ b/src/bin/22.rs
@@ -41,7 +41,7 @@ fn name_score_total(names: Vec) -> usize {
return total;
}
-fn main() {
+pub fn main() {
let names = read_names();
let total = name_score_total(names);
diff --git a/src/bin/3.rs b/src/bin/3.rs
index 6deed70..b2d33b9 100644
--- a/src/bin/3.rs
+++ b/src/bin/3.rs
@@ -29,7 +29,7 @@ fn largest_prime_factor(number: usize) -> usize {
return primes[primes.len() - 1];
}
-fn main() {
+pub fn main() {
let factor = largest_prime_factor(600851475143);
println!("The largest prime factor of 600851475143 is {factor}");
}
diff --git a/src/bin/4.rs b/src/bin/4.rs
index c83aab6..44b6ee9 100644
--- a/src/bin/4.rs
+++ b/src/bin/4.rs
@@ -5,6 +5,8 @@ A palindromic number reads the same both ways. The largest palindrome made from
Find the largest palindrome made from the product of two 3-digit numbers.
*/
+use rayon::prelude::*;
+
fn largest_pallindromic_number(lower_bound: usize, upper_bound: usize) -> usize {
let mut products: Vec = vec![];
@@ -16,7 +18,7 @@ fn largest_pallindromic_number(lower_bound: usize, upper_bound: usize) -> usize
// Filter for pallindromic numbers
let mut pallindromic = products
- .iter()
+ .par_iter()
.filter(|x| x.to_string() == x.to_string().chars().rev().collect::())
.collect::>();
@@ -27,7 +29,7 @@ fn largest_pallindromic_number(lower_bound: usize, upper_bound: usize) -> usize
return *pallindromic[0];
}
-fn main() {
+pub 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}");
diff --git a/src/bin/42.rs b/src/bin/42.rs
index 2ac6f56..947f6b4 100644
--- a/src/bin/42.rs
+++ b/src/bin/42.rs
@@ -49,7 +49,7 @@ fn count_triangle_words(words: Vec) -> usize {
return count;
}
-fn main() {
+pub fn main() {
let words = read_words();
let count = count_triangle_words(words);
diff --git a/src/bin/5.rs b/src/bin/5.rs
index a4b8ae1..553005b 100644
--- a/src/bin/5.rs
+++ b/src/bin/5.rs
@@ -45,7 +45,7 @@ fn first_value_divisible_by(start: usize, end: usize) -> Option {
return Some(result);
}
-fn main() {
+pub fn main() {
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}");
diff --git a/src/bin/6.rs b/src/bin/6.rs
index d8a7fed..61f3ac7 100644
--- a/src/bin/6.rs
+++ b/src/bin/6.rs
@@ -9,6 +9,8 @@ Hence the difference between the sum of the squares of the first ten natural num
Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.
*/
+use rayon::prelude::*;
+
const LOWER_BOUND: usize = 1;
const UPPER_BOUND: usize = 100;
@@ -23,7 +25,7 @@ fn sum_of_squares(lower_bound: usize, upper_bound: usize) -> Option {
squares.push(i.pow(2));
}
- return Some(squares.iter().sum());
+ return Some(squares.par_iter().sum());
}
fn square_of_sum(lower_bound: usize, upper_bound: usize) -> Option {
@@ -34,7 +36,7 @@ fn square_of_sum(lower_bound: usize, upper_bound: usize) -> Option {
return Some(((lower_bound..(upper_bound + 1)).sum::()).pow(2));
}
-fn main() {
+pub 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;
diff --git a/src/bin/67.rs b/src/bin/67.rs
index 6c974e7..63c8fe6 100644
--- a/src/bin/67.rs
+++ b/src/bin/67.rs
@@ -35,7 +35,7 @@ fn maximum_path_sum(triangle: Vec>) -> usize {
return tri[0][0];
}
-fn main() {
+pub fn main() {
let triangle = read_triangle();
let sum = maximum_path_sum(triangle);
println!("The maximum path sum of the triangle is {}!", sum);
diff --git a/src/bin/7.rs b/src/bin/7.rs
index 03decb9..2732943 100644
--- a/src/bin/7.rs
+++ b/src/bin/7.rs
@@ -54,7 +54,7 @@ fn nth_prime(n: usize) -> Option {
return Some(primes[n - 1]);
}
-fn main() {
+pub fn main() {
let number = nth_prime(10001).unwrap();
println!("The 10,001st prime number is {number}");
diff --git a/src/bin/8.rs b/src/bin/8.rs
index 775769a..bbdf547 100644
--- a/src/bin/8.rs
+++ b/src/bin/8.rs
@@ -71,7 +71,7 @@ fn largest_product(number: &str, adjacent_digits: usize) -> Option {
return Some(products[0]);
}
-fn main() {
+pub 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}");
diff --git a/src/bin/9.rs b/src/bin/9.rs
index c84d962..f98401e 100644
--- a/src/bin/9.rs
+++ b/src/bin/9.rs
@@ -34,7 +34,7 @@ fn triplet_with_sum(sum: isize) -> Option<(isize, isize, isize)> {
return None;
}
-fn main() {
+pub fn main() {
let (a, b, c) = triplet_with_sum(1000).unwrap();
println!("a = {a}, b = {b}, c = {c} // abc = {}", a * b * c);
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
new file mode 100644
index 0000000..0f186a8
--- /dev/null
+++ b/src/commands/mod.rs
@@ -0,0 +1,2 @@
+pub mod new;
+pub mod run;
diff --git a/src/commands/new.rs b/src/commands/new.rs
new file mode 100644
index 0000000..5672e9a
--- /dev/null
+++ b/src/commands/new.rs
@@ -0,0 +1,183 @@
+use owo_colors::OwoColorize;
+use regex::Regex;
+use scraper::{Html, Selector};
+use std::io::BufReader;
+use std::{
+ fs::{File, OpenOptions},
+ io::{BufRead, Write},
+};
+
+#[tokio::main]
+pub async fn execute(problem: Option) -> Result<(), Box> {
+ let code_path = euler::code_path();
+ let problem_number = euler::problem_number(
+ problem,
+ &code_path,
+ "Which problem would you like to solve?",
+ );
+
+ // Fetch the problem information
+ 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")?;
+ let content_selector = Selector::parse(".problem_content")?;
+ let html_tag_regex = Regex::new(r"<[^>]*>")?;
+
+ let mut title = document
+ .select(&title_selector)
+ .next()
+ .unwrap()
+ .text()
+ .collect::>()
+ .join("");
+
+ let mut problem = html_tag_regex
+ .replace_all(
+ document
+ .select(&content_selector)
+ .next()
+ .unwrap()
+ .inner_html()
+ .as_str(),
+ " ",
+ )
+ .to_string()
+ .replace("$$", " ");
+
+ let file_body = format!(
+ "/*
+Problem {} - {}
+
+{}
+*/
+
+pub fn main() {{
+ println!(\"Hello World!\");
+}}",
+ problem_number,
+ html_escape::decode_html_entities(&mut title).to_string(),
+ html_escape::decode_html_entities(&mut problem)
+ .split("\n")
+ .map(|s| s.trim())
+ .filter(|s| s != &"")
+ .collect::>()
+ .join("\n")
+ );
+
+ // Create the file
+ let mut file = File::create(code_path.join(format!("{problem_number}.rs")))?;
+ file.write(file_body.as_bytes())?;
+
+ drop(file);
+
+ // Read the contents of the readme for editing
+ let readme_path = euler::readme_path();
+ let mut readme_file = OpenOptions::new().read(true).open(&readme_path)?;
+
+ let mut readme_content = BufReader::new(&readme_file)
+ .lines()
+ .map(|s| s.unwrap())
+ .collect::>();
+
+ drop(readme_file);
+
+ // Mark the problem as done on the readme
+ let readme_regex = Regex::new(format!(" {problem_number} - (.*)").as_str())?;
+
+ for i in 0..readme_content.len() {
+ let line = readme_content[i].as_str();
+
+ 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()
+ );
+ }
+ }
+
+ // Update the summary statistics on the readme
+ let mut readme_string = readme_content.join("\n");
+
+ let completed_regex = Regex::new("([0-9]+)")?;
+
+ let new_completed =
+ completed_regex.captures(readme_string.as_str()).unwrap()[1].parse::()? + 1;
+
+ readme_string = completed_regex
+ .replace(
+ readme_string.as_str(),
+ format!("{new_completed}"),
+ )
+ .to_string();
+
+ // Write the new content to the readme
+ readme_file = OpenOptions::new().write(true).open(&readme_path)?;
+
+ readme_file.write(readme_string.as_bytes())?;
+
+ drop(readme_file);
+
+ // Modify the run command
+ let run_path = euler::run_path();
+ let mut run_file = OpenOptions::new().read(true).open(&run_path)?;
+
+ let mut run_content = BufReader::new(&run_file)
+ .lines()
+ .map(|s| s.unwrap())
+ .collect::>();
+
+ drop(run_file);
+
+ // Import the problem's file
+ let import_regex = Regex::new(r#"// #\[path = "\.\./bin/{x}\.rs"]"#.replace("{x}", problem_number.to_string().as_str()).as_str())?;
+
+ for i in 0..run_content.len() {
+ let line = run_content[i].as_str();
+
+ if import_regex.is_match(line) {
+ run_content[i] = line.replace("// ", "");
+ run_content[i + 1] = run_content[i + 1].replace("// ", "");
+
+ break;
+ }
+ }
+
+ // Add the problem to the match statement
+ let match_regex = Regex::new(
+ r"// {x} =>"
+ .replace("{x}", problem_number.to_string().as_str())
+ .as_str(),
+ )?;
+
+ for i in 0..run_content.len() {
+ let line = run_content[i].as_str();
+
+ if match_regex.is_match(line) {
+ run_content[i] = line.replace("// ", "");
+ break;
+ }
+ }
+
+ // Write the new content to the run file
+ run_file = OpenOptions::new()
+ .write(true)
+ .truncate(true)
+ .open(&run_path)?;
+
+ run_file.write(run_content.join("\n").as_bytes())?;
+
+ drop(run_file);
+
+ // Announce completion!
+ println!(
+ "{}",
+ "File successfully created! Good luck (:".green().bold()
+ );
+
+ Ok(())
+}
diff --git a/src/commands/run.rs b/src/commands/run.rs
new file mode 100644
index 0000000..0171793
--- /dev/null
+++ b/src/commands/run.rs
@@ -0,0 +1,338 @@
+use owo_colors::OwoColorize;
+
+#[path = "../bin/8.rs"]
+mod eight;
+#[path = "../bin/18.rs"]
+mod eighteen;
+#[path = "../bin/11.rs"]
+mod eleven;
+#[path = "../bin/15.rs"]
+mod fifteen;
+#[path = "../bin/5.rs"]
+mod five;
+#[path = "../bin/4.rs"]
+mod four;
+#[path = "../bin/14.rs"]
+mod fourteen;
+#[path = "../bin/9.rs"]
+mod nine;
+#[path = "../bin/1.rs"]
+mod one;
+#[path = "../bin/7.rs"]
+mod seven;
+#[path = "../bin/17.rs"]
+mod seventeen;
+#[path = "../bin/6.rs"]
+mod six;
+#[path = "../bin/16.rs"]
+mod sixteen;
+#[path = "../bin/10.rs"]
+mod ten;
+#[path = "../bin/13.rs"]
+mod thirteen;
+#[path = "../bin/3.rs"]
+mod three;
+#[path = "../bin/12.rs"]
+mod twelve;
+#[path = "../bin/2.rs"]
+mod two;
+// #[path = "../bin/19.rs"]
+// mod nineteen;
+// #[path = "../bin/20.rs"]
+// mod twenty;
+// #[path = "../bin/21.rs"]
+// mod twenty_one;
+#[path = "../bin/22.rs"]
+mod twenty_two;
+// #[path = "../bin/23.rs"]
+// mod twenty_three;
+// #[path = "../bin/24.rs"]
+// mod twenty_four;
+// #[path = "../bin/25.rs"]
+// mod twenty_five;
+// #[path = "../bin/26.rs"]
+// mod twenty_six;
+// #[path = "../bin/27.rs"]
+// mod twenty_seven;
+// #[path = "../bin/28.rs"]
+// mod twenty_eight;
+// #[path = "../bin/29.rs"]
+// mod twenty_nine;
+// #[path = "../bin/30.rs"]
+// mod thirty;
+// #[path = "../bin/31.rs"]
+// mod thirty_one;
+// #[path = "../bin/32.rs"]
+// mod thirty_two;
+// #[path = "../bin/33.rs"]
+// mod thirty_three;
+// #[path = "../bin/34.rs"]
+// mod thirty_four;
+// #[path = "../bin/35.rs"]
+// mod thirty_five;
+// #[path = "../bin/36.rs"]
+// mod thirty_six;
+// #[path = "../bin/37.rs"]
+// mod thirty_seven;
+// #[path = "../bin/38.rs"]
+// mod thirty_eight;
+// #[path = "../bin/39.rs"]
+// mod thirty_nine;
+// #[path = "../bin/40.rs"]
+// mod forty;
+// #[path = "../bin/41.rs"]
+// mod forty_one;
+#[path = "../bin/42.rs"]
+mod forty_two;
+// #[path = "../bin/43.rs"]
+// mod forty_three;
+// #[path = "../bin/44.rs"]
+// mod forty_four;
+// #[path = "../bin/45.rs"]
+// mod forty_five;
+// #[path = "../bin/46.rs"]
+// mod forty_six;
+// #[path = "../bin/47.rs"]
+// mod forty_seven;
+// #[path = "../bin/48.rs"]
+// mod forty_eight;
+// #[path = "../bin/49.rs"]
+// mod forty_nine;
+// #[path = "../bin/50.rs"]
+// mod fifty;
+// #[path = "../bin/51.rs"]
+// mod fifty_one;
+// #[path = "../bin/52.rs"]
+// mod fifty_two;
+// #[path = "../bin/53.rs"]
+// mod fifty_three;
+// #[path = "../bin/54.rs"]
+// mod fifty_four;
+// #[path = "../bin/55.rs"]
+// mod fifty_five;
+// #[path = "../bin/56.rs"]
+// mod fifty_six;
+// #[path = "../bin/57.rs"]
+// mod fifty_seven;
+// #[path = "../bin/58.rs"]
+// mod fifty_eight;
+// #[path = "../bin/59.rs"]
+// mod fifty_nine;
+// #[path = "../bin/60.rs"]
+// mod sixty;
+// #[path = "../bin/61.rs"]
+// mod sixty_one;
+// #[path = "../bin/62.rs"]
+// mod sixty_two;
+// #[path = "../bin/63.rs"]
+// mod sixty_three;
+// #[path = "../bin/64.rs"]
+// mod sixty_four;
+// #[path = "../bin/65.rs"]
+// mod sixty_five;
+// #[path = "../bin/66.rs"]
+// mod sixty_six;
+#[path = "../bin/67.rs"]
+mod sixty_seven;
+// #[path = "../bin/68.rs"]
+// mod sixty_eight;
+// #[path = "../bin/69.rs"]
+// mod sixty_nine;
+// #[path = "../bin/70.rs"]
+// mod seventy;
+// #[path = "../bin/71.rs"]
+// mod seventy_one;
+// #[path = "../bin/72.rs"]
+// mod seventy_two;
+// #[path = "../bin/73.rs"]
+// mod seventy_three;
+// #[path = "../bin/74.rs"]
+// mod seventy_four;
+// #[path = "../bin/75.rs"]
+// mod seventy_five;
+// #[path = "../bin/76.rs"]
+// mod seventy_six;
+// #[path = "../bin/77.rs"]
+// mod seventy_seven;
+// #[path = "../bin/78.rs"]
+// mod seventy_eight;
+// #[path = "../bin/79.rs"]
+// mod seventy_nine;
+// #[path = "../bin/80.rs"]
+// mod eighty;
+// #[path = "../bin/81.rs"]
+// mod eighty_one;
+// #[path = "../bin/82.rs"]
+// mod eighty_two;
+// #[path = "../bin/83.rs"]
+// mod eighty_three;
+// #[path = "../bin/84.rs"]
+// mod eighty_four;
+// #[path = "../bin/85.rs"]
+// mod eighty_five;
+// #[path = "../bin/86.rs"]
+// mod eighty_six;
+// #[path = "../bin/87.rs"]
+// mod eighty_seven;
+// #[path = "../bin/88.rs"]
+// mod eighty_eight;
+// #[path = "../bin/89.rs"]
+// mod eighty_nine;
+// #[path = "../bin/90.rs"]
+// mod ninety;
+// #[path = "../bin/91.rs"]
+// mod ninety_one;
+// #[path = "../bin/92.rs"]
+// mod ninety_two;
+// #[path = "../bin/93.rs"]
+// mod ninety_three;
+// #[path = "../bin/94.rs"]
+// mod ninety_four;
+// #[path = "../bin/95.rs"]
+// mod ninety_five;
+// #[path = "../bin/96.rs"]
+// mod ninety_six;
+// #[path = "../bin/97.rs"]
+// mod ninety_seven;
+// #[path = "../bin/98.rs"]
+// mod ninety_eight;
+// #[path = "../bin/99.rs"]
+// mod ninety_nine;
+// #[path = "../bin/100.rs"]
+// mod one_hundred;
+
+#[tokio::main]
+pub async fn execute(
+ problem: Option,
+ benchmark: bool,
+) -> Result<(), Box> {
+ let code_path = euler::code_path();
+ let problem_number =
+ euler::problem_number(problem, &code_path, "Which problem would you like to run?");
+
+ let start = std::time::Instant::now();
+ let mut exists = true;
+
+ match problem_number {
+ 1 => one::main(),
+ 2 => two::main(),
+ 3 => three::main(),
+ 4 => four::main(),
+ 5 => five::main(),
+ 6 => six::main(),
+ 7 => seven::main(),
+ 8 => eight::main(),
+ 9 => nine::main(),
+ 10 => ten::main(),
+ 11 => eleven::main(),
+ 12 => twelve::main(),
+ 13 => thirteen::main(),
+ 14 => fourteen::main(),
+ 15 => fifteen::main(),
+ 16 => sixteen::main(),
+ 17 => seventeen::main(),
+ 18 => eighteen::main(),
+ // 19 => nineteen::main(),
+ // 20 => twenty::main(),
+ // 21 => twenty_one::main(),
+ 22 => twenty_two::main(),
+ // 23 => twenty_three::main(),
+ // 24 => twenty_four::main(),
+ // 25 => twenty_five::main(),
+ // 26 => twenty_six::main(),
+ // 27 => twenty_seven::main(),
+ // 28 => twenty_eight::main(),
+ // 29 => twenty_nine::main(),
+ // 30 => thirty::main(),
+ // 31 => thirty_one::main(),
+ // 32 => thirty_two::main(),
+ // 33 => thirty_three::main(),
+ // 34 => thirty_four::main(),
+ // 35 => thirty_five::main(),
+ // 36 => thirty_six::main(),
+ // 37 => thirty_seven::main(),
+ // 38 => thirty_eight::main(),
+ // 39 => thirty_nine::main(),
+ // 40 => forty::main(),
+ // 41 => forty_one::main(),
+ // 42 => forty_two::main(),
+ // 43 => forty_three::main(),
+ // 44 => forty_four::main(),
+ // 45 => forty_five::main(),
+ // 46 => forty_six::main(),
+ // 47 => forty_seven::main(),
+ // 48 => forty_eight::main(),
+ // 49 => forty_nine::main(),
+ // 50 => fifty::main(),
+ // 51 => fifty_one::main(),
+ // 52 => fifty_two::main(),
+ // 53 => fifty_three::main(),
+ // 54 => fifty_four::main(),
+ // 55 => fifty_five::main(),
+ // 56 => fifty_six::main(),
+ // 57 => fifty_seven::main(),
+ // 58 => fifty_eight::main(),
+ // 59 => fifty_nine::main(),
+ // 60 => sixty::main(),
+ // 61 => sixty_one::main(),
+ // 62 => sixty_two::main(),
+ // 63 => sixty_three::main(),
+ // 64 => sixty_four::main(),
+ // 65 => sixty_five::main(),
+ // 66 => sixty_six::main(),
+ 67 => sixty_seven::main(),
+ // 68 => sixty_eight::main(),
+ // 69 => sixty_nine::main(),
+ // 70 => seventy::main(),
+ // 71 => seventy_one::main(),
+ // 72 => seventy_two::main(),
+ // 73 => seventy_three::main(),
+ // 74 => seventy_four::main(),
+ // 75 => seventy_five::main(),
+ // 76 => seventy_six::main(),
+ // 77 => seventy_seven::main(),
+ // 78 => seventy_eight::main(),
+ // 79 => seventy_nine::main(),
+ // 80 => eighty::main(),
+ // 81 => eighty_one::main(),
+ // 82 => eighty_two::main(),
+ // 83 => eighty_three::main(),
+ // 84 => eighty_four::main(),
+ // 85 => eighty_five::main(),
+ // 86 => eighty_six::main(),
+ // 87 => eighty_seven::main(),
+ // 88 => eighty_eight::main(),
+ // 89 => eighty_nine::main(),
+ // 90 => ninety::main(),
+ // 91 => ninety_one::main(),
+ // 92 => ninety_two::main(),
+ // 93 => ninety_three::main(),
+ // 94 => ninety_four::main(),
+ // 95 => ninety_five::main(),
+ // 96 => ninety_six::main(),
+ // 97 => ninety_seven::main(),
+ // 98 => ninety_eight::main(),
+ // 99 => ninety_nine::main(),
+ // 100 => one_hundred::main(),
+ _ => {
+ exists = false;
+ println!(
+ "{} {} {}",
+ "Problem".red().bold(),
+ problem_number.red().bold(),
+ "is not in this repository!".red().bold()
+ )
+ }
+ }
+
+ let duration = start.elapsed();
+
+ if benchmark && exists {
+ println!(
+ "Time elapsed when executing problem {} is: {:?}",
+ problem_number, duration
+ );
+ }
+
+ Ok(())
+}
diff --git a/src/lib.rs b/src/lib.rs
index 8d7b9ca..73760a9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -15,3 +15,51 @@ pub fn resources_path() -> PathBuf {
pub fn readme_path() -> PathBuf {
return fetch_dir().join("readme.md");
}
+
+pub fn run_path() -> PathBuf {
+ return fetch_dir().join("src").join("commands").join("run.rs");
+}
+
+pub fn problem_number(problem: Option, code_path: &PathBuf, prompt: &str) -> u8 {
+ if let Some(n) = problem {
+ return n;
+ } else {
+ return requestty::prompt_one(
+ requestty::Question::int("problemNumber")
+ .message(prompt)
+ .validate(|n, _| {
+ // All numbers must be positive
+ let mut pass = false;
+
+ // Ensure that the problem has not already got a file associated with it
+ let files = std::fs::read_dir(code_path).unwrap();
+
+ for file in files {
+ let file_number = file
+ .unwrap()
+ .file_name()
+ .to_str()
+ .unwrap()
+ .split('.')
+ .collect::>()[0]
+ .parse::()
+ .unwrap();
+
+ if n == file_number {
+ pass = true;
+ }
+ }
+
+ if pass {
+ Ok(())
+ } else {
+ Err("Please ensure that your input is valid!".to_owned())
+ }
+ })
+ .build(),
+ )
+ .unwrap()
+ .as_int()
+ .unwrap() as u8;
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 1243f2a..29c6790 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,12 +1,7 @@
+#![allow(dead_code)]
+
use clap::{Args, Parser, Subcommand};
-use owo_colors::OwoColorize;
-use regex::Regex;
-use scraper::{Html, Selector};
-use std::io::BufReader;
-use std::{
- fs::{self, File, OpenOptions},
- io::{BufRead, Write},
-};
+mod commands;
#[derive(Parser)]
#[clap(about, author, version)]
@@ -15,188 +10,33 @@ struct Value {
command: Commands,
}
-#[derive(Args, Clone)]
-struct NewOptions {
- /// The problem to complete
- problem: Option,
+#[derive(Args)]
+struct NewArgs {
+ problem: Option,
+}
+
+#[derive(Args)]
+struct RunArgs {
+ problem: Option,
+
+ #[arg(short, long, default_value_t = false)]
+ benchmark: bool,
}
#[derive(Subcommand)]
enum Commands {
/// Handles the initialisation of a new Project Euler Problem
- New(NewOptions),
+ New(NewArgs),
+
+ /// Runs the solution to a problem
+ Run(RunArgs),
}
-#[tokio::main]
-async fn new(problem: Option) -> Result<(), Box> {
- let code_path = euler::code_path();
- let problem_number: u16;
-
- // Determine the problem number
- match problem {
- Some(n) => problem_number = n,
- None => {
- problem_number = requestty::prompt_one(
- requestty::Question::int("problemNumber")
- .message("Which problem would you like to solve?")
- .validate(|n, _| {
- // All numbers must be positive
- let mut pass = n > 0;
-
- // Ensure that the problem has not already got a file associated with it
- let files = fs::read_dir(&code_path).unwrap();
-
- for file in files {
- let file_number = file
- .unwrap()
- .file_name()
- .to_str()
- .unwrap()
- .split('.')
- .collect::>()[0]
- .parse::()
- .unwrap();
-
- if n == file_number && pass {
- pass = false;
- }
- }
-
- if pass {
- Ok(())
- } else {
- Err("Please ensure that your input is valid!".to_owned())
- }
- })
- .build(),
- )
- .unwrap()
- .as_int()
- .unwrap() as u16;
- }
- }
-
- // Fetch the problem information
- 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")?;
- let content_selector = Selector::parse(".problem_content")?;
- let html_tag_regex = Regex::new(r"<[^>]*>").unwrap();
-
- let mut title = document
- .select(&title_selector)
- .next()
- .unwrap()
- .text()
- .collect::>()
- .join("");
-
- let mut problem = html_tag_regex
- .replace_all(
- document
- .select(&content_selector)
- .next()
- .unwrap()
- .inner_html()
- .as_str(),
- " ",
- )
- .to_string()
- .replace("$$", " ");
-
- let file_body = format!(
- "/*
-Problem {} - {}
-
-{}
-*/
-
-fn main() {{
- println!(\"Hello World!\");
-}}",
- problem_number,
- html_escape::decode_html_entities(&mut title).to_string(),
- html_escape::decode_html_entities(&mut problem)
- .split("\n")
- .map(|s| s.trim())
- .filter(|s| s != &"")
- .collect::>()
- .join("\n")
- );
-
- // Create the file
- let mut file = File::create(code_path.join(format!("{problem_number}.rs"))).unwrap();
- file.write(file_body.as_bytes()).unwrap();
- drop(file);
-
- // Read the contents of the readme for editing
- let readme_path = euler::readme_path();
-
- 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::>();
-
- drop(readme_file);
-
- // Mark the problem as done on the readme
- let readme_regex = Regex::new(format!(" {problem_number} - (.*)").as_str()).unwrap();
-
- for i in 0..readme_content.len() {
- let line = readme_content[i].as_str();
-
- 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()
- );
- }
- }
-
- // Update the summary statistics on the readme
- let mut readme_string = readme_content.join("\n");
-
- let completed_regex = Regex::new("([0-9]+)").unwrap();
-
- let new_completed = completed_regex.captures(readme_string.as_str()).unwrap()[1]
- .parse::()
- .unwrap()
- + 1;
-
- readme_string = completed_regex
- .replace(
- readme_string.as_str(),
- format!("{new_completed}"),
- )
- .to_string();
-
- // Write the new content to the readme
- 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()
- );
-
- Ok(())
-}
-
-fn main() {
+pub fn main() -> Result<(), Box> {
let value = Value::parse();
match value.command {
- Commands::New(options) => new(options.problem).unwrap(),
+ Commands::New(NewArgs { problem }) => commands::new::execute(problem),
+ Commands::Run(RunArgs { problem, benchmark }) => commands::run::execute(problem, benchmark),
}
}