Start learning free

LESSON 147 OF 414 · LOOPS & GLOBAL VARIABLES

Hacker Speak in Scala: Replacing Characters in a String

Practice Read the full explanation

Given a string, write a function that returns a coded (h4ck3r 5p34k) version of the string.

In order to work properly, the function should replace all "a"s with 4, "e"s with 3, "i"s with 1, "o"s with 0, and "s"s with 5.

Example 1:

Input:  "javascript is cool"

Output: "j4v45cr1pt 15 c00l"

Example 2:

Input:  "programming is fun"

Output: "pr0gr4mm1ng 15 fun"

Example 3:

Input:  "become a coder"

Output: "b3c0m3 4 c0d3r"
Hints:

We have to iterate through every character of input, check for each scenario and treat it accordingly:
  • Is it an 'a'? If so, replace with '4'. Otherwise:
  • Is it an 'e'? If so, replace with '3'. Otherwise:
  • Is it an 'i'? If so, replace with '1'. Otherwise:
  • Is it an 'o'? If so, replace with '0'. Otherwise:
  • Is it an 's'? If so, replace with '5'. Otherwise, keep it as it is.
Remember that strings are immutable. How does that affect us? How can we put this strategy into code?

Strings are immutable means you cannot directly change a character in a string like this: input(4) = '4'. This means we have to create a new string where we will store the solution as we create it. How can we translate these two hints in code?

Let's create a new string named solution, initially empty, where we will push all the encoded characters of input. We will use a for loop and a character variable c to iterate through input and treat the scenarios inside the loop:
var solution = ""
for (c <- input) {
    if (c == 'a') {
        solution += '4'
    } else if (c == 'e') {
        solution += '3'
    } else if (c == 'i') {
        solution += '1'
    } else if (c == 'o') {
        solution += '0'
    } else if (c == 's') {
        solution += '5'
    } else {
        solution += c
    }
}
return solution


We have a for loop that performs exactly n iterations (n is the length of input), thus the Time Complexity is O(n).
The extra space we use is the extra string solution. Its length will be n in the end, thus the Extra Space used is also O(n).
STEP 1 OF 9
    Ctrl + Enter to check

    SCALA · LOOPS & GLOBAL VARIABLES

    Hacker Speak in Scala, explained

    Problem overview

    The method convertToHackerSpeak receives a string and returns a coded copy of it. Five lowercase letters are replaced by digits: a becomes 4, e becomes 3, i becomes 1, o becomes 0 and s becomes 5. Every other character stays as it is, including spaces.

    For "javascript is cool" the result is "j4v45cr1pt 15 c00l". For "become a coder" it is "b3c0m3 4 c0d3r". In "programming is fun" the letters u and n don't change, so the result is "pr0gr4mm1ng 15 fun".

    Approach: build a new string character by character

    A Scala String is immutable, so you can't overwrite a character in the string you were given. Instead, you build a new string. Start with an empty one, look at each input character in order, and append either its replacement or the character itself. The new string ends up with exactly the same length as the input, with the letters swapped.

    Deciding what to append is a chain of questions. Is it an a? Then append 4. If not, is it an e? And so on through i, o and s. If none of them matched, append the character unchanged. Each character takes exactly one path through the chain.

    Step by step

    1. Declare var solution = "". It must be a var, because each append creates a longer string and stores it back into the variable.
    2. Loop with for (c <- input). Looping over a String gives its characters one at a time, each as a Char.
    3. Handle 'a'. Test c == 'a' and append '4' with solution += '4'. Single quotes make a Char literal, the same type as c. Double quotes would make a String.
    4. Handle 'e', 'i', 'o' and 's'. Each one is another else if on the chain. An else if is tested only when all the conditions before it were false, so only one branch runs per character.
    5. Finish with a plain else. It runs for every other character and appends c unchanged, which keeps spaces, punctuation, uppercase letters and the other lowercase letters.
    6. Return solution after the loop.

    The solution in Scala

    class Solution {
        def convertToHackerSpeak(input: String): String = {
            var solution = ""
            for (c <- input) {
                if (c == 'a') {
                    solution += '4'
                } else if (c == 'e') {
                    solution += '3'
                } else if (c == 'i') {
                    solution += '1'
                } else if (c == 'o') {
                    solution += '0'
                } else if (c == 's') {
                    solution += '5'
                } else {
                    solution += c
                }
            }
            return solution
        }
    }
    

    Language details

    • += on a String. solution += '4' means solution = solution + '4'. Adding a Char to a String gives a new String with that character at the end. The old string is not modified, which is why the variable has to be a var.
    • Char against String. 'a' is a character and "a" is a one-character string. Writing c == "a" doesn't compile: the compiler reports Values of types Char and String cannot be compared with == or !=.
    • Only lowercase letters change. Case matters: "Alice SEES" becomes "Al1c3 SEES". The capital A and the capitals in SEES are different characters from a and s, so they pass through the final else.
    • Order of the chain. The five tests are mutually exclusive, so the order doesn't change the result. Only the final else has to come last.

    Tracing a short input

    For the input "is a", the variable solution changes like this:

    cBranch takensolution afterwards
    'i''i'"1"
    's''s'"15"
    ' 'final else"15 "
    'a''a'"15 4"

    A match version

    The five-way else if chain is the plain way to write this, and it is what the lesson uses. Scala also has pattern matching with match, which expresses "one of several cases" more compactly. The body of the loop can become one expression:

    solution += (c match {
        case 'a' => '4'
        case 'e' => '3'
        case 'i' => '1'
        case 'o' => '0'
        case 's' => '5'
        case other => other
    })
    

    The last case, case other => other, matches any character not listed before it and gives it back unchanged, exactly like the final else. Wrapped in the same loop, it turns "become a coder" into "b3c0m3 4 c0d3r". Both forms do the same work, so use whichever reads better to you.

    Complexity

    The loop visits each of the n characters once, so there are n iterations of constant-looking work. The returned string has length n, so the extra space is O(n).

    One caveat applies to the time. Each += on a String copies the existing text to make the new, longer string, so the copying alone costs more than a constant per character: the total work for a long input grows roughly with the square of its length. For the short strings in this lesson that is not a concern. For long inputs, a StringBuilder with append avoids the repeated copying and keeps the work proportional to n. The branches stay the same, and only the accumulator changes:

    val sb = new StringBuilder
    for (c <- "banana") {
        if (c == 'a') sb.append('4') else sb.append(c)
    }
    println(sb.toString)
    

    That fragment prints b4n4n4.

    Edge cases and common mistakes

    • An empty string. The loop doesn't run and the method returns "".
    • Digits already in the input. A '4' or a '0' in the input is just another character. It goes through the final else and stays as it is, so the method never turns a digit back into a letter.
    • Nothing to replace. A string such as "fun" comes back unchanged.
    • Dropping the final else. Without it, characters that need no change would vanish from the result.
    • Forgetting that strings are immutable. Calling a method on the input and ignoring the returned string changes nothing.
    • Mixing Char and String literals. Use single quotes for the character comparisons and for the appended digits.

    Testing

    Try "javascript is cool" ("j4v45cr1pt 15 c00l"), "become a coder" ("b3c0m3 4 c0d3r"), "Alice SEES" ("Al1c3 SEES") and "" ("").

    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free