feat(cli): run command with benchmarking
This commit is contained in:
parent
5accea1fb2
commit
525ba998df
30 changed files with 830 additions and 240 deletions
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
@ -9,5 +9,9 @@
|
|||
"**/target": true,
|
||||
"**/Cargo.lock": true,
|
||||
"**/euler.png": true
|
||||
},
|
||||
"[rust]": {
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer",
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
}
|
||||
|
|
194
Cargo.lock
generated
194
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
11
readme.md
11
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
|
||||
|
||||
### <!-- completed -->22<!-- completed --> out of 100 public challenges completed.
|
||||
### <!-- completed -->21<!-- 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)
|
||||
|
@ -114,4 +119,4 @@ I originally started the challenge in [the-honk](https://github.com/newtykins/th
|
|||
- [ ] 99 - Largest exponential
|
||||
- [ ] 100 - Arranged probability
|
||||
|
||||
<sub>Check out Project Euler <a href="https://projecteuler.net">here</a>.</sub>
|
||||
<sub>Check out Project Euler <a href="https://projecteuler.net">here</a>.</sub>
|
||||
|
|
|
@ -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<usize>, upper_bound: usize) -> HashSet<usize> {
|
||||
|
@ -23,9 +24,9 @@ fn multiples_of(multipliers: &Vec<usize>, upper_bound: usize) -> HashSet<usize>
|
|||
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}");
|
||||
}
|
||||
|
|
|
@ -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<usize> {
|
||||
let mut mask = vec![true; upper_bound];
|
||||
let mut primes: Vec<usize> = vec![];
|
||||
|
@ -32,10 +35,10 @@ fn find_primes(upper_bound: usize) -> Vec<usize> {
|
|||
|
||||
fn sum_of_primes(upper_bound: usize) -> usize {
|
||||
let primes = find_primes(upper_bound);
|
||||
return primes.iter().sum::<usize>();
|
||||
return primes.par_iter().sum::<usize>();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
pub fn main() {
|
||||
let value = sum_of_primes(2000000);
|
||||
|
||||
println!("The sum of the primes up until 2000000 is {value}");
|
||||
|
|
|
@ -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<Vec<usize>>, adjacent_digits: usize) -> usize {
|
||||
let mut products: Vec<usize> = vec![];
|
||||
|
||||
|
@ -37,7 +39,7 @@ fn largest_grid_product(grid: Vec<Vec<usize>>, 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<Vec<usize>>, 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<Vec<usize>>, 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<Vec<usize>>, 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<usize>> = vec![
|
||||
vec![
|
||||
8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8,
|
||||
|
|
|
@ -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}");
|
||||
|
|
|
@ -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<usize> {
|
|||
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}");
|
||||
}
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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}");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -103,7 +103,7 @@ fn letter_count(upper_bound: usize) -> usize {
|
|||
sum
|
||||
}
|
||||
|
||||
fn main() {
|
||||
pub fn main() {
|
||||
let sum = letter_count(1000);
|
||||
|
||||
println!(
|
||||
|
|
|
@ -37,7 +37,7 @@ fn maximum_path_sum(triangle: Vec<Vec<usize>>) -> usize {
|
|||
return tri[0][0];
|
||||
}
|
||||
|
||||
fn main() {
|
||||
pub fn main() {
|
||||
let triangle: Vec<Vec<usize>> = 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);
|
||||
|
|
|
@ -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<usize> {
|
||||
// F_0 = 1, F_1 = 2
|
||||
let mut sequence = vec![1, 2];
|
||||
|
@ -19,9 +21,9 @@ fn fibonacci(upper_bound: usize) -> Vec<usize> {
|
|||
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!(
|
||||
|
|
|
@ -41,7 +41,7 @@ fn name_score_total(names: Vec<String>) -> usize {
|
|||
return total;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
pub fn main() {
|
||||
let names = read_names();
|
||||
let total = name_score_total(names);
|
||||
|
||||
|
|
|
@ -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}");
|
||||
}
|
||||
|
|
|
@ -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<usize> = 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::<String>())
|
||||
.collect::<Vec<&usize>>();
|
||||
|
||||
|
@ -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}");
|
||||
|
|
|
@ -49,7 +49,7 @@ fn count_triangle_words(words: Vec<String>) -> usize {
|
|||
return count;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
pub fn main() {
|
||||
let words = read_words();
|
||||
let count = count_triangle_words(words);
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ fn first_value_divisible_by(start: usize, end: usize) -> Option<usize> {
|
|||
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}");
|
||||
|
|
|
@ -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<usize> {
|
|||
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<usize> {
|
||||
|
@ -34,7 +36,7 @@ fn square_of_sum(lower_bound: usize, upper_bound: usize) -> Option<usize> {
|
|||
return Some(((lower_bound..(upper_bound + 1)).sum::<usize>()).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;
|
||||
|
|
|
@ -35,7 +35,7 @@ fn maximum_path_sum(triangle: Vec<Vec<usize>>) -> 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);
|
||||
|
|
|
@ -54,7 +54,7 @@ fn nth_prime(n: usize) -> Option<usize> {
|
|||
return Some(primes[n - 1]);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
pub fn main() {
|
||||
let number = nth_prime(10001).unwrap();
|
||||
|
||||
println!("The 10,001st prime number is {number}");
|
||||
|
|
|
@ -71,7 +71,7 @@ fn largest_product(number: &str, adjacent_digits: usize) -> Option<usize> {
|
|||
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}");
|
||||
|
|
|
@ -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);
|
||||
|
|
2
src/commands/mod.rs
Normal file
2
src/commands/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod new;
|
||||
pub mod run;
|
183
src/commands/new.rs
Normal file
183
src/commands/new.rs
Normal file
|
@ -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<u8>) -> Result<(), Box<dyn std::error::Error>> {
|
||||
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::<Vec<&str>>()
|
||||
.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::<Vec<&str>>()
|
||||
.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::<Vec<String>>();
|
||||
|
||||
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("<!-- completed -->([0-9]+)<!-- completed -->")?;
|
||||
|
||||
let new_completed =
|
||||
completed_regex.captures(readme_string.as_str()).unwrap()[1].parse::<u8>()? + 1;
|
||||
|
||||
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)?;
|
||||
|
||||
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::<Vec<String>>();
|
||||
|
||||
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(())
|
||||
}
|
338
src/commands/run.rs
Normal file
338
src/commands/run.rs
Normal file
|
@ -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<u8>,
|
||||
benchmark: bool,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
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(())
|
||||
}
|
48
src/lib.rs
48
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<u8>, 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::<Vec<&str>>()[0]
|
||||
.parse::<i64>()
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
|
202
src/main.rs
202
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<u16>,
|
||||
#[derive(Args)]
|
||||
struct NewArgs {
|
||||
problem: Option<u8>,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
struct RunArgs {
|
||||
problem: Option<u8>,
|
||||
|
||||
#[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<u16>) -> Result<(), Box<dyn std::error::Error>> {
|
||||
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::<Vec<&str>>()[0]
|
||||
.parse::<i64>()
|
||||
.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::<Vec<&str>>()
|
||||
.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::<Vec<&str>>()
|
||||
.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::<Vec<String>>();
|
||||
|
||||
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("<!-- completed -->([0-9]+)<!-- completed -->").unwrap();
|
||||
|
||||
let new_completed = completed_regex.captures(readme_string.as_str()).unwrap()[1]
|
||||
.parse::<u8>()
|
||||
.unwrap()
|
||||
+ 1;
|
||||
|
||||
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.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<dyn std::error::Error>> {
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue