# ICP22 lecture notes

## Thursday, September 15

topics for the day:

• how to evaluate simple definite loops
• more fun with strings: `ord`/`chr` operations

### quick quiz

Consider the following function:

``````def mystery(a):
b = 1
for _ in range(a):
b = b * a
return b``````
1. What would be the result of evaluating:

``>>> mystery(3)``

2. Briefly(!), what does the function compute? For example: “Returns the sum of the first n numbers.”:

answer: Returns `a` raised to the `a` power.

### Evaluating loops

Consider this familiar function:

``````def factorial(n):
product = 1
counter = 1
for _ in range(n):
product = product * counter
counter = counter + 1
return product``````

How does Pythone evaluate `factorial(4)`?

• the `n` (the input argument to function `factorial`) gets assigned the value 4
• `product` gets the value 1
• `counter` gets the value 1
• the definite loop (which will run 4 times) begins
``````times through loop   n   product   counter
------------------   -   ------    -------
0               4      1         1
1               4      1         2
2               4      2         3
3               4      6         4
4               4     24         5
------
return 24``````

(try this example using pythontutor)

In `for _ in range(...)` the underscore (`_`) is actually a variable, but it means we will ignore its value.

In contrast, when iterating over a string using ```for ... in <some string>``` as in:

``for c in s:``

the definite loop repeates a number of times equal to the length of the string (in this case the value of the variable `s`); each time through the loop the loop variable (in this case called `c`, but it can be named just as we name any other variable) takes on the next character in `s`. Consider:

``````def reverse(s):
"""Returns new string which is reverse of s.

>>> reverse('TAB')
'BAT'
"""
t = ''
for c in s:
t = c + t
return t``````

and then evaluating `reverse('TAB')`:

``````s         t        c
--------------------
'TAB'     ''       not yet defined
--- entering the loop ---
'TAB'     ''       'T'
'TAB'     'T'      'A'
'TAB'     'AT'     'B'
---- done with the loop ---
'TAB'     'BAT'    no longer needed``````

(try a similar example using pythontutor

### strings are sequences of characters

we have already mentioned that strings are sequences of characters and by characters we mean, in general, text symbols that loosely correspond to keyboard symbols; in Python characters are (circularly!) strings of length 1; but in many other PLs (and in general), characters are thought as distinct (and simpler things). The key concept is that characters are standardized: for decades, computer scientists across the globe have agreed that each character that can be displayed (or that has a standard meaning like `\n` for advancing the display to a new line) correspond to a positive whole number. First there was the ASCII code; now there is Unicode which is a superset of ASCII. (In this course we will mostly rely on ASCII). The code tells us that that a string such as

```CAB```

corresponds to a sequence of numbers, in this case:

``67   65   66``

simple takeaways about ASCII:

• consecutive symbols have consecutive codes
• lowercase different than uppercase
• lowercase comes after uppercase

in Python we can find the ASCII code of a character using the built-in `ord` function:

``````>>> ord('A')
65``````

we can use that in a loop like:

``````>>> for ch in 'Help me!':
print(ord(ch))
72
101
108
112
32
109
101
33``````

there is also the inverse functon, `chr`, which takes a positive whole numbers and returns the correspond ASCII (or Unicode) symbol as a one-character string:

``````>>> chr(66)
'B'``````

we can use `ord` and `chr` togehter in a function like:

``````def shift1(word):
"""Return new string that is each character of s shifted one place.

>>> shift1('HAL')
'IBM'
"""
shifted_word = ''
for symbol in word:
original_code = ord(symbol)
new_code = original_code + 1
new_symbol = chr(new_code)
shifted_word = shifted_word + new_symbol
return shifted_word``````

Looking ahead, we can see what happens when we do this:

``````def weird(s):
t = ''
for ch in s:
t = t + (chr(ord(ch) + 32))
return t``````

and then:

``````>>> weird('WHATEVER')
'whatever'
>>> weird('HELP ME!')
'help@meA'``````