Coffee Break Python Workbook
Coffee Break Python Workbook
Workbook
i
Contents
Contents ii
1 Introduction 1
3 Elo 17
3.1 How to Use This Book . . . . . . . . . . . 17
ii
CONTENTS iii
Introduction
1
2 CHAPTER 1. INTRODUCTION
4
2.1. OVERCOME THE KNOWLEDGE GAP 5
in the process.
1
https://en.wikipedia.org/wiki/Active_learning#
Research_evidence
2.8. ACTIVE BEATS PASSIVE LEARNING 13
2
http://journals.sagepub.com/doi/abs/10.1177/
1529100612453266
CHAPTER 2. A CASE FOR PUZZLE-BASED
14 LEARNING
ing. In contrast to other books, this book makes active
learning a first-class citizen. Solving code puzzles is an in-
herent active learning technique. You must figure out the
solution yourself for every single puzzle. The teacher is
as much in the background as possible—they only explain
the correct solution if you couldn’t work it out yourself.
But before telling you the correct solution, your knowl-
edge gap is already ripped wide open. Thus, you are
mentally ready to digest new material.
17
18 CHAPTER 3. ELO
2000
Your Elo
1500
1000
500
0
0 20 40 60 80 100 120
Number of Solved Puzzles
The puzzles are too easy/too hard. This book is for you if
you already have some coding experience. Your Python
skill level ranges from beginner to intermediate. If you
are already an advanced coder, this book is for you too—
if you read it differently. Simply measure the time you
need to solve the puzzles and limit your solution time
to 10–20 seconds. This introduces an additional chal-
lenge for solving the puzzles: time pressure. Solving puz-
zles under time pressure sharpens your rapid code under-
standing skills even more. Eventually, you will feel that
your coding intuition has improved. If the puzzles are too
hard, great. Your knowledge gap must be open before you
can effectively absorb information. Just take your time
to thoroughly understand every bit of new information.
Study the cheat sheets in Chapter 4 properly.
Why is this book not conventionally structured by topic?
The puzzles are sorted by Elo and not structured by topic.
Puzzles with a small Elo rating are easier and more funda-
mental. Puzzles with a higher Elo rating are harder. To
solve them, you need to combine the fundamental lessons
from the easier puzzles. Ordering puzzles by difficulty
has many advantages one being that you can solve puz-
zles at your skill level. As you get better, the puzzles
get harder. Finally, ordering by complexity allows us to
combine many topics in a single puzzle. For example, a
Python one-liner may use two topics: list comprehension
and lambda functions.
Learning to code is best done via coding projects. I agree
but it’s only part of the truth. Yes, you can improve
24 CHAPTER 3. ELO
27
CHAPTER 4. A QUICK OVERVIEW OF THE
28 PYTHON LANGUAGE
https://blog.finxter.com/subscribe/.
4.1 Keywords
All programming languages reserve certain words to have
a special meaning. These words are called keywords.
With keywords, you can issue commands to the compiler
or interpreter. They let you tell the computer what to
do. Without keywords, the computer would not be able
to understand the seemingly random text in your code
file. Note that, as keywords are reserved words, you can-
not use them as variable names.
The most important Python keywords are:
a = 20
print(a)
45
46 CHAPTER 5. PUZZLES: BASIC TO SCHOLAR
a = 20
b = 11
c = a - b
print(c)
my_string = 'abc'
print(my_string)
a = 2
print(type(a))
x = True
print(type(x))
5.6 Minimum
# Elo 1245
print(min([1, 2, 3, -4]))
first_str = 'Hello'
second_str = " world!"
print(str_)
my_str = '''Hello
world
how are
you?'''
print(my_str)
This puzzle does the same as the puzzle before but with
one difference: instead of encoding the new line using
'\n', we define a multi-line string using triple quote no-
tation.
The result is (again):
Hello
world
how
are you?
my_list = [1, 2, 3, 4, 5]
print(len(my_list))
bool_var = 1 == 1
print(bool_var)
bool_var = 1 > 2
print(bool_var)
a = b = c = 1
print(b)
6.1 Maximum
# Elo 1401
59
CHAPTER 6. PUZZLES: SCHOLAR TO
60 INTERMEDIATE
In this puzzle, we pass a list of arithmetic expressions
to the max() function. After evaluating these expres-
sions, the max() function returns the greatest value from
the list. In our case, the list looks like: [5, 10, 4.0].
Hence, this code prints 10.
question = answer
print(id(question)==id(answer))
a = 5
b = 'my string'
tmp = a
a = b
b = tmp
print(a)
print(b)
t1 = True
t2 = True
f1 = False
6.4. THE BOOLEAN OPERATOR AND 63
f2 = False
and_result = t1 and t2
print(and_result)
and_result = t1 and f1
print(and_result)
and_result = f1 and f2
print(and_result)
and_result = f1 and t2
print(and_result)
t1 = True
t2 = True
f1 = False
f2 = False
or_result = t1 or t2
print(or_result)
or_result = t1 or f1
print(or_result)
or_result = f2 or t2
print(or_result)
6.5. THE BOOLEAN OPERATOR OR 65
or_result = f1 or f2
print(or_result)
t1 = 5 + 2 == 7
f1 = 2 - 1 > 3
r = t1 or False
r = r and True and f1
print(r)
r = 3 + 5 - 2
print(type(r))
days_count = 219
days_per_week = 7
ha = 'ha'
ho = 'ho'
print(laughter)
my_str = 'cat'
length = len(my_str)
print(length)
my_str = 'superman'
print(my_str[0])
print(my_str[1])
print(my_str[len(my_str) - 1])
s u p e r m a n
0 1 2 3 4 5 6 7
print(shout)
print(whisper)
print(text)
print(space_count == total_count)
print(space_count == total_count)
print(idx)
print(idx > 0)
my_str = 'python'
print(min(my_str) + max(my_str))
my_str = 'python'
print(my_str[::-1])
my_str = 'python'
are_equal = my_str[:] == my_str
print(are_equal)
6.22. STRING EQUALITY 85
6.23 Slicing I
# Elo 1431
my_str = 'python'
my_substring = my_str[4:]
print(my_substring)
6.24 Slicing II
# Elo 1598
my_str = 'python'
my_substr = my_str[::2]
print(my_substr)
my_str = 'AaBbCcDdEeFf'
big = my_str[::2]
small = my_str[1::2]
6.26 Slicing IV
# Elo 1588
chars_1 = 'Rzotbo'
chars_2 = 'tigno'
print(mystery)
6.27 Slicing V
# Elo 1395
my_str = 'Batman'
other_str = my_str[0:len(my_str)]
print(other_str)
my_str = 'Aquaman'
id_1 = id(my_str)
my_str = my_str[4:]
id_2 = id(my_str)
print(id_1 == id_2)
my_list = [
'apple',
'banana',
'orange',
]
item = my_list[len(my_list)-2]
print(item)
my_list = [
'apple',
'orange',
'banana',
]
item = my_list[1]
print(item)
my_list = [
'apple',
'banana',
'orange',
]
item = my_list.pop()
print(item)
phone = 'smartphone'
x = phone.startswith('smart')
y = phone.endswith('phone')
print(x and y)
phone = 'smartphone'
x = 'xyz' in phone
print(not x)
print(x)
print(str_1 == str_2)
This puzzle is similar to the last one but with one differ-
ence: the second string does not strip leading and trailing
whitespaces. Instead, it replaces all occurrences of the
whitespace character ' ' with the empty string. This is
the same as removing all whitespace in the sentence.
While str_1 still has some whitespaces left (in between
each word), str_2 does not.
So, the result of the final print statement is False.
shopping_list = [
'bread',
'milk',
'cheese',
]
string = ','.join(shopping_list)
print(string)
my_list = [
'Bob',
'Alice',
'Donald',
'Goofy',
]
your_list = my_list.copy()
print(id(your_list) == id(my_list))
my_list = []
my_list.append('Tomato')
my_list = my_list + ['Pizza']
print(my_list)
odd = [1, 3, 5, 7]
even = [0, 2, 4, 6]
odd.extend(even)
print(len(odd))
my_list = []
my_list.append(1)
my_list.append(2)
my_list.pop()
print(len(my_list))
my_list = [4, 5, 6]
index = 0
my_list.insert(index, 3)
print(my_list[1])
my_list = [1, 2, 3, 4]
value = 2
index = 2
my_list.remove(value)
print(my_list[index])
my_list = [1, 2, 3, 3, 2, 3]
index = my_list.index(3)
print(index)
my_list = [1, 2, 3, 0, 2, 3]
CHAPTER 6. PUZZLES: SCHOLAR TO
108 INTERMEDIATE
count = my_list.count(3)
print(count)
print(len(my_list))
my_list = [4, 7, 3, 9, 1]
my_list.sort()
print(my_list)
my_list = [10, 9, 8, 7]
my_list.reverse()
print(my_list)
print(x)
bool_val = all([
1 == 1,
7 // 2 == 2 + 1,
2 == 6 % 4,
])
print(bool_val)
This puzzle goes one step further. You need to figure out
multiple logical expressions before testing whether all()
of them are True.
The first expression 1==1 is obviously True. The sec-
ond expression is also True because 7 // 2 = 3 = 2 +
1. Finally, the third expression is True as six modulo four
is 2.
Thus, the all() function returns True.
len_of_list = len(list(range(10)))
print(len_of_list)
l = list(range(10, 1, -1))
print(l)
a = 'world!'
b = 'hello '
b, a = a, b
print(a + b)
my_list = [1, 1, 1, 1]
my_list[1::2] = [2, 3]
print(my_list)
word = 'radar'
p = word == word[::-1]
print(p)
value_0 = int(True)
value_1 = int(False)
string = str(value_0) + str(value_1)
print(string)
print(1000 * False)
print((3 == 4) == 0)
print(bool([]))
• empty sequences,
• 0,
• 0.0,
n = 0
for i in range(0, 6, 3):
n += i
6.61. LOOPING OVER RANGES 125
print(n)
str_ = ''
for c in reversed('nohtyp'):
str_ += c
print(str_)
s = sum([
True,
False,
True,
True,
])
print(s)
my_list = []
id_1 = id(my_list)
print(id_1 == id_2)
my_list = []
id_1 = id(my_list)
my_list.append(1)
id_2 = id(my_list)
print(id_1 == id_2)
b = all([
bool('0'),
bool('?'),
bool('-'),
bool('e'),
])
print(b)
a = complex(2, 4)
b = complex(1, -3)
print(a + b)
6.68 Tuples
# Elo 1462
print(type(x) == type(y))
1. t1 = (1, 2), or
2. t2 = 1, 2.
x, y, z = 'cat'
print(y)
So printing y returns a.
my_bools = []
result = all(my_bools)
print(result)
b = any([
bool(None),
bool(0),
bool(dict()),
])
print(b)
1. it exists, and
2. len(c) > 0
my_list = [1, 1, 0]
s = 3
if my_list:
s = sum(my_list)
print(s)
CHAPTER 6. PUZZLES: SCHOLAR TO
138 INTERMEDIATE
What’s the output of this code snippet?
Correct: +10 Elo points / Wrong: -10 Elo points
6.73. ACCESSING COMPLEX NUMBERS 139
a = complex(2, 5)
b = complex(a.imag, a.real)
print(b)
p1 = (1, -1)
p2 = (2, 5)
p3 = (p1[0] + p2[0], p1[1] + p2[1])
print(p3)
index = 5
s = 'g'
print(s)
index = 5
string = 'g'
print(string)
index = 5
string = 'g'
else:
string += 'd'
print(string)
CHAPTER 6. PUZZLES: SCHOLAR TO
146 INTERMEDIATE
What’s the output of this code snippet?
Correct: +10 Elo points / Wrong: -10 Elo points
6.78. BASIC ARITHMETIC 147
print(magic(2, 3))
6.79 Dictionary
# Elo 1531
dict_ = {
1: 'one',
2: 'two',
3: 'three',
}
def to_str(number):
if number in dict_:
return dict_[number]
else:
return '?'
s1 = to_str(2)
s2 = to_str(7)
print(s1 + s2)
sales = {
100: {'item': 'apple', 'price': .95},
101: {'item': 'banana', 'price': .55},
102: {'item': 'orange', 'price': .75},
}
value = sales[102].get('price')
6.80. DICTIONARY OF DICTIONARIES 151
print(value)
roman = {
1: 'I', 2: 'II', 3: 'III', 4: 'IV', 5: 'V',
6: 'VI', 7: 'VII', 8: 'VIII', 9: 'IX', 10: 'X'
}
6.81. REVERSE DICTIONARY INDEX 153
arab = {}
print(arab['VII'])
r1 = func(1, 0)
r2 = func(1, 1, 2)
chars = 'dog!'
char_1 = chars[-2]
156
7.1. BUILDING STRINGS II 157
char_2 = chars[chars.find('o')]
char_3 = chars[-1]
chars = 'bretsamaty'
word = chars[1:7][::-1]
print(word)
odds = [1, 3, 5, 7]
s = sum(odds) + max(odds) + min(odds)
print(s)
numbers = '1-2-3-4-5-6-7-8-9'
my_list = numbers.split('-')
my_list[::2] = (len(numbers) // 4 + 1) * 'X'
out = ''.join(my_list)
out = out.replace('X', '')
print(out)
print(format(0.1, '.5f'))
CHAPTER 7. PUZZLES: INTERMEDIATE TO
162 PROFESSIONAL
What’s the output of this code snippet?
Correct: +10 Elo points / Wrong: -10 Elo points
7.6. FLOATING POINT COMPARISONS 163
print(a == b)
odd = [1, 3, 5]
even = [2, 4, 6]
print(nums)
CHAPTER 7. PUZZLES: INTERMEDIATE TO
166 PROFESSIONAL
What’s the output of this code snippet?
Correct: +10 Elo points / Wrong: -10 Elo points
7.8. THE NOT-SO-OBVIOUS CASE 167
Here, we have two sequences – one with odd and one with
even numbers.
Then, we create a list with six white-space characters
using simple list arithmetic. The white-space characters
serve as dummy values, intended only for initializing a list
of six elements.
Using a combination of slice assignments and multiple
assignments, we replace the elements with even indices
by the odd numbers and the elements with odd indices
by even numbers.
The result is the sequence [1, 2, 3, 4, 5, 6].
unknown = #input ??
str_ = unknown[0]
n = int('1101', 2)
print(n)
print(type_1 == type_2)
a = 1 > 0
if a or (1 / 0 == 0):
print('ok')
7.12. SHORT CIRCUITING 173
else:
print('nok')
n = 16
x = 0
while x < 3:
n /= 2
x += 1
print(n)
inc = lambda x : x + 1
print(inc(2))
7.15 Zip
# Elo 1721
print(len(l3))
list_ = list(range(5))
func = lambda x: x % 2 == 0
ns = []
ns.append(n)
print(ns)
def func(x):
return x % 2 == 0
list_ = list(range(4))
incs = [x + 1 for x in list_]
print(incs)
encrypted = 'Dbftbs!fodszqujpo!jt!opu!tfdvsf"'
decrypted = ''
7.18. ENCRYPTION BY OBFUSCATION 183
for c in encrypted:
decrypted += chr(ord(c) - 1)
print(decrypted)
1
This encryption is called Caesar’s cipher because it was used
by Julius Caesar to encrypt his private conversations.
7.19. STRING DICTIONARY 185
dict_ = {
0: ' ', 3: 'eat', 2: 'apple',
4: 's', 1: 'Bob', 5: '.',
}
words = [1, 0, 3, 4, 0, 2, 4, 5]
sentence = ''''''
for w in words:
sentence += dict_[w]
print(sentence)
a = func_dict[0](3, -1)
b = func_dict[1](4.0, 0.5)
7.20. FUNCTIONS ARE OBJECTS 187
print(a + b)
customers = {
100: {'name': 'Alice', 'zip': 1234},
101: {'name': 'Bob', 'zip': 1212},
102: {'name': 'Clare', 'zip': 1001},
7.21. DICTIONARY OF DICTIONARIES 189
customers[101].clear()
print(len(customers))
zip_codes = {
3001: 'Dolomite',
3002: 'Goodwater',
3003: 'Montevallo',
3004: 'Shelby',
3000: 'Vance',
}
7.22. SORTING DICTIONARY KEYS 191
keys = list(zip_codes.keys())
keys.sort()
print(keys[0])
item_prices = {}
print(item_prices['tomato'])
7.23. PYTHONIC LOOP ITERATION 193
item_prices = [
('car', 10000),
('boat', 7000),
('bike', 400),
('skateboard', 150),
('aircraft', 500000),
]
print(len(my_list))
7.24. FILTERING WITH LIST COMPREHENSION195
prices = [
('banana', 1.5),
('apple', 2.0),
('bread', 2.0),
('milk', 1.0),
('fish', 3.5)
]
print(a)
7.25. AGGREGATING WITH LIST
COMPREHENSION 197
What’s the output of this code snippet?
Correct: +10 Elo points / Wrong: -10 Elo points
CHAPTER 7. PUZZLES: INTERMEDIATE TO
198 PROFESSIONAL
In this puzzle, we calculate the average of all prices.
The list prices is initialized with 5 tuples of the form
(item_name, price). W
e use a list comprehension to access the price of each item
(the second tuple element x[1]) and create a list of floats.
Then, we sum all the float values using Python’s built-in
function sum().
Finally, we divide the result by the length of the list
prices (which is 5). The resulting float value 2.0 is
assigned to variable a.
Therefore, the printed output of a is 2.0.
speed = [
('car', 100),
('boat', 20),
('bike', 8),
('ski', 7),
('aircraft', 650),
]
print(max(speed)[1])
speed = [
7.27. THE KEY ARGUMENT 201
('car', 100),
('boat', 20),
('bike', 8),
('ski', 7),
('aircraft', 650),
]
del my_list
7.28. PUZZLE 123 203
print(my_list)
set_ = set()
print(len(set_))
set_1 = {1, 2, 3, 4}
set_2 = {3, 4, 5, 6}
set_1 = set_1.intersection(set_2)
CHAPTER 7. PUZZLES: INTERMEDIATE TO
206 PROFESSIONAL
set_2 = set_2.difference(set_1)
print(len(set_1) + len(set_2))
numbers = [9, 2, 3, 3, 3, 7, 4, 5, 1, 6, 8]
def magic(l):
if len(l) <= 1:
return l
p = l[0]
return magic([x for x in l[1:] if x < p]) \
CHAPTER 7. PUZZLES: INTERMEDIATE TO
208 PROFESSIONAL
+ [p] \
+ magic([x for x in l[1:] if x >= p])
my_list = magic(numbers)
print(my_list)
7.32 Fibonacci
# Elo 1809
cache = {}
def fib(n):
if n < 0:
raise ValueError
if n == 1:
return 0
elif n == 2:
return 1
if not n in cache:
cache[n] = fib(n-1) + fib(n-2)
7.32. FIBONACCI 211
return cache[n]
fib(10)
print(len(cache))
Final Remarks
214
215
218
219
Coffee Break
NumPy
Slicing
9.1 Arithmetic
# Puzzle 1
x = 5 // -3.0 * 4
print(x)
222
9.2. WHITESPACE 223
9.2 Whitespace
# Puzzle 2
x = len('py\tpy\n')
print(x)
9.3 Modulo
# Puzzle 3
x = 0
while x < 4:
x += 1
if x % 2:
continue
print('$', end='')
else:
print('$', end='')
9.4 Tuple
# Puzzle 4
x = tuple(list('hi'))
print(x)
9.5 Dictionary
# Puzzle 5
d = dict([(i, i%3) for i in range(8)])
print(d[5])
9.6 Asterisk
# Puzzle 6
*x, y, z = 1, 2, 3, 4
*x, y = x, y, z
print(x[1])
9.7 Slicing 1
# Puzzle 7
t = [10, 20, 30, 40]
t[100:103] = [10]
print(t)
The result of the previous puzzle is: [10, 20, 30, 40,
10].
9.8 Slicing 2
t = [10, 20, 30, 40]
t[2:0] = [10]
print(t)
The result of the previous puzzle is: [10, 20, 10, 30,
40].
9.11 Exception
# Puzzle 11
try:
x = -9 ** 1/2
print(x)
except:
x = 8 * 2 // 5
print(x)
9.12 Insert
# Puzzle 12
t = [3, 4, 5, 6]
t.insert(0, t.pop(t.index(5)))
print(t)
9.14 Default
# Puzzle 14
c = 11
d = 12
func(10, c, d)
9.16 Global
# Puzzle 16
a = 10
def func(x=a):
global a
a += 1
print(x, a)
func(3)
9.17 Flow 1
# Puzzle 17
a = [10]
def func(a):
a.append(20)
print(a)
a = [2]
func(a)
9.18 Flow 2
# Puzzle 18
a = 1
b = [10]
func(a, b)
print(a in b)
9.19 Enumerate
# Puzzle 19
t = {}, {1}, {1,2}, {1:2}
myList = [k for k, v in enumerate(t) \
if isinstance(v, set)]
print(myList[0])
9.20 Reverse
# Puzzle 20
t = ['world', 'hello', 'python']
sorted_t = t.sort(reverse=True)
print(sorted_t)
9.22 Sorting++
# Puzzle 22
d = {3:10, 4:8, 3:9}
print(sorted(d, key=lambda x: d[x], reverse=True))
9.23 Indexing
# Puzzle 23
t = [[1, 2], [3, 4]]
t2 = t * 1
t[0][0] = 10
print(t2[0][0])
9.24 Count
# Puzzle 24
word = 'banana'
print(word.count('ana'))
9.25 Power
# Puzzle 25
x = 2 ** 1 ** 2 % -5
print(x)
9.26 Lambda
# Puzzle 26
t = ['python', 'puzzle', 'fun', 'java']
f = lambda lst: lst.pop(0)
g = lambda lst: lst.pop(1)
h = lambda lst: lst.pop(2)
d = {0:f, 1: g, 2: h}
x = d[f(t) > g(t)](t)
print(x)
9.27 Recursion
# Puzzle 27
def f(word):
if len(word) > 3:
return '*'
else:
word += '*'
return '*' + f(word)
print(f('*'))
9.28 Kwargs
# Puzzle 28
def f(a, b, c, d=4, e=5):
print(a + b + c + d + e)
x = word_dict('banana')['n']
print(x)
9.31 Print
# Puzzle 31
s = [('hello', 'world'), ('I', 'love', 'python')]
for x in s:
print(*x, sep='-', end='-')
9.32 Logic
# Puzzle 32
easy = True and False == True and False
print(easy)
b = 20
print(f(1))
9.34 Pass
# Puzzle 34
for i in range(5, -1, -1):
if i % 1 == 0:
pass
if i % 2 == 0:
continue
if i % 3 == 0:
break
print(i, end='-')
9.36 Zipzip
# Puzzle 36
a = [1, 3]
b = [2, 4, 6]
crazy = zip(*zip(a, b))
print(list(crazy))
The result of the previous puzzle is: [(1, 3), (2, 4)].
9.37 Comprehension
# Puzzle 37
t = [[i for i in range(j)] for j in range(4)]
print(t[2][1])
9.39 Max
# Puzzle 39
t = 'iPhone', 'Italy', '10', '2'
print(max(t))
9.40 Zip
# Puzzle 40
x = 1, 2
y = list(zip(x))
print(y[0])
9.41 Unpack
# Puzzle 41
a = [1]
b = [2, 4, 6]
crazy = zip(*zip(a, b))
y = list(crazy)
print(y[0])
9.42 Minimax
# Puzzle 42
def f(x, y):
x, y = min(x, y), max(x, y)
if y % x == 0:
return x
else:
return f(x, y % x)
print(f(16, 72))
9.43 Sort
# Puzzle 43
scores = [100, 84, 63, 97]
scores_sorted = scores.sort()
print(scores[0])
9.45 While
# Puzzle 45
i = 2
while i % 3:
i += 2
print('!', end='-')
print('!')
s = []
for x in pairs:
s += x
print(len(s))
9.48 Count
# Puzzle 48
ones = [(1),
(1,),
(1,1)]
print(ones.count(1))
9.49 Cut
# Puzzle 49
hair = 100
hair = 50
hair = cut(2, 20)
print(hair)
9.50 End
# Puzzle 50
if 1 < 2 is True:
print('nice', end=' ')
if 'A' < 'a' is True:
print('bravo', end=' ')
else:
print('great')