Programming Challenge: Are You a Swift Ninja? Part 2

Do you consider yourself a Swift Ninja? Take our programming challenge! Beginners are also welcome to follow through and learn the craft. By Marin Todorov.

Leave a rating/review
Save for later
Share

Contents

Hide contents

Update 8/5/14: Series updated for Xcode6-beta 5.

Welcome back to our “Are you a Swift Ninja?” Programming Challenge!

In the first part of this series, you got some practice with default values in functions, variadic parameters, map/reduce, advanced switch statement features, and more.

Hopefully, you earned plenty of shurikens along the way!

In this second and final part of the series, you will get 4 more challenges to test your ninja skills.

In addition, this tutorial has a special final challenge, where you will get a chance to compete against other developers for fame and fortune!

The best solution to the final challenge will be featured in this post, and will also get a free copy of our upcoming Swift by Tutorials Bundle, which includes three books about programming in Swift.

Ninja mode activate – the challenge continues!

Challenge #5

Stretch those fingers and assume the position. It’s time to do another problem that involves recursion and function syntax.

Write a single function that reverses the text in a string. For example, when passed the string “Marin Todorov” will return the string “vorodoT niraM”.
Requirements:

  • You can’t use any loop operators nor subscripts (i.e. no square brackets in the code).
  • You can’t use any built-in Array functions.
  • Don’t use variables.

Here’s an example of a function call and its output:

reverseString("Marin Todorov") //--> "vorodoT niraM"

3shurikens

[spoiler title=”Hints”]
Use recursion to move all letters one by one from the first string to another, effectively reversing their order.

2shurikens
[/spoiler]

[spoiler title=”Tutorial”]
This problem has a solution very similar to the one of Problem #4. The difference is mostly due to the fact that the function reverseString you need to write takes one parameter while countFrom(from:, to:) takes two. You can easily skip around that fact by using what you’ve learned so far!

Start by defining a function that takes two parameters, the latter being an empty string by default. You’ll use this second parameter to accumulate the result of the function.

Every recursive call to your function will move one character from the input string input to the result string result — reversing the order characters appear in the text.

When there are no more characters in the input text, that means you’ve moved them all to the result, so you need to stop recursing.

Want to see it? Here’s the complete solution:

func reverseString (input: String, output: String="") -> String {
  if input.isEmpty {
    return output
  } else {
    return reverseString(
      input.substringToIndex(input.endIndex.predecessor()),
      output: output + input.substringFromIndex(input.endIndex.predecessor()))
    }
  }
}

First you check if input is empty – this is your stop condition. If yes, then just return output with the accumulated result.

If input still has characters, then remove the last one from input and add that character to output. Call the function recursively with these new input and output parameters.

To better understand how the function works look at the parameters of each recursive call:

(Marin Todorov, )
(Marin Todoro, v)
(Marin Todor, vo)
(Marin Todo, vor)
(Marin Tod, voro)
(Marin To, vorod)
(Marin T, vorodo)
(Marin , vorodoT)
(Marin, vorodoT )
(Mari, vorodoT n)
(Mar, vorodoT ni)
(Ma, vorodoT nir)
(M, vorodoT nira)
(, vorodoT niraM)

Give yourself 1shuriken for trying out the code in a Playground and producing the text output from above. Note: you’ll need to add a println() somewhere.
[/spoiler]

Challenge #6

Your next challenge has to do with operator overloading — one of the most powerful features of Swift. I hope you’ve had a chance to look into how to do that :]

Your challenge is to overload the “*” operator so it takes a Character and an Int and produces a String with the character repeated Int times.

Here’s an example usage and output:

"-" * 10 //output is: "----------"

Make usage of everything you learned so far and don’t use any variables, loops, inout parameters, or subscripts.

You might need to define an extra auxiliary function. At the time of writing, Xcode crashes when you try to define a nested function inside an operator overload. Hopefully this is corrected at some point.

3shurikens

[spoiler title=”Hints”]
Write a separate function that takes 3 parameters: the input character, the accumulated string result, and the times to repeat the character. Call this function recursively as you did in the previous challenge until the length of the result equals the target length.

2shurikens
[/spoiler]

[spoiler title=”Tutorial”]

For this solution, write a recursive function that takes the following parameters: a Character, a String to accumulate the result, and a Double to set the desired length of the resulting string:

func charMult(char: Character, var result: String, length: Double) -> String {
    if Int64(countElements(result)) < Int64(length) {
        result.append(char)
        return charMult(char, result, length)
    } else {
        return result
    }
}

This function is very similar to what you developed in the previous challenge. It keeps recursively calling itself and adding one more character to the accumulator(result) until the length of the result equals the given length parameter.

When you reach the target length, you just return the result.

In the function above, you need to define the length parameter as a Double because when you write an integer constant in your code (i.e. 10, 4, or 2014) Swift will by default cast it to a Double value.

In order to have your "*" operator work for on a character and an integer like this:

"x" * 20

... you have to make it work for a Character on the left side and a Double on the right side. It may feel a bit strange, but you'll soon find it's part of what makes Swift very powerful.

Finally, overload the operator itself and make it use your charMult(char: Character, result: String, length: Double) function:

func * (left: Character, right: Double) -> String {
    return charMult(left, "", right)
}

You declare a function with the operator itself as the name (func *). The two parameters to that functions are the values you will put on both sides of the * operator.

You declare that the left side of "*" should be a Character and right side a Double, and that the result of the operation is a String. You declare all this as you would declare any normal function.

For the body of the operator overload, you just call charMult(char: Character, result: String, length: Double) and return the result.

Give the new operator a try in a Playground, try fun things like these:

"-" * 10 + ">" //prints an arrow
"%" + "~" * 6  //prints a worm
"Z" * 20       //gets sleeping

Give yourself 1shuriken for trying the above examples in a Playground.

[/spoiler]

Contributors

Over 300 content creators. Join our team.