0

I'm not sure what I am doing wrong, but when I execute the code below:

func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
    let length = nums.count-1;

    for index1 in 0...length {
        let difference = target - nums[index1];
        print(target, difference, nums[index1])
        if (nums[index1] < difference) {
            for index2 in index1+1...length {
                if (nums[index2] == difference) {
                    return [index1, index2];
                }
            }
        }
    } 

    return [];
}

let summer = twoSum([-1,-2,-3,-4,-5], -8)

I get the following error:

Swift/ClosedRange.swift:347: Fatal error: Range requires lowerBound <= upperBound

Interestingly, if I change the condition for the if statement to nums[index1] <= target, it doesn't crash.

7
  • for index2 in index1+1...length but say for an 8-element array wouldn’t length be 7, so index1+1 can be 8 since ranges are inclusive and the first loop is 0-7? Commented Apr 24 at 23:44
  • Range operators in Swift
    – Stoic
    Commented Apr 24 at 23:58
  • FYI - in Swift, just like a for statement, if statements don’t require parentheses either.
    – HangarRash
    Commented Apr 25 at 0:06
  • When posting an error with a line number, it’s helpful to point out which line of code is at that line.
    – HangarRash
    Commented Apr 25 at 0:09
  • 1
    @ATL_DEV Semicolons are optional too. Very few Swift coders use parentheses on for or if (and others), nor semicolons. As a coder, you get to choose your style. Just be consistent about it. Always use them or never use them. Of course it's less typing if you choose not to use the optional syntax.
    – HangarRash
    Commented Apr 25 at 0:29

2 Answers 2

0

The issue is that in your inner for-loop, when index equals length, your inner loop becomes: for index2 in index1+1...length.

This is equivalent to for index2 in nums.count ... nums.count - 1. As the error says, the beginning of a loop range can't be larger than the end of the range.

Solution: You can just change if (nums[index1] < difference) to index1 + 1 <= length

2
  • Hmmm. I'm learning swift for the first time here. I presumed it wouldn't take the loop if the loop is out of range. It's precisely these types of fence post that plague software.
    – ATL_DEV
    Commented Apr 25 at 0:01
  • @ATL_DEV That's an understandable assumption, but almost every programming language works the same way. One of the beauties of swift is how it enforces correct, precise, and clearly-defined code... it's better to have to be extra-specific with the compiler than to have the compiler guess at what you meant :)
    – Stoic
    Commented Apr 25 at 0:21
0

In Swift, the lower bound of a range can never be greater than the upper bound. This may seem like an annoying restriction at first, but it actually has huge benefits. In all your code where you consume a range, you can always rely on it not being inverted, so you don't have to defensively check for this condition everywhere.

Stoic already gave one solution, but I'll suggest another: just don't create your own ranges.

  • nums.indices will produce exactly the range you're looking for your first loop bound, so it can just be for index1 in nums.indices.
  • For your second loop bound, you want the same range, just skipping the start. You can do that with .dropFirst(). This will correctly handle cases where you try to drop more elements than are in the range (it will just return an empty range).
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
    for index1 in nums.indices {
        let difference = target - nums[index1];
        
        print(target, difference, nums[index1])
        if nums[index1] < difference {
            for index2 in nums.indices.dropFirst(index1) {
                if (nums[index2] == difference) {
                    return [index1, index2];
                }
            }
        }
    } 

    return [];
}

let summer = twoSum([-1,-2,-3,-4,-5], -8)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.