diff --git a/euler.png b/euler.png new file mode 100644 index 0000000..d19e14a Binary files /dev/null and b/euler.png differ diff --git a/readme.md b/readme.md index aae5791..d2af165 100644 --- a/readme.md +++ b/readme.md @@ -1 +1,113 @@ -# readme coming soon +
+ +

euler

+
+ +> My solutions to many of Project Euler's problems. + +All of the solutions here are written in rust. [main.rs](src/main.rs) is the home to my helper command line that can 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. + +## Challenge Completion + +8 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) +- [x] 3 - [Largest prime factor](src/bin/3.rs) +- [x] 4 - [Largest palindrome product](src/bin/4.rs) +- [x] 5 - [Smallest multiple](src/bin/5.rs) +- [x] 6 - [Sum square difference](src/bin/6.rs) +- [x] 7 - [10001st prime](src/bin/7.rs) +- [x] 8 - [Largest product in a series](src/bin/8.rs) +- [ ] 9 - Special Pythagorean triplet +- [ ] 10 - Summation of primes +- [ ] 11 - Largest product in a grid +- [ ] 12 - Highly divisible triangular number +- [ ] 13 - Large sum +- [ ] 14 - Longest Collatz sequence +- [ ] 15 - Lattice paths +- [ ] 16 - Power digit sum +- [ ] 17 - Number letter counts +- [ ] 18 - Maximum path sum I +- [ ] 19 - Counting Sundays +- [ ] 20 - Factorial digit sum +- [ ] 21 - Amicable numbers +- [ ] 22 - Names scores +- [ ] 23 - Non-abundant sums +- [ ] 24 - Lexicographic permutations +- [ ] 25 - 1000-digit Fibonacci number +- [ ] 26 - Reciprocal cycles +- [ ] 27 - Quadratic primes +- [ ] 28 - Number spiral diagonals +- [ ] 29 - Distinct powers +- [ ] 30 - Digit fifth powers +- [ ] 31 - Coin sums +- [ ] 32 - Pandigital products +- [ ] 33 - Digit cancelling fractions +- [ ] 34 - Digit factorials +- [ ] 35 - Circular primes +- [ ] 36 - Double-base palindromes +- [ ] 37 - Truncatable primes +- [ ] 38 - Pandigital multiples +- [ ] 39 - Integer right triangles +- [ ] 40 - Champernowne's constant +- [ ] 41 - Pandigital prime +- [ ] 42 - Coded triangle numbers +- [ ] 43 - Sub-string divisibility +- [ ] 44 - Pentagon numbers +- [ ] 45 - Triangular, pentagonal, and hexagonal +- [ ] 46 - Goldbach's other conjecture +- [ ] 47 - Distinct primes factors +- [ ] 48 - Self powers +- [ ] 49 - Prime permutations +- [ ] 50 - Consecutive prime sum +- [ ] 51 - Prime digit replacements +- [ ] 52 - Permuted multiples +- [ ] 53 - Combinatoric selections +- [ ] 54 - Poker hands +- [ ] 55 - Lychrel numbers +- [ ] 56 - Powerful digit sum +- [ ] 57 - Square root convergents +- [ ] 58 - Spiral primes +- [ ] 59 - XOR decryption +- [ ] 60 - Prime pair sets +- [ ] 61 - Cyclical figurate numbers +- [ ] 62 - Cubic permutations +- [ ] 63 - Powerful digit counts +- [ ] 64 - Odd period square roots +- [ ] 65 - Convergents of e +- [ ] 66 - Diophantine equation +- [ ] 67 - Maximum path sum II +- [ ] 68 - Magic 5-gon ring +- [ ] 69 - Totient maximum +- [ ] 70 - Totient permutation +- [ ] 71 - Ordered fractions +- [ ] 72 - Counting fractions +- [ ] 73 - Counting fractions in a range +- [ ] 74 - Digit factorial chains +- [ ] 75 - Singular integer right triangles +- [ ] 76 - Counting summations +- [ ] 77 - Prime summations +- [ ] 78 - Coin partitions +- [ ] 79 - Passcode derivation +- [ ] 80 - Square root digital expansion +- [ ] 81 - Path sum: two ways +- [ ] 82 - Path sum: three ways +- [ ] 83 - Path sum: four ways +- [ ] 84 - Monopoly odds +- [ ] 85 - Counting rectangles +- [ ] 86 - Cuboid route +- [ ] 87 - Prime power triples +- [ ] 88 - Product-sum numbers +- [ ] 89 - Roman numerals +- [ ] 90 - Cube digit pairs +- [ ] 91 - Right triangles with integer coordinates +- [ ] 92 - Square digit chains +- [ ] 93 - Arithmetic expressions +- [ ] 94 - Almost equilateral triangles +- [ ] 95 - Amicable chains +- [ ] 96 - Su Doku +- [ ] 97 - Large non-Mersenne prime +- [ ] 98 - Anagramic squares +- [ ] 99 - Largest exponential +- [ ] 100 - Arranged probability diff --git a/src/main.rs b/src/main.rs index 1c13190..6203345 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,9 @@ use clap::{Parser, Subcommand}; use owo_colors::OwoColorize; -use std::{fs, path::Path, io::Write}; +use std::{fs::{self, File, OpenOptions}, path::Path, io::{Write, BufRead}}; use scraper::{Html, Selector}; use regex::Regex; +use std::io::{BufReader}; #[derive(Parser)] #[clap(about, author, version)] @@ -19,7 +20,8 @@ enum Commands { #[tokio::main] async fn new() -> Result<(), Box> { - let code_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("src").join("bin"); + let base_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + let code_path = base_dir.join("src").join("bin"); let problem_number = requestty::prompt_one( requestty::Question::int("problemNumber") @@ -61,10 +63,10 @@ async fn new() -> Result<(), Box> { // Fetch the problem information let body = reqwest::get(format!("https://projecteuler.net/problem={problem_number}")).await?.text().await?; - let document = Html::parse_document(Box::leak(body.into_boxed_str())); + let document = Html::parse_document(body.as_str()); let title_selector = Selector::parse("h2")?; let content_selector = Selector::parse(".problem_content")?; - let re = Regex::new(r"<[^>]*>").unwrap(); + let html_tag_regex = Regex::new(r"<[^>]*>").unwrap(); let mut title = document .select(&title_selector) @@ -74,16 +76,14 @@ async fn new() -> Result<(), Box> { .collect::>() .join(""); - let mut problem = re + let mut problem = html_tag_regex .replace_all( - Box::leak( - document + document .select(&content_selector) .next() .unwrap() .inner_html() - .into_boxed_str() - ), + .as_str(), " " ) .to_string() @@ -110,11 +110,60 @@ fn main() {{ ); // Create the file - let mut file = fs::File::create(code_path.join(format!("{problem_number}.rs"))).unwrap(); + let mut file = File::create(code_path.join(format!("{problem_number}.rs"))).unwrap(); file.write(file_body.as_bytes()).unwrap(); drop(file); - // todo: update readme + // Read the contents of the readme for editing + let readme_path = base_dir.join("readme.md"); + + let mut readme_file = OpenOptions::new() + .read(true) + .open(&readme_path) + .unwrap(); + + let mut readme_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());