# While loop¶

Recall the while loop from previous lecture.

In [1]:
n = 1000
a = 1
while a ** 3 < n:
print a ** 3,  # mind the comma
a = a + 1
print "end"

1 8 27 64 125 216 343 512 729 end


Let's write a loop that reads numbers until a certain condition is met:

In [2]:
a = input()
while a != 5:
print a
a = input()

1
1
2
2
3
3
4
4
5


Let's do the same as above but also sum the numbers.

In [3]:
n = 0
a = input()         # input first
while a != 0:
n = n + a
a = input()     # input second
print n

1
2
3
4
5
0
15


As you can see certain parts of the code is repeated: read the first number than read inside the while loop.

In other languages there is a do...while which evaluates the condition at the end of the loop.

do ... while ...

or

do... until ...

This is missing from python by design. It can be replaced with the following:

while True:
"""preparation"""
if """halt condition""":
break
"""further commands"""


An other type of loop would be unnecessary.

The previous example without code repetition:

In [4]:
n = 0
while True:       # start the loop
a = input()   # input once, no repetition
if a == 0:    # halt condition
break     # halt
n += a        # the actual body of the loop
print n

1
2
3
4
5
0
15


General purpose, commmon programming techniques.

## Summation¶

a.k.a. accumulation

Despite the name, it is not only for summation. If you have a series of numbers (or any other objects) and you want to collect (or accumulate) some information about them then you can use this paradigm.

In [5]:
n = 0            # accumulator variable
a = input()      # read the first
while a != 0:    # halt condition
n = n + a    # summation
a = input()  # read the rest
print n

1
2
3
0
6


It is not only for addition:

In [6]:
n = 1            # accumulator variable
a = input()      # read the first
while a != 0:    # halt condition
n = n * a    # summation
a = input()  # read the rest
print n

1
2
3
0
6


For a series of objects we wish to count the number of elemnets with a given property (for example count the odd numbers).

In [8]:
c = 0                # counter variable
a = input()          # read the first
while a != 0:        # halt condition
if a % 2 == 1:   # check the desired property
c += 1       # increase counter
a = input()      # read the rest
print c

1
2
3
4
0
2


A bit more complicated example: read strings until an empty string arrives and count the words containing the letter e !

In [6]:
c = 0
word = raw_input()
while word != "":
if "e" in word:
c += 1
word = raw_input()
print c

cat
dog
elephant

1


Remember that input is a security risk. There is a bit more secure way to read inputs if you know what type you want: wrap the raw_input function into the desired type:

In [7]:
numer = int(raw_input())
print number

cat

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-7675f9dec761> in <module>()
----> 1 numer = int(raw_input())
2 print number

ValueError: invalid literal for int() with base 10: 'cat'

## Finding extremum¶

For a given set of objects one wishes to find the best/worst element. Best/worst is ment by some aspect, it can be smallest/largest.

For example find the largest of some positive numbers.

In [8]:
largest = 0              # default extremum
a = input()              # read first
while a > 0:             # halt condition
if largest < a:   # compare to previous extremum
largest = a   # update extremum
a = input()          # read next
print "the largest:", largest

1
4
3
0
the largest: 4


Same without code-repetition:

In [9]:
largest = 0
while True:
a = input()
if a <= 0:
break
if largest < a:
largest = a
print "the largest:", largest

1
4
3
0
the largest: 4


## Find any¶

Find out if any of a given set of objects satisfy some condition. For example in prime testing if any of the smaller numbers is a divisor then it is not a prime.

In [11]:
n = input()                    # read the number
a = 2                          # variable for iterating over the possible divisors
hit = False                    # this variable remembers whether the condition is met
while a < n and not hit:       # halt condition (halt if already found one)
if n % a == 0:             # condition
hit = True             # it's a hit
a += 1                     # go for the next
print not hit                  # prime if the hit is False (no divisor)

10
False


For more complicated tasks, combine the individual paradigms. It is not the only way to solve programming exercises but it's a good start. Feel free to experiment with different solutions.

How many primes are there under 1000? Put a find any (prime test) inside a counting paradigm!

In [9]:
number = 2                                    # first number to check
prime_count = 0                               # counter variable in the counting paradigm
while number < 1000:                          # counting paradigm starts here
divisor = 2                               # first element of the "find any" part
composite = False                         # hit variable
while divisor < number and not composite: # loop for "find any"
if number % divisor == 0:             # check for hit
composite = True                  # set hit variable
divisor += 1                          # next element to check in "find any"
if not composite:                         # end of "find any"
prime_count += 1                      # if found then increase counter variable
number += 1                               # next in counting loop
print prime_count

168


# Lists¶

Lists are containers for a series of objects. For example store numbers:

In [14]:
l = [1, 2, 5]


Don't call a list object list because it is already the name of the type!

The list can be given with a square bracket, the emelents are comma separated list between the brackets. The elements of the list can be various objects, not necessarily of the same type (even lists).

In [15]:
l = [1, 5.3, "dog", [1, 2, 5], 12, "cat"]


## List indexing, sublists¶

A given element can be accessed by index:

In [16]:
l = ["a", "b", "c"]
print l[0]
print l[1]
print l[2]

a
b
c


As you can see the list indices start with $0$ and goes up to $n-1$ where $n$ is the length of the list.

Access a sublist. Mind that intervals are inclusive from left and exclusive from right.

In [10]:
l = ["a", "b", "c", "d", "e", "f"]
print l[1:3]       # from 1 to 3 (1 is actually the second)
print l[2:]        # from index 2 to the end
print l[:3]        # from the beginning up to index 3 (index 3 is not included)
print l[0:4:2]     # from the start to index 4, take every second element
print l[-1::-1]    # from last to first with -1 steps (reverse)

['b', 'c']
['c', 'd', 'e', 'f']
['a', 'b', 'c']
['a', 'c']
['f', 'e', 'd', 'c', 'b', 'a']

In [11]:
l[-2] # negative index is calculated from the back

Out[11]:
'e'

You can concatenate lists just like strings:

In [12]:
print [1, 2, 5] + [8, 5, 3]

[1, 2, 5, 8, 5, 3]


All the above works for strings (as they are list of characters)

In [13]:
s = "puppy"
print s[2]
print s[1:4]
print s[-1::-1]

p
upp
yppup


There are differences between strings and lists. One can assign a given value in a list (mutable) but not in a string (immutable).

In [14]:
l = [1, 2, 5]
l[2] = 3
print l

[1, 2, 3]


The same cannot be done with strings:

In [15]:
s = "puppy"
s[1] = "a"
print s

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-f53b63ec36a1> in <module>()
1 s = "puppy"
----> 2 s[1] = "a"
3 print s

TypeError: 'str' object does not support item assignment

You can manipulate strings but not this way!

## Methods for list manipulations¶

We learn some practical functions/methods for lists.

### Range¶

range creates a list, usually for creating a list of indices:

In [16]:
print range(4)

[0, 1, 2, 3]

In [17]:
print range(4, 10)

[4, 5, 6, 7, 8, 9]

In [18]:
print range(3, 15, 3)

[3, 6, 9, 12]


As you can see, it works like list indexing ("from", "to" and optional "step").

• If you give one parameter, then its the last index (zero included, the last excluded)
• If you give two parameters, then its a [from...to) list
• The optional third parameter is the step size (1 by default)

They can be manipulated as lists.

In [29]:
l = range(1, 4)
l[2] = 5
print l

[1, 2, 5]


### New elements / erasing elements¶

The append method inserts a new elements at the end:

In [30]:
l = [1, 2, 5]
l.append(4)
print l

[1, 2, 5, 4]

In [31]:
l = []
a = input()
while a != 0:
l.append(a)
a = input()
print l

1
2
3
0
[1, 2, 3]


The insert method inserts a new element to a given place:

In [34]:
l = [1, 2, 5]
l.insert(1, 1.5)
print l

[1, 1.5, 2, 5]


pop erases an element with a given index:

In [19]:
l = [1, 2, 4, 2, 5]
l.pop(2)
print l

[1, 2, 2, 5]


remove erases a given element (its first occurrance):

In [36]:
l = [1, 2, 3, 2, 2, 5]
l.remove(2)
print l

[1, 3, 2, 2, 5]

In [37]:
l = [1, 2, 2, 2, 5]
while 2 in l:
l.remove(2)
print l

[1, 5]


### Further list operations¶

The len function gives the length:

In [38]:
l = [1, 2, 5]
print len(l)

3


The count method gives how many times a given element occurrs:

In [39]:
l = [1, 2, 3, 4, 1, 2, 1, 4, 5, 1, 3, 2, 4]
print l.count(1)
print l.count(4)
print l.count(15)

4
3
0


The sort method sorts:

In [40]:
l = [1, 2, 3, 4, 1, 2, 1, 4, 5, 1, 3, 2, 4]
l.sort()
print l

[1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5]


# For loop¶

In Python the for loop and lists are hand-in-hand. A for loop can iterate through lists (and other iterable objects):

In [22]:
l = [1, 2, 5, "puppy"]
for elem in l:
print elem

1
2
5
puppy


One can iterate index-wise not element-wise. Use the range in that case:

In [23]:
l = [1, 2, 5, "puppy"]
for i in range(len(l)):
print l[i]

1
2
5
puppy


How does it work? The command range(len(l)) gives you exactly the indices of the list.

In [24]:
l = [1, 2, 5, "kutya"]
for i in range(len(l)):
print "index: ", i, " element: ", l[i]

index:  0  element:  1
index:  1  element:  2
index:  2  element:  5
index:  3  element:  kutya


### Summation/Accumulation¶

In [25]:
l = [1, 2, 5]
n = 0
for e in l:
n += e
print n

8


In [26]:
l = [1, 2, 5, 6, 4, 6, 7, 8]
c = 0
for e in l:
if e % 3 == 0:
c += 1
print c

2


### Finding extremum¶

In [27]:
l = [1, 2, 5, 6, 15, 4, 6, 7, 8]
largest = l[0]
for e in l:
if largest < e:
largest = e
print largest

15


### Find any¶

In [29]:
n = input()
composite = False
for divisor in range(2, n):
if n % divisor == 0:
print divisor
composite = True
break
print not divisor

12
2
False


Let's count how many "e" letters are in those strings which contain the letter "a" !

In [31]:
words = ["puppy", "elf", "cat", "elephant", "littlecat"]
c = 0
for word in words:
if "a" in word:
for i in range(len(word)):
if word[i] == "e":
c += 1
print c

3


With the use of the count method, you only have to use a counting paradigm:

In [32]:
words = ["puppy", "elf", "cat", "elephant", "littlecat"]
c = 0
for word in words:
if "a" in word:
c += word.count("e")
print c

3

In [ ]: