feat: rewrite tooling
This commit is contained in:
parent
19742c35b0
commit
7945bdd0ce
16 changed files with 754 additions and 915 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1 @@
|
||||||
/target
|
/target
|
||||||
/binaries
|
|
||||||
/old
|
|
||||||
|
|
6
.vscode/extensions.json
vendored
Normal file
6
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"vadimcn.vscode-lldb",
|
||||||
|
"rust-lang.rust-analyzer"
|
||||||
|
]
|
||||||
|
}
|
26
.vscode/launch.json
vendored
Normal file
26
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug executable 'euler'",
|
||||||
|
"cargo": {
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"--bin=euler",
|
||||||
|
"--package=euler"
|
||||||
|
],
|
||||||
|
"filter": {
|
||||||
|
"name": "euler",
|
||||||
|
"kind": "bin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
"new",
|
||||||
|
"30"
|
||||||
|
],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
850
Cargo.lock
generated
850
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
20
Cargo.toml
20
Cargo.toml
|
@ -5,17 +5,19 @@ edition = "2021"
|
||||||
default-run = "euler"
|
default-run = "euler"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.0.4", features = ["derive"] }
|
clap = { version = "4.4.10", features = ["derive"] }
|
||||||
scraper = "0.14.0"
|
scraper = "0.18.1"
|
||||||
requestty = "0.4.1"
|
requestty = "0.5.0"
|
||||||
reqwest = "0.11"
|
reqwest = "0.11.22"
|
||||||
tokio = { version = "1.23", features = ["full"] }
|
tokio = { version = "1.34.0", features = ["full"] }
|
||||||
regex = "1"
|
regex = "1.10.2"
|
||||||
html-escape = "0.2.13"
|
html-escape = "0.2.13"
|
||||||
phf = { version = "0.11.1", features = ["macros"] }
|
phf = { version = "0.11.2", features = ["macros"] }
|
||||||
rayon = "1.7.0"
|
rayon = "1.8.0"
|
||||||
owo-colors = "3.5.0"
|
owo-colors = "3.5.0"
|
||||||
num-bigint = "0.4.3"
|
num-bigint = "0.4.4"
|
||||||
|
once_cell = "1.18.0"
|
||||||
|
num-to-words = "0.1.1"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
|
|
14
build
14
build
|
@ -1,14 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
cargo build --release --bin "[0-9]*" -q
|
|
||||||
cargo build --release --bin "[0-9]*" -q --target x86_64-pc-windows-gnu
|
|
||||||
|
|
||||||
find ./target/release -maxdepth 1 -type f -perm 755 | while read file; do
|
|
||||||
arr=(${file//\// })
|
|
||||||
mv $file binaries/linux/${arr[3]} > /dev/null
|
|
||||||
done
|
|
||||||
|
|
||||||
find ./target/x86_64-pc-windows-gnu/release -maxdepth 1 -type f -perm 755 | while read file; do
|
|
||||||
arr=(${file//\// })
|
|
||||||
mv $file binaries/win64/${arr[4]} > /dev/null
|
|
||||||
done
|
|
|
@ -16,7 +16,7 @@ All of the solutions here are written in rust. [main.rs](src/main.rs) is the hom
|
||||||
|
|
||||||
## Challenge Completion
|
## Challenge Completion
|
||||||
|
|
||||||
### <!-- completed -->22<!-- completed --> out of 100 public challenges completed.
|
### 22 out of 100 public challenges completed.
|
||||||
|
|
||||||
- [x] 1 - [Multiples of 3 or 5](src/bin/1.rs)
|
- [x] 1 - [Multiples of 3 or 5](src/bin/1.rs)
|
||||||
- [x] 2 - [Even Fibonacci numbers](src/bin/2.rs)
|
- [x] 2 - [Even Fibonacci numbers](src/bin/2.rs)
|
||||||
|
@ -119,4 +119,4 @@ All of the solutions here are written in rust. [main.rs](src/main.rs) is the hom
|
||||||
- [ ] 99 - Largest exponential
|
- [ ] 99 - Largest exponential
|
||||||
- [ ] 100 - Arranged probability
|
- [ ] 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>
|
||||||
|
|
|
@ -4,6 +4,7 @@ Problem 16 - Power digit sum
|
||||||
2 15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
|
2 15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
|
||||||
What is the sum of the digits of the number 2 1000 ?
|
What is the sum of the digits of the number 2 1000 ?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use num_bigint::BigUint;
|
use num_bigint::BigUint;
|
||||||
|
|
||||||
fn get_digits(number: usize) -> Vec<u32> {
|
fn get_digits(number: usize) -> Vec<u32> {
|
||||||
|
|
|
@ -5,11 +5,13 @@ Using names.txt (right click and 'Save Link/Target As...'), a 46K text file co
|
||||||
For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 × 53 = 49714.
|
For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 × 53 = 49714.
|
||||||
What is the total of all the name scores in the file?
|
What is the total of all the name scores in the file?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use euler::RESOURCES;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
fn read_names() -> Vec<String> {
|
fn read_names() -> Vec<String> {
|
||||||
let mut names = fs::read_to_string(euler::resources_path().join("p022_names.txt"))
|
let mut names = fs::read_to_string(RESOURCES.join("p022_names.txt"))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.split(",")
|
.split(",")
|
||||||
.map(|name| Regex::new("\"").unwrap().replace_all(name, "").to_string())
|
.map(|name| Regex::new("\"").unwrap().replace_all(name, "").to_string())
|
||||||
|
|
|
@ -7,11 +7,12 @@ By converting each letter in a word to a number corresponding to its alphabetica
|
||||||
Using words.txt (right click and 'Save Link/Target As...'), a 16K text file containing nearly two-thousand common English words, how many are triangle words?
|
Using words.txt (right click and 'Save Link/Target As...'), a 16K text file containing nearly two-thousand common English words, how many are triangle words?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use euler::RESOURCES;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
fn read_words() -> Vec<String> {
|
fn read_words() -> Vec<String> {
|
||||||
return fs::read_to_string(euler::resources_path().join("p042_words.txt"))
|
return fs::read_to_string(RESOURCES.join("p042_words.txt"))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.split(",")
|
.split(",")
|
||||||
.map(|name| {
|
.map(|name| {
|
||||||
|
|
|
@ -9,10 +9,12 @@ That is, 3 + 7 + 4 + 9 = 23.
|
||||||
Find the maximum total from top to bottom in triangle.txt (right click and 'Save Link/Target As...'), a 15K text file containing a triangle with one-hundred rows.
|
Find the maximum total from top to bottom in triangle.txt (right click and 'Save Link/Target As...'), a 15K text file containing a triangle with one-hundred rows.
|
||||||
NOTE: This is a much more difficult version of Problem 18 . It is not possible to try every route to solve this problem, as there are 2 99 altogether! If you could check one trillion (10 12 ) routes every second it would take over twenty billion years to check them all. There is an efficient algorithm to solve it. ;o)
|
NOTE: This is a much more difficult version of Problem 18 . It is not possible to try every route to solve this problem, as there are 2 99 altogether! If you could check one trillion (10 12 ) routes every second it would take over twenty billion years to check them all. There is an efficient algorithm to solve it. ;o)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use euler::RESOURCES;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
fn read_triangle() -> Vec<Vec<usize>> {
|
fn read_triangle() -> Vec<Vec<usize>> {
|
||||||
return fs::read_to_string(euler::resources_path().join("p067_triangle.txt"))
|
return fs::read_to_string(RESOURCES.join("p067_triangle.txt"))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.split("\n")
|
.split("\n")
|
||||||
.map(|name| {
|
.map(|name| {
|
||||||
|
|
|
@ -1,176 +1,107 @@
|
||||||
|
use euler::{Problem, Result, BASE_DIR, README, SOLUTIONS};
|
||||||
|
use num_to_words::integer_to_en_us as num_to_words;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use scraper::{Html, Selector};
|
use std::fs;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::{
|
use std::{
|
||||||
fs::{File, OpenOptions},
|
fs::{File, OpenOptions},
|
||||||
io::{BufRead, Write},
|
io::{BufRead, Write},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tokio::main]
|
pub async fn execute(number: Option<u8>) -> Result<()> {
|
||||||
pub async fn execute(problem: Option<u8>) -> Result<(), Box<dyn std::error::Error>> {
|
let problem = Problem::new(number).await?;
|
||||||
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())?;
|
|
||||||
|
|
||||||
|
// create a file for the problem
|
||||||
|
let mut file = File::create(SOLUTIONS.join(format!("{}.rs", problem.number)))?;
|
||||||
|
file.write(problem.file_body().as_bytes())?;
|
||||||
drop(file);
|
drop(file);
|
||||||
|
|
||||||
// Read the contents of the readme for editing
|
// open readme
|
||||||
let readme_path = euler::readme_path();
|
let mut readme_file = OpenOptions::new().read(true).open(README.clone())?;
|
||||||
let mut readme_file = OpenOptions::new().read(true).open(&readme_path)?;
|
|
||||||
|
|
||||||
let mut readme_content = BufReader::new(&readme_file)
|
let readme_content = {
|
||||||
.lines()
|
// read
|
||||||
.map(|s| s.unwrap())
|
let mut content = BufReader::new(&readme_file)
|
||||||
.collect::<Vec<String>>();
|
.lines()
|
||||||
|
.map(|s| s.unwrap())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
drop(readme_file);
|
||||||
|
|
||||||
|
// mark problem as done on readme
|
||||||
|
content = content.replace(
|
||||||
|
&format!("\n- [ ] {}", problem.number),
|
||||||
|
&format!("\n- [x] {}", problem.number),
|
||||||
|
);
|
||||||
|
|
||||||
|
// update completed count
|
||||||
|
let completion_regex = Regex::new(r"(\d+) out of")?;
|
||||||
|
let problem_count = fs::read_dir(SOLUTIONS.clone())?.count();
|
||||||
|
|
||||||
|
content = completion_regex
|
||||||
|
.replace(&content, format!("{} out of", problem_count))
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
content
|
||||||
|
};
|
||||||
|
|
||||||
|
// write the new content to the readme
|
||||||
|
readme_file = OpenOptions::new().write(true).open(README.clone())?;
|
||||||
|
readme_file.write(readme_content.as_bytes())?;
|
||||||
drop(readme_file);
|
drop(readme_file);
|
||||||
|
|
||||||
// Mark the problem as done on the readme
|
// add the problem to the run command
|
||||||
let readme_regex = Regex::new(format!(" {problem_number} - (.*)").as_str())?;
|
let mut run_file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(BASE_DIR.join("src").join("commands").join("run.rs"))?;
|
||||||
|
|
||||||
for i in 0..readme_content.len() {
|
let run_content = {
|
||||||
let line = readme_content[i].as_str();
|
let mut content: String = BufReader::new(&run_file)
|
||||||
|
.lines()
|
||||||
|
.map(|s| s.unwrap())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("\n");
|
||||||
|
drop(run_file);
|
||||||
|
|
||||||
if readme_regex.is_match(line) {
|
// add new mod
|
||||||
let matched = readme_regex.captures(line).unwrap();
|
let mod_regex = Regex::new(r#"#\[path = ".+"\]\nmod [A-Za-z_]+;"#)?;
|
||||||
readme_content[i] = format!(
|
let final_mod = mod_regex.find_iter(&content).last().unwrap();
|
||||||
"- [x] {problem_number} - [{}](src/bin/{problem_number}.rs)",
|
let word_number = num_to_words(problem.number as i64)?.replace(" ", "_");
|
||||||
&matched[1].trim()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the summary statistics on the readme
|
content.insert_str(
|
||||||
let mut readme_string = readme_content.join("\n");
|
final_mod.end(),
|
||||||
|
&format!(
|
||||||
|
r#"
|
||||||
|
#[path = "../bin/{}.rs"]
|
||||||
|
mod {};"#,
|
||||||
|
problem.number, word_number
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
let completed_regex = Regex::new("<!-- completed -->([0-9]+)<!-- completed -->")?;
|
// add to match
|
||||||
|
let match_regex = Regex::new(r"\d+ => .+\(\),")?;
|
||||||
|
let final_branch = match_regex.find_iter(&content).last().unwrap();
|
||||||
|
|
||||||
let new_completed =
|
content.insert_str(
|
||||||
completed_regex.captures(readme_string.as_str()).unwrap()[1].parse::<u8>()? + 1;
|
final_branch.end(),
|
||||||
|
&format!(
|
||||||
|
r#"
|
||||||
|
{} => {}::main(),"#,
|
||||||
|
problem.number, word_number
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
readme_string = completed_regex
|
content
|
||||||
.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
|
// Write the new content to the run file
|
||||||
run_file = OpenOptions::new()
|
run_file = OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
.open(&run_path)?;
|
.open(BASE_DIR.join("src").join("commands").join("run.rs"))?;
|
||||||
|
run_file.write(run_content.as_bytes())?;
|
||||||
run_file.write(run_content.join("\n").as_bytes())?;
|
|
||||||
|
|
||||||
drop(run_file);
|
drop(run_file);
|
||||||
|
|
||||||
// Announce completion!
|
// Announce completion!
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
use euler::Problem;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
#[path = "../bin/8.rs"]
|
#[path = "../bin/8.rs"]
|
||||||
mod eight;
|
mod eight;
|
||||||
|
@ -10,6 +12,8 @@ mod eleven;
|
||||||
mod fifteen;
|
mod fifteen;
|
||||||
#[path = "../bin/5.rs"]
|
#[path = "../bin/5.rs"]
|
||||||
mod five;
|
mod five;
|
||||||
|
#[path = "../bin/42.rs"]
|
||||||
|
mod forty_two;
|
||||||
#[path = "../bin/4.rs"]
|
#[path = "../bin/4.rs"]
|
||||||
mod four;
|
mod four;
|
||||||
#[path = "../bin/14.rs"]
|
#[path = "../bin/14.rs"]
|
||||||
|
@ -26,6 +30,8 @@ mod seventeen;
|
||||||
mod six;
|
mod six;
|
||||||
#[path = "../bin/16.rs"]
|
#[path = "../bin/16.rs"]
|
||||||
mod sixteen;
|
mod sixteen;
|
||||||
|
#[path = "../bin/67.rs"]
|
||||||
|
mod sixty_seven;
|
||||||
#[path = "../bin/10.rs"]
|
#[path = "../bin/10.rs"]
|
||||||
mod ten;
|
mod ten;
|
||||||
#[path = "../bin/13.rs"]
|
#[path = "../bin/13.rs"]
|
||||||
|
@ -34,186 +40,29 @@ mod thirteen;
|
||||||
mod three;
|
mod three;
|
||||||
#[path = "../bin/12.rs"]
|
#[path = "../bin/12.rs"]
|
||||||
mod twelve;
|
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"]
|
#[path = "../bin/27.rs"]
|
||||||
mod twenty_seven;
|
mod twenty_seven;
|
||||||
// #[path = "../bin/28.rs"]
|
#[path = "../bin/22.rs"]
|
||||||
// mod twenty_eight;
|
mod twenty_two;
|
||||||
// #[path = "../bin/29.rs"]
|
#[path = "../bin/2.rs"]
|
||||||
// mod twenty_nine;
|
mod two;
|
||||||
// #[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(
|
pub async fn execute(
|
||||||
problem: Option<u8>,
|
problem: Option<u8>,
|
||||||
benchmark: bool,
|
benchmark: bool,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let code_path = euler::code_path();
|
let problem = problem
|
||||||
let problem_number =
|
.unwrap_or_else(|| Problem::prompt_number("Please select a problem:", true).unwrap());
|
||||||
euler::problem_number(problem, &code_path, "Which problem would you like to run?");
|
let mut exists = true; // assume it exists
|
||||||
|
|
||||||
let start = std::time::Instant::now();
|
let start = if benchmark {
|
||||||
let mut exists = true;
|
Some(Instant::now())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
match problem_number {
|
// execute the solution
|
||||||
|
match problem {
|
||||||
1 => one::main(),
|
1 => one::main(),
|
||||||
2 => two::main(),
|
2 => two::main(),
|
||||||
3 => three::main(),
|
3 => three::main(),
|
||||||
|
@ -232,105 +81,28 @@ pub async fn execute(
|
||||||
16 => sixteen::main(),
|
16 => sixteen::main(),
|
||||||
17 => seventeen::main(),
|
17 => seventeen::main(),
|
||||||
18 => eighteen::main(),
|
18 => eighteen::main(),
|
||||||
// 19 => nineteen::main(),
|
|
||||||
// 20 => twenty::main(),
|
|
||||||
// 21 => twenty_one::main(),
|
|
||||||
22 => twenty_two::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(),
|
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(),
|
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;
|
exists = false;
|
||||||
println!(
|
println!(
|
||||||
"{} {} {}",
|
"{}",
|
||||||
"Problem".red().bold(),
|
format!("Problem #{problem} is yet to be solved!")
|
||||||
problem_number.red().bold(),
|
.red()
|
||||||
"is not in this repository!".red().bold()
|
.bold()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let duration = start.elapsed();
|
// if the script exists, print the time elapsed
|
||||||
|
|
||||||
if benchmark && exists {
|
if benchmark && exists {
|
||||||
|
let duration = start.unwrap().elapsed();
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Time elapsed when executing problem {} is: {:?}",
|
"
|
||||||
problem_number, duration
|
Time elapsed when executing problem {} is: {:?}",
|
||||||
|
problem, duration
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
73
src/lib.rs
73
src/lib.rs
|
@ -1,65 +1,16 @@
|
||||||
use std::path::{Path, PathBuf};
|
mod problem;
|
||||||
|
|
||||||
fn fetch_dir() -> &'static Path {
|
use once_cell::sync::Lazy;
|
||||||
return Path::new(env!("CARGO_MANIFEST_DIR"));
|
pub use problem::Problem;
|
||||||
}
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub fn code_path() -> PathBuf {
|
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
return fetch_dir().join("src").join("bin");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resources_path() -> PathBuf {
|
// paths
|
||||||
return fetch_dir().join("resources");
|
pub const BASE_DIR: Lazy<PathBuf> = Lazy::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")));
|
||||||
}
|
pub const SOLUTIONS: Lazy<PathBuf> = Lazy::new(|| BASE_DIR.join("src").join("bin"));
|
||||||
|
pub const RESOURCES: Lazy<PathBuf> = Lazy::new(|| BASE_DIR.join("resources"));
|
||||||
|
pub const README: Lazy<PathBuf> = Lazy::new(|| BASE_DIR.join("readme.md"));
|
||||||
|
|
||||||
pub fn readme_path() -> PathBuf {
|
// panic channel
|
||||||
return fetch_dir().join("readme.md");
|
pub static mut SILENT_PANIC: bool = false;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -1,8 +1,12 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use clap::{Args, Parser, Subcommand};
|
|
||||||
mod commands;
|
mod commands;
|
||||||
|
|
||||||
|
use std::panic;
|
||||||
|
|
||||||
|
use clap::{Args, Parser, Subcommand};
|
||||||
|
use euler::{Result, SILENT_PANIC};
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[clap(about, author, version)]
|
#[clap(about, author, version)]
|
||||||
struct Value {
|
struct Value {
|
||||||
|
@ -32,11 +36,22 @@ enum Commands {
|
||||||
Run(RunArgs),
|
Run(RunArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
#[tokio::main]
|
||||||
|
pub async fn main() -> Result<()> {
|
||||||
|
panic::set_hook(Box::new(move |panic_info| {
|
||||||
|
if unsafe { SILENT_PANIC } {
|
||||||
|
std::process::exit(0);
|
||||||
|
} else {
|
||||||
|
println!("{}", panic_info.to_string());
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
let value = Value::parse();
|
let value = Value::parse();
|
||||||
|
|
||||||
match value.command {
|
match value.command {
|
||||||
Commands::New(NewArgs { problem }) => commands::new::execute(problem),
|
Commands::New(NewArgs { problem }) => commands::new::execute(problem).await,
|
||||||
Commands::Run(RunArgs { problem, benchmark }) => commands::run::execute(problem, benchmark),
|
Commands::Run(RunArgs { problem, benchmark }) => {
|
||||||
|
commands::run::execute(problem, benchmark).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
126
src/problem.rs
Normal file
126
src/problem.rs
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
use crate::{Result, SILENT_PANIC, SOLUTIONS};
|
||||||
|
use regex::Regex;
|
||||||
|
use scraper::{Html, Selector};
|
||||||
|
|
||||||
|
pub struct Problem {
|
||||||
|
pub number: u8,
|
||||||
|
title: String,
|
||||||
|
content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Problem {
|
||||||
|
pub fn prompt_number(prompt: &str, want_solved: bool) -> Result<u8> {
|
||||||
|
unsafe {
|
||||||
|
SILENT_PANIC = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let number = requestty::prompt_one(
|
||||||
|
requestty::Question::int("problemNumber")
|
||||||
|
.message(prompt)
|
||||||
|
.validate(|n, _| {
|
||||||
|
// ensure the number is in bound
|
||||||
|
if n <= 0 {
|
||||||
|
Err("Please enter a number greater than 0".to_string())
|
||||||
|
} else if n > 100 {
|
||||||
|
Err("Please enter a number less than or equal to 100".to_string())
|
||||||
|
}
|
||||||
|
// ensure that the problem has not already got a file associated with it
|
||||||
|
else {
|
||||||
|
let has_file = std::fs::read_dir(SOLUTIONS.clone()).unwrap().any(|x| {
|
||||||
|
x.unwrap()
|
||||||
|
.file_name()
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.split(".")
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.parse::<i64>()
|
||||||
|
.unwrap()
|
||||||
|
== n
|
||||||
|
});
|
||||||
|
|
||||||
|
if !want_solved && has_file {
|
||||||
|
Err("This problem has already been solved".to_string())
|
||||||
|
} else if want_solved && !has_file {
|
||||||
|
Err("This problem has not been solved yet".to_string())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build(),
|
||||||
|
)?
|
||||||
|
.as_int()
|
||||||
|
.unwrap() as u8;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
SILENT_PANIC = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(number)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn new(number: Option<u8>) -> Result<Self> {
|
||||||
|
let number = number
|
||||||
|
.unwrap_or_else(|| Self::prompt_number("Please select a problem:", false).unwrap());
|
||||||
|
|
||||||
|
let body = reqwest::get(format!("https://projecteuler.net/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 title = document
|
||||||
|
.select(&title_selector)
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.text()
|
||||||
|
.collect::<Vec<&str>>()
|
||||||
|
.join("");
|
||||||
|
|
||||||
|
let problem = html_tag_regex
|
||||||
|
.replace_all(
|
||||||
|
document
|
||||||
|
.select(&content_selector)
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.inner_html()
|
||||||
|
.as_str(),
|
||||||
|
" ",
|
||||||
|
)
|
||||||
|
.to_string()
|
||||||
|
.replace("$$", " ");
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
number,
|
||||||
|
title: title.trim().to_string(),
|
||||||
|
content: problem.trim().to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_body(&self) -> String {
|
||||||
|
format!(
|
||||||
|
"/*
|
||||||
|
Problem {} - {}
|
||||||
|
|
||||||
|
{}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub fn main() {{
|
||||||
|
println!(\"Hello World!\");
|
||||||
|
}}",
|
||||||
|
self.number,
|
||||||
|
html_escape::decode_html_entities(&self.title).to_string(),
|
||||||
|
html_escape::decode_html_entities(&self.content)
|
||||||
|
.split("\n")
|
||||||
|
.map(|s| s.trim())
|
||||||
|
.filter(|s| s != &"")
|
||||||
|
.collect::<Vec<&str>>()
|
||||||
|
.join("\n")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue