## Session 12

### Opening Exercise: Another Infinite Series

Here is another cool expression that converges to a specific value:

```    1/0! + 1/1! + 1/2! + 1/3! + 1/4! + ...
```

What is the value?

Recall that ! means 'factorial', and refers to the product all integers from 1 to the number. So, 4! = 4 * 3 * 2 * 1 = 24. By definition, 0! = 1.

Write a Python program that computes the sum for n terms, whatever n is. Start your accumulator with a value of 1, and compute n terms up to the one that contains n!.

### Lessons from the Lab

The goal of Lab 6 was to introduce you the idea of methods and to give you more practice writing loops. We used strings for both.

Task 1 asked you to experiment with string case methods. A method is a function that is associated with a specific kind of object. A couple of things to note:

• New syntax. We invoke a method using "dot" notation:
```    >>> name = 'eugene'
>>> name.count('e')
3
```

The string on the lefthand side of the dot is like one of the values we send to a function.

• Replace a loop. To count the 'e's in a string, we could write a for. The count() method finds that answer for us in one expression.

Many of the string methods you learned about in Chapter 4 replace a loop in a similar way. Knowing the most useful methods for strings enables us to write shorter, clearer code.

That said, knowing how to implement the behavior of a method in a loop of our own design is an essential skill. Your textbook and I will occasionally ask you to do just that. Sometimes it's for practice, and sometimes it's because we want to do something slightly different than the built-in method. Try writing code to mimic find(), isalpha(), or replace() by hand...

Task 2 asked you to write code to compute the Scrabble score for a string. This can be done with an ordinary for loop that determines which point-value group each letter is in:

```    score = 0
for ch in word:
if ch in one_point_letters:
value = 1
elif ch in two_point_letters:
value = 2
elif ch in three_point_letters:
value = 3
elif ch in four_point_letters:
value = 4
elif ch in five_point_letters:
value = 5
elif ch in eight_point_letters:
value = 8
else:
value = 10
score += value
```

Yes, that is the running total pattern again. It really does show up in a lot of different situations. It would be nice not to have to write such a long if statement... Soon.

Finally, Task 3 asked you to write code to compute a student's average grade from a comma-separated string of grades. As noted in the assignment, this extends an idea we had seen in class the day before. There, we printed items separated by commas in a string; here we wanted to tally them up and find their average.

```    total = 0     # new, for running total
count = 0     # new, for running count

start = 0
index = 0
count += 1                           # printing
start = index + 1
index += 1

total += grade                               # of final
count += 1                                   # print

average = total / count
```

A couple of things to note:

• Read template code. Many of you struggled at the outset of this task because you didn't understand what this code was doing:
```    end_of_name = record.find(',')
name   = record[0:end_of_name]
```

It created grades, which is a string with only grades and separating commas. That puts you in position to use the code from last session.

• Study the patterns. It generally isn't useful to memorize large chunks of code, but you do want to study them. This will help you understand how the work. Over time, that sort of study will help you see the bigger picture and reuse the ideas you find in the code.

• A Shortcut? Now that we know about the find() method, perhaps we could use it to take a shortcut:
```    index = grades.find(',')
```

Yes, we can. I like the resulting code, but it is enough different from the example we saw in class that I didn't want to confuse you any more. If you'd like to study it, here it is. (If you want to see a version of that program which eliminates the need for processing the last value after the loop terminates, let me know.)

We can write code that does remarkable things with relatively simple constructs like if, for, and while, coupled with simple sequences of statements. They are like the atoms we find in the periodic table: the basic building blocks of the computational universe.

### Lessons from the Homework

Spec 1 asked you to compute a really big number and then put that number into context. The solution looks a lot like the solution to the tasks on Homework 2, with a short loop thrown in

```    total_grains = 0
for i in range(64):
new_grains = 2**i
total_grains += new_grains
```

That's all. A few things stand out to me:

• Python handles big numbers well, and reasonably fast. 18446744073709551615 -- a lot of rice.

• We can test our result quickly if we know a nice fact about powers of two:
```    20 + 21 + ... + 2n  =  2n+1 - 1
```
So, the total number of grains should be equal to 264 - 1.

• In programs like this, managing the dimensions of numbers is critical. I wrote my program verbosely, with extra lines for the conversion of one dimension to another, in an effort to be careful.

• When presenting data to the user, choosing an appropriate dimension is critical for making the numbers easy to understand. This isn't a computer science skill per se, but it is part of a penumbra of skills that computer scientists often develop.

I liked the idea behind Spec 2 because it is a great example of an algorithm. We all know how to multiply numbers (or learned how to, once), but we rarely think about the fact that there are other ways to do it. With very simple tools: doubling, halving, and adding, we can multiply quite effectively. The principle that underlies the so-called Russian Peasant algorithm is useful even today with powerful computers, because the principle can be used to compute the products of very large numbers more efficiently than native hardware!

Again, the core solution is a humble while loop:

```    product = 0
while n > 0:
if n % 2 == 1:
product += m
m *= 2
n //= 2
```

The spec asked us to let users compute multiple products, so I used a version of the "loop and a half" pattern:

```    while True:
if m == -1:
break
# CALCULATE PRODUCT    -- loop from above
# DISPLAY OUTPUT
```

I wanted to print a more complete final answer for the user, so I built my 'label' before letting my loop change the values of m and n. I could just as easily have made copies in two new variables before entering the loop. Keep in mind: the programmer controls what the program does.

### Looking to the Exam

What will be on there?

• code to trace or debug
• code to write

You have seen many examples of code to trace, debug, and write in class. They are scattered throughout the lecture notes, along with a few "quick exercises" that we didn't do in class.

You don't need to memorize all the esoteric details of Python. In class, we have used a relatively small subset of what the textbook presents. Many of those are nice power tools for us to use once we understand how to write code. On the exam, I will generally ask you to use something specific.

The exam will not last the entire period. We will open with a few minutes of something else first, and then spend 50-60 minutes on the exam.

Do you have any questions? I have office hours and have been known to read a little e-mail...

### Wrap Up

• Code -- today's zip file