leet-tui 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/CLASS_HARNESS_PLAN.md +191 -0
- package/scripts/TEST_ISSUES.md +76 -0
- package/scripts/__pycache__/analyze_tests.cpython-312.pyc +0 -0
- package/scripts/__pycache__/fix_and_validate.cpython-312.pyc +0 -0
- package/scripts/add_boundary_cases.py +282 -0
- package/scripts/analyze_tests.py +326 -0
- package/scripts/batch_fix_testcases.py +218 -0
- package/scripts/fix_and_validate.py +826 -0
- package/scripts/generate_edge_cases.py +456 -0
- package/scripts/test_languages.py +637 -0
- package/scripts/test_languages.sh +216 -16
- package/scripts/test_report.json +16618 -0
- package/scripts/test_runner.py +1110 -0
- package/scripts/test_solutions/002_add_two_numbers.js +14 -0
- package/scripts/test_solutions/002_add_two_numbers.py +17 -0
- package/scripts/test_solutions/003_longest_substring_no_repeat.js +13 -0
- package/scripts/test_solutions/003_longest_substring_no_repeat.py +10 -0
- package/scripts/test_solutions/004_median_two_sorted_arrays.js +23 -0
- package/scripts/test_solutions/004_median_two_sorted_arrays.py +20 -0
- package/scripts/test_solutions/005_longest_palindromic_substring.js +17 -0
- package/scripts/test_solutions/005_longest_palindromic_substring.py +17 -0
- package/scripts/test_solutions/010_regular_expression_matching.js +20 -0
- package/scripts/test_solutions/010_regular_expression_matching.py +15 -0
- package/scripts/test_solutions/011_container_with_most_water.js +11 -0
- package/scripts/test_solutions/011_container_with_most_water.py +11 -0
- package/scripts/test_solutions/015_3sum.js +19 -0
- package/scripts/test_solutions/015_3sum.py +22 -0
- package/scripts/test_solutions/017_letter_combinations.js +16 -0
- package/scripts/test_solutions/017_letter_combinations.py +15 -0
- package/scripts/test_solutions/019_remove_nth_from_end.js +11 -0
- package/scripts/test_solutions/019_remove_nth_from_end.py +15 -0
- package/scripts/test_solutions/020_valid_parentheses.js +14 -0
- package/scripts/test_solutions/020_valid_parentheses.py +11 -0
- package/scripts/test_solutions/021_merge_two_sorted_lists.js +16 -0
- package/scripts/test_solutions/021_merge_two_sorted_lists.py +18 -0
- package/scripts/test_solutions/022_generate_parentheses.js +13 -0
- package/scripts/test_solutions/022_generate_parentheses.py +14 -0
- package/scripts/test_solutions/023_merge_k_sorted_lists.js +24 -0
- package/scripts/test_solutions/023_merge_k_sorted_lists.py +27 -0
- package/scripts/test_solutions/025_reverse_nodes_k_group.js +13 -0
- package/scripts/test_solutions/025_reverse_nodes_k_group.py +21 -0
- package/scripts/test_solutions/033_search_rotated_sorted_array.js +15 -0
- package/scripts/test_solutions/033_search_rotated_sorted_array.py +17 -0
- package/scripts/test_solutions/036_valid_sudoku.js +17 -0
- package/scripts/test_solutions/036_valid_sudoku.py +16 -0
- package/scripts/test_solutions/039_combination_sum.js +14 -0
- package/scripts/test_solutions/039_combination_sum.py +16 -0
- package/scripts/test_solutions/040_combination_sum_ii.js +16 -0
- package/scripts/test_solutions/040_combination_sum_ii.py +19 -0
- package/scripts/test_solutions/042_trapping_rain_water.js +16 -0
- package/scripts/test_solutions/042_trapping_rain_water.py +17 -0
- package/scripts/test_solutions/043_multiply_strings.js +15 -0
- package/scripts/test_solutions/043_multiply_strings.py +13 -0
- package/scripts/test_solutions/045_jump_game_ii.js +11 -0
- package/scripts/test_solutions/045_jump_game_ii.py +8 -0
- package/scripts/test_solutions/046_permutations.js +16 -0
- package/scripts/test_solutions/046_permutations.py +18 -0
- package/scripts/test_solutions/048_rotate_image.js +11 -0
- package/scripts/test_solutions/048_rotate_image.py +7 -0
- package/scripts/test_solutions/050_pow_x_n.js +11 -0
- package/scripts/test_solutions/050_pow_x_n.py +13 -0
- package/scripts/test_solutions/051_n_queens.js +22 -0
- package/scripts/test_solutions/051_n_queens.py +34 -0
- package/scripts/test_solutions/053_maximum_subarray.js +8 -0
- package/scripts/test_solutions/053_maximum_subarray.py +6 -0
- package/scripts/test_solutions/054_spiral_matrix.js +13 -0
- package/scripts/test_solutions/054_spiral_matrix.py +21 -0
- package/scripts/test_solutions/055_jump_game.js +8 -0
- package/scripts/test_solutions/055_jump_game.py +7 -0
- package/scripts/test_solutions/056_merge_intervals.js +13 -0
- package/scripts/test_solutions/056_merge_intervals.py +15 -0
- package/scripts/test_solutions/057_insert_interval.js +15 -0
- package/scripts/test_solutions/057_insert_interval.py +15 -0
- package/scripts/test_solutions/062_unique_paths.js +9 -0
- package/scripts/test_solutions/062_unique_paths.py +6 -0
- package/scripts/test_solutions/066_plus_one.js +7 -0
- package/scripts/test_solutions/066_plus_one.py +7 -0
- package/scripts/test_solutions/070_climbing_stairs.js +6 -0
- package/scripts/test_solutions/070_climbing_stairs.py +7 -0
- package/scripts/test_solutions/072_edit_distance.js +11 -0
- package/scripts/test_solutions/072_edit_distance.py +14 -0
- package/scripts/test_solutions/073_set_matrix_zeroes.js +10 -0
- package/scripts/test_solutions/073_set_matrix_zeroes.py +19 -0
- package/scripts/test_solutions/074_search_2d_matrix.js +12 -0
- package/scripts/test_solutions/074_search_2d_matrix.py +13 -0
- package/scripts/test_solutions/076_minimum_window_substring.js +21 -0
- package/scripts/test_solutions/076_minimum_window_substring.py +23 -0
- package/scripts/test_solutions/078_subsets.js +13 -0
- package/scripts/test_solutions/078_subsets.py +12 -0
- package/scripts/test_solutions/079_word_search.js +14 -0
- package/scripts/test_solutions/079_word_search.py +19 -0
- package/scripts/test_solutions/084_largest_rectangle_histogram.js +14 -0
- package/scripts/test_solutions/084_largest_rectangle_histogram.py +12 -0
- package/scripts/test_solutions/090_subsets_ii.js +15 -0
- package/scripts/test_solutions/090_subsets_ii.py +15 -0
- package/scripts/test_solutions/091_decode_ways.js +14 -0
- package/scripts/test_solutions/091_decode_ways.py +19 -0
- package/scripts/test_solutions/097_interleaving_string.js +13 -0
- package/scripts/test_solutions/097_interleaving_string.py +15 -0
- package/scripts/test_solutions/098_validate_bst.js +8 -0
- package/scripts/test_solutions/098_validate_bst.py +9 -0
- package/scripts/test_solutions/100_same_tree.js +5 -0
- package/scripts/test_solutions/100_same_tree.py +6 -0
- package/scripts/test_solutions/102_binary_tree_level_order.js +17 -0
- package/scripts/test_solutions/102_binary_tree_level_order.py +19 -0
- package/scripts/test_solutions/1046_last_stone_weight.js +9 -0
- package/scripts/test_solutions/1046_last_stone_weight.py +11 -0
- package/scripts/test_solutions/104_max_depth_binary_tree.js +4 -0
- package/scripts/test_solutions/104_max_depth_binary_tree.py +4 -0
- package/scripts/test_solutions/105_construct_tree_preorder_inorder.js +15 -0
- package/scripts/test_solutions/105_construct_tree_preorder_inorder.py +16 -0
- package/scripts/test_solutions/110_balanced_binary_tree.js +10 -0
- package/scripts/test_solutions/110_balanced_binary_tree.py +11 -0
- package/scripts/test_solutions/1143_longest_common_subsequence.js +14 -0
- package/scripts/test_solutions/1143_longest_common_subsequence.py +13 -0
- package/scripts/test_solutions/115_distinct_subsequences.js +11 -0
- package/scripts/test_solutions/115_distinct_subsequences.py +9 -0
- package/scripts/test_solutions/121_best_time_to_buy_sell_stock.js +8 -0
- package/scripts/test_solutions/121_best_time_to_buy_sell_stock.py +7 -0
- package/scripts/test_solutions/124_binary_tree_max_path_sum.js +12 -0
- package/scripts/test_solutions/124_binary_tree_max_path_sum.py +13 -0
- package/scripts/test_solutions/125_valid_palindrome.js +8 -0
- package/scripts/test_solutions/125_valid_palindrome.py +9 -0
- package/scripts/test_solutions/127_word_ladder.js +19 -0
- package/scripts/test_solutions/127_word_ladder.py +18 -0
- package/scripts/test_solutions/128_longest_consecutive.js +12 -0
- package/scripts/test_solutions/128_longest_consecutive.py +12 -0
- package/scripts/test_solutions/130_surrounded_regions.js +14 -0
- package/scripts/test_solutions/130_surrounded_regions.py +27 -0
- package/scripts/test_solutions/131_palindrome_partitioning.js +16 -0
- package/scripts/test_solutions/131_palindrome_partitioning.py +23 -0
- package/scripts/test_solutions/133_clone_graph.js +12 -0
- package/scripts/test_solutions/133_clone_graph.py +15 -0
- package/scripts/test_solutions/134_gas_station.js +10 -0
- package/scripts/test_solutions/134_gas_station.py +10 -0
- package/scripts/test_solutions/136_single_number.js +3 -0
- package/scripts/test_solutions/136_single_number.py +4 -0
- package/scripts/test_solutions/138_copy_list_random_pointer.js +13 -0
- package/scripts/test_solutions/138_copy_list_random_pointer.py +14 -0
- package/scripts/test_solutions/139_word_break.js +11 -0
- package/scripts/test_solutions/139_word_break.py +10 -0
- package/scripts/test_solutions/141_linked_list_cycle.js +9 -0
- package/scripts/test_solutions/141_linked_list_cycle.py +8 -0
- package/scripts/test_solutions/143_reorder_list.js +16 -0
- package/scripts/test_solutions/143_reorder_list.py +21 -0
- package/scripts/test_solutions/1448_count_good_nodes.js +12 -0
- package/scripts/test_solutions/1448_count_good_nodes.py +14 -0
- package/scripts/test_solutions/146_lru_cache.js +16 -0
- package/scripts/test_solutions/146_lru_cache.py +19 -0
- package/scripts/test_solutions/150_evaluate_reverse_polish.js +13 -0
- package/scripts/test_solutions/150_evaluate_reverse_polish.py +16 -0
- package/scripts/test_solutions/152_maximum_product_subarray.js +10 -0
- package/scripts/test_solutions/152_maximum_product_subarray.py +9 -0
- package/scripts/test_solutions/153_find_min_rotated_sorted_array.js +9 -0
- package/scripts/test_solutions/153_find_min_rotated_sorted_array.py +9 -0
- package/scripts/test_solutions/155_min_stack.js +12 -0
- package/scripts/test_solutions/155_min_stack.py +20 -0
- package/scripts/test_solutions/1584_min_cost_connect_points.js +18 -0
- package/scripts/test_solutions/1584_min_cost_connect_points.py +22 -0
- package/scripts/test_solutions/167_two_sum_ii.js +10 -0
- package/scripts/test_solutions/167_two_sum_ii.py +11 -0
- package/scripts/test_solutions/1851_minimum_interval.js +17 -0
- package/scripts/test_solutions/1851_minimum_interval.py +19 -0
- package/scripts/test_solutions/1899_merge_triplets.js +11 -0
- package/scripts/test_solutions/1899_merge_triplets.py +11 -0
- package/scripts/test_solutions/191_number_of_1_bits.js +5 -0
- package/scripts/test_solutions/191_number_of_1_bits.py +6 -0
- package/scripts/test_solutions/198_house_robber.js +9 -0
- package/scripts/test_solutions/198_house_robber.py +7 -0
- package/scripts/test_solutions/199_binary_tree_right_side_view.js +15 -0
- package/scripts/test_solutions/199_binary_tree_right_side_view.py +18 -0
- package/scripts/test_solutions/200_number_of_islands.js +14 -0
- package/scripts/test_solutions/200_number_of_islands.py +21 -0
- package/scripts/test_solutions/2013_detect_squares.js +16 -0
- package/scripts/test_solutions/2013_detect_squares.py +17 -0
- package/scripts/test_solutions/202_happy_number.js +10 -0
- package/scripts/test_solutions/202_happy_number.py +10 -0
- package/scripts/test_solutions/206_reverse_linked_list.js +10 -0
- package/scripts/test_solutions/206_reverse_linked_list.py +8 -0
- package/scripts/test_solutions/207_course_schedule.js +14 -0
- package/scripts/test_solutions/207_course_schedule.py +18 -0
- package/scripts/test_solutions/208_implement_trie.js +16 -0
- package/scripts/test_solutions/208_implement_trie.py +27 -0
- package/scripts/test_solutions/210_course_schedule_ii.js +13 -0
- package/scripts/test_solutions/210_course_schedule_ii.py +18 -0
- package/scripts/test_solutions/211_add_search_words.js +17 -0
- package/scripts/test_solutions/211_add_search_words.py +26 -0
- package/scripts/test_solutions/212_word_search_ii.js +17 -0
- package/scripts/test_solutions/212_word_search_ii.py +34 -0
- package/scripts/test_solutions/213_house_robber_ii.js +12 -0
- package/scripts/test_solutions/213_house_robber_ii.py +13 -0
- package/scripts/test_solutions/215_kth_largest_element.js +11 -0
- package/scripts/test_solutions/215_kth_largest_element.py +4 -0
- package/scripts/test_solutions/226_invert_binary_tree.js +5 -0
- package/scripts/test_solutions/226_invert_binary_tree.py +5 -0
- package/scripts/test_solutions/230_kth_smallest_bst.js +11 -0
- package/scripts/test_solutions/230_kth_smallest_bst.py +16 -0
- package/scripts/test_solutions/235_lca_bst.js +7 -0
- package/scripts/test_solutions/235_lca_bst.py +8 -0
- package/scripts/test_solutions/238_product_except_self.js +8 -0
- package/scripts/test_solutions/238_product_except_self.py +12 -0
- package/scripts/test_solutions/239_sliding_window_maximum.js +10 -0
- package/scripts/test_solutions/239_sliding_window_maximum.py +14 -0
- package/scripts/test_solutions/252_meeting_rooms.js +7 -0
- package/scripts/test_solutions/252_meeting_rooms.py +6 -0
- package/scripts/test_solutions/253_meeting_rooms_ii.js +10 -0
- package/scripts/test_solutions/253_meeting_rooms_ii.py +10 -0
- package/scripts/test_solutions/261_graph_valid_tree.js +11 -0
- package/scripts/test_solutions/261_graph_valid_tree.py +21 -0
- package/scripts/test_solutions/269_alien_dictionary.js +20 -0
- package/scripts/test_solutions/269_alien_dictionary.py +28 -0
- package/scripts/test_solutions/271_encode_decode_strings.js +15 -0
- package/scripts/test_solutions/271_encode_decode_strings.py +14 -0
- package/scripts/test_solutions/286_walls_and_gates.js +15 -0
- package/scripts/test_solutions/286_walls_and_gates.py +20 -0
- package/scripts/test_solutions/287_find_duplicate_number.js +7 -0
- package/scripts/test_solutions/287_find_duplicate_number.py +12 -0
- package/scripts/test_solutions/295_find_median_data_stream.js +12 -0
- package/scripts/test_solutions/295_find_median_data_stream.py +17 -0
- package/scripts/test_solutions/297_serialize_deserialize_tree.js +17 -0
- package/scripts/test_solutions/297_serialize_deserialize_tree.py +34 -0
- package/scripts/test_solutions/300_longest_increasing_subsequence.js +9 -0
- package/scripts/test_solutions/300_longest_increasing_subsequence.py +11 -0
- package/scripts/test_solutions/309_best_time_buy_sell_cooldown.js +10 -0
- package/scripts/test_solutions/309_best_time_buy_sell_cooldown.py +8 -0
- package/scripts/test_solutions/312_burst_balloons.js +14 -0
- package/scripts/test_solutions/312_burst_balloons.py +10 -0
- package/scripts/test_solutions/322_coin_change.js +10 -0
- package/scripts/test_solutions/322_coin_change.py +8 -0
- package/scripts/test_solutions/323_number_of_connected_components.js +10 -0
- package/scripts/test_solutions/323_number_of_connected_components.py +16 -0
- package/scripts/test_solutions/329_longest_increasing_path_matrix.js +17 -0
- package/scripts/test_solutions/329_longest_increasing_path_matrix.py +20 -0
- package/scripts/test_solutions/332_reconstruct_itinerary.js +16 -0
- package/scripts/test_solutions/332_reconstruct_itinerary.py +18 -0
- package/scripts/test_solutions/355_design_twitter.js +14 -0
- package/scripts/test_solutions/355_design_twitter.py +23 -0
- package/scripts/test_solutions/416_partition_equal_subset_sum.js +13 -0
- package/scripts/test_solutions/416_partition_equal_subset_sum.py +15 -0
- package/scripts/test_solutions/417_pacific_atlantic_water_flow.js +18 -0
- package/scripts/test_solutions/417_pacific_atlantic_water_flow.py +25 -0
- package/scripts/test_solutions/424_longest_repeating_char_replacement.js +11 -0
- package/scripts/test_solutions/424_longest_repeating_char_replacement.py +13 -0
- package/scripts/test_solutions/435_non_overlapping_intervals.js +9 -0
- package/scripts/test_solutions/435_non_overlapping_intervals.py +10 -0
- package/scripts/test_solutions/494_target_sum.js +11 -0
- package/scripts/test_solutions/494_target_sum.py +11 -0
- package/scripts/test_solutions/518_coin_change_ii.js +8 -0
- package/scripts/test_solutions/518_coin_change_ii.py +7 -0
- package/scripts/test_solutions/543_diameter_binary_tree.js +11 -0
- package/scripts/test_solutions/543_diameter_binary_tree.py +13 -0
- package/scripts/test_solutions/567_permutation_in_string.js +12 -0
- package/scripts/test_solutions/567_permutation_in_string.py +15 -0
- package/scripts/test_solutions/572_subtree_of_another_tree.js +10 -0
- package/scripts/test_solutions/572_subtree_of_another_tree.py +13 -0
- package/scripts/test_solutions/621_task_scheduler.js +7 -0
- package/scripts/test_solutions/621_task_scheduler.py +7 -0
- package/scripts/test_solutions/647_palindromic_substrings.js +6 -0
- package/scripts/test_solutions/647_palindromic_substrings.py +13 -0
- package/scripts/test_solutions/678_valid_parenthesis_string.js +11 -0
- package/scripts/test_solutions/678_valid_parenthesis_string.py +17 -0
- package/scripts/test_solutions/684_redundant_connection.js +9 -0
- package/scripts/test_solutions/684_redundant_connection.py +16 -0
- package/scripts/test_solutions/695_max_area_of_island.js +11 -0
- package/scripts/test_solutions/695_max_area_of_island.py +15 -0
- package/scripts/test_solutions/703_kth_largest_stream.js +9 -0
- package/scripts/test_solutions/703_kth_largest_stream.py +15 -0
- package/scripts/test_solutions/704_binary_search.js +10 -0
- package/scripts/test_solutions/704_binary_search.py +11 -0
- package/scripts/test_solutions/739_daily_temperatures.js +11 -0
- package/scripts/test_solutions/739_daily_temperatures.py +10 -0
- package/scripts/test_solutions/743_network_delay_time.js +17 -0
- package/scripts/test_solutions/743_network_delay_time.py +23 -0
- package/scripts/test_solutions/746_min_cost_climbing_stairs.js +8 -0
- package/scripts/test_solutions/746_min_cost_climbing_stairs.py +6 -0
- package/scripts/test_solutions/763_partition_labels.js +11 -0
- package/scripts/test_solutions/763_partition_labels.py +13 -0
- package/scripts/test_solutions/778_swim_in_rising_water.js +18 -0
- package/scripts/test_solutions/778_swim_in_rising_water.py +17 -0
- package/scripts/test_solutions/787_cheapest_flights_k_stops.js +12 -0
- package/scripts/test_solutions/787_cheapest_flights_k_stops.py +12 -0
- package/scripts/test_solutions/846_hand_of_straights.js +16 -0
- package/scripts/test_solutions/846_hand_of_straights.py +14 -0
- package/scripts/test_solutions/853_car_fleet.js +8 -0
- package/scripts/test_solutions/853_car_fleet.py +10 -0
- package/scripts/test_solutions/875_koko_eating_bananas.js +10 -0
- package/scripts/test_solutions/875_koko_eating_bananas.py +12 -0
- package/scripts/test_solutions/973_k_closest_points.js +3 -0
- package/scripts/test_solutions/973_k_closest_points.py +2 -0
- package/scripts/test_solutions/981_time_based_key_value_store.js +16 -0
- package/scripts/test_solutions/981_time_based_key_value_store.py +23 -0
- package/scripts/test_solutions/994_rotting_oranges.js +25 -0
- package/scripts/test_solutions/994_rotting_oranges.py +34 -0
package/package.json
CHANGED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Plan: Class-Based Test Harnesses
|
|
2
|
+
|
|
3
|
+
## Current Status
|
|
4
|
+
- **116/131 problems passing** (89%)
|
|
5
|
+
- **15 problems skipped** - require custom test harnesses for class-based or special input/output handling
|
|
6
|
+
|
|
7
|
+
## Skipped Problems by Category
|
|
8
|
+
|
|
9
|
+
### Category 1: Class-Based Design Problems (9 problems)
|
|
10
|
+
These use a method-call sequence format: `[["ClassName", "method1", "method2"], [[], [args1], [args2]]]`
|
|
11
|
+
|
|
12
|
+
| Problem | File | Methods |
|
|
13
|
+
|---------|------|---------|
|
|
14
|
+
| 146 LRUCache | `146_lru_cache.json` | `LRUCache(capacity)`, `get(key)`, `put(key, value)` |
|
|
15
|
+
| 155 MinStack | `155_min_stack.json` | `MinStack()`, `push(val)`, `pop()`, `top()`, `getMin()` |
|
|
16
|
+
| 208 Trie | `208_implement_trie.json` | `Trie()`, `insert(word)`, `search(word)`, `startsWith(prefix)` |
|
|
17
|
+
| 211 WordDictionary | `211_add_search_words.json` | `WordDictionary()`, `addWord(word)`, `search(word)` |
|
|
18
|
+
| 295 MedianFinder | `295_find_median_data_stream.json` | `MedianFinder()`, `addNum(num)`, `findMedian()` |
|
|
19
|
+
| 355 Twitter | `355_design_twitter.json` | `Twitter()`, `postTweet()`, `getNewsFeed()`, `follow()`, `unfollow()` |
|
|
20
|
+
| 703 KthLargest | `703_kth_largest_stream.json` | `KthLargest(k, nums)`, `add(val)` |
|
|
21
|
+
| 981 TimeMap | `981_time_based_key_value_store.json` | `TimeMap()`, `set(key, value, timestamp)`, `get(key, timestamp)` |
|
|
22
|
+
| 2013 DetectSquares | `2013_detect_squares.json` | `DetectSquares()`, `add(point)`, `count(point)` |
|
|
23
|
+
|
|
24
|
+
**Harness Pattern:**
|
|
25
|
+
```javascript
|
|
26
|
+
const [methods, args] = testCase.input;
|
|
27
|
+
const results = [];
|
|
28
|
+
let instance = null;
|
|
29
|
+
for (let i = 0; i < methods.length; i++) {
|
|
30
|
+
const method = methods[i];
|
|
31
|
+
const arg = args[i];
|
|
32
|
+
if (method === 'ClassName') {
|
|
33
|
+
instance = new ClassName(...arg);
|
|
34
|
+
results.push(null);
|
|
35
|
+
} else {
|
|
36
|
+
results.push(instance[method](...arg));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return results;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Category 2: Serialize/Deserialize (2 problems)
|
|
43
|
+
|
|
44
|
+
| Problem | File | Description |
|
|
45
|
+
|---------|------|-------------|
|
|
46
|
+
| 297 Codec | `297_serialize_deserialize_tree.json` | Serialize/deserialize binary tree |
|
|
47
|
+
| 271 Encode/Decode | `271_encode_decode_strings.json` | Encode/decode string array |
|
|
48
|
+
|
|
49
|
+
**297 Codec Pattern:** Test that `decode(encode(tree)) === tree`
|
|
50
|
+
```javascript
|
|
51
|
+
const codec = new Codec();
|
|
52
|
+
const tree = arrayToTree(input);
|
|
53
|
+
const result = treeToArray(codec.deserialize(codec.serialize(tree)));
|
|
54
|
+
return compareArrays(result, expected);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**271 Pattern:** Test that `decode(encode(strs)) === strs`
|
|
58
|
+
```javascript
|
|
59
|
+
const result = decode(encode(input));
|
|
60
|
+
return arraysEqual(result, expected);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Category 3: Graph/Linked List with Special Structures (4 problems)
|
|
64
|
+
|
|
65
|
+
| Problem | File | Description |
|
|
66
|
+
|---------|------|-------------|
|
|
67
|
+
| 133 cloneGraph | `133_clone_graph.json` | Clone graph with adjacency list input |
|
|
68
|
+
| 138 copyRandomList | `138_copy_list_with_random_pointer.json` | Copy linked list with random pointers |
|
|
69
|
+
| 141 hasCycle | `141_linked_list_cycle.json` | Detect cycle in linked list |
|
|
70
|
+
| 23 mergeKLists | `023_merge_k_sorted_lists.json` | Merge k sorted linked lists |
|
|
71
|
+
|
|
72
|
+
**133 cloneGraph Pattern:**
|
|
73
|
+
```javascript
|
|
74
|
+
// Input: adjacency list [[1,2],[0,2],[0,1]] means node 0 connects to 1,2, etc.
|
|
75
|
+
const buildGraph = (adj) => {
|
|
76
|
+
if (!adj || adj.length === 0) return null;
|
|
77
|
+
const nodes = adj.map((_, i) => ({ val: i, neighbors: [] }));
|
|
78
|
+
adj.forEach((neighbors, i) => {
|
|
79
|
+
nodes[i].neighbors = neighbors.map(n => nodes[n]);
|
|
80
|
+
});
|
|
81
|
+
return nodes[0];
|
|
82
|
+
};
|
|
83
|
+
const graphToAdj = (node) => { /* BFS to rebuild adjacency list */ };
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**138 copyRandomList Pattern:**
|
|
87
|
+
```javascript
|
|
88
|
+
// Input: [[val, random_index], ...] e.g. [[7,null],[13,0],[11,4]]
|
|
89
|
+
const buildList = (arr) => {
|
|
90
|
+
const nodes = arr.map(([val]) => ({ val, next: null, random: null }));
|
|
91
|
+
arr.forEach(([val, randomIdx], i) => {
|
|
92
|
+
if (i < arr.length - 1) nodes[i].next = nodes[i + 1];
|
|
93
|
+
if (randomIdx !== null) nodes[i].random = nodes[randomIdx];
|
|
94
|
+
});
|
|
95
|
+
return nodes[0];
|
|
96
|
+
};
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**141 hasCycle Pattern:**
|
|
100
|
+
```javascript
|
|
101
|
+
// Input: [array, pos] where pos is the index the tail connects to (-1 for no cycle)
|
|
102
|
+
const buildCyclicList = (arr, pos) => {
|
|
103
|
+
if (!arr.length) return null;
|
|
104
|
+
const nodes = arr.map(v => ({ val: v, next: null }));
|
|
105
|
+
for (let i = 0; i < nodes.length - 1; i++) nodes[i].next = nodes[i + 1];
|
|
106
|
+
if (pos >= 0) nodes[nodes.length - 1].next = nodes[pos];
|
|
107
|
+
return nodes[0];
|
|
108
|
+
};
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**23 mergeKLists Pattern:**
|
|
112
|
+
```javascript
|
|
113
|
+
// Input: array of arrays, each representing a linked list
|
|
114
|
+
const lists = input.map(arr => arrayToList(arr));
|
|
115
|
+
const result = mergeKLists(lists);
|
|
116
|
+
return listToArray(result);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Category 4: Tree with Node Reference (1 problem)
|
|
120
|
+
|
|
121
|
+
| Problem | File | Description |
|
|
122
|
+
|---------|------|-------------|
|
|
123
|
+
| 235 LCA BST | `p235_lowest_common_ancestor_of_bst.json` | Find LCA given tree + two node values |
|
|
124
|
+
|
|
125
|
+
**Pattern:**
|
|
126
|
+
```javascript
|
|
127
|
+
// Input: [treeArray, p_val, q_val]
|
|
128
|
+
const root = arrayToTree(treeArray);
|
|
129
|
+
const findNode = (node, val) => { /* BFS/DFS to find node by value */ };
|
|
130
|
+
const p = findNode(root, p_val);
|
|
131
|
+
const q = findNode(root, q_val);
|
|
132
|
+
const result = lowestCommonAncestor(root, p, q);
|
|
133
|
+
return result.val;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Implementation Plan
|
|
137
|
+
|
|
138
|
+
### Step 1: Create Generic Class Harness
|
|
139
|
+
Add to `fix_and_validate.py` a generic handler for class-based problems:
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
class_funcs = {
|
|
143
|
+
'LRUCache': 'LRUCache',
|
|
144
|
+
'MinStack': 'MinStack',
|
|
145
|
+
'Trie': 'Trie',
|
|
146
|
+
'WordDictionary': 'WordDictionary',
|
|
147
|
+
'MedianFinder': 'MedianFinder',
|
|
148
|
+
'Twitter': 'Twitter',
|
|
149
|
+
'KthLargest': 'KthLargest',
|
|
150
|
+
'TimeMap': 'TimeMap',
|
|
151
|
+
'DetectSquares': 'DetectSquares'
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Generate JavaScript test code:
|
|
156
|
+
```javascript
|
|
157
|
+
const [methods, args] = tc.input;
|
|
158
|
+
const results = [];
|
|
159
|
+
let instance = null;
|
|
160
|
+
for (let i = 0; i < methods.length; i++) {
|
|
161
|
+
if (methods[i] === 'ClassName') {
|
|
162
|
+
instance = new ClassName(...args[i]);
|
|
163
|
+
results.push(null);
|
|
164
|
+
} else {
|
|
165
|
+
results.push(instance[methods[i]](...args[i]));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Step 2: Add Serialize/Deserialize Harness
|
|
171
|
+
For Codec and encode/decode, test roundtrip equality.
|
|
172
|
+
|
|
173
|
+
### Step 3: Add Graph/LinkedList Constructors
|
|
174
|
+
Add helper functions for:
|
|
175
|
+
- Building cyclic linked lists
|
|
176
|
+
- Building graphs from adjacency lists
|
|
177
|
+
- Building linked lists with random pointers
|
|
178
|
+
|
|
179
|
+
### Step 4: Add LCA Harness
|
|
180
|
+
Find nodes by value in tree, then call LCA function.
|
|
181
|
+
|
|
182
|
+
## Estimated Effort
|
|
183
|
+
- Generic class harness: 30 lines of Python
|
|
184
|
+
- Codec harness: 20 lines
|
|
185
|
+
- Graph constructors: 40 lines JavaScript helpers
|
|
186
|
+
- LCA harness: 15 lines
|
|
187
|
+
- Testing and debugging: varies
|
|
188
|
+
|
|
189
|
+
## Files to Modify
|
|
190
|
+
1. `scripts/fix_and_validate.py` - Add new harness logic
|
|
191
|
+
2. Potentially create `scripts/test_harness_helpers.js` for reusable JavaScript helpers
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Test Suite Status
|
|
2
|
+
|
|
3
|
+
## Current Status (After Comprehensive Fixes)
|
|
4
|
+
- **Total Problems:** 131 (15 class-based problems skipped)
|
|
5
|
+
- **Passed:** 104 (79%)
|
|
6
|
+
- **Failed:** 12 (9%)
|
|
7
|
+
- **Skipped:** 15 (12%) - Class-based problems needing custom harness
|
|
8
|
+
|
|
9
|
+
## Progress Summary
|
|
10
|
+
- **Starting point:** 37/150 passed (25%)
|
|
11
|
+
- **After fixes:** 104/131 passed (79%)
|
|
12
|
+
- **Test cases fixed:** 500+ incorrect expected values corrected
|
|
13
|
+
|
|
14
|
+
## What Was Fixed
|
|
15
|
+
|
|
16
|
+
### Test Data Issues (Fixed)
|
|
17
|
+
Many test cases had incorrect expected values. Examples:
|
|
18
|
+
- `001 twoSum`: 26 cases fixed
|
|
19
|
+
- `003 lengthOfLongestSubstring`: 22 cases fixed
|
|
20
|
+
- `011 maxArea`: 15 cases fixed
|
|
21
|
+
- `042 trap`: 10 cases fixed
|
|
22
|
+
- `309 maxProfit (cooldown)`: 32 cases fixed
|
|
23
|
+
- `312 burst balloons`: 64 cases fixed
|
|
24
|
+
- And many more...
|
|
25
|
+
|
|
26
|
+
### Test Harness Improvements
|
|
27
|
+
1. Added order-independent comparison for set-like outputs (subsets, combinations, etc.)
|
|
28
|
+
2. Added floating-point tolerance comparison for myPow, etc.
|
|
29
|
+
3. Fixed input handling for both array and object input formats
|
|
30
|
+
4. Added linked list and tree conversion helpers
|
|
31
|
+
|
|
32
|
+
## Remaining Issues (12 Failures)
|
|
33
|
+
|
|
34
|
+
### Near-Complete (Minor Issues)
|
|
35
|
+
| Problem | Pass Rate | Issue Type |
|
|
36
|
+
|---------|-----------|------------|
|
|
37
|
+
| 002 addTwoNumbers | 92/94 | Linked list edge cases |
|
|
38
|
+
| 020 isValid | 99/104 | Edge cases with non-bracket chars |
|
|
39
|
+
| 025 reverseKGroup | 81/82 | 1 linked list case |
|
|
40
|
+
| 049 groupAnagrams | 99/101 | Output order |
|
|
41
|
+
| 131 partition | 97/99 | Order comparison |
|
|
42
|
+
| 287 findDuplicate | 101/104 | Edge case with repeated values |
|
|
43
|
+
|
|
44
|
+
### In-Place Function Issues
|
|
45
|
+
| Problem | Pass Rate | Issue |
|
|
46
|
+
|---------|-----------|-------|
|
|
47
|
+
| 073 setZeroes | 93/96 | Test harness not capturing in-place changes |
|
|
48
|
+
| 130 solve | 49/50 | In-place modification |
|
|
49
|
+
| 286 wallsAndGates | 78/82 | In-place BFS |
|
|
50
|
+
|
|
51
|
+
### Significant Issues
|
|
52
|
+
| Problem | Pass Rate | Issue |
|
|
53
|
+
|---------|-----------|-------|
|
|
54
|
+
| 051 solveNQueens | 37/44 | Order comparison still failing |
|
|
55
|
+
| 212 findWords | 40/126 | Trie-based solution needs review |
|
|
56
|
+
| 076 minWindow | 0/1 | Timeout - solution too slow |
|
|
57
|
+
|
|
58
|
+
## Skipped Problems (Need Custom Harness)
|
|
59
|
+
These problems use class-based implementations that need special test harnesses:
|
|
60
|
+
- LRUCache, MinStack, Trie, WordDictionary
|
|
61
|
+
- MedianFinder, Twitter, KthLargest, TimeMap
|
|
62
|
+
- DetectSquares, Codec, encodeDecode
|
|
63
|
+
- cloneGraph, copyRandomList, hasCycle, detectCycle
|
|
64
|
+
- mergeKLists, lowestCommonAncestor
|
|
65
|
+
|
|
66
|
+
## Files Modified
|
|
67
|
+
- `testcases/*.json` - Fixed 500+ test case expected values
|
|
68
|
+
- `scripts/fix_and_validate.py` - Updated test harness with:
|
|
69
|
+
- Order-independent comparison
|
|
70
|
+
- Float tolerance
|
|
71
|
+
- Better input handling
|
|
72
|
+
|
|
73
|
+
## To Run Validation
|
|
74
|
+
```bash
|
|
75
|
+
python3 scripts/fix_and_validate.py
|
|
76
|
+
```
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Add boundary and failure test cases to all problems."""
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import subprocess
|
|
6
|
+
import tempfile
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
PROJECT_DIR = Path(__file__).parent.parent
|
|
11
|
+
SOLUTIONS_DIR = PROJECT_DIR / "scripts" / "test_solutions"
|
|
12
|
+
TESTCASES_DIR = PROJECT_DIR / "testcases"
|
|
13
|
+
PROBLEMS_DIR = PROJECT_DIR / "problems"
|
|
14
|
+
|
|
15
|
+
# Problem-specific edge cases based on common LeetCode patterns
|
|
16
|
+
PROBLEM_SPECIFIC_CASES = {
|
|
17
|
+
# Two Sum - no solution case, same element twice
|
|
18
|
+
'001': [
|
|
19
|
+
{'nums': [1, 2, 3], 'target': 10}, # no solution
|
|
20
|
+
{'nums': [3, 3], 'target': 6}, # same element
|
|
21
|
+
{'nums': [0, 0], 'target': 0}, # zeros
|
|
22
|
+
{'nums': [-1, -2, -3], 'target': -5}, # negatives
|
|
23
|
+
],
|
|
24
|
+
# Add Two Numbers - carry edge cases
|
|
25
|
+
'002': [
|
|
26
|
+
[[9, 9, 9], [1]], # carry propagation
|
|
27
|
+
[[0], [0]], # zeros
|
|
28
|
+
[[9, 9, 9, 9], [9, 9, 9, 9]], # max carry
|
|
29
|
+
],
|
|
30
|
+
# Longest Substring - repeating chars
|
|
31
|
+
'003': [
|
|
32
|
+
{'s': ''}, # empty
|
|
33
|
+
{'s': 'aaaaaaa'}, # all same
|
|
34
|
+
{'s': 'abcabcabc'}, # repeating pattern
|
|
35
|
+
],
|
|
36
|
+
# Valid Parentheses - unbalanced cases
|
|
37
|
+
'020': [
|
|
38
|
+
{'s': '('}, # single open
|
|
39
|
+
{'s': ')'}, # single close
|
|
40
|
+
{'s': '(((('}, # all open
|
|
41
|
+
{'s': '))))'}, # all close
|
|
42
|
+
{'s': '([)]'}, # interleaved wrong
|
|
43
|
+
{'s': '((())'}, # unbalanced
|
|
44
|
+
],
|
|
45
|
+
# Merge Two Sorted Lists
|
|
46
|
+
'021': [
|
|
47
|
+
[[], []], # both empty
|
|
48
|
+
[[1], []], # one empty
|
|
49
|
+
[[], [1]], # other empty
|
|
50
|
+
[[1, 1, 1], [1, 1, 1]], # all same
|
|
51
|
+
],
|
|
52
|
+
# Search in Rotated Array - edge rotations
|
|
53
|
+
'033': [
|
|
54
|
+
{'nums': [1], 'target': 1}, # single found
|
|
55
|
+
{'nums': [1], 'target': 0}, # single not found
|
|
56
|
+
{'nums': [2, 1], 'target': 1}, # two elements
|
|
57
|
+
{'nums': [1, 2, 3, 4, 5], 'target': 6}, # not rotated, not found
|
|
58
|
+
{'nums': [3, 1], 'target': 3}, # pivot at start
|
|
59
|
+
],
|
|
60
|
+
# Maximum Subarray
|
|
61
|
+
'053': [
|
|
62
|
+
{'nums': [-1]}, # single negative
|
|
63
|
+
{'nums': [-2, -1]}, # all negative
|
|
64
|
+
{'nums': [0]}, # single zero
|
|
65
|
+
{'nums': [-1, 0, -1]}, # zero in middle
|
|
66
|
+
],
|
|
67
|
+
# Climbing Stairs - small cases
|
|
68
|
+
'070': [
|
|
69
|
+
{'n': 1},
|
|
70
|
+
{'n': 2},
|
|
71
|
+
{'n': 3},
|
|
72
|
+
{'n': 45}, # larger case
|
|
73
|
+
],
|
|
74
|
+
# Best Time to Buy and Sell Stock
|
|
75
|
+
'121': [
|
|
76
|
+
{'prices': [7, 6, 5, 4, 3, 2, 1]}, # always decreasing (no profit)
|
|
77
|
+
{'prices': [1, 2, 3, 4, 5, 6, 7]}, # always increasing
|
|
78
|
+
{'prices': [2, 1, 2, 1, 2, 1]}, # oscillating
|
|
79
|
+
{'prices': [1]}, # single price
|
|
80
|
+
{'prices': [1, 1, 1, 1]}, # all same
|
|
81
|
+
],
|
|
82
|
+
# Valid Palindrome
|
|
83
|
+
'125': [
|
|
84
|
+
{'s': ''}, # empty
|
|
85
|
+
{'s': 'a'}, # single
|
|
86
|
+
{'s': '.,'}, # only punctuation
|
|
87
|
+
{'s': ' '}, # only spaces
|
|
88
|
+
{'s': 'race a car'}, # not palindrome
|
|
89
|
+
{'s': '0P'}, # alphanumeric
|
|
90
|
+
],
|
|
91
|
+
# Linked List Cycle - cycle positions
|
|
92
|
+
'141': [
|
|
93
|
+
[[], -1], # empty
|
|
94
|
+
[[1], -1], # single no cycle
|
|
95
|
+
[[1], 0], # single with cycle to self
|
|
96
|
+
[[1, 2], -1], # two no cycle
|
|
97
|
+
[[1, 2], 0], # two cycle to first
|
|
98
|
+
[[1, 2], 1], # two cycle to second
|
|
99
|
+
],
|
|
100
|
+
# LRU Cache
|
|
101
|
+
'146': [
|
|
102
|
+
[['LRUCache', 'get'], [[1], [1]]], # get from empty
|
|
103
|
+
[['LRUCache', 'put', 'get'], [[1], [1, 1], [1]]], # single capacity
|
|
104
|
+
],
|
|
105
|
+
# Number of Islands
|
|
106
|
+
'200': [
|
|
107
|
+
{'grid': [[]]}, # empty grid
|
|
108
|
+
{'grid': [['0']]}, # single water
|
|
109
|
+
{'grid': [['1']]}, # single land
|
|
110
|
+
{'grid': [['1', '1'], ['1', '1']]}, # all land
|
|
111
|
+
{'grid': [['0', '0'], ['0', '0']]}, # all water
|
|
112
|
+
],
|
|
113
|
+
# House Robber
|
|
114
|
+
'198': [
|
|
115
|
+
{'nums': []}, # empty
|
|
116
|
+
{'nums': [0]}, # single zero
|
|
117
|
+
{'nums': [100]}, # single value
|
|
118
|
+
{'nums': [1, 2]}, # two houses
|
|
119
|
+
{'nums': [2, 1]}, # two houses reversed
|
|
120
|
+
],
|
|
121
|
+
# Binary Search
|
|
122
|
+
'704': [
|
|
123
|
+
{'nums': [], 'target': 1}, # empty array
|
|
124
|
+
{'nums': [1], 'target': 1}, # single found
|
|
125
|
+
{'nums': [1], 'target': 0}, # single not found
|
|
126
|
+
{'nums': [1, 2], 'target': 1}, # two elements first
|
|
127
|
+
{'nums': [1, 2], 'target': 2}, # two elements second
|
|
128
|
+
{'nums': [1, 2], 'target': 0}, # two elements not found
|
|
129
|
+
],
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def compute_expected(solution_file, func_name, input_case):
|
|
134
|
+
"""Run solution to compute expected value."""
|
|
135
|
+
with open(solution_file) as f:
|
|
136
|
+
solution = f.read()
|
|
137
|
+
|
|
138
|
+
helpers = '''
|
|
139
|
+
const arrayToTree = (arr) => {
|
|
140
|
+
if (!arr || arr.length === 0 || arr[0] === null) return null;
|
|
141
|
+
const root = { val: arr[0], left: null, right: null };
|
|
142
|
+
const queue = [root];
|
|
143
|
+
let i = 1;
|
|
144
|
+
while (queue.length > 0 && i < arr.length) {
|
|
145
|
+
const node = queue.shift();
|
|
146
|
+
if (i < arr.length && arr[i] !== null) {
|
|
147
|
+
node.left = { val: arr[i], left: null, right: null };
|
|
148
|
+
queue.push(node.left);
|
|
149
|
+
}
|
|
150
|
+
i++;
|
|
151
|
+
if (i < arr.length && arr[i] !== null) {
|
|
152
|
+
node.right = { val: arr[i], left: null, right: null };
|
|
153
|
+
queue.push(node.right);
|
|
154
|
+
}
|
|
155
|
+
i++;
|
|
156
|
+
}
|
|
157
|
+
return root;
|
|
158
|
+
};
|
|
159
|
+
const treeToArray = (root) => {
|
|
160
|
+
if (!root) return [];
|
|
161
|
+
const result = [];
|
|
162
|
+
const queue = [root];
|
|
163
|
+
while (queue.length > 0) {
|
|
164
|
+
const node = queue.shift();
|
|
165
|
+
if (node) { result.push(node.val); queue.push(node.left); queue.push(node.right); }
|
|
166
|
+
else { result.push(null); }
|
|
167
|
+
}
|
|
168
|
+
while (result.length > 0 && result[result.length - 1] === null) result.pop();
|
|
169
|
+
return result;
|
|
170
|
+
};
|
|
171
|
+
const arrayToList = (arr) => {
|
|
172
|
+
if (!arr || arr.length === 0) return null;
|
|
173
|
+
let head = { val: arr[0], next: null };
|
|
174
|
+
let curr = head;
|
|
175
|
+
for (let i = 1; i < arr.length; i++) { curr.next = { val: arr[i], next: null }; curr = curr.next; }
|
|
176
|
+
return head;
|
|
177
|
+
};
|
|
178
|
+
const listToArray = (head) => {
|
|
179
|
+
const result = [];
|
|
180
|
+
while (head) { result.push(head.val); head = head.next; }
|
|
181
|
+
return result;
|
|
182
|
+
};
|
|
183
|
+
'''
|
|
184
|
+
|
|
185
|
+
# Convert input for the test
|
|
186
|
+
if isinstance(input_case, dict):
|
|
187
|
+
inputs = list(input_case.values())
|
|
188
|
+
else:
|
|
189
|
+
inputs = input_case
|
|
190
|
+
|
|
191
|
+
test_code = solution + helpers + f'''
|
|
192
|
+
try {{
|
|
193
|
+
let inputs = {json.dumps(inputs)};
|
|
194
|
+
let result = {func_name}(...inputs);
|
|
195
|
+
if (result && typeof result === 'object' && 'val' in result && 'next' in result) result = listToArray(result);
|
|
196
|
+
if (result && typeof result === 'object' && 'val' in result && 'left' in result) result = treeToArray(result);
|
|
197
|
+
console.log(JSON.stringify({{ success: true, result }}));
|
|
198
|
+
}} catch (e) {{
|
|
199
|
+
console.log(JSON.stringify({{ success: false, error: e.message }}));
|
|
200
|
+
}}
|
|
201
|
+
'''
|
|
202
|
+
|
|
203
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.js', delete=False) as f:
|
|
204
|
+
f.write(test_code)
|
|
205
|
+
temp_file = f.name
|
|
206
|
+
|
|
207
|
+
try:
|
|
208
|
+
result = subprocess.run(['bun', 'run', temp_file], capture_output=True, text=True, timeout=5)
|
|
209
|
+
os.unlink(temp_file)
|
|
210
|
+
if result.returncode == 0 and result.stdout.strip():
|
|
211
|
+
data = json.loads(result.stdout.strip())
|
|
212
|
+
if data.get('success'):
|
|
213
|
+
return data.get('result')
|
|
214
|
+
return None
|
|
215
|
+
except:
|
|
216
|
+
if os.path.exists(temp_file):
|
|
217
|
+
os.unlink(temp_file)
|
|
218
|
+
return None
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def add_specific_cases(problem_id):
|
|
222
|
+
"""Add problem-specific edge cases."""
|
|
223
|
+
if problem_id not in PROBLEM_SPECIFIC_CASES:
|
|
224
|
+
return 0
|
|
225
|
+
|
|
226
|
+
# Get files
|
|
227
|
+
prob_files = list(PROBLEMS_DIR.glob(f"{problem_id}_*.json"))
|
|
228
|
+
sol_files = list(SOLUTIONS_DIR.glob(f"{problem_id}_*.js"))
|
|
229
|
+
tc_files = list(TESTCASES_DIR.glob(f"{problem_id}_*.json"))
|
|
230
|
+
|
|
231
|
+
if not all([prob_files, sol_files, tc_files]):
|
|
232
|
+
return 0
|
|
233
|
+
|
|
234
|
+
with open(prob_files[0]) as f:
|
|
235
|
+
prob_info = json.load(f)
|
|
236
|
+
func_name = prob_info.get('function_name', '')
|
|
237
|
+
|
|
238
|
+
with open(tc_files[0]) as f:
|
|
239
|
+
tc_data = json.load(f)
|
|
240
|
+
|
|
241
|
+
existing = tc_data.get('run_tests', []) + tc_data.get('submit_tests', [])
|
|
242
|
+
existing_inputs = {json.dumps(t.get('input'), sort_keys=True) for t in existing}
|
|
243
|
+
|
|
244
|
+
added = 0
|
|
245
|
+
for case in PROBLEM_SPECIFIC_CASES[problem_id]:
|
|
246
|
+
key = json.dumps(case, sort_keys=True)
|
|
247
|
+
if key in existing_inputs:
|
|
248
|
+
continue
|
|
249
|
+
|
|
250
|
+
expected = compute_expected(sol_files[0], func_name, case)
|
|
251
|
+
if expected is not None:
|
|
252
|
+
tc_data.setdefault('submit_tests', []).append({'input': case, 'expected': expected})
|
|
253
|
+
existing_inputs.add(key)
|
|
254
|
+
added += 1
|
|
255
|
+
|
|
256
|
+
if added > 0:
|
|
257
|
+
with open(tc_files[0], 'w') as f:
|
|
258
|
+
json.dump(tc_data, f, indent=2)
|
|
259
|
+
|
|
260
|
+
return added
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def main():
|
|
264
|
+
total = 0
|
|
265
|
+
updated = 0
|
|
266
|
+
|
|
267
|
+
for prob_id in PROBLEM_SPECIFIC_CASES:
|
|
268
|
+
print(f"Processing {prob_id}...", end=' ', flush=True)
|
|
269
|
+
added = add_specific_cases(prob_id)
|
|
270
|
+
if added > 0:
|
|
271
|
+
print(f"Added {added} cases")
|
|
272
|
+
total += added
|
|
273
|
+
updated += 1
|
|
274
|
+
else:
|
|
275
|
+
print("No new cases")
|
|
276
|
+
|
|
277
|
+
print(f"\n{'='*60}")
|
|
278
|
+
print(f"Added {total} boundary/failure cases to {updated} problems")
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
if __name__ == '__main__':
|
|
282
|
+
main()
|