diff --git a/Cargo.toml b/Cargo.toml index d97a5dc..530719f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ repository = "https://github.com/coding-kelps/leetcode-cli" rust-version = "1.83" [[bin]] -name = "leetcode_cli" +name = "leetcode-cli" path = "src/main.rs" [lib] @@ -35,3 +35,5 @@ colored = "3.0.0" nanohtml2text = "0.2.1" html2md = "0.2.15" tempfile = "3.20.0" +regex = "1.11.1" +thiserror = "2.0.12" diff --git a/src/cli.rs b/src/cli.rs index a2c35f0..0210fd6 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -20,7 +20,7 @@ pub enum Commands { id: u32, #[arg(short = 'l', long = "lang")] - language: String, + language: Option, }, Test { #[arg(short = 'i', long)] diff --git a/src/config.rs b/src/config.rs index c7a3cc7..4ba18e1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -23,6 +23,12 @@ pub struct RuntimeConfigSetup { pub config: ConfigFile, } +impl Default for RuntimeConfigSetup { + fn default() -> Self { + Self::new() + } +} + impl RuntimeConfigSetup { pub fn new() -> Self { let home_dir = @@ -87,9 +93,9 @@ impl RuntimeConfigSetup { let raw_str = raw.as_ref(); let mut path = if raw_str == "~" { self.home_dir.clone() - } else if raw_str.starts_with("~/") { + } else if let Some(stripped) = raw_str.strip_prefix("~/") { let home = self.home_dir.clone(); - home.join(&raw_str[2..]) + home.join(stripped) } else { PathBuf::from(raw_str) }; diff --git a/src/leetcode_api_runner.rs b/src/leetcode_api_runner.rs index 278c394..a11e4cb 100644 --- a/src/leetcode_api_runner.rs +++ b/src/leetcode_api_runner.rs @@ -23,10 +23,10 @@ pub struct LeetcodeApiRunner { } impl LeetcodeApiRunner { - pub async fn new(rcs: RuntimeConfigSetup) -> Self { + pub async fn new(rcs: &RuntimeConfigSetup) -> Self { let api = UserApi::new(&rcs.config.leetcode_token).await.unwrap(); LeetcodeApiRunner { - rcs, + rcs: rcs.clone(), api, } } @@ -155,19 +155,19 @@ impl LeetcodeApiRunner { let result = match language { ProgrammingLanguage::Rust => Command::new("cargo") - .args(&["init", "--name", pb_name, "--vcs", "none"]) + .args(["init", "--name", pb_name, "--vcs", "none"]) .current_dir(problem_dir) .output(), ProgrammingLanguage::JavaScript | ProgrammingLanguage::TypeScript => Command::new("npm") - .args(&["init", "-y"]) + .args(["init", "-y"]) .current_dir(problem_dir) .output(), ProgrammingLanguage::Go => { let module_name = format!("leetcode-{}", pb_name.replace("_", "-")); Command::new("go") - .args(&["mod", "init", &module_name]) + .args(["mod", "init", &module_name]) .current_dir(problem_dir) .output() }, diff --git a/src/lib.rs b/src/lib.rs index 497c796..0f66a72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ pub mod cli; pub mod config; pub mod leetcode_api_runner; +pub mod readme_parser; pub mod utils; pub use cli::{ diff --git a/src/main.rs b/src/main.rs index c240346..4ce5f4b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ async fn main() -> Result<(), Box> { let cli = Cli::parse(); let mut rcs = RuntimeConfigSetup::new(); rcs.status()?; - let api_runner = LeetcodeApiRunner::new(rcs).await; + let api_runner = LeetcodeApiRunner::new(&rcs).await; match &cli.command { Commands::Info { @@ -24,11 +24,13 @@ async fn main() -> Result<(), Box> { id, language, } => { - let language = utils::parse_programming_language(language); - println!( - "{}\nHappy Coding :)", - api_runner.start_problem(*id, language).await? - ); + let default = &rcs.config.default_language.unwrap(); + let lang = match language { + Some(lang) => utils::parse_programming_language(lang)?, + None => utils::parse_programming_language(default)?, + }; + let start_problem = api_runner.start_problem(*id, lang).await?; + println!("{}\n\nHappy coding :)", start_problem); }, Commands::Test { id, diff --git a/src/readme_parser.rs b/src/readme_parser.rs new file mode 100644 index 0000000..bb8b0b0 --- /dev/null +++ b/src/readme_parser.rs @@ -0,0 +1,89 @@ +use regex::Regex; +use thiserror; + +pub struct LeetcodeReadmeParser { + pub raw: String, +} + +pub struct ProblemTestData { + pub example_count: usize, + pub inputs: Vec, + pub outputs: Vec, +} + +#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)] +pub enum LeetcodeReadmeParserError { + #[error("can't parse empty readme")] + EmptyReadme, +} + +impl LeetcodeReadmeParser { + pub fn new(readme: &str) -> Self { + LeetcodeReadmeParser { + raw: readme.to_string(), + } + } + + pub fn parse(&self) -> Result { + if self.raw.is_empty() { + return Err(LeetcodeReadmeParserError::EmptyReadme); + } + Ok(ProblemTestData { + example_count: self.count_examples(), + inputs: self.extract_inputs(), + outputs: self.extract_outputs(), + }) + } + + fn count_examples(&self) -> usize { + self.raw + .lines() + .filter(|line| line.starts_with("**Example")) + .count() + } + + fn extract_inputs(&self) -> Vec { + self.extract_from_pattern(r"(?m)^\s*\*?\*?Input:\*?\*?\s*(.*)$") + } + + fn extract_outputs(&self) -> Vec { + self.extract_from_pattern(r"(?m)^\s*\*?\*?Output:\*?\*?\s*(.*)$") + } + + fn extract_from_pattern(&self, pattern: &str) -> Vec { + let re = Regex::new(pattern).unwrap(); + + let mut result = Vec::new(); + for capture in re.captures_iter(&self.raw) { + if let Some(matched) = capture.get(1) { + let input = matched + .as_str() + .replace(['\n', '\t'], " ") + .trim() + .to_string(); + + let trimmed = if input.contains('=') { + input + .split(',') + .filter_map(|part| { + if let Some(eq_pos) = part.find('=') { + Some(part[eq_pos + 1..].trim()) + } else { + // Handle continuation of previous array/value + let trimmed_part = part.trim(); + (!trimmed_part.is_empty()) + .then_some(trimmed_part) + } + }) + .collect::>() + .join(",") + } else { + input.to_string() + }; + + result.push(trimmed); + } + } + result + } +} diff --git a/src/utils.rs b/src/utils.rs index 8a59506..18b7d0b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -34,31 +34,35 @@ pub fn write_to_file( pub fn parse_programming_language( lang: &str, -) -> leetcoderustapi::ProgrammingLanguage { +) -> Result { match lang.to_ascii_lowercase().as_str() { - "cpp" | "c++" => leetcoderustapi::ProgrammingLanguage::CPP, - "java" => leetcoderustapi::ProgrammingLanguage::Java, - "python" | "py" => leetcoderustapi::ProgrammingLanguage::Python, - "python3" | "py3" => leetcoderustapi::ProgrammingLanguage::Python3, - "c" => leetcoderustapi::ProgrammingLanguage::C, - "csharp" | "c#" => leetcoderustapi::ProgrammingLanguage::CSharp, - "javascript" | "js" => leetcoderustapi::ProgrammingLanguage::JavaScript, - "typescript" | "ts" => leetcoderustapi::ProgrammingLanguage::TypeScript, - "ruby" => leetcoderustapi::ProgrammingLanguage::Ruby, - "swift" => leetcoderustapi::ProgrammingLanguage::Swift, - "go" | "golang" => leetcoderustapi::ProgrammingLanguage::Go, - "bash" | "shell" => leetcoderustapi::ProgrammingLanguage::Bash, - "scala" => leetcoderustapi::ProgrammingLanguage::Scala, - "kotlin" | "kt" => leetcoderustapi::ProgrammingLanguage::Kotlin, - "rust" | "rs" => leetcoderustapi::ProgrammingLanguage::Rust, - "php" => leetcoderustapi::ProgrammingLanguage::PHP, - "racket" => leetcoderustapi::ProgrammingLanguage::Racket, - "erlang" => leetcoderustapi::ProgrammingLanguage::Erlang, - "elixir" => leetcoderustapi::ProgrammingLanguage::Elixir, - "dart" => leetcoderustapi::ProgrammingLanguage::Dart, - "pandas" => leetcoderustapi::ProgrammingLanguage::Pandas, - "react" => leetcoderustapi::ProgrammingLanguage::React, - _ => panic!("Unsupported language: {}", lang), + "cpp" | "c++" => Ok(leetcoderustapi::ProgrammingLanguage::CPP), + "java" => Ok(leetcoderustapi::ProgrammingLanguage::Java), + "python" | "py" => Ok(leetcoderustapi::ProgrammingLanguage::Python), + "python3" | "py3" => Ok(leetcoderustapi::ProgrammingLanguage::Python3), + "c" => Ok(leetcoderustapi::ProgrammingLanguage::C), + "csharp" | "c#" => Ok(leetcoderustapi::ProgrammingLanguage::CSharp), + "javascript" | "js" => { + Ok(leetcoderustapi::ProgrammingLanguage::JavaScript) + }, + "typescript" | "ts" => { + Ok(leetcoderustapi::ProgrammingLanguage::TypeScript) + }, + "ruby" => Ok(leetcoderustapi::ProgrammingLanguage::Ruby), + "swift" => Ok(leetcoderustapi::ProgrammingLanguage::Swift), + "go" | "golang" => Ok(leetcoderustapi::ProgrammingLanguage::Go), + "bash" | "shell" => Ok(leetcoderustapi::ProgrammingLanguage::Bash), + "scala" => Ok(leetcoderustapi::ProgrammingLanguage::Scala), + "kotlin" | "kt" => Ok(leetcoderustapi::ProgrammingLanguage::Kotlin), + "rust" | "rs" => Ok(leetcoderustapi::ProgrammingLanguage::Rust), + "php" => Ok(leetcoderustapi::ProgrammingLanguage::PHP), + "racket" => Ok(leetcoderustapi::ProgrammingLanguage::Racket), + "erlang" => Ok(leetcoderustapi::ProgrammingLanguage::Erlang), + "elixir" => Ok(leetcoderustapi::ProgrammingLanguage::Elixir), + "dart" => Ok(leetcoderustapi::ProgrammingLanguage::Dart), + "pandas" => Ok(leetcoderustapi::ProgrammingLanguage::Pandas), + "react" => Ok(leetcoderustapi::ProgrammingLanguage::React), + _ => Err(format!("Unsupported language: {}", lang)), } } diff --git a/tests/cli_tests.rs b/tests/cli_tests.rs index bd08c2a..a929928 100644 --- a/tests/cli_tests.rs +++ b/tests/cli_tests.rs @@ -28,7 +28,7 @@ fn test_cli_start_command() { language, } => { assert_eq!(id, 1); - assert_eq!(language, "rust"); + assert_eq!(language.unwrap(), "rust"); }, _ => panic!("Expected Start command"), } diff --git a/tests/data/1004.md b/tests/data/1004.md new file mode 100644 index 0000000..aea12bf --- /dev/null +++ b/tests/data/1004.md @@ -0,0 +1,28 @@ +# Problem 1004: Max_Consecutive_Ones_III + +Given a binary array `nums` and an integer `k`, return *the maximum number of consecutive* `1`*'s in the array if you can flip at most* `k` `0`'s. + +**Example 1:** + +``` +Input: nums = [1,1,1,0,0,0,1,1,1,1,0], k = 2 +Output: 6 +Explanation: [1,1,1,0,0,1,1,1,1,1,1] +Bolded numbers were flipped from 0 to 1. The longest subarray is underlined. +``` + +**Example 2:** + +``` +Input: nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], k = 3 +Output: 10 +Explanation: [0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1] +Bolded numbers were flipped from 0 to 1. The longest subarray is underlined. + +``` + +**Constraints:** + +* `1 <= nums.length <= 105` +* `nums[i]` is either `0` or `1`. +* `0 <= k <= nums.length` \ No newline at end of file diff --git a/tests/data/1768.md b/tests/data/1768.md new file mode 100644 index 0000000..eb00ee1 --- /dev/null +++ b/tests/data/1768.md @@ -0,0 +1,46 @@ +# Problem 1768: Merge_Strings_Alternately + +You are given two strings `word1` and `word2`. Merge the strings by adding letters in alternating order, starting with `word1`. If a string is longer than the other, append the additional letters onto the end of the merged string. + +Return *the merged string.* + +**Example 1:** + +``` +Input: word1 = "abc", word2 = "pqr" +Output: "apbqcr" +Explanation: The merged string will be merged as so: +word1: a b c +word2: p q r +merged: a p b q c r + +``` + +**Example 2:** + +``` +Input: word1 = "ab", word2 = "pqrs" +Output: "apbqrs" +Explanation: Notice that as word2 is longer, "rs" is appended to the end. +word1: a b +word2: p q r s +merged: a p b q r s + +``` + +**Example 3:** + +``` +Input: word1 = "abcd", word2 = "pq" +Output: "apbqcd" +Explanation: Notice that as word1 is longer, "cd" is appended to the end. +word1: a b c d +word2: p q +merged: a p b q c d + +``` + +**Constraints:** + +* `1 <= word1.length, word2.length <= 100` +* `word1` and `word2` consist of lowercase English letters. \ No newline at end of file diff --git a/tests/data/221.md b/tests/data/221.md new file mode 100644 index 0000000..22adc2e --- /dev/null +++ b/tests/data/221.md @@ -0,0 +1,38 @@ +# Problem 221: Maximal_Square + +Given an `m x n` binary `matrix` filled with `0`'s and `1`'s, *find the largest square containing only* `1`'s *and return its area*. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2020/11/26/max1grid.jpg) + +``` +Input: matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]] +Output: 4 + +``` + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2020/11/26/max2grid.jpg) + +``` +Input: matrix = [["0","1"],["1","0"]] +Output: 1 + +``` + +**Example 3:** + +``` +Input: matrix = [["0"]] +Output: 0 + +``` + +**Constraints:** + +* `m == matrix.length` +* `n == matrix[i].length` +* `1 <= m, n <= 300` +* `matrix[i][j]` is `'0'` or `'1'`. \ No newline at end of file diff --git a/tests/data/3467.md b/tests/data/3467.md new file mode 100644 index 0000000..09c2fff --- /dev/null +++ b/tests/data/3467.md @@ -0,0 +1,36 @@ +# Problem 3467: Transform_Array_by_Parity + +You are given an integer array `nums`. Transform `nums` by performing the following operations in the **exact** order specified: + +1. Replace each even number with 0. +2. Replace each odd numbers with 1. +3. Sort the modified array in **non-decreasing** order. + +Return the resulting array after performing these operations. + +**Example 1:** + +**Input:** nums = [4,3,2,1] + +**Output:** [0,0,1,1] + +**Explanation:** + +* Replace the even numbers (4 and 2) with 0 and the odd numbers (3 and 1) with 1. Now, `nums = [0, 1, 0, 1]`. +* After sorting `nums` in non-descending order, `nums = [0, 0, 1, 1]`. + +**Example 2:** + +**Input:** nums = [1,5,1,4,2] + +**Output:** [0,0,1,1,1] + +**Explanation:** + +* Replace the even numbers (4 and 2) with 0 and the odd numbers (1, 5 and 1) with 1. Now, `nums = [1, 1, 1, 0, 0]`. +* After sorting `nums` in non-descending order, `nums = [0, 0, 1, 1, 1]`. + +**Constraints:** + +* `1 <= nums.length <= 100` +* `1 <= nums[i] <= 1000` \ No newline at end of file diff --git a/tests/data/392.md b/tests/data/392.md new file mode 100644 index 0000000..c02fecb --- /dev/null +++ b/tests/data/392.md @@ -0,0 +1,28 @@ +# 392 Is Subsequence +Given two strings `s` and `t`, return `true` *if* `s` *is a **subsequence** of* `t`*, or* `false` *otherwise*. + +A **subsequence** of a string is a new string that is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (i.e., `"ace"` is a subsequence of `"abcde"` while `"aec"` is not). + +**Example 1:** + +``` +Input: s = "abc", t = "ahbgdc" +Output: true + +``` + +**Example 2:** + +``` +Input: s = "axc", t = "ahbgdc" +Output: false + +``` + +**Constraints:** + +* `0 <= s.length <= 100` +* `0 <= t.length <= 10^4` +* `s` and `t` consist only of lowercase English letters. + +**Follow up:** Suppose there are lots of incoming `s`, say `s1, s2, ..., sk` where `k >= 10^9`, and you want to check one by one to see if `t` has its subsequence. In this scenario, how would you change your code? \ No newline at end of file diff --git a/tests/data/823.md b/tests/data/823.md new file mode 100644 index 0000000..b1ececd --- /dev/null +++ b/tests/data/823.md @@ -0,0 +1,29 @@ +# Problem 823: Binary_Trees_With_Factors + +Given an array of unique integers, `arr`, where each integer `arr[i]` is strictly greater than `1`. + +We make a binary tree using these integers, and each number may be used for any number of times. Each non-leaf node's value should be equal to the product of the values of its children. + +Return *the number of binary trees we can make*. The answer may be too large so return the answer **modulo** `109 + 7`. + +**Example 1:** + +``` +Input: arr = [2,4] +Output: 3 +Explanation: We can make these trees: [2], [4], [4, 2, 2] +``` + +**Example 2:** + +``` +Input: arr = [2,4,5,10] +Output: 7 +Explanation: We can make these trees: [2], [4], [5], [10], [4, 2, 2], [10, 2, 5], [10, 5, 2]. +``` + +**Constraints:** + +* `1 <= arr.length <= 1000` +* `2 <= arr[i] <= 109` +* All the values of `arr` are **unique**. \ No newline at end of file diff --git a/tests/readme_parser_tests.rs b/tests/readme_parser_tests.rs new file mode 100644 index 0000000..9a9a32b --- /dev/null +++ b/tests/readme_parser_tests.rs @@ -0,0 +1,286 @@ +use leetcode_cli::readme_parser::{ + LeetcodeReadmeParser, + LeetcodeReadmeParserError, +}; + +#[test] +fn new_leetcode_readme_parser() { + let readme_content = "# a random LeetCode Problem!"; + let lrp = LeetcodeReadmeParser::new(readme_content); + + assert_eq!(lrp.raw, readme_content); +} + +#[test] +fn test_parse_empty_readme() { + let empty_readme = String::new(); + let lrp = LeetcodeReadmeParser::new(&empty_readme); + + match lrp.parse() { + Ok(_) => { + panic!("Unexpected Ok result when testing empty readme parsing") + }, + Err(e) => { + assert!( + matches!(e, LeetcodeReadmeParserError::EmptyReadme), + "Unexpected error when testing empty readme parsing" + ); + }, + } +} + +#[test] +fn test_3467_count_example() { + let readme_content = std::fs::read_to_string("tests/data/3467.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + assert_eq!( + problem_data.example_count, 2, + "Expected 2 test cases in the readme" + ); +} + +#[test] +fn test_3467_inputs_0_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/3467.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + + let input = &problem_data.inputs[0]; + let expected = "[4,3,2,1]"; + + assert_eq!(input, expected, "first input mismatch"); +} + +#[test] +fn test_3467_outputs_1_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/3467.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + + let output = &problem_data.outputs[1]; + let expected = "[0,0,1,1,1]"; + + assert_eq!(output, expected, "second output mismatch"); +} + +#[test] +fn test_392_count_example() { + let readme_content = std::fs::read_to_string("tests/data/392.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + assert_eq!( + problem_data.example_count, 2, + "Expected 1 test case in the readme" + ); +} + +#[test] +fn test_392_inputs_0_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/392.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + + let input = &problem_data.inputs[0]; + let expected = "\"abc\",\"ahbgdc\""; + + assert_eq!(input, expected, "first input mismatch"); +} + +#[test] +fn test_392_outputs_1_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/392.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + + let output = &problem_data.outputs[1]; + let expected = "false"; + + assert_eq!(output, expected, "second output mismatch"); +} + +#[test] +fn test_823_count_example() { + let readme_content = std::fs::read_to_string("tests/data/823.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + assert_eq!( + problem_data.example_count, 2, + "Expected 2 test cases in the readme" + ); +} + +#[test] +fn test_823_inputs_0_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/823.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + let input = &problem_data.inputs[0]; + let expected = "[2,4]"; + assert_eq!(input, expected, "first input mismatch"); +} + +#[test] +fn test_823_outputs_1_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/823.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + let output = &problem_data.outputs[1]; + let expected = "7"; + assert_eq!(output, expected, "second output mismatch"); +} + +#[test] +fn test_1768_count_example() { + let readme_content = std::fs::read_to_string("tests/data/1768.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + assert_eq!( + problem_data.example_count, 3, + "Expected 3 test cases in the readme" + ); +} + +#[test] +fn test_1768_inputs_0_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/1768.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + let input = &problem_data.inputs[0]; + let expected = "\"abc\",\"pqr\""; + assert_eq!(input, expected, "first input mismatch"); +} + +#[test] +fn test_1768_outputs_1_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/1768.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + let output = &problem_data.outputs[1]; + let expected = "\"apbqrs\""; + assert_eq!(output, expected, "second output mismatch"); +} + +#[test] +fn test_1768_outputs_2_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/1768.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + let output = &problem_data.outputs[2]; + let expected = "\"apbqcd\""; + assert_eq!(output, expected, "3rd output mismatch"); +} + +#[test] +fn test_1004_count_example() { + let readme_content = std::fs::read_to_string("tests/data/1004.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + assert_eq!( + problem_data.example_count, 2, + "Expected 2 test cases in the readme" + ); +} + +#[test] +fn test_1004_inputs_0_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/1004.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + let input = &problem_data.inputs[0]; + let expected = "[1,1,1,0,0,0,1,1,1,1,0],2"; + assert_eq!(input, expected, "first input mismatch"); +} + +#[test] +fn test_1004_inputs_1_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/1004.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + let input = &problem_data.inputs[1]; + let expected = "[0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1],3"; + assert_eq!(input, expected, "first input mismatch"); +} + +#[test] +fn test_1004_outputs_0_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/1004.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + let output = &problem_data.outputs[0]; + let expected = "6"; + assert_eq!(output, expected, "second output mismatch"); +} + +#[test] +fn test_1004_outputs_1_parse_readme() { + let readme_content = std::fs::read_to_string("tests/data/1004.md") + .expect("Failed to read test readme file"); + let lrp = LeetcodeReadmeParser::new(&readme_content); + let result = lrp.parse(); + assert!(result.is_ok(), "Failed to parse readme: {:?}", result.err()); + let problem_data = result.unwrap(); + let output = &problem_data.outputs[1]; + let expected = "10"; + assert_eq!(output, expected, "second output mismatch"); +} diff --git a/tests/utils_tests.rs b/tests/utils_tests.rs index 2b41335..425b2e2 100644 --- a/tests/utils_tests.rs +++ b/tests/utils_tests.rs @@ -15,15 +15,15 @@ fn assert_language(actual: ProgrammingLanguage, expected: ProgrammingLanguage) { fn test_parse_programming_language() { // Test valid programming languages assert_language( - utils::parse_programming_language("rust"), + utils::parse_programming_language("rust").unwrap(), ProgrammingLanguage::Rust, ); assert_language( - utils::parse_programming_language("python3"), + utils::parse_programming_language("python3").unwrap(), ProgrammingLanguage::Python3, ); assert_language( - utils::parse_programming_language("javascript"), + utils::parse_programming_language("javascript").unwrap(), ProgrammingLanguage::JavaScript, ); }