Professional Documents
Culture Documents
1.1 ISBN
# read first nine digits of an ISBN-10 code and convert them to integers
x1 = int(input())
x2 = int(input())
x3 = int(input())
x4 = int(input())
x5 = int(input())
x6 = int(input())
x7 = int(input())
x8 = int(input())
x9 = int(input())
1
son = (a + b - b * c) // (c - 1)
2
2 Series 02: conditional statements
2.1 ISBN
"""
alternative solution:
if x10 == check_digit:
print(’OK’)
else:
print(’WRONG’)
"""
3
2.3 Fizz buzz
# read number
number = int(input())
# determine pronunciation
if not number % 3 and not number % 5:
pronunciation = ’fizz buzz’
elif not number % 3:
pronunciation = ’fizz’
elif not number % 5:
pronunciation = ’buzz’
else:
pronunciation = number
# output pronunciation
print(pronunciation)
import math
# resultaat uitschrijven
print(f’The Grand Prix of {location} runs over {laps} laps ({laps * lap_distance} km).’)
4
2.6 Rock-paper-scissors-lizard-Spock
else:
"""
alternative way to determine the position, without using lists
if gesture1 == ’scissors’:
gesture1 = 0
elif gesture1 == ’paper’:
gesture1 = 1
elif gesture1 == ’rock’:
gesture1 = 2
elif gesture1 == ’lizard’:
gesture1 = 3
else:
gesture1 = 4
if gesture2 == ’scissors’:
gesture2 = 0
elif gesture2 == ’paper’:
gesture2 = 1
elif gesture2 == ’rock’:
gesture2 = 2
elif gesture2 == ’lizard’:
gesture2 = 3
else:
gesture2 = 4
"""
# gesture beats other gesture that is one or three positions further down
# the list; modulo operator is used because the list is circular
if (gesture1 + 1) % 5 == gesture2 or (gesture1 + 3) % 5 == gesture2:
outcome = ’player1 wins’
else:
outcome = ’player2 wins’
5
3 Series 03: loops
3.1 ISBN
# read first number from the sequence; for now there is not previous number
previous, current = None, input()
# getallen uit de reeks één voor één inlezen totdat er een regel wordt ingelezen
# die de tekst NYT bevat; het vorige getal uit de reeks wordt telkens
# onthouden zodat kan nagegaan worden of het huidige getal gevormd wordt door
# het increment op te tellen bij het vorige getal
# read numbers from sequence one by one, until a line is read that contains the
# text NYT; previous number in the sequence is remembered so that we can check
# if the current number is equal to the sum of the previous number and the
# increment
while current != ’NYT’:
# check if current number equals the sum of the increment and the previous
# number
if previous is not None and previous + increment != current:
print(f’{previous} -> {current} ({current - previous:+d})’)
# read next number from sequence and remember the previous number
previous, current = current, input()
6
# import module defining data structure to represent dates in Python
import datetime
current_year = datetime.date.today().year
verb = ’was’ if birth_year + age < current_year else ’turns’
print(f’{name} {verb} {age} in {birth_year + age}.’)
else:
3.4 All-or-nothing
# initialize variable that indicates if a player didn’t gamble more money than
# he has left
valid_bet = True
7
print(f’You cannot bet {bet} dollar if you only have {capital} dollar.’)
3.5 Canvascrack
# determine profit crack has made after each table has been played
for table in range(1, tables + 1):
else:
# functional representation of the operators less than (<) and greater than (>)
from operator import lt, gt
# iterate over all possible numbers of white roses: we know there are at least
# 2 roses of each color, so the number of white roses can’t be larger than the
# number of red and white roses minus two and the number of white and blue roses
# minus two
for white in range(2, min(red_white, white_blue) - 1):
# the total number of red and white roses is fixed, so for a given number of
# white roses we can also determine the total number of red roses
red = red_white - white
# the total number of blue and white roses is fixed, so for a given number of
# white roses we can also determine the total number of blue roses
blue = white_blue - white
8
# output the total number of blue, white and red roses if the condition
# imposed on the total number of white and blue roses is fulfilled
if operator(blue + red, white_blue):
print(blue, white, red, sep=’\n’)
9
4 Series 04: strings
4.1 ISBN
"""
# compute check digit: alternative solution using generator expression
check_digit = sum((i + 1) * int(code[i]) for i in range(9)) % 11
"""
# check whether computed and extracted check digits are the same
if (check_digit == 10 and x10 == ’X’) or x10 == str(check_digit):
print(’OK’)
else:
print(’WRONG’)
4.2 Atbash
def encoding(character):
if not character.isalpha():
return character
def atbash(message):
translation = ’’
for character in message:
translation += encoding(character)
return translation
"""
# alternative using generator expression
return ’’.join(encoding(character) for character in message)
"""
cases = int(input())
for _ in range(cases):
message = input()
print(atbash(message))
10
4.3 Vampire numbers
def isvampire(number):
"""
>>> isvampire(1260)
True
>>> isvampire(1234)
False
>>> isvampire(1395)
True
"""
11
4.5 The language of science
12
5 Series 05: functions
5.1 ISBN
def isISBN(code):
"""
Return True if the argument is a string that contains a valid ISBN-10 code,
False otherwise.
>>> isISBN(’9971502100’)
True
>>> isISBN(’9971502108’)
False
>>> isISBN(’53WKEFF2C’)
False
>>> isISBN(4378580136)
False
"""
def checkdigit(code):
"""
Computes the check digit for a given string that contains the first nine
digits of an ISBN-10 code. A string representation of the check digit is
returned, with the value 10 represented as the letter X.
>>> checkdigit(’997150210’)
’0’
>>> checkdigit(’938389293’)
’5’
"""
if __name__ == ’__main__’:
import doctest
doctest.testmod()
5.2 123
def evenOdd(number):
"""
>>> evenOdd(886328712442992)
(10, 5)
>>> evenOdd(10515)
(1, 4)
13
>>> evenOdd(145)
(1, 2)
"""
even, odd = 0, 0
for digit in str(number):
digit = int(digit)
if digit % 2:
odd += 1
else:
even += 1
def step(number):
"""
>>> step(886328712442992)
10515
>>> step(10515)
145
>>> step(145)
123
"""
def steps(number):
"""
>>> steps(886328712442992)
3
>>> steps(1217637626188463187643618416764317864)
4
>>> steps(0)
2
>>> steps(1)
5
>>> steps(2)
2
>>> steps(3)
5
"""
steps = 0
while number != 123:
number = step(number)
steps += 1
return steps
if __name__ == ’__main__’:
import doctest
doctest.testmod()
5.3 Numeronym
def numeronym(word):
"""
>>> numeronym(’internationalization’)
’i18n’
>>> numeronym(’TAKEDOWN’)
’T6N’
>>> numeronym(’Random’)
’R4m’
14
>>> numeronym(’DNA’)
’DNA’
"""
def template(numeronym):
"""
>>> template(’i18n’)
’i..................n’
>>> template(’TAK3N’)
’TAK...N’
>>> template(’R2D2’)
’R..D..’
>>> template(’se7en’)
’se.......en’
>>> template(’C3PO’)
’C...PO’
"""
# process last number (only in case the word ends with a number)
if number:
template += ’.’ * int(number)
return template
"""
>>> isnumeronym(’i18n’, ’internationalization’)
True
>>> isnumeronym(’TAK3N’, ’TAKEDOWN’)
False
>>> isnumeronym(’R2D2’, ’Random’)
True
>>> isnumeronym(’se7en’, ’semicitizen’)
True
>>> isnumeronym(’C3PO’, ’cuerpo’)
True
"""
# check if all positions of the word match the corresponding position of the
# template
# NOTE: conversion to uppercase for case insensitive comparisons
for letter1, letter2 in zip(word.upper(), numeronym.upper()):
15
if letter2 not in ’.’ + letter1:
return False
return True
"""
# alternative solution using regular expression
import re
return bool(re.fullmatch(template(numeronym), word, flags=re.IGNORECASE))
"""
if __name__ == ’__main__’:
import doctest
doctest.testmod()
def longestPolydivisiblePrefix(number):
"""
>>> longestPolydivisiblePrefix(1234356789)
123
>>> longestPolydivisiblePrefix(381654729)
381654729
>>> longestPolydivisiblePrefix(381654728)
38165472
"""
assert isinstance(number, int) and number > 0, ’argument must be a strictly positive
integer’
digits = int(log10(number)) + 1
power = pow(10, digits - 1)
for prefix in range(2, digits + 1):
power //= 10
if (number // power) % prefix:
return number // (10 * power)
return number
"""
# alternative solution: works with strings instead of integers
number = str(number)
for digits in range(2, len(number) + 1):
if int(number[:digits]) % digits:
return int(number[:digits - 1])
return int(number)
"""
def isPolydivisible(number):
"""
>>> isPolydivisible(1234356789)
False
>>> isPolydivisible(381654729)
True
>>> isPolydivisible(381654728)
False
"""
def polydivisibleExtensions(number):
16
"""
>>> polydivisibleExtensions(12)
4
>>> polydivisibleExtensions(23)
0
>>> polydivisibleExtensions(381654729)
1
"""
if not isPolydivisible(number):
return 0
count = 0
number *= 10
digits = int(log10(number)) + 1
for digit in range(10):
if not (number + digit) % digits:
count += 1
return count
if __name__ == ’__main__’:
import doctest
doctest.testmod()
def pigword(word):
"""
>>> pigword(’egg’)
’eggway’
>>> pigword(’trash’)
’ashtray’
>>> pigword(’quit’)
’itquay’
>>> pigword(’Pig’)
’Igpay’
>>> pigword(’Latin’)
’Atinlay’
>>> pigword(’BaNaNa’)
’ANaNabay’
>>> pigword(’DNa’)
’AdNay’
>>> pigword(’plover’)
’overplay’
>>> pigword(’plunder’)
’underplay’
"""
# definition of vowels
vowels = ’aeiou’
17
):
if word[pos:].lower().startswith(’qu’):
pos += 2
else:
pos += 1
# split parts
part1 = word[:pos]
part2 = word[pos:]
def piglatin(text):
"""
>>> piglatin(’And now for something completely different!’)
’Andway ownay orfay omethingsay ompletelycay ifferentday!’
>>> piglatin(’Stwike him, centuwion, stwike him vewy wuffly’)
’Ikestway imhay, entuwioncay, ikestway imhay ewyvay ufflyway’
"""
if character.isalpha():
else:
return pigtext
if __name__ == ’__main__’:
import doctest
doctest.testmod()
5.6 Geohash
import string
def geo2dec(geohash):
18
"""
>>> geo2dec(’ezs42’)
14672002
>>> geo2dec(’DRUGGED’)
13684424108
>>> geo2dec(’ZUR1CH’)
1068205424
"""
# base 32 decoding
return sum(
charmap.index(char) * 32 ** index
for index, char in enumerate(geohash.upper()[::-1])
)
def geo2bin(geohash):
"""
>>> geo2bin(’ezs42’)
’0110111111110000010000010’
>>> geo2bin(’DRUGGED’)
’01100101111101001111011110110101100’
>>> geo2bin(’ZUR1CH’)
’111111101010111000010101110000’
"""
def unravel(bitstring):
"""
>>> unravel(’0110111111110000010000010’)
(’0111110000000’, ’101111001001’)
>>> unravel(’01100101111101001111011110110101100’)
(’010011001101110010’, ’10111110111101110’)
>>> unravel(’111111101010111000010101110000’)
(’111111110000100’, ’111000100111100’)
"""
return (
’’.join(bitstring[index] for index in range(0, len(bitstring), 2)),
’’.join(bitstring[index] for index in range(1, len(bitstring), 2))
)
"""
>>> bin2coord(’0111110000000’, -180, 180)
(-5.625, -5.5810546875)
>>> bin2coord(’101111001001’, -90, 90)
(42.5830078125, 42.626953125)
>>> bin2coord(’010011001101110010’, -180, 180)
(-71.91375732421875, -71.91238403320312)
>>> bin2coord(’10111110111101110’, -90, 90)
(44.27215576171875, 44.273529052734375)
19
>>> bin2coord(’111111110000100’, -180, 180)
(178.6376953125, 178.648681640625)
>>> bin2coord(’111000100111100’, -90, 90)
(69.23583984375, 69.2413330078125)
"""
def geo2coord(geohash):
"""
>>> geo2coord(’ezs42’)
(-5.60302734375, 42.60498046875)
>>> geo2coord(’DRUGGED’)
(-71.91307067871094, 44.27284240722656)
>>> geo2coord(’ZUR1CH’)
(178.6431884765625, 69.23858642578125)
"""
if __name__ == ’__main__’:
import doctest
doctest.testmod()
20
6 Series 06: lists and tuples
6.1 ISBN
def isISBN(code):
"""
Checks if the given ISBN-10 code is valid.
>>> isISBN(’9-9715-0210-0’)
True
>>> isISBN(’997-150-210-0’)
False
>>> isISBN(’9-9715-0210-8’)
False
"""
# check if dashes are at the correct positions and if each group has the
# correct number of digits
groups = code.split(’-’)
if [len(e) for e in groups] != [1, 4, 4, 1]:
return False
def checkdigit(code):
"""
>>> checkdigit(’997150210’)
’0’
>>> checkdigit(’938389293’)
’5’
"""
if __name__ == ’__main__’:
import doctest
doctest.testmod()
def average(sequence):
"""
>>> average((5, 6, 7, 8, 9))
7.0
>>> average([1, 2, 3, 4])
2.5
21
"""
"""
>>> seq1 = [5, 6, 7, 8, 9]
>>> seq2 = [1, 2, 3, 4]
>>> seq3 = [5]
>>> move1(seq1, seq2, seq3)
>>> seq1
[6, 7, 8, 9]
>>> seq2
[1, 2, 3, 4, 5]
>>> seq3
[5]
"""
"""
>>> seq1 = (5, 6, 7, 8, 9)
>>> seq2 = [1, 2, 3, 4]
>>> seq3 = [5]
>>> move2(seq1, seq2, seq3)
([6, 7, 8, 9], [1, 2, 3, 4, 5])
>>> seq1
(5, 6, 7, 8, 9)
>>> seq2
[1, 2, 3, 4]
>>> seq3
[5]
"""
# create two new lists as copies of the numbers of the two given sequences
# NOTE: it’s important to copy the numbers in the given sequences in two
# new lists, in order not to change the given sequences
list1, list2 = list(sequence1), list(sequence2)
# remove numbers from first list and add elements to second list
move1(list1, list2, numbers)
"""
>>> iswillrogers([5, 6, 7, 8, 9], [1, 2, 3, 4], [5])
True
>>> iswillrogers((5, 6, 7, 8, 9), (1, 2, 3, 4), (7, 9))
False
"""
22
return before1 < after1 and before2 < after2
if __name__ == ’__main__’:
import doctest
doctest.testmod()
def positions(word):
"""
>>> positions(’LOVE’)
(11, 14, 21, 4)
>>> positions(’mutual’)
(12, 20, 19, 20, 0, 11)
"""
"""
>>> ismutual((11, 14, 21, 4), 26)
True
>>> ismutual([12, 20, 19, 20, 0, 11], 26)
False
"""
def mutual_love(word):
"""
>>> mutual_love(’LOVE’)
True
>>> mutual_love(’mutual’)
False
"""
if __name__ == ’__main__’:
23
import doctest
doctest.testmod()
import math
def iszapreadable(page_numbers):
"""
>>> iszapreadable([7, 5, 3, 1, 8, 6, 4, 2])
True
>>> iszapreadable([1, 2, 4, 7, 3, 8, 6, 5])
False
>>> iszapreadable([1, 2, 5, 3, 8, 7, 4, 6])
True
>>> iszapreadable([1, 1, 1, 1, 1, 1, 1, 1])
False
"""
return True
def zapbook(pages):
"""
>>> zapbook(1)
[1]
>>> zapbook(6)
[5, 3, 1, 6, 4, 2]
>>> zapbook(7)
[]
>>> zapbook(8)
[1, 2, 5, 3, 8, 7, 4, 6]
"""
return []
24
# intialize page numbers of the book
page_numbers = [0] * pages
# page_numbers teruggeven
return page_numbers
if __name__ == ’__main__’:
import doctest
doctest.testmod()
"""
>>> cards = [’KS’, ’4H’, ’KH’, ’JD’, ’10S’, ’2D’, ’9C’, ’JH’]
>>> group(cards, 2)
[(’KS’, ’4H’), (’KH’, ’JD’), (’10S’, ’2D’), (’9C’, ’JH’)]
>>> group(cards, 4)
[(’KS’, ’4H’, ’KH’, ’JD’), (’10S’, ’2D’, ’9C’, ’JH’)]
>>> group(cards, 3)
Traceback (most recent call last):
AssertionError: invalid grouping
>>> group(cards, [2, 4, 2])
[(’KS’, ’4H’), (’KH’, ’JD’, ’10S’, ’2D’), (’9C’, ’JH’)]
>>> group(cards, (3, 2, 3))
[(’KS’, ’4H’, ’KH’), (’JD’, ’10S’), (’2D’, ’9C’, ’JH’)]
>>> group(cards, [3, 1, 3])
Traceback (most recent call last):
AssertionError: invalid grouping
"""
if isinstance(sizes, int):
# check if the sum of all group sizes equals the number of cards in the
# given pile
assert len(pile) == sum(sizes), ’invalid grouping’
else:
25
raise AssertionError(’invalid grouping’)
"""
>>> cards = [’7C’, ’2D’, ’JC’, ’7H’, ’10S’, ’9D’, ’5C’, ’AH’, ’3C’, ’AD’, ’9C’, ’KD’, ’10C
’, ’QH’, ’JS’, ’4D’, ’AS’, ’8D’]
>>> pile1 = group(cards[:9], 3)
>>> pile1
[(’7C’, ’2D’, ’JC’), (’7H’, ’10S’, ’9D’), (’5C’, ’AH’, ’3C’)]
>>> pile2 = group(cards[9:], [2, 4, 3])
>>> pile2
[(’AD’, ’9C’), (’KD’, ’10C’, ’QH’, ’JS’), (’4D’, ’AS’, ’8D’)]
>>> pile3 = group(cards[9:], [1, 3, 2, 3])
>>> pile3
[(’AD’,), (’9C’, ’KD’, ’10C’), (’QH’, ’JS’), (’4D’, ’AS’, ’8D’)]
>>> riffle_shuffle(pile1, pile2)
[’7C’, ’2D’, ’JC’, ’AD’, ’9C’, ’7H’, ’10S’, ’9D’, ’KD’, ’10C’, ’QH’, ’JS’, ’5C’, ’AH’, ’3C
’, ’4D’, ’AS’, ’8D’]
>>> riffle_shuffle(pile1, pile3)
Traceback (most recent call last):
AssertionError: different number of groups
def mixed_pairs(pile):
# check if all pairs of successive cards contain one red and one black card
red = ’DH’
return all(
(card1[-1] in red) != (card2[-1] in red)
for card1, card2 in group(pile, 2)
)
if __name__ == ’__main__’:
import doctest
doctest.testmod()
26
6.6 Bitcoins
"""
>>> profit([5, 11, 4, 2, 8, 10, 7, 4, 3, 6], ’BS-B-S--BS’)
17
>>> profit((4, 2, 5, 11, 10, 4, 11, 7, 4, 11, 3, 11), ’-B-S-BS-BSBS’)
31
>>> profit([10, 9, 9, 10, 10, 9, 1, 4, 9, 3, 5, 6, 10], ’-B-S--B-SB--S’)
16
>>> profit((12, 4, 9, 5, 6, 7, 9, 9, 11, 7, 10), ’-BSB----SBS’)
14
>>> profit([10, 9, 8, 7, 6, 5, 4, 3, 2, 1], ’----------’)
0
>>> profit((10, 4, 2, 4, 8, 12), ’B---SS’)
Traceback (most recent call last):
AssertionError: invalid actions
"""
# compute profit based on bitcoin values and check actions throughout the
# period
for value, action in zip(values, actions):
if action == ’B’:
assert not bitcoin, message
bitcoin = True
profit -= value
elif action == ’S’:
assert bitcoin, message
bitcoin = False
profit += value
else:
assert action == ’-’, message
return profit
def optimisation(values):
"""
>>> optimisation([5, 11, 4, 2, 8, 10, 7, 4, 3, 6])
(17, ’BS-B-S--BV’)
>>> optimisation ((4, 2, 5, 11, 10, 4, 11, 7, 4, 11, 3, 11))
(31, ’-B-S-BS-BSBV’)
>>> optimisation([10, 9, 9, 10, 10, 9, 1, 4, 9, 3, 5, 6, 10])
(16, ’--B-S-B-SB--V’)
>>> optimisation((12, 4, 9, 5, 6, 7, 9, 9, 11, 7, 10))
(14, ’-BSB----SBV’)
>>> optimisation([10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
(0, ’----------’)
>>> optimisation((10, 4, 2, 4, 8, 12))
(10, ’--B--V’)
27
"""
maximal_profit = 0
optimal_actions = ’’
bitcoin = False
for index, value in enumerate(values[:-1]):
if bitcoin:
# only sell bitcoin if it becomes cheaper the next day
if value > values[index + 1]:
bitcoin = False
maximal_profit += value
optimal_actions += ’S’
else:
optimal_actions += ’-’
else:
# only buy bitcoin if it becomes more expensive the next day
if value < values[index + 1]:
bitcoin = True
maximal_profit -= value
optimal_actions += ’B’
else:
optimal_actions += ’-’
def maximal_profit(values):
"""
>>> maximal_profit([5, 11, 4, 2, 8, 10, 7, 4, 3, 6])
17
>>> maximal_profit((4, 2, 5, 11, 10, 4, 11, 7, 4, 11, 3, 11))
31
>>> maximal_profit([10, 9, 9, 10, 10, 9, 1, 4, 9, 3, 5, 6, 10])
16
>>> maximal_profit((12, 4, 9, 5, 6, 7, 9, 9, 11, 7, 10))
14
>>> maximal_profit([10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
0
>>> maximal_profit((10, 4, 2, 4, 8, 12))
10
"""
return optimisation(values)[0]
def optimal_actions(values):
"""
>>> optimal_actions([5, 11, 4, 2, 8, 10, 7, 4, 3, 6])
’BS-B-S--BV’
>>> optimal_actions((4, 2, 5, 11, 10, 4, 11, 7, 4, 11, 3, 11))
’-B-S-BS-BSBV’
>>> optimal_actions([10, 9, 9, 10, 10, 9, 1, 4, 9, 3, 5, 6, 10])
’--B-S-B-SB--V’
>>> optimal_actions((12, 4, 9, 5, 6, 7, 9, 9, 11, 7, 10))
’-BSB----SBV’
28
>>> optimal_actions([10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
’----------’
>>> optimal_actions((10, 4, 2, 4, 8, 12))
’--B--V’
"""
return optimisation(values)[1]
if __name__ == ’__main__’:
import doctest
doctest.testmod()
29
7 Series 07: more about functions and modules
7.1 ISBN
def isISBN10(code):
"""
Checks whether the given ISBN-10 code is valid.
>>> isISBN10(’9971502100’)
True
>>> isISBN10(’9971502108’)
False
"""
def isISBN13(code):
"""
Checks whether the given ISBN-13 code is valid.
>>> isISBN13(’9789743159664’)
True
>>> isISBN13(’9787954527409’)
False
>>> isISBN13(’8799743159665’)
False
"""
30
# check whether first nine characters of given code are digits
if not code[:12].isdigit():
return False
"""
>>> isISBN(’9789027439642’, False)
False
>>> isISBN(’9789027439642’, True)
True
>>> isISBN(’9789027439642’)
True
>>> isISBN(’080442957X’)
False
>>> isISBN(’080442957X’, False)
True
"""
"""
>>> codes = [’0012345678’, ’0012345679’, ’9971502100’, ’080442957X’, 5, True, ’The
Practice of Computing Using Python’, ’9789027439642’, ’5486948320146’]
>>> areISBN(codes)
[False, True, True, True, False, False, False, True, False]
>>> areISBN(codes, True)
[False, False, False, False, False, False, False, True, False]
>>> areISBN(codes, False)
[False, True, True, True, False, False, False, False, False]
"""
if isinstance(code, str):
if isbn13 is None:
checks.append(isISBN(code, len(code) == 13))
else:
checks.append(isISBN(code, isbn13))
else:
checks.append(False)
if __name__ == ’__main__’:
import doctest
doctest.testmod()
def floors(apartments):
"""
31
>>> apartments = (1, 4, 3, 2, 3, 1)
>>> floors(apartments)
[[False, True, False, False, False, False], [False, True, True, False, True, False], [
False, True, True, True, True, False], [True, True, True, True, True, True]]
"""
return floors
"""
>>> apartments = (1, 4, 3, 2, 3, 1)
>>> print(front_view(apartments, air=’~’))
~~~~###~~~~~~~~~~~~~~~~
~~~~###~###~~~~~###~~~~
~~~~###~###~###~###~~~~
###~###~###~###~###~###
>>> print(front_view([1, 4, 3, 2, 3, 1], width=4, distance=0, apartment=’<’, air="-"))
----<<<<----------------
----<<<<<<<<----<<<<----
----<<<<<<<<<<<<<<<<----
<<<<<<<<<<<<<<<<<<<<<<<<
"""
return ’\n’.join(
(distance * air).join(
width * (apartment if color else air)
for color in floor
)
for floor in floors(apartments)
)
def brush_strokes(apartments):
"""
>>> brush_strokes([1, 4, 3, 2, 3, 1])
5
"""
brush_strokes = 0
for floor in floors(apartments):
brush_stroke = False
for apartment in floor:
if apartment and not brush_stroke:
brush_strokes += 1
brush_stroke = apartment
return brush_strokes
if __name__ == ’__main__’:
import doctest
doctest.testmod()
7.3 Timeless
"""
>>> first_difference(2018, 2019)
datetime.date(2019, 1, 1)
>>> first_difference(2018, 2024)
32
datetime.date(2024, 2, 29)
>>> first_difference(2018, 2029)
"""
while (
date1.day == date2.day and
date1.month == date2.month and
date1.year == year1 and
date1.weekday() == date2.weekday()
):
date1 += timedelta(1)
date2 += timedelta(1)
if date1.year == year1:
return date2
"""
>>> reuse_calendar(2018)
2029
>>> reuse_calendar(2018, True)
2007
>>> reuse_calendar(2019, previous=False)
2030
>>> reuse_calendar(2019, previous=True)
2013
"""
return year2
"""
>>> reuse_calendars(2018, 10)
[2029, 2035, 2046, 2057, 2063, 2074, 2085, 2091, 2103, 2114]
>>> reuse_calendars(2018, 10, True)
[2007, 2001, 1990, 1979, 1973, 1962, 1951, 1945, 1934, 1923]
>>> reuse_calendars(2019, 10, previous=False)
[2030, 2041, 2047, 2058, 2069, 2075, 2086, 2097, 2109, 2115]
>>> reuse_calendars(2019, 10, previous=True)
[2013, 2002, 1991, 1985, 1974, 1963, 1957, 1946, 1935, 1929]
"""
if __name__ == ’__main__’:
import doctest
doctest.testmod()
import random
33
def taboo_length(words, minimum=None, maximum=None):
"""
>>> words = [’forest’, ’meadow’, ’scenery’, ’hills’]
>>> taboo_length(words)
3
>>> taboo_length(words, minimum=2)
4
>>> taboo_length(words, maximum=3)
1
>>> taboo_length(words, minimum=2, maximum=3)
3
>>> taboo_length(words, minimum=-2, maximum=6)
1
"""
"""
>>> words = [’forest’, ’meadow’, ’scenery’, ’hills’]
>>> taboo_words(words)
[’forest’, ’hills’, ’meadow’, ’scenery’]
>>> taboo_words(words, minimum=2)
[’forest’, ’meadow’, ’scenery’]
>>> taboo_words(words, maximum=3)
[’forest’, ’hills’, ’meadow’]
>>> taboo_words(words, minimum=2, maximum=3)
[’hills’, ’meadow’, ’scenery’]
>>> taboo_words(words, minimum=-2, maximum=6)
[’forest’, ’hills’, ’meadow’, ’scenery’]
"""
if __name__ == ’__main__’:
import doctest
doctest.testmod()
"""
>>> from datetime import date
>>> birthday(date(1969, 10, 5), date(2015, 10, 5))
True
34
>>> birthday(date(1969, 10, 5), date(1989, 10, 4))
False
"""
# determine if the month and the day of the month are the same
return (
date.day == birth.day and
date.month == birth.month
)
"""
>>> from datetime import date
>>> sameweekday(date(1969, 10, 5), date(2002, 5, 5))
True
>>> sameweekday(date(1969, 10, 5), date(1989, 10, 4))
False
"""
# determine if the day of the month and the weekday are the same
return (
date.day == birth.day and
date.weekday() == birth.weekday()
)
"""
>>> from datetime import date
>>> hundredday(date(1969, 10, 5), date(1975, 10, 14))
True
>>> hundredday(date(1969, 10, 5), date(1989, 10, 4))
False
"""
"""
>>> from datetime import date
>>> unbirthday(date(1969, 10, 5), date(2015, 10, 5))
False
>>> unbirthday(date(1969, 10, 5), date(1989, 10, 4))
True
"""
"""
alternative solution:
def birthdays(
birth,
birthday=birthday,
start=None,
end=None
):
35
"""
>>> from datetime import date
>>> birthdays(date(1969, 10, 5), end=date(1972, 1, 1))
(datetime.date(1969, 10, 5), datetime.date(1970, 10, 5), datetime.date(1971, 10, 5))
>>> birthdays(date(1969, 10, 5), birthday=sameweekday, start=date(2014, 1, 1))
(datetime.date(2014, 1, 5), datetime.date(2014, 10, 5), datetime.date(2015, 4, 5),
datetime.date(2015, 7, 5))
>>> birthdays(date(1969, 10, 5), start=date(1975, 1, 1), end=date(1976, 1, 1), birthday=
hundredday)
(datetime.date(1975, 3, 28), datetime.date(1975, 7, 6), datetime.date(1975, 10, 14))
"""
# traverse all days between the start date and the end date
days = []
date = start
while date <= end:
if __name__ == ’__main__’:
import doctest
doctest.testmod()
"""
>>> flip((9, 2, 7, 5, 8, 1, 4, 6, 3))
(3, 6, 4, 1, 8, 5, 7, 2, 9)
>>> flip((-9, -2, -7, 5, 8, -1, -4, -6, 3), burnt=True)
(-3, 6, 4, 1, -8, -5, 7, 2, 9)
"""
"""
>>> flip_top((1, 4, 6, 3, 5, 2, 7, 8, 9), 3)
(6, 4, 1, 3, 5, 2, 7, 8, 9)
36
>>> flip_top((6, 4, 1, 3, 5, 2, 7, 8, 9), 6)
(2, 5, 3, 1, 4, 6, 7, 8, 9)
>>> flip_top((-1, -4, -6, 3, -5, -2, 7, 8, 9), 3, burnt=True)
(6, 4, 1, 3, -5, -2, 7, 8, 9)
>>> flip_top((6, 4, 1, 3, -5, -2, 7, 8, 9), 1, burnt=True)
(-6, 4, 1, 3, -5, -2, 7, 8, 9)
>>> flip_top((-6, 4, 1, 3, -5, -2, 7, 8, 9), 6, burnt=True)
(2, 5, -3, -1, -4, 6, 7, 8, 9)
"""
"""
>>> find_largest((1, 4, 6, 3, 5, 2, 7, 8, 9), 6)
3
>>> find_largest((-1, -4, -6, 3, -5, -2, 7, 8, 9), 6)
3
"""
"""
>>> sorting_step((1, 4, 6, 3, 5, 2, 7, 8, 9), 6)
(2, 5, 3, 1, 4, 6, 7, 8, 9)
>>> sorting_step((-1, -4, -6, 3, -5, -2, 7, 8, 9), 6, burnt=True)
(2, 5, -3, -1, -4, 6, 7, 8, 9)
"""
"""
>>> sorting_steps((1, 8, 5, 7, 2, 9, 4, 6, 3))
[(1, 8, 5, 7, 2, 9, 4, 6, 3), (3, 6, 4, 1, 8, 5, 7, 2, 9), (2, 7, 5, 3, 6, 4, 1, 8, 9),
(1, 4, 6, 3, 5, 2, 7, 8, 9), (2, 5, 3, 1, 4, 6, 7, 8, 9), (4, 1, 3, 2, 5, 6, 7, 8, 9),
(2, 3, 1, 4, 5, 6, 7, 8, 9), (1, 2, 3, 4, 5, 6, 7, 8, 9)]
>>> sorting_steps((1, -8, -5, 7, 2, 9, -4, -6, 3), burnt=True)
[(1, -8, -5, 7, 2, 9, -4, -6, 3), (-3, 6, 4, 1, -8, -5, 7, 2, 9), (-2, -7, 5, -3, 6, 4, 1,
8, 9), (-1, -4, -6, 3, -5, -2, 7, 8, 9), (2, 5, -3, -1, -4, 6, 7, 8, 9), (4, 1, 3, 2,
5, 6, 7, 8, 9), (-2, -3, -1, 4, 5, 6, 7, 8, 9), (1, -2, 3, 4, 5, 6, 7, 8, 9), (1, 2,
3, 4, 5, 6, 7, 8, 9)]
>>> sorting_steps((-1, -2, -3, -4, -5), burnt=True)
[(-1, -2, -3, -4, -5), (-1, -2, -3, -4, 5), (-1, -2, -3, 4, 5), (-1, -2, 3, 4, 5), (-1, 2,
3, 4, 5), (1, 2, 3, 4, 5)]
"""
steps = [stack]
for count in range(len(stack), 0, -1):
stack = sorting_step(stack, count, burnt)
if stack != steps[-1]:
steps.append(stack)
return steps
if __name__ == ’__main__’:
import doctest
doctest.testmod()
37
8 Series 08: sets and dictionaries
8.1 ISBN
def isISBN13(code):
"""
Checks whether the given ISBN-13 code is valid.
>>> isISBN13(’9789743159664’)
True
>>> isISBN13(’9787954527409’)
False
>>> isISBN13(’8799743159665’)
False
"""
def check_digit(code):
"""
Helper function that computes the ISBN-13 check digit.
"""
def overview(codes):
"""
>>> codes = [
... ’9789743159664’, ’9785301556616’, ’9797668174969’, ’9781787559554’,
... ’9780817481461’, ’9785130738708’, ’9798810365062’, ’9795345206033’,
... ’9792361848797’, ’9785197570819’, ’9786922535370’, ’9791978044523’,
... ’9796357284378’, ’9792982208529’, ’9793509549576’, ’9787954527409’,
... ’9797566046955’, ’9785239955499’, ’9787769276051’, ’9789910855708’,
... ’9783807934891’, ’9788337967876’, ’9786509441823’, ’9795400240705’,
... ’9787509152157’, ’9791478081103’, ’9780488170969’, ’9795755809220’,
... ’9793546666847’, ’9792322242176’, ’9782582638543’, ’9795919445653’,
... ’9796783939729’, ’9782384928398’, ’9787590220100’, ’9797422143460’,
... ’9798853923096’, ’9784177414990’, ’9799562126426’, ’9794732912038’,
... ’9787184435972’, ’9794455619207’, ’9794270312172’, ’9783811648340’,
... ’9799376073039’, ’9798552650309’, ’9798485624965’, ’9780734764010’,
... ’9783635963865’, ’9783246924279’, ’9797449285853’, ’9781631746260’,
... ’9791853742292’, ’9781796458336’, ’9791260591924’, ’9789367398012’
... ]
>>> overview(codes)
38
English speaking countries: 8
French speaking countries: 4
German speaking countries: 6
Japan: 3
Russian speaking countries: 7
China: 8
Other countries: 11
Errors: 9
"""
# display overview
print(f’English speaking countries: {groups[0] + groups[1]}’)
print(f’French speaking countries: {groups[2]}’)
print(f’German speaking countries: {groups[3]}’)
print(f’Japan: {groups[4]}’)
print(f’Russian speaking countries: {groups[5]}’)
print(f’China: {groups[7]}’)
print(f’Other countries: {groups[6] + groups[8] + groups[9]}’)
print(f’Errors: {groups[10]}’)
if __name__ == ’__main__’:
import doctest
doctest.testmod()
8.2 Autogram
def letter_frequencies(sentence):
"""
>>> frequentie = letter_frequencies("fifteen e’s, seven f’s, four g’s, six h’s, eight i’s,
four n’s, five o’s, six r’s, eighteen s’s, eight t’s, four u’s, three v’s, two w’s,
three x’s")
>>> frequentie[’e’]
15
>>> frequentie[’f’]
7
>>> frequentie[’g’]
4
>>> frequentie = letter_frequencies("sixteen e’s, five f’s, three g’s, six h’s, nine i’s,
five n’s, four o’s, six r’s, eighteen s’s, eight t’s, three u’s, three v’s, two w’s,
four x’s")
>>> frequentie[’e’]
16
>>> frequentie[’f’]
5
>>> frequentie[’g’]
3
"""
"""
# alternative solution:
39
freq = {}
for character in sentence.lower():
if character.isalpha():
freq[character] = freq.get(character, 0) + 1
return freq
"""
def letter_positions(sentence):
"""
>>> positions = letter_positions("fifteen e’s, seven f’s, four g’s, six h’s, eight i’s,
four n’s, five o’s, six r’s, eighteen s’s, eight t’s, four u’s, three v’s, two w’s,
three x’s")
>>> positions[’e’]
{97, 67, 4, 5, 8, 43, 141, 14, 142, 16, 83, 88, 89, 121, 122}
>>> positions[’f’]
{0, 64, 2, 108, 19, 54, 24}
>>> positions[’g’]
{99, 29, 45, 85}
>>> positions = letter_positions("sixteen e’s, five f’s, three g’s, six h’s, nine i’s,
five n’s, four o’s, six r’s, eighteen s’s, eight t’s, three u’s, three v’s, two w’s,
four x’s")
>>> positions[’e’]
{96, 4, 5, 8, 46, 110, 16, 111, 82, 87, 56, 88, 26, 27, 121, 122}
>>> positions[’f’]
{18, 138, 13, 53, 63}
>>> positions[’g’]
{98, 84, 29}
"""
# iterate over all characters in the given sentence and add the position of
# each letter to the dictionary
positions = {}
for index, character in enumerate(sentence.lower()):
if character.isalpha():
if character not in positions:
positions[character] = {index}
else:
positions[character].add(index)
# return a dictionary that maps each letter in the sentence onto the set of
# all positions where that letter occurs in the sentence
return positions
if __name__ == ’__main__’:
import doctest
doctest.testmod()
8.3 Code 39
"""
>>> key = {
... ’U’: ’SbSbSbSsS’, ’Z’: ’SsBsSbBsS’, ’P’: ’BbSsSsBsS’, ’R’: ’SsSbBsBsS’,
... ’H’: ’SsBbBsSsS’, ’W’: ’SbBsSsBsS’, ’D’: ’SbBsSsSsB’, ’K’: ’BsSsSsBbS’,
... ’-’: ’SsSbBsSsB’, ’M’: ’SbSsSbSbS’, ’O’: ’SsSbSsBsB’, ’7’: ’SsSbSbSbS’,
... ’+’: ’BsSsBbSsS’, ’1’: ’SsSsBbBsS’, ’ ’: ’SsBsBbSsS’, ’.’: ’SsBbSsBsS’,
... ’/’: ’SsSsBsBbS’, ’V’: ’SbSsBsBsS’, ’X’: ’SbSbSsSbS’, ’C’: ’SbSsBsSsB’,
... ’Y’: ’BsSsSbBsS’, ’G’: ’BsBsSsSbS’, ’4’: ’SsBbSsSsB’, ’Q’: ’SsBsSbSsB’,
... ’J’: ’SsSsSsBbB’, ’F’: ’BsSsSbSsB’, ’A’: ’SsBsSsSbB’, ’6’: ’BsSsSsSbB’,
... ’2’: ’BsBsSbSsS’, ’$’: ’SsSsSbBsB’, ’0’: ’BsSbBsSsS’, ’N’: ’SsBsBsSbS’,
... ’I’: ’BsSbSsSsB’, ’9’: ’BbSsBsSsS’, ’L’: ’BsSbSsBsS’, ’,’: ’SsSsBsSbB’,
... ’5’: ’BsSsBsSbS’, ’B’: ’BbBsSsSsS’, ’%’: ’SsBsSsBbS’, ’S’: ’BsBbSsSsS’,
... ’3’: ’SbBsBsSsS’, ’T’: ’BbSsSsSsB’, ’*’: ’SsSsBbSsB’, ’E’: ’SbSsSsBsB’
... }
>>> reverse(key)
40
{’SbSbSbSsS’: ’U’, ’SsBsSbBsS’: ’Z’, ’BbSsSsBsS’: ’P’, ’SsSbBsBsS’: ’R’, ’SsBbBsSsS’: ’H’, ’
SbBsSsBsS’: ’W’, ’SbBsSsSsB’: ’D’, ’BsSsSsBbS’: ’K’, ’SsSbBsSsB’: ’-’, ’SbSsSbSbS’: ’M’, ’
SsSbSsBsB’: ’O’, ’SsSbSbSbS’: ’7’, ’BsSsBbSsS’: ’+’, ’SsSsBbBsS’: ’1’, ’SsBsBbSsS’: ’ ’, ’
SsBbSsBsS’: ’.’, ’SsSsBsBbS’: ’/’, ’SbSsBsBsS’: ’V’, ’SbSbSsSbS’: ’X’, ’SbSsBsSsB’: ’C’, ’
BsSsSbBsS’: ’Y’, ’BsBsSsSbS’: ’G’, ’SsBbSsSsB’: ’4’, ’SsBsSbSsB’: ’Q’, ’SsSsSsBbB’: ’J’, ’
BsSsSbSsB’: ’F’, ’SsBsSsSbB’: ’A’, ’BsSsSsSbB’: ’6’, ’BsBsSbSsS’: ’2’, ’SsSsSbBsB’: ’$’, ’
BsSbBsSsS’: ’0’, ’SsBsBsSbS’: ’N’, ’BsSbSsSsB’: ’I’, ’BbSsBsSsS’: ’9’, ’BsSbSsBsS’: ’L’, ’
SsSsBsSbB’: ’,’, ’BsSsBsSbS’: ’5’, ’BbBsSsSsS’: ’B’, ’SsBsSsBbS’: ’%’, ’BsBbSsSsS’: ’S’, ’
SbBsBsSsS’: ’3’, ’BbSsSsSsB’: ’T’, ’SsSsBbSsB’: ’*’, ’SbSsSsBsB’: ’E’}
>>> encoded = code39(’Sulfur, so good.’, key)
>>> encoded
’
BsBbSsSsSsSbSbSbSsSsBsSbSsBsSsBsSsSbSsBsSbSbSbSsSsSsSbBsBsSsSsSsBsSbBsSsBsBbSsSsBsBbSsSsSsSsSbSsBsBsSsB
’
>>> decode39(encoded, key)
’SULFUR, SO GOOD.’
"""
def reverse(encoding):
return {
code: character
for character, code in encoding.items()
}
decoding = reverse(encoding)
return ’’.join(
decoding[code[index:index + 9]]
for index in range(0, len(code), 10)
)
if __name__ == ’__main__’:
import doctest
doctest.testmod()
def numbers(square):
"""
>>> numbers([[2, 7, 6], [9, 5, 1], [4, 3, 8]])
{1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> numbers([[2, 1, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
>>> numbers([[2, 15, 5, 13], [16, 3, 7, 12], [9, 8, 14, 1], [6, 4, 11, 10]])
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
"""
# iterate over the rows of the square and add all numbers on each row to the
# set of all number in the square
numbers = set()
for row in square:
numbers.update(row)
def sums(square):
"""
>>> sums([[2, 7, 6], [9, 5, 1], [4, 3, 8]])
41
{15}
>>> sums([[2, 1, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
{34, 35, 36, 58, 40, 10, 42, 26, 29, 31}
>>> sums([[2, 15, 5, 13], [16, 3, 7, 12], [9, 8, 14, 1], [6, 4, 11, 10]])
{32, 33, 34, 35, 36, 37, 38, 29, 30, 31}
"""
# i-th row
sums.add(sum(square[i]))
# i-th column
sums.add(sum(square[j][i] for j in range(n)))
def ismagic(square):
"""
>>> ismagic([[2, 7, 6], [9, 5, 1], [4, 3, 8]])
True
>>> ismagic([[2, 1, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
False
>>> ismagic([[2, 15, 5, 13], [16, 3, 7, 12], [9, 8, 14, 1], [6, 4, 11, 10]])
False
"""
def ishetero(square):
"""
>>> ishetero([[2, 7, 6], [9, 5, 1], [4, 3, 8]])
False
>>> ishetero([[2, 1, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
True
>>> ishetero([[2, 15, 5, 13], [16, 3, 7, 12], [9, 8, 14, 1], [6, 4, 11, 10]])
True
"""
def isantimagic(square):
"""
>>> isantimagic([[2, 7, 6], [9, 5, 1], [4, 3, 8]])
42
False
>>> isantimagic([[2, 1, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
False
>>> isantimagic([[2, 15, 5, 13], [16, 3, 7, 12], [9, 8, 14, 1], [6, 4, 11, 10]])
True
"""
if __name__ == ’__main__’:
import doctest
doctest.testmod()
def letter_value(letters):
"""
>>> letter_value(’OYCDHBNKEgtvuialwr’)
{’O’: -9, ’Y’: -8, ’C’: -7, ’D’: -6, ’H’: -5, ’B’: -4, ’N’: -3, ’K’: -2, ’E’: -1, ’G’: 1,
’T’: 2, ’V’: 3, ’U’: 4, ’I’: 5, ’A’: 6, ’L’: 7, ’W’: 8, ’R’: 9}
>>> letter_value(list(’oycdhbnkeGTVUIALWR’))
{’O’: -9, ’Y’: -8, ’C’: -7, ’D’: -6, ’H’: -5, ’B’: -4, ’N’: -3, ’K’: -2, ’E’: -1, ’G’: 1,
’T’: 2, ’V’: 3, ’U’: 4, ’I’: 5, ’A’: 6, ’L’: 7, ’W’: 8, ’R’: 9}
>>> letter_value(tuple(’oycdhbnkeGTVUIALWR’))
{’O’: -9, ’Y’: -8, ’C’: -7, ’D’: -6, ’H’: -5, ’B’: -4, ’N’: -3, ’K’: -2, ’E’: -1, ’G’: 1,
’T’: 2, ’V’: 3, ’U’: 4, ’I’: 5, ’A’: 6, ’L’: 7, ’W’: 8, ’R’: 9}
>>> letter_value(’abc’)
Traceback (most recent call last):
AssertionError: invalid letters
>>> letter_value(’abba’)
Traceback (most recent call last):
AssertionError: invalid letters
"""
# return dictionary that maps uppercase letters onto their letter value
43
return {
letter: (
index - len(letters) // 2
if index < len(letters) // 2
else index - len(letters) // 2 + 1
)
for index, letter in enumerate(letters)
}
"""
>>> word_value(’black’, ’OYCDHBNKEGTVUIALWR’)
0
>>> word_value(’BROWN’, ’oycdhbnkeGTVUIALWR’)
1
>>> word_value(’red’, ’OYCDHBNKEgtvuialwr’)
2
>>> word_value(’ORANGE’, ’oycdhbnkegtvuialwr’)
3
>>> word_value(’yellow’, ’OYCDHBNKEGTVUIALWR’)
4
>>> word_value(’GREEN’, ’oycdhbnkeGTVUIALWR’)
5
>>> word_value(’blue’, ’OYCDHBNKEgtvuialwr’)
6
>>> word_value(’VIOLET’, ’oycdhbnkegtvuialwr’)
7
>>> word_value(’GRAY’, ’OYCDHBNKEGTVUIALWR’)
8
>>> word_value(’white’, ’oycdhbnkeGTVUIALWR’)
9
>>> word_value(’SILVER’, ’OYCDHBNKEGTVUIALWR’)
Traceback (most recent call last):
AssertionError: invalid word
"""
# construct dictionary that maps uppercase letters onto their letter value
waarde = letter_value(letters)
"""
>>> rainbow([’BLACK’, ’brown’, ’RED’, ’orange’, ’YELLOW’, ’green’, ’BLUE’, ’violet’, ’GRAY
’, ’White’], ’OYCDHBNKEgtvuialwr’)
True
>>> rainbow([’BLACK’, ’YELLOW’, ’violet’, ’green’, ’White’, ’orange’, ’GRAY’, ’BLUE’, ’RED
’, ’brown’], ’OYCDHBNKEgtvuialwr’)
False
>>> rainbow((’BLACK’, ’brown’, ’RED’, ’orange’, ’YELLOW’, ’green’, ’BLUE’, ’violet’, ’GRAY
’, ’White’), ’bwdiucankYOGTHELRV’)
False
"""
44
# NOTE: this function is not part of the exam
def reflect(colors, letters):
"""
>>> colors = [’BLACK’, ’YELLOW’, ’violet’, ’green’, ’White’, ’orange’, ’GRAY’, ’BLUE’, ’
RED’, ’brown’]
>>> reflect(colors, ’OYCDHBNKEgtvuialwr’)
>>> colors
[’BLACK’, ’brown’, ’RED’, ’orange’, ’YELLOW’, ’green’, ’BLUE’, ’violet’, ’GRAY’, ’White’]
>>> colors = [’BLACK’, ’YELLOW’, ’violet’, ’green’, ’White’, ’orange’, ’GRAY’, ’BLUE’, ’
RED’, ’brown’]
>>> reflect(colors, ’bwdiucankYOGTHELRV’)
>>> colors
[’BLACK’, ’brown’, ’BLUE’, ’White’, ’RED’, ’GRAY’, ’orange’, ’YELLOW’, ’green’, ’violet’]
"""
"""
>>> colors = [’BLACK’, ’YELLOW’, ’violet’, ’green’, ’White’, ’orange’, ’GRAY’, ’BLUE’, ’
RED’, ’brown’]
>>> reflected(colors, ’OYCDHBNKEgtvuialwr’)
(’BLACK’, ’brown’, ’RED’, ’orange’, ’YELLOW’, ’green’, ’BLUE’, ’violet’, ’GRAY’, ’White’)
>>> colors
[’BLACK’, ’YELLOW’, ’violet’, ’green’, ’White’, ’orange’, ’GRAY’, ’BLUE’, ’RED’, ’brown’]
>>> colors = (’BLACK’, ’YELLOW’, ’violet’, ’green’, ’White’, ’orange’, ’GRAY’, ’BLUE’, ’
RED’, ’brown’)
>>> reflected(colors, ’bwdiucankYOGTHELRV’)
(’BLACK’, ’brown’, ’BLUE’, ’White’, ’RED’, ’GRAY’, ’orange’, ’YELLOW’, ’green’, ’violet’)
"""
# return tuple containing given colors that are sorted in increasing order
# according to their word value; words having the same word value are sorted
# in alphabetic order
colors = list(colors)
reflect(colors, letters)
return tuple(colors)
"""
# alternatieve oplossing
return tuple(
sorted(
colors,
key=lambda color: (word_value(color, letters), color.upper())
)
)
"""
if __name__ == ’__main__’:
import doctest
doctest.testmod()
8.6 Fuse
"""
>>> grid = list_representation(’1221133113322222’, 4)
>>> grid
[[1, 2, 2, 1], [1, 3, 3, 1], [1, 3, 3, 2], [2, 2, 2, 2]]
"""
45
# square grid by default
if cols is None:
cols = rows
def string_representation(grid):
"""
>>> grid = [[1, 2, 2, 1], [1, 3, 3, 1], [1, 3, 3, 2], [2, 2, 2, 2]]
>>> string_representation(grid)
(’1221133113322222’, 4, 4)
"""
"""
>>> grid = [[1, 2, 2, 1], [1, 3, 3, 1], [1, 3, 3, 2], [2, 2, 2, 2]]
>>> move(-1, {(1, 2), (1, 1), (2, 1), (2, 2)}, grid)
[[1, 2, 2, 1], [1, 2, 2, 1], [1, 2, 2, 2], [2, 2, 2, 2]]
>>> move(+1, {(0, 3), (1, 3)}, grid)
[[1, 2, 2, 2], [1, 2, 2, 2], [1, 2, 2, 2], [2, 2, 2, 2]]
>>> move(+1, {(2, 0), (1, 0), (0, 0)}, grid)
[[2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2]]
"""
return grid
def is_solved(grid):
"""
>>> grid = [[2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2]]
>>> is_solved(grid)
True
"""
numbers = set()
for row in grid:
numbers.update(row)
return len(numbers) == 1
"""
>>> grid = [[1, 2, 2, 1], [1, 3, 3, 1], [1, 3, 3, 2], [2, 2, 2, 2]]
>>> group((2, 1), grid)
{(1, 2), (1, 1), (2, 1), (2, 2)}
>>> group((0, 3), grid)
{(0, 3), (1, 3)}
>>> group((1, 0), grid)
{(2, 0), (1, 0), (0, 0)}
"""
46
group, todo = set(), {position}
rows, cols = len(grid), len(grid[0])
number = grid[position[0]][position[1]]
while todo:
r, k = todo.pop()
group.add((r, k))
for dr, dk in ((0, 1), (0, -1), (1, 0), (-1, 0)):
if (
0 <= r + dr < rows and
0 <= k + dk < cols and
(r + dr, k + dk) not in group and
grid[r + dr][k + dk] == number
):
todo.add((r + dr, k + dk))
return group
"""
>>> grid = [[1, 2, 2, 1], [1, 3, 3, 1], [1, 3, 3, 2], [2, 2, 2, 2]]
>>> is_solution([(1, 1, False), (3, 2, False)], grid)
True
>>> grid
[[1, 2, 2, 1], [1, 3, 3, 1], [1, 3, 3, 2], [2, 2, 2, 2]]
>>> is_solution([(1, 3, True), (3, 2, False), (0, 1, True)], grid)
False
>>> grid
[[1, 2, 2, 1], [1, 3, 3, 1], [1, 3, 3, 2], [2, 2, 2, 2]]
"""
# perform moves
for (row, col, increment) in moves:
move(
+1 if increment else -1,
group((row, col), grid),
grid
)
return is_solved(grid)
if __name__ == ’__main__’:
import doctest
doctest.testmod()
47