Learn How to Think with Karel the Robot. Chapter 9. Text Strings

Chapter 9
Text Strings

In this chapter you will learn:

  • How to work with text strings and text string variables.
  • How to assign text strings to variables.
  • How to display them and compare with each other.
  • How to concatenate them and multiply with integers.
  • How to obtain the length of a text string.
  • How to use the for loop to parse text strings one character at a time.
  • How to extract individual characters from a text string using their indices.
  • How to reverse and slice text strings.
  • How to display quotes and check for substrings.

At the end we will solve some very interesting tasks:

  • Counting occurrences of a substring in a text string.
  • Finding where a substring is located in a text string.
  • Searching for substrings and replacing them with others.
  • Removing substrings from text strings.
  • Swapping substrings in a text string,
  • and even executing a text string as Karel code!

9.1. Raw text strings and text string variables

In the Karel language, working with text strings is similar to Python, although Karel does not implement all Python’s functionality.

A text string is a sequence of characters enclosed in either single quotes, such as ’Hello World!’ or in double quotes, such as ~I am Karel~. It does not matter whether single or double quotes are used. A text string which contains no characters is called empty text string. The following screenshot shows a few examples:


PIC

Figure 9.1: *

Sample text strings.


9.2. Assigning, displaying, and comparing text strings

A text string can be assigned to a variable using the standard assignment operator =:

1name = Karel

Both raw text strings and text string variables can be displayed using the print statement exactly as you would expect:

1print(name) 
2print(~My name is~, name)

Output:


PIC


Text strings (in either raw form or as text string variables) can be compared using the same comparison operator == as numbers:

1str1 = Karel 
2if str1 == Karel 
3  print(~Thats him, Karel!~) 
4else 
5    print(~No, thats not him.~)

Output:


PIC


9.3. Concatenating text strings

One can concatenate two or more text strings using the same + symbol which is used to add numbers:

Program 9.1: Concatenating text strings
1str1 = Tomorrow  
2str2 = I will visit  
3result = str1 + str2 + ~Karel.~ 
4print(result)

As you can see, it does not matter whether one concatenates raw text strings or text string variables. The output of this program is:


PIC


Notice that each of the text strings str1 and str2 had an empty space at the end. It is important to account for empty spaces, they are not inserted automatically. Let’s see what happens when we leave them out:

Program 9.2: Pay attention to empty spaces!
1str1 = Tomorrow 
2str2 = I will visit 
3result = str1 + str2 + ~Karel.~ 
4print(result)

Output:


PIC


9.4. Multiplying text strings with integers

Any text string (in raw form or as a variable) can be multiplied with a (positive) integer, as shown in the following example:

Program 9.3: Multiplying text strings with integers
1name = Karel  
2text = name * 5 + everywhere! 
3print(text)

Output:


PIC


9.5. Length of a text string

Karel provides the Python function len to obtain the length of a text string. The following example shows various flavors of using it:

1print(len(Karel)) 
2txt1 = I am Karel 
3print(len(txt1)) 
4txt2 = Karel rocks! 
5n = len(txt2) 
6print(n)

Output:


PIC


9.6. Parsing a text string with the for loop

Karel provides the Python for loop to parse text strings one character at a time. The keyword for is followed by a variable for the individual characters, the keyword in and the name of the text string to be parsed. For example, let’s parse the text string ’Karel’ and just display all the characters:

1for c in Karel 
2  print(c)

Output:


PIC


9.7. Reversing text strings

As another example, let’s use the for loop to reverse a text string!

1name = Karel the Robot 
2r =  
3for c in name 
4  r = c + r 
5print(r)

Output:


PIC


9.8. Extracting individual characters by their indices

Characters in a text string are internally enumerated, starting with 0 (first character), 1 (second character), 2 (third character), etc. These numbers are called indices (the singular of the word is index). Appending the index in square brackets at the end of either a raw text string or a text string variable yields the desired character. For illustration, let’s extract all five individual characters from the text string ’Robot’ using their indices 0, 1, 2, 3 and 4:

1name = Karel the Robot 
2print(name[0]) 
3print(name[1]) 
4print(name[2]) 
5print(name[3]) 
6print(name[4])

Output:


PIC


picture

Now let’s extract individual characters from a raw text string:

1print(Karel the Robot[10]) 
2print(Karel the Robot[11]) 
3print(Karel the Robot[12]) 
4print(Karel the Robot[13]) 
5print(Karel the Robot[14])

Output:


PIC


9.9. Using negative indices

When one needs to extract characters from the end of a text string, it is possible to use negative indices. The last character has index -1, the one before last has index -2, etc. Let’s illustrate this on a simple example:

1name = Karel the Robot 
2print(name[-5]) 
3print(name[-4]) 
4print(name[-3]) 
5print(name[-2]) 
6print(name[-1])

Output:


PIC


picture

9.10. Slicing text strings

Slicing text strings is another useful functionality provided by Python. Sometimes one needs to extract not only one character, but an entire word or a substring. Actually, you already know how to do this: To extract a five-character word from the beginning of a text string name, one can type name[0] + name[1] + name[2] + name[3] + name[4]:

1name = Karel the Robot 
2first = name[0] + name[1] + name[2] + name[3] + name[4] 
3print(first)

Output:


PIC


But, the same can be done more easily using slicing. A five-character slice from the beginning of a text string name is name[:5]:

1name = Karel the Robot 
2first = name[:5] 
3print(first)

Output:


PIC


A three-character slice starting with the second letter is name[1:4]:

1name = Karel the Robot 
2word = name[1:4] 
3print(word)

Output:


PIC


A five-character slice from the end of the text string name is name[-5:]:

1name = Karel the Robot 
2last = name[-5:] 
3print(last)

Output:


PIC


A three-character slice starting with the fifth letter from the end is name[-5:-2]:

1name = Karel the Robot 
2word = name[-5:-2] 
3print(word)

Output:


PIC


9.11. Displaying quotes in text strings

Displaying quotes is a bit tricky, because these are the symbols which are used to define text strings. To illustrate the problem one can get into, let’s try to display the text She said: ~Hello, it is nice to meet you.~:

1print(~She said: ~Hello, it is nice to meet you.~~)

Output:


PIC


The reason why this did not work is that the interpreter found a complete and correct text string ~She said:~ in the print function. Then it expected either a closing parenthesis, or a comma, or perhaps one of the + or * operators. But instead, it found Hello which did not make any sense. Was this a misplaced variable? The interpreter had no choice other than to throw an error.

The way to prevent this confusion is to enclose the text string that contains double quotes in single quotes:

1print(She said: ~Hello, it is nice to meet you.~)

Output:


PIC


An analogous problem will arise when one tries to display a text string that contains single quotes by enclosing it in single quotes:

1print(Hi, its Karel!)

Output:


PIC


The problem can be fixed by enclosing the text string in double quotes:

1print(~Hi, its Karel!~)

Output:


PIC


9.12. Checking for substrings

Another Python feature provided in the Karel language is the ability to check if a text string contains a given substring. This is done using the keyword in:

Program 9.4: Checking for a raw substring
1txt = ~The robot is really good. His name is Karel.~ 
2if ~Karel~ in txt 
3  print(~The text string contains the word Karel.~) 
4else 
5  print(~The text string does not contain the word Karel.~)

Output:


PIC


And of course this can be done using a variable as well:

Program 9.5: Checking for a text string variable
1txt = ~Karel the IV was a Roman emperor. But Karel the robot is cooler.~ 
2name = ~Karel~ 
3if name in txt 
4  print(~The text string contains the word Karel.~) 
5else 
6  print(~The text string does not contain the word Karel.~)

Output:


PIC


9.13. Counting occurrences of substrings

Sometimes one needs to count how many times certain text string is present in another text string. Python has a built-in functionality for this which is not present in Karel. So, let’s implement it! Your task is to write a function count(sub, txt) to count the number of occurrences of a substring sub in a text string txt. If the substring is not found, the function should return zero. Try to solve this task by yourself before looking at the solution below!

Solution: You already know from Section 9.10 (page 781) how to slice text strings. As the first thing we will introduce a counting variable (named for example result), initialize it with zero, and measure the length of both sub and txt. Let’s denote their lengths by l1 and l2, respectively. The algorithm will be very simple. We will take the first [0:l1] slice of txt and compare it with sub. If there is a match, we will increase result by one. Then we will do the same for the [1:l1+1] slice of txt, for the [2:l1+2] slice of txt, etc. There are l2-l1+1 such slices. At the end, we will return the value of result. Here is the corresponding Karel code:

Program 9.6: Count the occurrences of a substring in a text string!
1# Count the occurrences of the substring sub in the text string txt: 
2def count(sub, txt) 
3  result = 0 
4  l1 = len(sub) 
5  l2 = len(txt) 
6  index = 0 
7  repeat l2 - l1 + 1 
8    slice = txt[index:index+l1] 
9    if slice == sub 
10      inc(result) 
11    inc(index) 
12  return result 
13 
14# Main program: 
15text = ~The Karel programming language was named after Karel Čapek.~ 
16word = ~Karel~ 
17print(~The word ~ + word + ~ was found~, count(word, text), ~times.~)

Output:


PIC


9.14. Finding the positions of substrings

Sometimes one needs to locate the position of a text string in another text string. This means, if the substring is present, to find the index of its first character in the longer text string. If the substring is not present, the result should be -1. Again, this is a built-in functionality in Python which is not provided in Karel. Therefore, let’s implement it! Your task is to write a function find(sub, txt) to return the position of (the first occurrence of) a substring sub in a text string txt. If the substring is not found, return -1. Try to solve this task by yourself before looking at the solution below!

Solution: In Section 9.13 (page 815) we learned how to count the occurrences of a substring in a text string. We will use it as the first thing to check if the substring sub is part of the text string txt. If not, we will return -1. The rest will be similar to the function count from Section 9.13: We will run a loop and compare the [0:l1], [1:l1+1], [2:l1+2] etc. slices of txt to sub. We know at this point that the substring is there because if it was not there, we would have returned -1 previously. So, once a match is found, we return the starting index of the slice. Here is the corresponding program:

Program 9.7: Find the position of a substring sub in a text string txt!
1# Return the position of (the first occurrence of) a substring sub 
2# in a text string txt. If the substring is not found, return -1: 
3def find(sub, txt) 
4  # Check for the substring: 
5  if not sub in txt 
6    return -1 
7  # Now we know the substring is there: 
8  index = 0 
9  l1 = len(sub) 
10  l2 = len(txt) 
11  repeat l2 - l1 + 1 
12    slice = txt[index:index+l1] 
13    if sub == slice 
14      return index 
15    inc(index) 
16 
17# Main program: 
18text = ~The Karel programming language was named after Karel Čapek.~ 
19word = ~Karel~ 
20result = find(word, text) 
21if result == -1 
22  print(~The substring was not found.~) 
23else 
24  print(~The substring was found at position~, result)

Output:


PIC


9.15. Searching and replacing in text strings

Another functionality which is provided in Python but not in Karel is searching for substrings in text strings and replacing them with other substrings. Therefore, let’s implement it! Your task is to write a function replace(txt, sub1, sub2) which in the text string txt finds all occurrences of the substring sub1, replaces them with the substring sub2, and returns the result as a new text string. Try to solve the task on your own before looking at the solution below!

Solution: We will begin with creating an empty text string for the result (named, for example, result). This is where we will add parts of the text string txt which do not contain sub1, and where we will add sub2 instead of sub1. At the beginning, we will call find(sub1, txt) to find the position pos of the first occurrence of the substring sub1 in txt. While the substring is there (pos is not -1), we will add to result the part of txt which precedes sub1 (its [:pos] slice) and sub2. Then we remove this part from txt by redefining txt by its slice txt[pos + len(sub1):]. This process is repeated while the substring sub1 is present in txt. At the end, we add the remaining part of txt to result and return it. Here is the corresponding code:

Program 9.8: Replace all occurrences of a substring sub1 with another substring sub2!
1# Replace all occurrences of substring sub1 with substring sub2: 
2def replace(txt, sub1, sub2) 
3  result =  
4  pos = find(sub1, txt) 
5  while pos != -1 
6    result += txt[:pos] + sub2 
7    txt = txt[pos + len(sub1):] 
8    pos = find(sub1, txt) 
9  return result + txt 
10 
11# Main program: 
12text = ~The Carlos programming language was named after Carlos Čapek.~ 
13result = replace(text, ~Carlos~, ~Karel~) 
14print(result)

Output:


PIC


9.16. Removing substrings

Your next task is to write a function remove(sub, txt) to remove all occurrences of a substring sub from a text string txt. Try to solve this task by yourself before checking the solution below!

Solution: This is a simple application of the function replace() from Section 9.15 (page 823). It is sufficient to replace all occurrences of the substring sub with an empty text string ~~:

Program 9.9: Remove all occurrences of a substring from a text string!
1# Replace all occurrences of substring sub with the empty string ~~: 
2def remove(sub, txt) 
3  return replace(txt, sub, ~~) 
4 
5# Main program: 
6text = ~The Karel the Robot programming language was named after Karel Čapek.~ 
7result = remove(~the Robot ~, text) 
8print(result)

Output:


PIC


9.17. Swapping substrings

Your next task is to write a function swap(txt, sub1, sub2) to swap the substrings sub1 and sub2 in the text string txt. Try to come up with a solution on your own before looking at our solution below!

Solution: This is another simple application of the function replace() from Section 9.15 (page 823). Let’s define a helper text string which for sure will not be present in the text string txt. For example, we can define help = ~__NCLAB_HELPER_STRING__~. Then, one can perform the following three steps:

(1)
Replace in txt all occurrences of the substring sub2 with help.
(2)
Replace in txt all occurrences of the substring sub1 with sub2.
(3)
Replace in txt all occurrences of the substring help with sub1.

Here is the corresponding program:

Program 9.10: Swap two substrings in a text string!
1# Swap substrings sub1 and sub2 in text string txt: 
2def swap(txt, sub1, sub2) 
3  help = ~__NCLAB_HELPER_STRING__~ 
4  txt = replace(txt, sub2, help) 
5  txt = replace(txt, sub1, sub2) 
6  txt = replace(txt, help, sub1) 
7  return txt 
8 
9# Main program: 
10text = ~The Čapek programming language was named after Čapek Karel.~ 
11result = swap(text, ~Karel~, ~Čapek~) 
12print(result)

Output:


PIC


9.18. Executing text strings as code

Executing text strings as code is another built-in functionality in Python which is not present in Karel. So let’s implement it! This will be really neat – imagine sending a robot an SMS from your phone and watch him act on it! Hence, your task is to write a function eval(txt) to execute the text string txt as Karel code. There will be some limitations on how this text string may look like (these limitations help you because they make your programming simpler):

  • All characters in the text string txt should be lowercase.
  • The text string should not contain empty spaces at the ebginning or at the end.
  • Individual commands should be separated with exactly one empty space ’ ’.
  • The text string only should contain the five basic commands go, left, right, get and put.

An example of such a text string txt is ~go get left go put right go~.

Solution: This is a straightforward application of the if-elif-else statement. If the first two characters of the text string txt are ~go~, we will execute the command go, and remove this command and the following empty space from txt by redefining txt = txt[3:]. Otherwise, if the first four characters of txt are ~left~ then we execute the command left and remove this command and the following empty space from txt by redefining txt = txt[5:]. The same we do for the remaining commands right, get and put. The else branch should be used for the case when there is a problem with the text string txt and none of the five basic commands is recognized. All of this should be enclosed in a while loop which checks whether the text string txt is not empty.

Here is the corresponding program:

Program 9.11: Evaluate a text string as Karel code!
1# Evaluate text string txt as Karel code. 
2# Only the basic commands go, left, right, get, put are accepted. 
3# All commands must be lowercase, and separated with one empty space. 
4# No empty spaces at the beginning or at the end! 
5def eval(txt) 
6  while txt != ~~ 
7    if txt[:2] == ~go~ 
8      go 
9      txt = txt[3:] 
10    elif txt[:4] == ~left~ 
11      left 
12      txt = txt[5:] 
13    elif txt[:5] == ~right~ 
14      right 
15      txt = txt[6:] 
16    elif txt[:3] == ~get~ 
17      get 
18      txt = txt[4:] 
19    elif txt[:3] == ~put~ 
20      put 
21      txt = txt[4:] 
22    else 
23      print(~Unknown command, exiting.~) 
24      return 
25  print(~Finished!~) 
26  return 
27 
28# Main program: 
29txt = ~go get left go put right go~ 
30eval(txt)

We will test the program on a simple maze where Karel needs to make one step forward, collect a gold bugget, turn left, make another step forward, put the nugget in the bag, make a right turn, and make one more step to enter his home square. In other words, the text string will have the form ~go get left go put right go~:


PIC


After the program finishes, the nugget is in the bag and Karel is home:


PIC


Also, the following message is displayed at the end:


PIC


9.19. Your homework

The function eval(txt) from Section 9.18 (page 834) has a few technical limitations which are easy to remove:

  • All characters in the text string txt should be lowercase.
  • The text string should not contain empty spaces at the ebginning or at the end.
  • Individual commands should be separated with exactly one empty space ’ ’.

Remove all of them in order to make the function more robust!

Then there is one more substantial limitation:

  • The text string only should contain the five basic commands go, left, right, get and put.

Extend the function eval(txt) to allow simple repeat loops (not nested) whose body is enclosed in two empty spaces!

9.20. Review questions

Friendly reminder - for every question either none, one, or several answers may be correct.

QUESTION 9.1. Which of the following are valid text strings?

A
Hi, I am Karel!
B
’Hi, I am Karel!’
C
~Hi, I am Karel!~
D
(Hi, I am Karel!)

QUESTION 9.2. What is the correct way to assign the text string ~Karel~ to a text string variable name?

A
name := ~Karel~
B
name == ~Karel~
C
name = ~Karel~
D
~Karel~ == name

QUESTION 9.3. What is the correct way to compare two text strings str1 and str2?

A
if str1 = str2
B
if str1 == str2
C
if str2 = str1
D
if str2 == str1

QUESTION 9.4. How can one display the contents of a text string variable txt?

A
print(~txt~)
B
print(’txt’)
C
print(txt)
D
print[txt]

QUESTION 9.5. How can one concatenate two text strings txt1 and txt2?

A
txt1, txt2
B
concat(txt1, txt2)
C
txt1 + txt2
D
txt1 * txt2

QUESTION 9.6. How can one define a new text string echo which contains 10 times the text string ~Help! ~?

A
echo = ~Help!~ * 10
B
echo = ~Help! ~ + 10
C
echo = ~Help! ~ * 10
D
echo = ~Help! Help! ~ * 5

QUESTION 9.7. What is the way to obtain the length of a text string text?

A
len(text)
B
length(text)
C
length text
D
text(length)

QUESTION 9.8. What is the correct way to parse a text string story one character at a time?

A
for c in story
B
for story in c
C
in story for c
D
repeat for c in story

QUESTION 9.9. What is the index of the letter ’e’ in Karel?

A
2
B
3
C
4
D
-2

QUESTION 9.10. What is the slice txt[3:6] of the text string ~Thermometer~?

A
~rmo~
B
~mom~
C
~ome~
D
~met~

QUESTION 9.11. What is the slice txt[-6:-3] of the text string ~Thermometer~?

A
~rmo~
B
~mom~
C
~ome~
D
~met~

QUESTION 9.12. Which of the following are valid text strings in Karel?

A
’Hi, it’s me!’
B
~Hi, it’s me!~
C
~Hi, it~s me!~
D
’Hi, it~s me”

QUESTION 9.13. How can one check if text string txt contains a substring sub?

A
if txt has sub
B
if sub in txt
C
if txt in sub
D
if contains(txt, sub)

QUESTION 9.14. How can one swap the contents of two text strings str1 and str2?

A
Execute str1 = str2 and then str2 = str1
B
Create a helper variable help. Execute help = str2, then str2 = str1 and then str2 = help
C
Create a helper variable help. Execute help = str1, then str2 = str1 and then str2 = help
D
Create a helper variable help. Execute help = str2, then str2 = str1 and then str1 = help


Table of Contents

Created on September 27, 2018 in Karel.
Add Comment
0 Comment(s)

Your Comment

By posting your comment, you agree to the privacy policy and terms of service.