### CS51A - Spring 2019 - Class 6

#### Example code in this lecture

while.py
scores-lists.py

#### Lecture notes

- assignment 2

• prime numbers
- what is a prime number?
- a number that is only divisible by 1 and itself
- what are the first 10 prime numbers?
- the first 100?
- the first 1000?
- How could we write a program that figured this out?
- To start with, how can we tell if a number is prime?
- try and divide it by all of the numbers between 1 and the number
- if none of them divide evenly, then it's prime, otherwise it's not
- A few questions:
- do we need to check all of the numbers up to that number?
- just need to check up to sqrt(number) (inclusive)
- how can we check to see if a number divides evenly?
- use the remainder/modulo operator and see if it equals 0 (i.e. no remainder)
- how can we check all of the numbers?
- use a for loop

• look at isprime function in while.py code
- for loop starting at 2 up to the sqrt of the number
- there are multiple versions of the range function
- range with a simple parameter starts counting at 0 up to but not including the specified number
- range with 2 parameters starts counting at the first number up to, but not including, the second number

for i in range(10, 20):
print i

would print out the numbers from 10 - 19 (but not 20)

- the if statement checks to see if the number is divisible by i
- if we find this we can stop early!
- the minute we find this, we know it's not prime so we can return False
- what does "return True" do?
- if we've checked all of the numbers and none of them were divisible (otherwise we would have exited the function with the return False), so return True
- we can use this to see if a number is prime

>>> isprime(5)
True
>>> isprime(6)
False
>>> isprime(100)
False
>>> isprime(101)
True

• import math
- A second way to import: import module_name
- To reference a function within that module, you then say module_name.function_name
- Why might we use this option, i.e. when would we use:
from math import *

vs.

import math

- Use the first if you're going to be using the functions a lot and it's clear that they come from that module
- Use the second to be extra clear where the functions are coming from and to avoid naming conflicts

• how could we use isprime to print out the first 10 (100, 1000, etc) prime numbers?
- like to do some sort of loop
- will a for loop work?
- we don't know when we're going to stop
- we'd like to keep a count of how many we've seen and only stop when we've reached the number we want

• while loop
- another way to do repetition

while <bool expression>:
statement1
statement2
...

statement3

as long as the <bool expression> evaluates to True, it continues to repeat the statements, when it becomes False, it then continues on and executes statement3, etc.

- specifically:
evaluates the boolean expression
- if it's False
- it "exits" the loop and goes on to statement3 and continues there
- if it's True
- executes statement1, statement2, ... (all statements inside the "block" of the loop, just like a for loop)
- go back to beginning and repeat

- how could we use a while loop for our prime numbers problem?
- keep a count of how many primes we've found (initially starts at 0)
- start count from 1 and work our way up
- check each number
- if it's prime
- print it out
- increment the counter of how many primes we've found
- keep repeating this as long as (while) the number of primes we've printed is less than the number we want

• can you emulate a for loop with a while loop?
- yes!

for i in range(10):
...

is equivalent to writing:

i = 0

while i < 10:
...
i = i + 1

• look at firstprimes function in while.py code
- current += 1 every time through the loop we increment the number we're examining
- if that current number happens to be prime, we increment count
- the loop continues "while" count < num, that is as long as the number we've found is less than the number we're looking for

• infinite loops
- what would the following code do?

while True:
print("hello")

- will never stop
- in this case you should see some output
- sometimes, it will look like the program just froze if you're not actually printing anything out
- you can stop this by selecting "reset shell"
- be careful about these with your program. They're called an infinite loop.
- if you think you might have an infinite loop
- put in some print statements to debug
- think about when the boolean expression will become False and make sure that is going to happen in your loop

• run scores-lists.py code
- First, prompts the user to enter a list of scores one at a time
- how is this done?
- while loop
- what is the exit condition?
- checks to see if the line is empty

while line != ""

- then, calculate various statistics based on what was entered
- how are we calculating these statistics?
- average?
- could keep track of the sum and the number of things entered
- divide at the end
- max?
- keep track of the largest seen so far
- each time a new one is entered, see if it's larger, if so, update the largest
- min?
- same thing
- median?
- the challenge with median is that we can't calculate it until we have all of the scores
- need to sort them and then find the middle score

- why can't we do this using int/float variables?
- we don't know how many scores are going to be entered
- even if we did, if we had 100 students in the class, we'd need 100 variables!

• lists
- lists are a data structure in Python
- what is a data structure?
- a way of storing and organizing data

- lists allow us to store multiple values with a single variable

• creating lists: we can create a new list using square brackets
>>> [7, 4, 3, 6, 1, 2]
[7, 4, 3, 6, 1, 2]
>>> 10 # not a list
10
>>> [10]
[10]
>>> l = [7, 4, 3, 6, 1, 2]
>>> l
[7, 4, 3, 6, 1, 2]
>>> type(l)
<type 'list'>

lists are a type and represent a value, just like floats, ints, bools and strings. We can assign them to variables, print them, etc.

- what do you think [] represents?
- empty list
>>> []
[]

• accessing lists
- we can get at particular values in the list by using the [] to "index" into the list
>>> l = [7, 4, 3, 6, 1, 2]
>>> l[3]
6

notice that indexing starts counting at 0, not at 1!

>>> l[0]
7

- What do you think l[20] will give us?
>>> l[20]
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
IndexError: list index out of range

we can only index from 0 up to the length of the list minus 1

- What do you think l[-1] will give us?
>>> l[-1]
2

if the index is negative it counts back from the end of the list

- notice that the type thing in the list is as you'd expect:
>>> type(l[3])
<type 'int'>

• storing other things in lists
- draw the list representation
- a list is a contiguous set of spaces in memory
- we can store anything in each of these spaces

>>> ["this", "is", "a", "list", "of", "strings"]
['this', 'is', 'a', 'list', 'of', 'strings']
>>> list_of_strings = ["this", "is", "a", "list", "of", "strings"]
>>> list_of_strings[0]
'this'
>>> [1, 5.0, "my string"]
[1, 5.0, 'my string']
>>> l = [1, 5.0, "my string"]
>>> type(l[0])
<type 'int'>
>>> type(l[1])
<type 'float'>
>>> type(l[2])
<type 'str'>

- In general, it's a good idea to have lists be homogeneous, i.e. be of the same type

• slicing
- sometimes we want more than just one item from the list (this is called "slicing")
- We can specify a range in the square brackets, [], using the colon (:)

>>> l = ["this", "is", "a", "list", "of", "strings"]
>>> l[0:3]
['this', 'is', 'a']
>>> l[1:5]
['is', 'a', 'list', 'of']
>>> l[1:1]
[]
>>> l[-3:-1]
['list', 'of']

- generates a *new* list
- that includes the items from the list starting at the first number and up to, but not including, the second number