From 0a47fcbb86e3f4f7ea66e30406b8d73ab50acd77 Mon Sep 17 00:00:00 2001 From: Lam <15622383059@163.com> Date: Thu, 4 Jul 2019 23:00:11 +0800 Subject: [PATCH 1/3] add feature - generate random problem use "cargo run random" to generate a random problem. --- src/main.rs | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 438c3edc..1dbaeb87 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,8 +16,18 @@ fn main() { if args.len() < 2 { panic!("problem id must be provided"); } - let id = &args[1]; - let id = id.parse::().expect(&format!("not a number: {}", id)); + let id_arg = &args[1]; + let mut id :u32 = 0; + match id_arg.as_ref() { + "random" => { + println!("You select random mode."); + id = get_random_id(); + println!("Generate random problem: {}", &id); + }, + _ => { + id = id_arg.parse::().expect(&format!("not a number: {}", id)); + } + } let problem = problem::get_problem(id) .expect(&format!("problem #{} not found", id)); @@ -58,6 +68,32 @@ fn main() { writeln!(lib_file, "mod {};", file_name); } +fn get_random_id() -> u32 { + use std::fs; + let paths = fs::read_dir("./src").unwrap(); + let mut solved_ids = Vec::new(); + + for path in paths { + let path = path.unwrap().path(); + let s = path.to_str().unwrap(); + if s.chars().next().unwrap() != 'n' { + continue; + } + let id = &s[7..11]; + let id = id.parse::().unwrap(); + solved_ids.push(id); + } + use rand::Rng; + let mut rng = rand::thread_rng(); + loop { + let res :u32 = rng.gen_range(1, 1106); + if !solved_ids.contains(&res) { + return res; + } + println!("Generate a random num ({}), but it is solved. Regenerate..", res); + } +} + fn parse_extra_use(code: &str) -> String { let mut extra_use_line = String::new(); // a linked-list problem From d683d19286fb5ae2ebdb1d571a5d04816ac12583 Mon Sep 17 00:00:00 2001 From: Lam <15622383059@163.com> Date: Sat, 6 Jul 2019 12:06:33 +0800 Subject: [PATCH 2/3] Regenerate an id in case the previous generated id is invalide. Now that using "cargo run" is ok! Then the user could follow the guide of the system output to do what he/she wants to do (e.g., generate a random problem or select a particular problem). --- src/main.rs | 137 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 80 insertions(+), 57 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1dbaeb87..1c4c0a78 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,67 +9,98 @@ use std::env; use std::fs; use std::path::{Path}; use std::io::Write; +use std::io; /// main() helps to generate the submission template .rs fn main() { - let args: Vec = env::args().collect(); - if args.len() < 2 { - panic!("problem id must be provided"); - } - let id_arg = &args[1]; - let mut id :u32 = 0; - match id_arg.as_ref() { - "random" => { - println!("You select random mode."); - id = get_random_id(); - println!("Generate random problem: {}", &id); - }, - _ => { - id = id_arg.parse::().expect(&format!("not a number: {}", id)); + println!("Welcome to leetcode-rust system."); + let mut solved_ids = get_solved_ids(); + loop { + println!("Please enter a problem id, or enter \"random\" to generate a random problem."); + let mut is_random = false; + let mut id :u32 = 0; + let mut id_arg = String::new(); + io::stdin().read_line(&mut id_arg) + .expect("Failed to read line"); + let id_arg = id_arg.trim(); + match id_arg { + "random" => { + println!("You select random mode."); + id = generate_random_id(&solved_ids); + is_random = true; + println!("Generate random problem: {}", &id); + }, + _ => { + id = id_arg.parse::().expect(&format!("not a number: {}", id_arg)); + if solved_ids.contains(&id) { + println!("The problem you chose is invalid (the problem may have been solved \ + or may have no rust version)."); + continue; + } + } } - } - let problem = problem::get_problem(id) - .expect(&format!("problem #{} not found", id)); - let code = problem.code_definition.iter() - .filter(|&d| { d.value == "rust" }) - .next() - .expect("problem has no rust support yet"); + let problem = problem::get_problem(id) + .expect(&format!("problem #{} not found", id)); + let code = problem.code_definition.iter() + .filter(|&d| { d.value == "rust" }) + .next(); + if code.is_none() { + println!("Problem {} has no rust version.", &id); + solved_ids.push(id); + continue; + } + let code = code.unwrap(); - let file_name = format!("n{:04}_{}", id, problem.title_slug.replace("-", "_")); - let file_path = Path::new("./src").join(format!("{}.rs", file_name)); - if file_path.exists() { - panic!("problem already initialized"); - } + let file_name = format!("n{:04}_{}", id, problem.title_slug.replace("-", "_")); + let file_path = Path::new("./src").join(format!("{}.rs", file_name)); + if file_path.exists() { + panic!("problem already initialized"); + } - let template = fs::read_to_string("./template.rs").unwrap(); - let source = template - .replace("__PROBLEM_TITLE__", &problem.title) - .replace("__PROBLEM_DESC__", &build_desc(&problem.content)) - .replace("__PROBLEM_DEFAULT_CODE__", &code.default_code) - .replace("__PROBLEM_ID__", &format!("{}", id)) - .replace("__EXTRA_USE__", &parse_extra_use(&code.default_code)); + let template = fs::read_to_string("./template.rs").unwrap(); + let source = template + .replace("__PROBLEM_TITLE__", &problem.title) + .replace("__PROBLEM_DESC__", &build_desc(&problem.content)) + .replace("__PROBLEM_DEFAULT_CODE__", &code.default_code) + .replace("__PROBLEM_ID__", &format!("{}", id)) + .replace("__EXTRA_USE__", &parse_extra_use(&code.default_code)); - let mut file = fs::OpenOptions::new() - .write(true) - .create(true) - .truncate(true) - .open(&file_path) - .unwrap(); + let mut file = fs::OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(&file_path) + .unwrap(); - file.write_all(source.as_bytes()).unwrap(); - drop(file); + file.write_all(source.as_bytes()).unwrap(); + drop(file); - let mut lib_file = fs::OpenOptions::new() - .write(true) - .append(true) - .open("./src/lib.rs") - .unwrap(); - writeln!(lib_file, "mod {};", file_name); + let mut lib_file = fs::OpenOptions::new() + .write(true) + .append(true) + .open("./src/lib.rs") + .unwrap(); + writeln!(lib_file, "mod {};", file_name); + break; + } } -fn get_random_id() -> u32 { +fn generate_random_id(except_ids : &Vec) -> u32 { use std::fs; + use rand::Rng; + let mut rng = rand::thread_rng(); + loop { + let res :u32 = rng.gen_range(1, 1106); + if !except_ids.contains(&res) { + return res; + } + println!("Generate a random num ({}), but it is invalid (the problem may have been solved \ + or may have no rust version). Regenerate..", res); + } +} + +fn get_solved_ids() -> Vec { let paths = fs::read_dir("./src").unwrap(); let mut solved_ids = Vec::new(); @@ -83,15 +114,7 @@ fn get_random_id() -> u32 { let id = id.parse::().unwrap(); solved_ids.push(id); } - use rand::Rng; - let mut rng = rand::thread_rng(); - loop { - let res :u32 = rng.gen_range(1, 1106); - if !solved_ids.contains(&res) { - return res; - } - println!("Generate a random num ({}), but it is solved. Regenerate..", res); - } + solved_ids } fn parse_extra_use(code: &str) -> String { From c6847a529eb321df209eb659c2ac42e5e65fe99c Mon Sep 17 00:00:00 2001 From: Lam <15622383059@163.com> Date: Sun, 7 Jul 2019 12:06:31 +0800 Subject: [PATCH 3/3] panic when the problem is locked --- src/main.rs | 4 +++- src/problem.rs | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 1c4c0a78..5460227b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,7 +41,9 @@ fn main() { } let problem = problem::get_problem(id) - .expect(&format!("problem #{} not found", id)); + .expect(&format!("Error: failed to get problem #{} \ + (The problem may be paid-only or may not be exist).", + id)); let code = problem.code_definition.iter() .filter(|&d| { d.value == "rust" }) .next(); diff --git a/src/problem.rs b/src/problem.rs index bd920f45..ba51f04f 100644 --- a/src/problem.rs +++ b/src/problem.rs @@ -21,6 +21,11 @@ pub fn get_problem(id: u32) -> Option { let problems = get_problems().unwrap(); for problem in problems.stat_status_pairs.iter() { if problem.stat.question_id == id { + + if problem.paid_only { + return None + } + let client = reqwest::Client::new(); let resp: RawProblem = client.post(GRAPHQL_URL) .json(&Query::question_query(problem.stat.question_title_slug.as_ref().unwrap()))