From 410c574317fa2913a09e95615189e1d975a043c3 Mon Sep 17 00:00:00 2001 From: Cal Barkman Date: Thu, 18 Sep 2025 18:26:47 -0700 Subject: [PATCH 1/5] This almost gets things running. Executes all tests, does not debug. --- .vscode/launch.json | 50 ++++++++- .vscode/tasks.json | 72 +++++++++++++ c++/Makefile | 35 +++++++ c++/hello_world/hello_world.cpp | 16 +++ c++/problems/problem_001/problem_001.json | 26 +++++ c++/problems/problem_001/solution.cpp | 8 ++ c++/problems/problem_001/solution.hpp | 11 ++ c++/tests_runner/tests_runner.cpp | 119 ++++++++++++++++++++++ 8 files changed, 335 insertions(+), 2 deletions(-) create mode 100644 .vscode/tasks.json create mode 100644 c++/Makefile create mode 100644 c++/hello_world/hello_world.cpp create mode 100644 c++/problems/problem_001/problem_001.json create mode 100644 c++/problems/problem_001/solution.cpp create mode 100644 c++/problems/problem_001/solution.hpp create mode 100644 c++/tests_runner/tests_runner.cpp diff --git a/.vscode/launch.json b/.vscode/launch.json index 5f9b49c..3fc31a5 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -3,9 +3,55 @@ // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", + // "inputs": [ + // { + // // This input is for the DEBUGGER configuration + // "id": "problemNumber", + // "description": "Enter the 3-digit problem number to DEBUG:", + // "default": "001", + // "type": "promptString" + // }, + // { + // // This input constructs the path for the build task + // "id": "buildAndDebugProblemExePath", + // "type": "command", + // "command": "extension.commandvariable.transform", + // "args": { + // "text": "build/problem_${input:problemNumber}/runner.exe" + // } + // } + // ], "configurations": [ { - "name": "Run LeetCode Solution", + // CONFIGURATION 1: RUN ALL TESTS (Default for F5) + "name": "c++ - Run All Tests", + "type": "cppvsdbg", // Use "cppdbg" for non-windows GDB + "request": "launch", + "program": "C:/Windows/System32/cmd.exe", // Dummy program, task does the work + "preLaunchTask": "Run All Tests", + "console": "integratedTerminal", // Shows output in VS Code's terminal + "cwd": "${workspaceFolder}/c++" // <-- Add this line + }, + { + "name": "C++ - Run LeetCode Solution", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/tests_runner.exe", + "args": [ + "-f", + // Dynamically constructs the path to the JSON file + "problem_${input:problemNumber}/problem_${input:problemNumber}.json" + ], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "MIMode": "gdb", + // IMPORTANT: Update this path to your gdb.exe location! + "miDebuggerPath": "C:/msys64/mingw64/bin/gdb.exe", + // This runs the "Build Problem" task before launching the debugger + "preLaunchTask": "Build Problem" + }, + { + "name": "py - Run LeetCode Solution", "type": "python", "request": "launch", "program": "${file}", @@ -13,7 +59,7 @@ "cwd": "${workspaceFolder}" }, { - "name": "Run All Tests", + "name": "py - Run All Tests", "type": "python", "request": "launch", "program": "${workspaceFolder}/run_all_tests.py", diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..a75f86e --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,72 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Run All Tests", + // Use "process" to run the command directly without shell interference + "type": "process", + "command": "C:/msys64/usr/bin/bash.exe", + "args": [ + "-ic", + // This command string is now passed directly and correctly to bash + "cd \"$(cygpath '${workspaceFolder}')/c++\" && make clean && make test-all" + ], + "options": { + "env": { + "PATH": "C:\\msys64\\ucrt64\\bin;C:\\msys64\\usr\\bin;${env:PATH}" + } + }, + "group": { + "kind": "test", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "dedicated", + "clear": true + }, + "problemMatcher": ["$gcc"] + }, + { + "label": "Build Single Problem for Debug", + // Also change this task to "process" + "type": "process", + "command": "C:/msys64/usr/bin/bash.exe", + "args": [ + "-ic", + // Fixed a bug here to correctly pass the argument to make + "cd \"$(cygpath '${workspaceFolder}')/c++\" && make ${input:buildAndDebugProblemExePath}" + ], + "options": { + "env": { + "PATH": "C:\\msys64\\ucrt64\\bin;C:\\msys64\\usr\\bin;${env:PATH}" + } + }, + "group": "build", + "problemMatcher": ["$gcc"] + }, + { + "type": "cppbuild", + "label": "C/C++: gcc.exe build active file", + "command": "C:\\msys64\\ucrt64\\bin\\gcc.exe", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}\\${fileBasenameNoExtension}.exe" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ] +} \ No newline at end of file diff --git a/c++/Makefile b/c++/Makefile new file mode 100644 index 0000000..8984387 --- /dev/null +++ b/c++/Makefile @@ -0,0 +1,35 @@ +# --- Compiler and Flags --- +CXX := C:/msys64/ucrt64/bin/g++.exe +CXXFLAGS := -O2 -std=c++20 -g -Wall -IC:/msys64/ucrt64/include +# Add the -static-libgcc flag to this line +LDFLAGS := -LC:/msys64/ucrt64/lib -ljsoncpp -static-libstdc++ -static-libgcc + +# --- Project Structure --- +BUILD_DIR := build +TEST_RUNNER_SRC := tests_runner/tests_runner.cpp + +# --- Auto-discovery of Problems --- +PROBLEM_DIRS := $(wildcard problems/problem_*) +PROBLEM_NUMS := $(patsubst problems/problem_%,%,$(PROBLEM_DIRS)) + +# --- Main Targets --- +.PHONY: test-all +test-all: $(addprefix test-, $(PROBLEM_NUMS)) + @echo "" + @echo "✅ All tests completed." + +.PHONY: test-% +test-%: $(BUILD_DIR)/problem_%/runner.exe + @echo "--- Running tests for Problem $* ---" + @$(BUILD_DIR)/problem_$*/runner.exe -f problems/problem_$*/problem_$*.json + +# --- Build Rules --- +$(BUILD_DIR)/problem_%/runner.exe: $(TEST_RUNNER_SRC) problems/problem_%/solution.cpp + @mkdir -p $(@D) + $(CXX) $(CXXFLAGS) -Iproblems/problem_$* -Itests_runner $^ -o $@ $(LDFLAGS) + +# --- Utility Targets --- +.PHONY: clean +clean: + @echo "Cleaning build directory..." + @rm -rf $(BUILD_DIR) \ No newline at end of file diff --git a/c++/hello_world/hello_world.cpp b/c++/hello_world/hello_world.cpp new file mode 100644 index 0000000..244c95d --- /dev/null +++ b/c++/hello_world/hello_world.cpp @@ -0,0 +1,16 @@ +#include +#include +#include + +using namespace std; + +int main() +{ + vector msg {"Hello", "C++", "World", "from", "VS Code", "and the C++ extension!"}; + + for (const string& word : msg) + { + cout << word << " "; + } + cout << endl; +} \ No newline at end of file diff --git a/c++/problems/problem_001/problem_001.json b/c++/problems/problem_001/problem_001.json new file mode 100644 index 0000000..9765bbd --- /dev/null +++ b/c++/problems/problem_001/problem_001.json @@ -0,0 +1,26 @@ +{ + "method": "twoSum", + "tests": [ + { + "Input": { + "nums": "[2,7,11,15]", + "target": "9" + }, + "Output": "[0,1]" + }, + { + "Input": { + "nums": "[3,2,4]", + "target": "6" + }, + "Output": "[1,2]" + }, + { + "Input": { + "nums": "[3,3]", + "target": "6" + }, + "Output": "[0,1]" + } + ] +} \ No newline at end of file diff --git a/c++/problems/problem_001/solution.cpp b/c++/problems/problem_001/solution.cpp new file mode 100644 index 0000000..abc9bc0 --- /dev/null +++ b/c++/problems/problem_001/solution.cpp @@ -0,0 +1,8 @@ +#include "solution.hpp" + +// Standard LeetCode solution for Two Sum +std::vector Solution::twoSum(std::vector& nums, int target) { + int i = 0; + + return std::vector(); // Should not happen for valid inputs +} \ No newline at end of file diff --git a/c++/problems/problem_001/solution.hpp b/c++/problems/problem_001/solution.hpp new file mode 100644 index 0000000..b02181e --- /dev/null +++ b/c++/problems/problem_001/solution.hpp @@ -0,0 +1,11 @@ +#ifndef SOLUTION_HPP_ +#define SOLUTION_HPP_ + +#include + +class Solution { +public: + std::vector twoSum(std::vector& nums, int target); +}; + +#endif // SOLUTION_HPP_ \ No newline at end of file diff --git a/c++/tests_runner/tests_runner.cpp b/c++/tests_runner/tests_runner.cpp new file mode 100644 index 0000000..08a2b9a --- /dev/null +++ b/c++/tests_runner/tests_runner.cpp @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include + +// This is the only external library header we need +#include + +// Include the solution file for the problem being tested +#include "solution.hpp" + +// --- Simple ANSI Color Codes for Terminal Output --- +const char* const RESET_COLOR = "\033[0m"; +const char* const GREEN_COLOR = "\033[32m"; +const char* const RED_COLOR = "\033[31m"; +const char* const BOLD_WHITE = "\033[1m\033[37m"; + +// --- Helper function to parse stringified vectors like "[1,2,3]" --- +std::vector parse_int_vector_string(const std::string& s) { + std::string content = s.substr(1, s.length() - 2); // Remove brackets + if (content.empty()) { + return {}; + } + std::vector vec; + std::stringstream ss(content); + std::string item; + while (std::getline(ss, item, ',')) { + vec.push_back(std::stoi(item)); + } + return vec; +} + +// --- Main Test Runner Logic --- +int main(int argc, char* argv[]) { + // 1. Parse Command-Line Arguments for the JSON file path + std::string json_path; + for (int i = 1; i < argc; ++i) { + std::string arg = argv[i]; + if (arg == "-f" && i + 1 < argc) { + json_path = argv[++i]; + } + } + + if (json_path.empty()) { + std::cerr << RED_COLOR << "Error: No JSON test file provided. Usage: -f " << RESET_COLOR << std::endl; + return 1; + } + + // 2. Read and Parse the JSON file + std::ifstream ifs(json_path); + if (!ifs.is_open()) { + std::cerr << RED_COLOR << "Error: Could not open file: " << json_path << RESET_COLOR << std::endl; + return 1; + } + + Json::Value root; + try { + ifs >> root; + } catch (const std::exception& e) { + std::cerr << RED_COLOR << "Error: Failed to parse JSON file: " << e.what() << RESET_COLOR << std::endl; + return 1; + } + + // 3. Execute Tests + std::string method_name = root["method"].asString(); + const Json::Value& tests = root["tests"]; + + std::cout << BOLD_WHITE << "Running tests for method: " << method_name << RESET_COLOR << std::endl; + std::cout << "------------------------------------------" << std::endl; + + Solution solution; + int tests_passed = 0; + int total_tests = tests.size(); + + for (int i = 0; i < total_tests; ++i) { + const auto& test = tests[i]; + std::cout << "Test Case #" << (i + 1) << "... "; + + try { + if (method_name == "twoSum") { + // Parse inputs and expected output + auto nums = parse_int_vector_string(test["Input"]["nums"].asString()); + int target = std::stoi(test["Input"]["target"].asString()); + auto expected = parse_int_vector_string(test["Output"].asString()); + + // Run the actual function + auto actual = solution.twoSum(nums, target); + + // Sort both vectors to handle different ordering (e.g., [0,1] vs [1,0]) + std::sort(expected.begin(), expected.end()); + std::sort(actual.begin(), actual.end()); + + // Assert and report + if (actual == expected) { + std::cout << GREEN_COLOR << "PASS" << RESET_COLOR << std::endl; + tests_passed++; + } else { + std::cout << RED_COLOR << "FAIL" << RESET_COLOR << std::endl; + // You can add more detailed failure output here if you want + } + } + // Add more 'else if' blocks here for other problems + // else if (method_name == "anotherProblem") { ... } + + } catch (const std::exception& e) { + std::cout << RED_COLOR << "ERROR: " << e.what() << RESET_COLOR << std::endl; + } + } + + // 4. Print Final Summary + std::cout << "------------------------------------------" << std::endl; + std::cout << BOLD_WHITE << "Summary: " << tests_passed << " / " << total_tests << " tests passed." << RESET_COLOR << std::endl; + + // Return a non-zero exit code if any tests failed, so 'make' will know + return (tests_passed == total_tests) ? 0 : 1; +} \ No newline at end of file From c38cc9c65acbc268c50bae1def943400a0bdfe76 Mon Sep 17 00:00:00 2001 From: Cal Barkman Date: Thu, 18 Sep 2025 19:22:08 -0700 Subject: [PATCH 2/5] Correct debug paths. Messy but at least it works. --- .vscode/launch.json | 121 +++++++++++++++++++------------------------- .vscode/tasks.json | 87 +++++++++++++++---------------- 2 files changed, 95 insertions(+), 113 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 3fc31a5..23c256b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,73 +1,58 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - // "inputs": [ - // { - // // This input is for the DEBUGGER configuration - // "id": "problemNumber", - // "description": "Enter the 3-digit problem number to DEBUG:", - // "default": "001", - // "type": "promptString" - // }, - // { - // // This input constructs the path for the build task - // "id": "buildAndDebugProblemExePath", - // "type": "command", - // "command": "extension.commandvariable.transform", - // "args": { - // "text": "build/problem_${input:problemNumber}/runner.exe" - // } - // } - // ], - "configurations": [ - { - // CONFIGURATION 1: RUN ALL TESTS (Default for F5) - "name": "c++ - Run All Tests", - "type": "cppvsdbg", // Use "cppdbg" for non-windows GDB + "version": "0.2.0", + "inputs": [ + { + "id": "problemNumber", + "description": "Enter the 3-digit problem number to DEBUG:", + "default": "001", + "type": "promptString" + } + ], + "configurations": [ + { + "name": "C++: Run All Tests", + "type": "cppdbg", "request": "launch", - "program": "C:/Windows/System32/cmd.exe", // Dummy program, task does the work + "program": "C:/Windows/System32/cmd.exe", "preLaunchTask": "Run All Tests", - "console": "integratedTerminal", // Shows output in VS Code's terminal - "cwd": "${workspaceFolder}/c++" // <-- Add this line + "console": "integratedTerminal", + "cwd": "${workspaceFolder}/c++" }, - { - "name": "C++ - Run LeetCode Solution", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/build/tests_runner.exe", - "args": [ - "-f", - // Dynamically constructs the path to the JSON file - "problem_${input:problemNumber}/problem_${input:problemNumber}.json" - ], - "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "MIMode": "gdb", - // IMPORTANT: Update this path to your gdb.exe location! - "miDebuggerPath": "C:/msys64/mingw64/bin/gdb.exe", - // This runs the "Build Problem" task before launching the debugger - "preLaunchTask": "Build Problem" - }, - { - "name": "py - Run LeetCode Solution", - "type": "python", - "request": "launch", - "program": "${file}", - "console": "integratedTerminal", - "cwd": "${workspaceFolder}" - }, - { - "name": "py - Run All Tests", - "type": "python", - "request": "launch", - "program": "${workspaceFolder}/run_all_tests.py", - "args": [ - "test-results.xml" - ], - "console": "integratedTerminal", - "cwd": "${workspaceFolder}" - } - ] + { + "name": "C++: Debug Single Problem", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/c++/build/problem_${input:problemNumber}/runner.exe", + "args": [ + "-f", + "problems/problem_${input:problemNumber}/problem_${input:problemNumber}.json" + ], + "stopAtEntry": false, + "cwd": "${workspaceFolder}/c++", + "MIMode": "gdb", + "miDebuggerPath": "C:/msys64/ucrt64/bin/gdb.exe", + // This is the only change: point to the new build task + "preLaunchTask": "C++: Build active problem for debugger", + "console": "integratedTerminal" + }, + { + "name": "Python: Run Active File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "cwd": "${fileDirname}" + }, + { + "name": "Python: Run All Tests", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/run_all_tests.py", + "args": [ + "test-results.xml" + ], + "console": "integratedTerminal", + "cwd": "${workspaceFolder}" + } + ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index a75f86e..f597ebc 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,14 +1,52 @@ { "version": "2.0.0", + "inputs": [ + { + "id": "problemNumber", + "description": "Enter the 3-digit problem number to build:", + "default": "001", + "type": "promptString" + } + ], "tasks": [ + { + "label": "C++: Build active problem for debugger", + "type": "process", + "command": "C:/msys64/ucrt64/bin/g++.exe", + "args": [ + "-g", + "-std=c++20", + "-Wall", + // --- Include Paths --- + "-IC:/msys64/ucrt64/include", + // CORRECTED: Added "problem_" prefix + "-Iproblems/problem_${input:problemNumber}", + "-Itests_runner", + // --- Source Files --- + "tests_runner/tests_runner.cpp", + // CORRECTED: Added "problem_" prefix + "problems/problem_${input:problemNumber}/solution.cpp", + // --- Output File --- + "-o", + "build/problem_${input:problemNumber}/runner.exe", + // --- Linker Flags --- + "-LC:/msys64/ucrt64/lib", + "-ljsoncpp", + "-static-libstdc++", + "-static-libgcc" + ], + "options": { + "cwd": "${workspaceFolder}/c++" + }, + "problemMatcher": ["$gcc"], + "group": "build" + }, { "label": "Run All Tests", - // Use "process" to run the command directly without shell interference "type": "process", "command": "C:/msys64/usr/bin/bash.exe", "args": [ "-ic", - // This command string is now passed directly and correctly to bash "cd \"$(cygpath '${workspaceFolder}')/c++\" && make clean && make test-all" ], "options": { @@ -26,47 +64,6 @@ "clear": true }, "problemMatcher": ["$gcc"] - }, - { - "label": "Build Single Problem for Debug", - // Also change this task to "process" - "type": "process", - "command": "C:/msys64/usr/bin/bash.exe", - "args": [ - "-ic", - // Fixed a bug here to correctly pass the argument to make - "cd \"$(cygpath '${workspaceFolder}')/c++\" && make ${input:buildAndDebugProblemExePath}" - ], - "options": { - "env": { - "PATH": "C:\\msys64\\ucrt64\\bin;C:\\msys64\\usr\\bin;${env:PATH}" - } - }, - "group": "build", - "problemMatcher": ["$gcc"] - }, - { - "type": "cppbuild", - "label": "C/C++: gcc.exe build active file", - "command": "C:\\msys64\\ucrt64\\bin\\gcc.exe", - "args": [ - "-fdiagnostics-color=always", - "-g", - "${file}", - "-o", - "${fileDirname}\\${fileBasenameNoExtension}.exe" - ], - "options": { - "cwd": "${fileDirname}" - }, - "problemMatcher": [ - "$gcc" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "detail": "Task generated by Debugger." - } - ] + } + ] } \ No newline at end of file From cffe1c1a471461a1054bf36c89f4cc2295364c33 Mon Sep 17 00:00:00 2001 From: Cal Barkman Date: Thu, 18 Sep 2025 19:22:50 -0700 Subject: [PATCH 3/5] Add a gitignore for executables. --- c++/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 c++/.gitignore diff --git a/c++/.gitignore b/c++/.gitignore new file mode 100644 index 0000000..adb36c8 --- /dev/null +++ b/c++/.gitignore @@ -0,0 +1 @@ +*.exe \ No newline at end of file From edffeb3ba9c6027f1fa16c75986f31e9b8980dbd Mon Sep 17 00:00:00 2001 From: Cal Barkman Date: Thu, 18 Sep 2025 20:01:49 -0700 Subject: [PATCH 4/5] I still don't like it, but refined wrapper. --- c++/tests_runner/tests_runner.cpp | 134 +++++++++++++++++------------- 1 file changed, 76 insertions(+), 58 deletions(-) diff --git a/c++/tests_runner/tests_runner.cpp b/c++/tests_runner/tests_runner.cpp index 08a2b9a..8aac848 100644 --- a/c++/tests_runner/tests_runner.cpp +++ b/c++/tests_runner/tests_runner.cpp @@ -5,51 +5,92 @@ #include #include #include +#include +#include -// This is the only external library header we need #include - -// Include the solution file for the problem being tested #include "solution.hpp" -// --- Simple ANSI Color Codes for Terminal Output --- +// --- ANSI Color Codes for Terminal Output --- const char* const RESET_COLOR = "\033[0m"; const char* const GREEN_COLOR = "\033[32m"; const char* const RED_COLOR = "\033[31m"; const char* const BOLD_WHITE = "\033[1m\033[37m"; -// --- Helper function to parse stringified vectors like "[1,2,3]" --- -std::vector parse_int_vector_string(const std::string& s) { - std::string content = s.substr(1, s.length() - 2); // Remove brackets - if (content.empty()) { - return {}; +// --- Generic Helpers for Parsing and Comparing --- +namespace helpers { + // A set of simple, explicit functions for parsing types from JSON + int parse_int(const Json::Value& value) { + return std::stoi(value.asString()); } - std::vector vec; - std::stringstream ss(content); - std::string item; - while (std::getline(ss, item, ',')) { - vec.push_back(std::stoi(item)); + + std::string parse_string(const Json::Value& value) { + return value.asString(); } - return vec; + + std::vector parse_int_vector(const Json::Value& value) { + std::string s = value.asString(); + std::string content = s.substr(1, s.length() - 2); + if (content.empty()) return {}; + std::vector vec; + std::stringstream ss(content); + std::string item; + while (std::getline(ss, item, ',')) { + vec.push_back(std::stoi(item)); + } + return vec; + } +} + +// --- Test Case Handler Framework --- +using TestCaseHandler = std::function; +static std::map test_registry; + +// ======================================================================= +// =================== PROBLEM HANDLERS GO HERE ========================== +// ======================================================================= + +// With helpers, handlers are concise and easy to read. +bool handleTwoSum(Solution& solution, const Json::Value& test) { + auto nums = helpers::parse_int_vector(test["Input"]["nums"]); + auto target = helpers::parse_int(test["Input"]["target"]); + auto expected = helpers::parse_int_vector(test["Output"]); + + auto actual = solution.twoSum(nums, target); + + // Normalize for comparison, since order doesn't matter for this problem + std::sort(actual.begin(), actual.end()); + std::sort(expected.begin(), expected.end()); + + return actual == expected; +} + +// ======================================================================= +// =================== REGISTER ALL HANDLERS HERE ======================== +// ======================================================================= + +void register_all_tests() { + test_registry["twoSum"] = handleTwoSum; + // To add a new problem, you would add a new handler and register it here. } -// --- Main Test Runner Logic --- +// ======================================================================= +// =================== MAIN TEST RUNNER LOGIC ============================ +// ======================================================================= int main(int argc, char* argv[]) { - // 1. Parse Command-Line Arguments for the JSON file path + register_all_tests(); + std::string json_path; for (int i = 1; i < argc; ++i) { - std::string arg = argv[i]; - if (arg == "-f" && i + 1 < argc) { + if (std::string(argv[i]) == "-f" && i + 1 < argc) { json_path = argv[++i]; } } - if (json_path.empty()) { std::cerr << RED_COLOR << "Error: No JSON test file provided. Usage: -f " << RESET_COLOR << std::endl; return 1; } - // 2. Read and Parse the JSON file std::ifstream ifs(json_path); if (!ifs.is_open()) { std::cerr << RED_COLOR << "Error: Could not open file: " << json_path << RESET_COLOR << std::endl; @@ -57,17 +98,17 @@ int main(int argc, char* argv[]) { } Json::Value root; - try { - ifs >> root; - } catch (const std::exception& e) { - std::cerr << RED_COLOR << "Error: Failed to parse JSON file: " << e.what() << RESET_COLOR << std::endl; - return 1; - } + ifs >> root; - // 3. Execute Tests std::string method_name = root["method"].asString(); - const Json::Value& tests = root["tests"]; + if (test_registry.find(method_name) == test_registry.end()) { + std::cerr << RED_COLOR << "Error: No test handler registered for method '" << method_name << "'" << RESET_COLOR << std::endl; + return 1; + } + TestCaseHandler handler = test_registry[method_name]; + + const Json::Value& tests = root["tests"]; std::cout << BOLD_WHITE << "Running tests for method: " << method_name << RESET_COLOR << std::endl; std::cout << "------------------------------------------" << std::endl; @@ -76,44 +117,21 @@ int main(int argc, char* argv[]) { int total_tests = tests.size(); for (int i = 0; i < total_tests; ++i) { - const auto& test = tests[i]; std::cout << "Test Case #" << (i + 1) << "... "; - try { - if (method_name == "twoSum") { - // Parse inputs and expected output - auto nums = parse_int_vector_string(test["Input"]["nums"].asString()); - int target = std::stoi(test["Input"]["target"].asString()); - auto expected = parse_int_vector_string(test["Output"].asString()); - - // Run the actual function - auto actual = solution.twoSum(nums, target); - - // Sort both vectors to handle different ordering (e.g., [0,1] vs [1,0]) - std::sort(expected.begin(), expected.end()); - std::sort(actual.begin(), actual.end()); - - // Assert and report - if (actual == expected) { - std::cout << GREEN_COLOR << "PASS" << RESET_COLOR << std::endl; - tests_passed++; - } else { - std::cout << RED_COLOR << "FAIL" << RESET_COLOR << std::endl; - // You can add more detailed failure output here if you want - } + if (handler(solution, tests[i])) { + std::cout << GREEN_COLOR << "PASS" << RESET_COLOR << std::endl; + tests_passed++; + } else { + std::cout << RED_COLOR << "FAIL" << RESET_COLOR << std::endl; } - // Add more 'else if' blocks here for other problems - // else if (method_name == "anotherProblem") { ... } - } catch (const std::exception& e) { - std::cout << RED_COLOR << "ERROR: " << e.what() << RESET_COLOR << std::endl; + std::cout << RED_COLOR << "ERROR: An exception occurred: " << e.what() << RESET_COLOR << std::endl; } } - // 4. Print Final Summary std::cout << "------------------------------------------" << std::endl; std::cout << BOLD_WHITE << "Summary: " << tests_passed << " / " << total_tests << " tests passed." << RESET_COLOR << std::endl; - // Return a non-zero exit code if any tests failed, so 'make' will know return (tests_passed == total_tests) ? 0 : 1; } \ No newline at end of file From 7a5937459ac0f4de941585644d94f6075651e23f Mon Sep 17 00:00:00 2001 From: Cal Barkman Date: Thu, 18 Sep 2025 20:02:18 -0700 Subject: [PATCH 5/5] Easy nlog(n) solution for problem 001. --- c++/problems/problem_001/solution.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/c++/problems/problem_001/solution.cpp b/c++/problems/problem_001/solution.cpp index abc9bc0..3316811 100644 --- a/c++/problems/problem_001/solution.cpp +++ b/c++/problems/problem_001/solution.cpp @@ -2,7 +2,22 @@ // Standard LeetCode solution for Two Sum std::vector Solution::twoSum(std::vector& nums, int target) { - int i = 0; + // Input: nums = [2,7,11,15], target = 9 + // Output: [0,1] + // Explanation: Because nums[0] + nums[1] == 9, we return [0, 1]. + + for(auto it=nums.begin(); it != nums.end(); ++it){ + for(auto j=(it + 1); j != nums.end(); ++j){ + if(*it + *j == target) { + auto retval = std::vector(); + int index = std::distance(nums.begin(), it); + int index2 = std::distance(nums.begin(), j); + retval.push_back(index); + retval.push_back(index2); + return retval; + } + } + } return std::vector(); // Should not happen for valid inputs } \ No newline at end of file