Start learning free

LESSON 142 OF 338 · LOOPS & GLOBAL VARIABLES

H4ck3r Sp34k in Go: Building a String from Runes

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:
solution = ""
for each c in 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

    GO · LOOPS & GLOBAL VARIABLES

    Hacker Speak in Go, explained

    Problem overview

    The function convertToHackerSpeak receives a string and returns a coded copy of it. Every a becomes 4, every e becomes 3, every i becomes 1, every o becomes 0 and every s becomes 5. All other characters stay as they are.

    For example, "javascript is cool" becomes "j4v45cr1pt 15 c00l", and "become a coder" becomes "b3c0m3 4 c0d3r". Only lowercase letters are replaced: an uppercase S or A is left untouched, because it is a different character from s or a.

    Approach

    Go strings are immutable, so you can't overwrite a character in place: there is no way to turn the fifth character of the input into a 4. The solution instead builds a new string. It starts with an empty one, walks through the input one character at a time, and appends either the replacement digit or the original character.

    Each character needs a decision with five special cases and a default. A chain of if and else if branches expresses this directly: the first condition that is true decides, and the rest are skipped. The final else catches everything that is not one of the five letters.

    Step by step

    1. Declare solution as an empty string with :=. The empty string literal makes the variable a string, and it will collect the output.
    2. Loop over the input with for ... range. Ranging over a string yields the byte position and the character of each step. The position isn't needed, so it is discarded with _, and the character is named c.
    3. Test for 'a'. If c is that letter, append "4". The letter is written in single quotes because c is a rune, Go's type for a single character, while the digit is written in double quotes because it is appended to a string.
    4. Test for 'e' in an else if and append "3".
    5. Test for 'i' in the next else if and append "1".
    6. Test for 'o' and append "0".
    7. Test for 's' and append "5".
    8. Handle everything else in a final else by appending the original character. Go won't add a rune to a string directly, so it is converted with string(c) first.
    9. Return solution after the loop, once every character has been processed.

    The solution in Go

    func convertToHackerSpeak(input string) string {
        solution := ""
        for _, c := range 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 += string(c)
            }
        }
        return solution
    }
    

    The Go details worth a closer look:

    • Bytes versus runes. A string is a sequence of bytes. Indexing with input[i] gives a single byte, while range decodes the string into runes (Unicode code points). For the two-character string "hé", len is 3 because é takes two bytes, and range visits h at position 0 and é at position 1. Looping with range keeps non-ASCII characters intact.
    • Single quotes and double quotes. 'a' is a rune literal, a number under the hood (97 for a), and "a" is a string. Comparing a rune with a string, as in c == "a", does not compile.
    • string(c) on a rune. Converting a rune gives a one-character string. Converting an arbitrary int this way is a common source of surprises, since it produces the character with that code and not the digits of the number, but for a rune it is exactly what you want.
    • else if placement. Go requires else on the same line as the closing brace of the previous block: } else if ... {. Starting a line with else is a syntax error.
    • Strings can't be edited. input[4] = '4' does not compile. Each += creates a new string.

    Complexity

    Let n be the length of the input. The loop runs once per character, and the work per character is a few comparisons, so the logic is O(n) time and the result needs O(n) space.

    There is a catch for very long inputs. Each solution += ... may copy the string built so far, so repeated appending can cost more than O(n) in total. For lesson-sized strings this does not matter. In code that handles large text, the usual tool is strings.Builder, which appends into a growing buffer: create it with var sb strings.Builder, call sb.WriteRune(c) for each character, and read the result with sb.String().

    Edge cases and common mistakes

    • Empty string. The loop never runs and the function returns "".
    • Uppercase letters. "Seas" becomes "S345". The capital S is not replaced, since only lowercase letters are listed.
    • Characters that need no change. Spaces, digits, punctuation and letters such as f or u reach the final else and are copied unchanged.
    • Forgetting the final else. Without it, every unlisted character would be dropped from the result.
    • Using separate if statements. With a chain of plain ifs, the final else would belong only to the last if, and every letter that was already replaced would be copied as well. else if keeps the cases exclusive.
    • Appending c without conversion. solution += c fails to compile because a rune can't be added to a string.

    Testing

    • "javascript is cool" gives "j4v45cr1pt 15 c00l".
    • "programming is fun" gives "pr0gr4mm1ng 15 fun".
    • "become a coder" gives "b3c0m3 4 c0d3r".
    • "Seas" gives "S345".
    • "" gives "".
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free