0

How can I fix this code so I no longer get an error. The error I get is fatal error: Array index out of range. The code checks how many "x" and "o" there are in a string

var input = "xxxoxoooxoxo"

var inputString = Array(input.characters)

var XString = ""

var OString = ""

for var i = 0; i <= inputString.count; ++i {

    if inputString[i] == "x" {

        XString.append(inputString[i])

    }

    else if inputString[i] == "o" {

        OString.append(inputString[i])

    }

}

if XString.characters.count == OString.characters.count {

    print("equal")

}

else {

    print("Not Equal")

}

Thanks for the help.

3
  • If your goal is counting, why construct new strings? Commented Mar 20, 2016 at 7:04
  • 2
    Keep in mind the standard for loop will be deprecated in swift 2.2 and removed in 3.0 Commented Mar 20, 2016 at 7:11
  • 1
    as will ++ and -- I believe. Commented Mar 21, 2016 at 1:07

4 Answers 4

3

Replace this

for var i = 0; i <= inputString.count; ++i

with this:

for var i = 0; i < inputString.count; ++i

Arrays are zero indexed. That means the first element has the index 0. The second element has index 1. ... . The last element has the index array.count-1.

Sign up to request clarification or add additional context in comments.

Comments

3

@dasdom is correct. but here is a more Swift-y way to do it:

// input string
var input = "ooooxxxxxxxoxoooxoxo" 

// difference between number of x's and number of o's
var diff = 0 

// perform this function for each character in `input.characters`:
input.characters.forEach {
    switch $0 // $0 is the argument to our function (unnamed)
    {
        case "x": diff += 1          // x's are +1
        case "o": diff -= 1          // o's are -1
        default: fatalError()        // we expect only 'x' or 'o'... if we get something else, just crash
    }
}

// use the ternary (?:) operator to print the answer.
// (<result> = <condition> ? <if-true value> : <if-false value>)
print( diff == 0 ? "equal" : "not equal" )

A shorter version, inspired by @Eendje's answer :)

print( input.characters.reduce(0) { $0 + [ "x":1, "o":-1 ][ $1 ]! } != 0 ? "not" : "", "equal" )

6 Comments

Haha, nice one! I really like the use of a dictionary here. I would use ?? 0 instead of implicitly unwrapping it though :) (Maybe I should add that in my answer! :P)
The second version is quite interesting, but I think it's to much for someone struggling with the number of elements in an array. ;)
I used force unwrap to catch "invalid" characters... but if you don't care about that, then ?? 0 works, sure.
I wonder, lets say input has over 1000 characters. How expensive is it to create a dictionary for every iteration? Do you happen to have any idea?
hopefully, since it's a literal it won't be created every time? but if that's a concern, the dictionary could be created outside the closure...
|
2

While everyone is giving you an alternative, I thought this would be a nice addition as well:

var input = "xxxxxoxoooxoxo"

You can get the count by using filter:

let xCount = input.characters.filter { $0 == "x" }.count
let oCount = input.characters.filter { $0 == "o" }.count

print( xCount == oCount ? "equal" : "not equal" )

In your case, using reduce would be more efficient and it's shorter:

let result = input.characters.reduce(0) { $0 + ($1 == "x" ? 1 : -1) }

print(result == 0 ? "equal" : "not equal") // not equal

This is only if you're sure input only contains x and o. If not, then you'll have to change the evaluation to:

{ $0 + ($1 == "x" ? 1 : $1 == "o" ? -1 : 0) }

Comments

0

You are enumerating pass the range of the array. Use this instead.

for var i = 0; i < inputString.count; ++i {

Or you can use this more idiomatic code:

var input = "xxxoxoooxoxo"


var xString = 0

var oString = 0

for c in input.characters {

    if c == "x" {

        xString++

    }

    else if c == "o" {

        oString++

    }

}

if oString == xString {

    print("equal")

}

else {

    print("Not Equal")

}

Comments

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.