Control flow - while loop¶
Download exercises zip¶
Let’s see how to repeat instructions by executing them inside while
loops.
The main feature of while
loop is allowing to explicitly control when the loop should end. Typically, such loops are used when we must iterate on a sequence of which we don’t know the dimension, or it can vary over time, or several conditions might determine the cycle stop.
What to do¶
Unzip exercises zip in a folder, you should obtain something like this:
control-flow
flow1-if.ipynb
flow1-if-sol.ipynb
flow2-for.ipynb
flow2-for-sol.ipynb
flow3-while.ipynb
flow3-while-sol.ipynb
jupman.py
WARNING: to correctly visualize the notebook, it MUST be in an unzipped folder !
open Jupyter Notebook from that folder. Two things should open, first a console and then a browser. The browser should show a file list: navigate the list and open the notebook
flow3-while.ipynb
Go on reading the exercises file, sometimes you will find paragraphs marked Exercises graded from ✪ to ✪✪✪✪ which will ask to write Python commands in the following cells.
Shortcut keys:
to execute Python code inside a Jupyter cell, press
Control + Enter
to execute Python code inside a Jupyter cell AND select next cell, press
Shift + Enter
to execute Python code inside a Jupyter cell AND a create a new cell aftwerwards, press
Alt + Enter
If the notebooks look stuck, try to select
Kernel -> Restart
Introduction¶
A while
cycle is a code block which is executed when a certain boolean condition is verified. The code block is repeatedly executed as long as the condition is true.
Let’s see an example:
[2]:
i = 1
while i < 4:
print('Counted', i)
i += 1
print('Loop is over!')
Counted 1
Counted 2
Counted 3
Loop is over!
In the example, the boolean condition is
i < 4
the block to repeatedly executed is
print('Counted', i)
i += 1
Like any Python code blocks, the block is indented with spaces (usually 4).
Have a better look at the execution in Python Tutor and read the following comment.
[3]:
# WARNING: FOR PYTHON TUTOR TO WORK, REMEMBER TO EXECUTE THIS CELL with Shift+Enter
# (it's sufficient to execute it only once)
import jupman
[4]:
i = 1
while i < 4:
print('Counted', i)
i += 1
print('Loop is over !')
jupman.pytut()
Counted 1
Counted 2
Counted 3
Loop is over !
[4]:
In the example we used a variable we called i
and we initialized it to zero.
At the beginning of the cycle i
is valued 1
, so the boolean expression i < 4
is evaluated as True
. Since it’s True
, execution continues inside the block with the print
and finally MODIFIES i
by incrementing i += 1
.
Now the execution goes to while
row, and condition i < 4
is evaluated again. At this second iteration i
is valued 2
, so the boolean expression i < 4
is again evaluated to True
and the execution remains inside the block. A new print is done and i
gets incremented.
Another loop is done until i
is valued 4
. A that point i < 4
produces False
so in that moment execution exits the while
block and goes on with the commands at the same indentation level as the while
Terminating while
¶
When we have a while
cycle, typically sooner or later we want it to terminate (programs which hang aren’t users’ favourites …). To guarantee termination, we need:
initializing a variable outside the cycle
a condition after the
while
command which evaluates that variable (and optionally other things)at least one instruction in the internal block which MODIFIES the variable, so that sooner or later is going to satisfy condition 2
If any of these points is omitted, we will have problems. Let’s try forgetting them on purpose:
Error 1: omit initialization. As in those cases in Python where we forgot to initialize a variable (let’s try j
in this case), the execution is interrupted as soon we try using the variable:
print("About to enter the cycle ..")
while j < 4:
print('Counted', j)
j += 1
print('Loop is over !')
About to enter the cycle ..
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-277-3f311955204d> in <module>()
1 print("About to enter the cycle ..")
----> 2 while j < 4:
3 print('Counted', j)
4 j += 1
5
NameError: name 'j' is not defined
Error 2: omit using the variable in the condition. If we forget to evaluate the variable, for example using another one by mistake (say x
), the loop will never stop:
i = 1
x = 1
print('About to enter the cycle ..')
while x < 4: # evalutes x instead of i
print('Counted', i)
i += 1
print('Loop is over !')
About to enter the cycle ..
Counted 1
Counted 2
Counted 3
Counted 4
Counted 5
Counted 6
.
.
Error 3: Omit to MODIFY the variable in the internal block. If we forget to place at least one instruction which MODIFIES the variable used in the condition, whenever the condition is evaluated it will always produce the same boolean value False
preventing a cycle exit:
i = 1
print('About to enter the cycle ..')
while i < 4:
print('Counted', i)
print('Loop is over !')
About to enter the cycle ..
Counted 1
Counted 1
Counted 1
Counted 1
Counted 1
.
.
Questions¶
QUESTION: Look at the following code fragments , and for each try guessing the result it produces (or if it gives an error):
i = 0 while i < 3: print(i)
k = 0 while k < 5: print(k) k + 1
i = 0 while i < 3: print(i) i += 1
i = 0 while False: print(i) i += 1 print('Done !')
i = 0 while i < 3: print(i) i += 1
k = 0 while k < 2 print(i) k += 1
i = 0 while i < 3: print('GAM') i = i + 1
while zanza < 2 print('ZANZA') zanza += 1
i = 0 while False: print(i) i = i + 1 print('DARK')
i = 0 while True: print(i) i = i + 1 print('LIGHT')
while 2 + 3: print('z') print('')
i = 10 while i > 0: if i > 5: print(i) i -= 1 print('WAM')
i = 10 while i > 0: if i > 5: print(i) i -= 1 print('MAW')
import random x = 0 while x < 7: x = random.randint(1,10) print(x) print('LUCK')
x,y = 0,0 while x + y < 4: x += 1 y += 1 print(x,y)
x,y = 0,3 while x < y: print(x,y) x += 1 y -= 1
Esercises - introduction¶
Exercise - printeven¶
✪ Write some code to print all the odd numbers from 1
to k
in a while
cycle
for
k<1
prints nothing
Example - given:
k = 5
after your code it must print:
1
3
5
[5]:
k = 5 # 1 3 5
#k = 1 # 1
#k = 0 # no print
# write here
1
3
5
Exercise - average¶
✪ Write some code that given a list numbers
, calculates the average of values using a while
and then prints it.
if the list is not empty, the average is supposed to be
0.0
DO NOT use the function
sum
DO NOT create variables called
sum
(would violate the V COMMANDMENT: you shall never ever redefine system functions)
Example - given:
numbers = [8,6,5,9]
prints
7.0
[6]:
numbers = [8,6,5,9] # 7.0
#numbers = [3,1,2] # 2.0
#numbers = [] # 0
# write here
7.0
break
and continue
commands¶
For getting even more control on cycle execution we can use the commands break
and continue
NOTE: Use them sparingly!
When there is a lot of code in the cycle it’s easy to ‘forget’ about their presence and introduce hard-to-discover bugs. On the other hand, in some selected cases these commands may increase code readability, so as everything use your judgement.
Terminate with a break
¶
The scheme we’ve seen to have a terminating while
is the recommended one, but if we have a condition which does NOT evaluate the variable we are incrementing (like for example the constant expression True
), as an alternative to immediatly exit the cycle we can use the command break
:
[7]:
i = 1
while True:
print('Counted', i)
if i > 3:
print('break! Exiting the loop!')
break
print('After the break')
i += 1
print('Loop is over !')
Counted 1
Counted 2
Counted 3
Counted 4
break! Exiting the loop!
Loop is over !
Note After the break
is not shown.
Jumping with continue
¶
We can bring the execution immediately to the next iteration by calling continue
, which directly jumps to the condition check without executing the instructions after the continue
.
WARNING: continue
instructions if used carelessly can cause infinite loops !
When using continue
ensure it doesn’t jump the instriction which modifies the variable used in the termination condition (or it doesn’t jump a break
needed for exiting the cycle)!
To avoid problems here we incremented i
before the if
with a continue
:
[8]:
i = 1
while i < 5:
print('Counted', i)
i += 1
if i % 2 == 1:
print('continue, jumping to condition check')
continue
print('After the continue')
print('arrived till the end')
print('Loop is over !')
Counted 1
arrived till the end
Counted 2
continue, jumping to condition check
Counted 3
arrived till the end
Counted 4
continue, jumping to condition check
Loop is over !
Let’s try combining break
and continue
, and see what happens in Python Tutor:
[9]:
i = 1
while i < 5:
print('Counted', i)
if i > 3:
print('break! Exiting the cycle!')
break
print('After the break')
i += 1
if i % 2 == 1:
print('continue, jumping to next condition check')
continue
print('After the continue')
print('arrived till the end')
print('Loop is over !')
jupman.pytut()
Counted 1
arrived till the end
Counted 2
continue, jumping to next condition check
Counted 3
arrived till the end
Counted 4
break! Exiting the cycle!
Loop is over !
[9]:
Questions about break
and continue
¶
QUESTION: Look at the following code fragments , and for each try guessing the result it produces (or if it gives an error):
i = 1 while i < 4: print('Counted', i) i += 1 continue print('Loop is over !')
i = 1 while i < 4: print('Counted', i) continue i += 1 print('Loop is over !')
i = 3 while i > 0: print('Counted', i) if i == 2: print('continue, jumping to condition check') continue i -= 1 print('arrived till the end') print('Loop is over !')
i = 0 while True: i += 1 print(i) if i > 3: break print('BONG')
i = 0 while True: if i < 3: continue else: break i += 1 print('ZONG')
i = 0 while True: i += 1 if i < 3: continue else: break print('ZANG')
Exercise - findchar¶
✪✪ Write some code that using a while
searches the character list la
for a character specified in car
variable. As soon as the FIRST character occurrence is found, it stops and prints the index where it was found.
if it doesn’t find the character, prints a Not found message.
Example 1 - given:
car = 'z'
la = ['b','a','f','g','z','h','z','r']
after your code it must print:
Found first z at index 4
Example 2 - given:
car = 'z'
la = ['b','a','f','g','h','r']
must print:
Didn't find z
[10]:
car = 'z'
# 0 1 2 3 4 5 6 7
la = ['b','a','f','g','z','h','z','r'] # Found first z at index 4
#la = ['b','a','f','g','h','r'] # Didn't find z
# write here
Found first z at index 4
Questions - Are they equivalent?¶
Look at the following code fragments: each contains two parts, A and B. For each value of the variables they depend on, try guessing whether part A will print exactly the same result printed by code in part B
FIRST think about the answer
THEN try executing with each of the values of suggested variables
Are they equivalent? - BORG¶
print('A:')
while True:
print('BORG')
break
print('\nB:')
while False:
pass
print('BORG')
Are they equivalent? - until 3¶
print('A:')
x = 0
while x < 3:
print(x)
x += 1
print('\nB:')
x = 1
while x <= 3:
print(x-1)
x += 1
Are they equivalent? - by chance¶
Remember randint(a, b)
gives back a random integer N
such that a <= N <= b
print('A:')
x = 0
while x < 3:
x += 1
print(x)
print('\nB:')
x = 0
import random
while x != 3:
x = random.randint(1,5)
print(x)
Are they equivalent? - until six¶
print('A:')
i = 0
while i < 3:
print(i)
i += 1
while i < 6:
print(i)
i += 1
print('\nB:')
i = 0
while i < 6:
print(i)
i += 1
Are they equivalent? - countdown 1¶
print('A:')
i = 2
print(i)
while i > 0:
i -= 1
print(i)
print('\nB:')
i = 2
while i > 0:
print(i)
i -= 1
Are they equivalent? - countdown 2¶
print('A:')
i = 2
print(i)
while i > 0:
i -= 1
print(i)
print('\nB:')
i = 2
while i > 0:
print(i)
i -= 1
print(i)
Are they equivalent? - sorcery¶
print('A:')
s = 'sorcery'
i = 0
while s[i] != 'g':
i += 1
print(s[i:])
print('B:')
s = 'sorcery'
i = len(s)
while s[i] != 'g':
i -= 1
print(s[i:])
Are they equivalent? - ping pong¶
print('A:')
ping,pong = 0,3
while ping < 3 or pong > 0:
print(ping,pong)
ping += 1
pong -= 1
print('\nB:')
ping,pong = 0,3
while not(ping >= 3 and pong <= 0):
print(ping,pong)
ping += 1
pong -= 1
Are they equivalent? - zanna¶
print('A:')
n,i,s = 0,0,'zanna'
while i < len(s):
if s[i] == 'n':
n += 1
i += 1
print(n)
print('\nB:')
n,i,s = 0,0,'zanna'
while i < len(s):
i += 1
if s[i-1] == 'n':
n += 1
print(n)
Are they equivalent? - pasticcio¶
print('A:')
c,i,s = 0,0,'pasticcio'
while i < len(s):
if s[i] == 'c':
c += 1
i += 1
print(c)
print('\nB:')
no,k,s = 0,0,'pasticcio'
while k < len(s):
if s[k] != 'c':
no += 1
else:
k += 1
print(len(s) - no)
Exercises - counters¶
Exercise - don’t break 1¶
✪ Look at the following code, and write in the following cell some code which produces the same result with a while
and without using break
[11]:
x = 3
while True:
print(x)
if x == 0:
break
x -= 1
3
2
1
0
[12]:
x = 3
# write here
3
2
1
0
Exercise - don’t break 2¶
✪ Look at the following code, and write in the following cell some code which produces the same result with a while
and without using break
[13]:
la = [2,3,7,5,6]
k = 7 # 2 3 7
#k = 5 # 2 3 7 5 6
#k = 13 # 2 3 7 5 6
i = 0
while True:
print(la[i])
if i >= len(la)-1 or la[i] == k:
break
else:
i += 1
2
3
7
[14]:
la = [2,3,7,5,6]
k = 7 # 2 3 7
#k = 6 # 2 3 7 5 6
#k = 13 # 2 3 7 5 6
i = 0
# write here
2
3
7
Exercise - Give me a break¶
✪ Look at the following code, and write in the next cell some code which produces the same result with a while
this time using a break
[15]:
x,y = 1,5 # (1,5) (2,4)
#x,y = 2,8 # (2, 8) (3, 7) (4, 6)
while x < y or x == 4:
print((x,y))
x += 1
y -= 1
(1, 5)
(2, 4)
[16]:
x,y = 1,5 # (1,5) (2,4)
#x,y = 2,8 # (2, 8) (3, 7) (4, 6)
# write here
(1, 5)
(2, 4)
Exercise - paperboard¶
✪ Prints integer numbers from 0
to k
INCLUDED using a while
, and for each number prints to its side one among the strings 'PA'
, 'PER'
and 'BOARD'
alternating them
Ex - for k=8
prints
0 PA
1 PER
2 BOARD
3 PA
4 PER
5 BOARD
6 PA
7 PER
8 BOARD
[17]:
k = 8
# write here
0 PA
1 PER
2 BOARD
3 PA
4 PER
5 BOARD
6 PA
7 PER
8 BOARD
Exercise - until ten¶
✪ Given two numbers x
and y
, write some code with a while
which prints and increments the numbers, stopping as soon as one of them reaches ten.
x,y = 5,7
after your code it must result:
5 7
6 8
7 9
8 10
[18]:
x,y = 5,7
#x,y = 8,4
# write here
5 7
6 8
7 9
8 10
Exercise - cccc¶
✪ Write some code using a while
which given a number y
, prints y
rows containing the character c
as many times as the row number.
Example - given:
y = 4
Prints:
c
cc
ccc
cccc
[19]:
y = 4
# write here
c
cc
ccc
cccc
Exercise - converge¶
✪ Given two numbers x
and k
, using a while
modify and print x
until it reaches k
included
NOTE:
k
can either be greater or lesser thanx
, you must handle both cases
Example 1 - given:
x,k = 3,5
prints:
3
4
5
Example 2 - given:
x,k = 6,2
prints:
6
5
4
3
2
[20]:
x,k = 3,5 # 3 4 5
#x,k = 6,2 # 6 5 4 3 2
#x,k = 4,4 # 4
# write here
3
4
5
Exercise - wow¶
✪ Given a list of strings la
, write some code that searches inside the list for the first occurrence of a string beginning with the character 2
(for example 'wow'
. As soon as it is found, the program stops and prints Found wow
. Otherwise, prints Not found!
Use a while
cycle.
Example 1 - given:
la = ['a','d','g','wow','f','wonder','r']
Prints:
examined a
examined d
examined g
Found wow
Example 2 - given:
la = ['d','v','q','c','e']
Prints:
examined d
examined v
examined q
examined c
examined e
Not found!
[21]:
la = ['a','d','g','wow','f','wonder','r'] # a d g Found wow
#la = ['a','d','g','f','wonder','r', 'woman'] # a d g f Found wonder
#la = ['d','v','q','c','e'] # d v q c e Not found!
# write here
examined a
examined d
examined g
Found wow
Exercise - Wild West¶
✪✪ The two outlaws Carson and Butch agreed to bury a treasure in the jolly town of Tombstone, ma now each of them wants to take back the treasure without sharing anything with the partner.
For arriving to the treasure there is a
road
fromSanta Fe
untilTombstone
which we represent as a list of stringswe use two indexes
butch
andcarson
to represent where the outlaws are on the roadeach outlaw starts from a different town
at each turn Carson moves of one city
at each turn Butch moves of two cities, because he has a fast Mustang horse
Write some code which prints the run and terminates as soon as one them arrives to the last city, telling who got the treasure.
In the case both outlaws arrive to the last city at the same time, prints
Final duel in Tombstone!
your code must work for any
road
and initial positioncarson
andbutch
Example - 1 given:
# 0 1 2 3 4 5
road = ['Santa Fe','Denver','Dodge City', 'Silverton', 'Agua Caliente', 'Tombstone']
carson,butch = 3, 0
it must print:
Carson starts from Silverton
Butch starts from Santa Fe
Carson reaches Agua Caliente
Butch reaches Dodge City
Carson reaches Tombstone
Butch reaches Agua Caliente
Carson takes the treasure in Tombstone !
Example 2 - given:
# 0 1 2 3 4 5
road = ['Santa Fe','Denver','Dodge City', 'Silverton', 'Agua Caliente', 'Tombstone']
carson,butch = 3, 2
it must print:
Carson starts from Silverton
Butch starts from Dodge City
Carson reaches Agua Caliente
Butch reaches Agua Caliente
Carson reaches Tombstone
Butch reaches Tombstone
Final duel in Tombstone !
[22]:
# 0 1 2 3 4 5
road = ['Santa Fe','Denver','Dodge City', 'Silverton', 'Agua Caliente', 'Tombstone']
carson,butch = 3, 0 # Carson takes the treasure in Tombstone !
#carson,butch = 0, 0 # Butch takes the treasure in Tombstone !
#carson,butch = 3, 2 # Final duel in Tombstone !
# write here
Carson starts from Silverton
Butch starts from Santa Fe
Carson reaches Agua Caliente
Butch reaches Dodge City
Carson reaches Tombstone
Butch reaches Agua Caliente
Carson takes the treasure in Tombstone !
Modifying sequences¶
In the tutorial on for
loops we’ve seen an important warning we repeat here:
X COMMANDMENT: You shall never ever add or remove elements from a sequence you are iterating with a for
!
Falling into such temptations would produce totally unpredictable behaviours (do you know the expression pulling the rug out from under your feet ? )
If you really need to remove elements from a sequence you are iterating, use a while cycle or duplicate first a copy of the original sequence.
Note the advice is only about for
cycles. In case of necessity, at the end suggests to adopt while
loops. Let’s see when and how ot use them.
Stack - Drawing from a card deck¶
Suppose having a deck of cards which we represent as a list of strings, and we want to draw all the cards, reading them one by one.
We can write a while
that as long as the deck contains cards, keeps removing cards from the top with the pop method and prints their name. Remember pop
MODIFIES the list by removing the last element AND gives back the element as call result, which we can save in a variable we will call card
:
[23]:
deck = ['3 hearts', # <---- bottom
'2 spades',
'9 hearts',
'5 diamonds',
'8 clubs'] # <---- top
while len(deck) > 0:
card = deck.pop()
print('Drawn', card)
print('No more cards!')
jupman.pytut()
Drawn 8 clubs
Drawn 5 diamonds
Drawn 9 hearts
Drawn 2 spades
Drawn 3 hearts
No more cards!
[23]:
Looking at the code, we can notice that:
the variable
deck
is initializedwe verify that
deck
dimension is greater than zeroat each step the list
deck
is MODIFIED by reducing its dimensionit returns to step 2
The first three points are the conditions which guarantee the while
loop will sooner or later actually terminate.
Stack - Drawing until condition¶
Suppose now to continue drawing cards until we find a heart suit. The situation is more complicated, because now the cycle can terminate in two ways:
we find hearts, and interrupt the search
there aren’t heart cards, and the deck is exhausted
In any case, in the end we must tell the user a result. To do so, it’s convenient initializing card
at the beginning like an empty string for handling the case when no hearts cards are found (or the deck is empty).
Let’s try a first implementation which uses an internal if
to verify whether we have found hearts, and in that case exits with a break
command.
Try executing the code by uncomment the second deck which has no hearts cards, and look at the different execution.
[24]:
deck = ['3 hearts','2 spades','9 hearts','5 diamonds','8 clubs']
#deck = ['8 spades','2 spades','5 diamonds','4 clubs'] # no hearts!
card = ''
while len(deck) > 0:
card = deck.pop()
print('Drawn', card)
if 'hearts' in card:
break
if 'hearts' in card:
print('Found hearts!')
else:
print("Didn't find hearts!")
jupman.pytut()
Drawn 8 clubs
Drawn 5 diamonds
Drawn 9 hearts
Found hearts!
[24]:
Exercise - Don’t break my heart¶
✪ Write some code which solves the same previous problem:
this time DO NOT use
break
ensure the code works with a deck without hearts, and also with an empty deck
HINT: put a multiple condition in the
while
[25]:
deck = ['3 hearts','2 spades','9 hearts','5 diamonds','8 clubs']
#deck = ['8 spades','2 spades','5 diamonds','4 clubs'] # no hearts!
#deck = [] # no hearts !
card = ''
# write here
Drawn 8 clubs
Drawn 5 diamonds
Drawn 9 hearts
Found hearts!
Questions - what happens?¶
QUESTION: Look at the following code fragments , and for each try guessing the result it produces (or if it gives an error):
while []: print('z') print('BIG')
while ['a']: print('z') print('BUG')
la = [] while len(la) < 3: la.append('x') print(la)
la = ['x','y','z'] while len(la) > 0: print(la.pop())
la = ['x','y','z'] while la: print(la.pop(0))
la = [4,5,8,10] while la.pop() % 2 == 0: print(la)
Questions - are they equivalent?¶
Look at the following code fragments: each contains two parts, A and B. For each value of the variables they depend on, try guessing whether part A will print exactly the same result printed by code in part B
FIRST think about the answer
THEN try executing with each of the values of suggested variables
Are they equivalent? - train¶
print('A:')
la = ['t','r','a','i','n']
while len(la) > 0:
print(la.pop())
print('\nB:')
la = ['t','r','a','i','n']
la.reverse()
while len(la) > 0:
print(la.pop(0))
Are they equivalent? - append nx¶
print('A:')
x,n,la = 2,0,[]
while x not in la:
la.append(n)
n += 1
print(la)
print('\nB:')
x,la = 2,[]
while len(la) < 3:
la.append(x)
x += 1
print(la)
Exercises - stack¶
Exercise - break sum¶
✪ Look at the following code, and rewrite it in the following cell as while
this time use command
break
[26]:
lst = []
i = 0
k = 10
while sum(lst) < k:
lst.append(i)
i += 1
print(lst)
[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3, 4]
[27]:
lst = []
i = 0
# write here
[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3, 4]
Exercise - travelbook¶
✪✪ Suppose you visited the attic and found a stack of books, which we represent as a list of strings. Each string is prefixed by a label of one character indicating the category (D for Detective story, T for Travel, H for History)
stack = ['H-Middle Ages', # <---- bottom
'T-Australia',
'T-Scotland',
'D-Suspects',
'T-Caribbean'] # <---- top
Since we are passionate about travel books, we want to examine stack
one book at a time to transfer books into another pile we call ŧravel
, which at the beginning is empty. We start from the top book in stack
, and transfer into travel
only the books starting with the label T
like ('T-Australia'
)
travel = []
Write some code that produces the following print:
At the beginning:
stack: ['H-Middle Ages', 'T-Australia', 'T-Scotland', 'D-Suspects', 'T-Caribbean']
travel: []
Taken T-Caribbean
stack: ['H-Middle Ages', 'T-Australia', 'T-Scotland', 'D-Suspects']
travel: ['T-Caribbean']
Discarded D-Suspects
stack: ['H-Middle Ages', 'T-Australia', 'T-Scotland']
travel: ['T-Caribbean']
Taken T-Scotland
stack: ['H-Middle Ages', 'T-Australia']
travel: ['T-Caribbean', 'T-Scotland']
Taken T-Australia
stack: ['H-Middle Ages']
travel: ['T-Caribbean', 'T-Scotland', 'T-Australia']
Discarded H-Middle Ages
stack: []
travel: ['T-Caribbean', 'T-Scotland', 'T-Australia']
The non-travel books are not interesting and must be discarded
Your code must work with any
stack
list
[28]:
stack = ['H-Middle Ages', # <---- bottom
'T-Australia',
'T-Scotland',
'D-Suspects',
'T-Caribbean'] # <---- top
travel = []
# write here
At the beginning:
stack: ['H-Middle Ages', 'T-Australia', 'T-Scotland', 'D-Suspects', 'T-Caribbean']
travel: []
Taken T-Caribbean
stack: ['H-Middle Ages', 'T-Australia', 'T-Scotland', 'D-Suspects']
travel: ['T-Caribbean']
Discarded D-Suspects
stack: ['H-Middle Ages', 'T-Australia', 'T-Scotland']
travel: ['T-Caribbean']
Taken T-Scotland
stack: ['H-Middle Ages', 'T-Australia']
travel: ['T-Caribbean', 'T-Scotland']
Taken T-Australia
stack: ['H-Middle Ages']
travel: ['T-Caribbean', 'T-Scotland', 'T-Australia']
Discarded H-Middle Ages
stack: []
travel: ['T-Caribbean', 'T-Scotland', 'T-Australia']
Exercise - BANG !¶
✪✪ There are two stacks of objects right_stack
and left_stack
which we represent as lists of strings. As a pastime, a cowboy decides to shoot the objects at the top of the stacks, alternating the stack at each shoot. The cowboy is skilled and always hits the target, so each shot decreases a stack.
Suppose the objects on top are the ones at the end of the list
To keep track of which stack to hit, use a variable
shoot
holding either'R'
or'L'
characterAfter each shot the cowboy if possible changes the stack , otherwise keeps shooting at the same stack until it’s empty.
your code must work for any stack and initial shot
Example - given:
left_stack = ['box','boot','horseshoe','bucket']
right_stack = ['bin','saddle','tin can']
shoot = 'R'
after your code, it must print:
Ready?
left_stack: ['box', 'boot', 'horseshoe', 'bucket']
right_stack: ['bin', 'saddle', 'tin can']
BANG! right: tin can
left_stack: ['box', 'boot', 'horseshoe', 'bucket']
right_stack: ['bin', 'saddle']
BANG! left: bucket
left_stack: ['box', 'boot', 'horseshoe']
right_stack: ['bin', 'saddle']
BANG! right: saddle
left_stack: ['box', 'boot', 'horseshoe']
right_stack: ['bin']
BANG! left: horseshoe
left_stack: ['box', 'boot']
right_stack: ['bin']
BANG! right: bin
left_stack: ['box', 'boot']
right_stack: []
BANG! left: boot
left_stack: ['box']
right_stack: []
Nothing to shoot on the right!
left_stack: ['box']
right_stack: []
BANG! left: box
left_stack: []
right_stack: []
[29]:
left_stack = ['box','boot','horseshoe','bucket']
right_stack = ['bin','saddle','tin can']
shoot = 'R'
#shoot = 'L'
#left_stack = ['bucket', 'box']
# write here
Ready?
left_stack: ['box', 'boot', 'horseshoe', 'bucket']
right_stack: ['bin', 'saddle', 'tin can']
BANG! right: tin can
left_stack: ['box', 'boot', 'horseshoe', 'bucket']
right_stack: ['bin', 'saddle']
BANG! left: bucket
left_stack: ['box', 'boot', 'horseshoe']
right_stack: ['bin', 'saddle']
BANG! right: saddle
left_stack: ['box', 'boot', 'horseshoe']
right_stack: ['bin']
BANG! left: horseshoe
left_stack: ['box', 'boot']
right_stack: ['bin']
BANG! right: bin
left_stack: ['box', 'boot']
right_stack: []
BANG! left: boot
left_stack: ['box']
right_stack: []
Nothing to shoot on the right!
left_stack: ['box']
right_stack: []
BANG! left: box
left_stack: []
right_stack: []
Exercise - Growing or degrowing?¶
✪✪ Write some code which given a list la
, keeps MODIFYING the list according to this procedure:
if the last element is odd (i.e.
7
), attaches a new number at the end of the list obtained by multiplying by two the last element (i.e. attaches14
)if the last element is even, removes the last two elements
DO NOT create a new list (so no rows starting with
la =
)WARNING: when we want both grow and degrow the sequence we are considering in a cycle, we must convince ourselves that sooner or later the termination condition will happen, it’s easy to make mistakes and end up with an infinite cycle!
HINT: to degrow the list, you can use the pop method
Example - given:
la = [3,5,6,7]
Executing the code, it must print:
Odd: attaching 14
la becomes [3, 5, 6, 7, 14]
Even: removing 14
removing 7
la becomes [3, 5, 6]
Even: removing 6
removing 5
la becomes [3]
Odd: attaching 6
la becomes [3, 6]
Even: removing 6
removing 3
la becomes []
Done! la is []
[30]:
la = [3,5,6,7]
# write here
Odd: attaching 14
la becomes [3, 5, 6, 7, 14]
Even: removing 14
removing 7
la becomes [3, 5, 6]
Even: removing 6
removing 5
la becomes [3]
Odd: attaching 6
la becomes [3, 6]
Even: removing 6
removing 3
la becomes []
Done! la is []