// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 Two Sum Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <vector>
#include <unordered_map>

/**
 * Finds two numbers in the array that add up to the target sum
 * Uses hash map for O(n) time complexity
 * @param nums Vector of integers to search
 * @param target Target sum to find
 * @return Vector containing indices of the two numbers, empty if not found
 */
std::vector<int> twoSum(std::vector<int>& nums, int target) {
    std::unordered_map<int, int> numMap; // value -> index
    
    for (int i = 0; i < nums.size(); i++) {
        int complement = target - nums[i];
        
        // Check if complement exists in map
        if (numMap.find(complement) != numMap.end()) {
            return {numMap[complement], i};
        }
        
        // Store current number and its index
        numMap[nums[i]] = i;
    }
    
    return {}; // No solution found
}

/**
 * Prints the array elements
 * @param nums Vector to print
 */
void printArray(const std::vector<int>& nums) {
    std::cout << "[";
    for (int i = 0; i < nums.size(); i++) {
        std::cout << nums[i];
        if (i < nums.size() - 1) std::cout << ", ";
    }
    std::cout << "]";
}

int main() {
    // Example test cases
    std::vector<int> nums1 = {2, 7, 11, 15};
    int target1 = 9;
    
    std::vector<int> nums2 = {3, 2, 4};
    int target2 = 6;
    
    std::vector<int> nums3 = {3, 3};
    int target3 = 6;
    
    // Test case 1
    std::cout << "Test Case 1:" << std::endl;
    std::cout << "Array: ";
    printArray(nums1);
    std::cout << ", Target: " << target1 << std::endl;
    
    std::vector<int> result1 = twoSum(nums1, target1);
    if (!result1.empty()) {
        std::cout << "Indices: [" << result1[0] << ", " << result1[1] << "]" << std::endl;
        std::cout << "Values: [" << nums1[result1[0]] << ", " << nums1[result1[1]] << "]" << std::endl;
    } else {
        std::cout << "No solution found" << std::endl;
    }
    std::cout << std::endl;
    
    // Test case 2
    std::cout << "Test Case 2:" << std::endl;
    std::cout << "Array: ";
    printArray(nums2);
    std::cout << ", Target: " << target2 << std::endl;
    
    std::vector<int> result2 = twoSum(nums2, target2);
    if (!result2.empty()) {
        std::cout << "Indices: [" << result2[0] << ", " << result2[1] << "]" << std::endl;
        std::cout << "Values: [" << nums2[result2[0]] << ", " << nums2[result2[1]] << "]" << std::endl;
    } else {
        std::cout << "No solution found" << std::endl;
    }
    std::cout << std::endl;
    
    // Test case 3
    std::cout << "Test Case 3:" << std::endl;
    std::cout << "Array: ";
    printArray(nums3);
    std::cout << ", Target: " << target3 << std::endl;
    
    std::vector<int> result3 = twoSum(nums3, target3);
    if (!result3.empty()) {
        std::cout << "Indices: [" << result3[0] << ", " << result3[1] << "]" << std::endl;
        std::cout << "Values: [" << nums3[result3[0]] << ", " << nums3[result3[1]] << "]" << std::endl;
    } else {
        std::cout << "No solution found" << std::endl;
    }
    
    return 0;
}