leetcode

Log | Files | Refs | README

commit 0dee5398929c1bc2852d0cb2e9ba53e649b83298
parent 13d0eac9f15815774bad57244e2d93e3cac54718
Author: ling0x <ling0x@users.noreply.github.com>
Date:   Sun, 12 Apr 2026 03:03:13 +0100

tests

Diffstat:
MCargo.toml | 2+-
Msrc/hash_table/two_sum.rs | 145++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/main.rs | 14+++++++++++++-
Msrc/test_utils/benchmark.rs | 20++++++++++++++++++++
4 files changed, 115 insertions(+), 66 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" [dependencies] tracing = "*" +tracing-subscriber = "*" [dev-dependencies] -tracing-subscriber = "*" diff --git a/src/hash_table/two_sum.rs b/src/hash_table/two_sum.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use tracing::info; // 101ms, 2.37MB @@ -38,12 +40,14 @@ pub fn two_sum_2(nums: Vec<i32>, target: i32) -> Vec<i32> { } // 86ms, 2.28MB +// if I replace rposition with position it becomes 56ms, which means that +// position is faster than rposition pub fn two_sum_3(nums: Vec<i32>, target: i32) -> Vec<i32> { for (i, x) in nums.iter().enumerate() { let idx = nums .iter() .enumerate() - .position(|(i2, y)| i2 != i && *y == target - x); + .rposition(|(i2, y)| i2 != i && *y == target - x); if let Some(idx) = idx { return Vec::from([i as i32, idx as i32]); } @@ -51,92 +55,105 @@ pub fn two_sum_3(nums: Vec<i32>, target: i32) -> Vec<i32> { Vec::new() } -pub fn two_sums_3(nums: Vec<i32>, target: i32) -> Vec<i32> { - let mut seen = Vec::<String>::new(); +// 27ms 2.22MB +pub fn two_sum_4(nums: Vec<i32>, target: i32) -> Vec<i32> { + for (i, x) in nums.iter().enumerate() { + let i2 = nums.iter().position(|y| y == &(target - x)); + if i2.is_some_and(|z| z != i) { + return vec![i as i32, i2.unwrap() as i32]; + } + } + Vec::new() +} - for (i, x) in nums.iter().enumerate() {} +pub fn two_sum_5(nums: Vec<i32>, target: i32) -> Vec<i32> { todo!() } #[cfg(test)] mod tests { - use tracing::info; - - use crate::hash_table::two_sum::{two_sum_1, two_sum_2, two_sum_3}; - use crate::test_utils::benchmark::{init_benchmark_tracing, run_with_metrics}; + use crate::hash_table::two_sum::{two_sum_1, two_sum_2, two_sum_3, two_sum_4}; + use crate::test_utils::benchmark::{init_benchmark_tracing, run_and_assert_vec_any_order}; - fn assert_indices_any_order(mut actual: Vec<i32>, mut expected: Vec<i32>) { - actual.sort_unstable(); - expected.sort_unstable(); - assert_eq!(actual, expected); + #[derive(Clone)] + struct TwoSumCase { + name: &'static str, + nums: Vec<i32>, + target: i32, + expected: Vec<i32>, } - #[test] - // #[ignore] - fn two_sum_1_test_1() { - init_benchmark_tracing(); - let (result, _) = run_with_metrics("two_sum_1_test_1", || two_sum_1(vec![2, 7, 11, 15], 9)); - assert_indices_any_order(result, vec![0, 1]); - } - #[test] - // #[ignore] - fn two_sum_1_test_2() { - init_benchmark_tracing(); - let (result, _) = run_with_metrics("two_sum_1_test_2", || two_sum_1(vec![3, 2, 3], 6)); - assert_indices_any_order(result, vec![0, 2]); - } - #[test] - // #[ignore] - fn two_sum_1_test_3() { - init_benchmark_tracing(); - let (result, _) = run_with_metrics("two_sum_1_test_3", || two_sum_1(vec![3, 2, 4], 6)); - assert_indices_any_order(result, vec![1, 2]); + fn full_cases() -> Vec<TwoSumCase> { + vec![ + TwoSumCase { + name: "case_1", + nums: vec![2, 7, 11, 15], + target: 9, + expected: vec![0, 1], + }, + TwoSumCase { + name: "case_2", + nums: vec![3, 2, 3], + target: 6, + expected: vec![0, 2], + }, + TwoSumCase { + name: "case_3", + nums: vec![3, 2, 4], + target: 6, + expected: vec![1, 2], + }, + TwoSumCase { + name: "case_4", + nums: vec![-3, 4, 3, 90], + target: 0, + expected: vec![0, 2], + }, + ] } - #[test] - // #[ignore] - fn two_sum_2_test_1() { + fn run_solver_cases( + solver_name: &str, + solver: fn(Vec<i32>, i32) -> Vec<i32>, + cases: Vec<TwoSumCase>, + ) { init_benchmark_tracing(); - let (result, _) = run_with_metrics("two_sum_2_test_1", || two_sum_2(vec![2, 7, 11, 15], 9)); - assert_indices_any_order(result, vec![0, 1]); + for case in cases { + run_and_assert_vec_any_order( + &format!("{solver_name}_{}", case.name), + case.expected, + || solver(case.nums, case.target), + ); + } } + #[test] - // #[ignore] - fn two_sum_2_test_2() { - init_benchmark_tracing(); - let (result, _) = run_with_metrics("two_sum_2_test_2", || two_sum_2(vec![3, 2, 3], 6)); - assert_indices_any_order(result, vec![0, 2]); + #[ignore] + fn two_sum_1_cases() { + run_solver_cases("two_sum_1", two_sum_1, full_cases()); } + #[test] - // #[ignore] - fn two_sum_2_test_3() { - init_benchmark_tracing(); - let (result, _) = run_with_metrics("two_sum_2_test_3", || two_sum_2(vec![3, 2, 4], 6)); - assert_indices_any_order(result, vec![1, 2]); + #[ignore] + fn two_sum_2_cases() { + run_solver_cases("two_sum_2", two_sum_2, full_cases()); } #[test] - // #[ignore] - fn two_sum_3_test_1() { - init_benchmark_tracing(); - let (result, _) = run_with_metrics("two_sum_3_test_1", || two_sum_3(vec![2, 7, 11, 15], 9)); - info!("{result:?}"); - assert_indices_any_order(result, vec![0, 1]); + #[ignore] + fn two_sum_3_cases() { + run_solver_cases("two_sum_3", two_sum_3, full_cases()); } + #[test] - // #[ignore] - fn two_sum_3_test_2() { - init_benchmark_tracing(); - let (result, _) = run_with_metrics("two_sum_3_test_2", || two_sum_3(vec![3, 2, 3], 6)); - info!("{result:?}"); - assert_indices_any_order(result, vec![0, 2]); + #[ignore] + fn two_sum_4_cases() { + run_solver_cases("two_sum_4", two_sum_4, full_cases()); } + #[test] // #[ignore] - fn two_sum_3_test_3() { - init_benchmark_tracing(); - let (result, _) = run_with_metrics("two_sum_3_test_3", || two_sum_3(vec![3, 2, 4], 6)); - info!("{result:?}"); - assert_indices_any_order(result, vec![1, 2]); + fn two_sum_5_cases() { + run_solver_cases("two_sum_5", two_sum_5, full_cases()); } } diff --git a/src/main.rs b/src/main.rs @@ -1,3 +1,15 @@ +use leetcode::hash_table::two_sum::two_sum_5; +use tracing::info; +use tracing_subscriber::fmt; + fn main() { - println!("Cargo test all the leetcode cases"); + fmt().with_target(false).compact().init(); + info!("-----------------------"); + two_sum_5(vec![2, 7, 11, 15], 9); + info!("-----------------------"); + two_sum_5(vec![3, 2, 3], 6); + info!("-----------------------"); + two_sum_5(vec![3, 2, 4], 6); + info!("-----------------------"); + two_sum_5(vec![-3, 4, 3, 90], 0); } diff --git a/src/test_utils/benchmark.rs b/src/test_utils/benchmark.rs @@ -1,4 +1,5 @@ use std::alloc::{GlobalAlloc, Layout, System}; +use std::fmt::Debug; use std::sync::Once; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::{Duration, Instant}; @@ -97,3 +98,22 @@ where (output, result) } + +pub fn assert_vec_any_order<T>(mut actual: Vec<T>, mut expected: Vec<T>) +where + T: Ord + Debug, +{ + actual.sort_unstable(); + expected.sort_unstable(); + assert_eq!(actual, expected); +} + +pub fn run_and_assert_vec_any_order<T, F>(label: &str, expected: Vec<T>, test: F) -> BenchmarkResult +where + T: Ord + Debug, + F: FnOnce() -> Vec<T>, +{ + let (actual, metrics) = run_with_metrics(label, test); + assert_vec_any_order(actual, expected); + metrics +}