feat(tools): readme updater!
This commit is contained in:
parent
4fa26b9720
commit
5b18aab18d
3 changed files with 173 additions and 12 deletions
BIN
euler.png
Normal file
BIN
euler.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 75 KiB |
114
readme.md
114
readme.md
|
@ -1 +1,113 @@
|
||||||
# readme coming soon
|
<div align="center">
|
||||||
|
<img src="./euler.png">
|
||||||
|
<h1>euler</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
> 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
|
||||||
|
|
||||||
|
<!-- completed -->8<!-- 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)
|
||||||
|
- [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
|
||||||
|
|
71
src/main.rs
71
src/main.rs
|
@ -1,8 +1,9 @@
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use owo_colors::OwoColorize;
|
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 scraper::{Html, Selector};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
use std::io::{BufReader};
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[clap(about, author, version)]
|
#[clap(about, author, version)]
|
||||||
|
@ -19,7 +20,8 @@ enum Commands {
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn new() -> Result<(), Box<dyn std::error::Error>> {
|
async fn new() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
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(
|
let problem_number = requestty::prompt_one(
|
||||||
requestty::Question::int("problemNumber")
|
requestty::Question::int("problemNumber")
|
||||||
|
@ -61,10 +63,10 @@ async fn new() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Fetch the problem information
|
// Fetch the problem information
|
||||||
let body = reqwest::get(format!("https://projecteuler.net/problem={problem_number}")).await?.text().await?;
|
let body = reqwest::get(format!("https://projecteuler.net/problem={problem_number}")).await?.text().await?;
|
||||||
|
|
||||||
let document = Html::parse_document(Box::leak(body.into_boxed_str()));
|
let document = Html::parse_document(body.as_str());
|
||||||
let title_selector = Selector::parse("h2")?;
|
let title_selector = Selector::parse("h2")?;
|
||||||
let content_selector = Selector::parse(".problem_content")?;
|
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
|
let mut title = document
|
||||||
.select(&title_selector)
|
.select(&title_selector)
|
||||||
|
@ -74,16 +76,14 @@ async fn new() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.collect::<Vec<&str>>()
|
.collect::<Vec<&str>>()
|
||||||
.join("");
|
.join("");
|
||||||
|
|
||||||
let mut problem = re
|
let mut problem = html_tag_regex
|
||||||
.replace_all(
|
.replace_all(
|
||||||
Box::leak(
|
document
|
||||||
document
|
|
||||||
.select(&content_selector)
|
.select(&content_selector)
|
||||||
.next()
|
.next()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.inner_html()
|
.inner_html()
|
||||||
.into_boxed_str()
|
.as_str(),
|
||||||
),
|
|
||||||
" "
|
" "
|
||||||
)
|
)
|
||||||
.to_string()
|
.to_string()
|
||||||
|
@ -110,11 +110,60 @@ fn main() {{
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create the file
|
// 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();
|
file.write(file_body.as_bytes()).unwrap();
|
||||||
drop(file);
|
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::<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!
|
// Announce completion!
|
||||||
println!("{}", "File successfully created! Good luck (:".green());
|
println!("{}", "File successfully created! Good luck (:".green());
|
||||||
|
|
Loading…
Reference in a new issue