1. doctest
do you remember the module doctest
which allows writing tests inside a functions doc comment?
take a look at the code below, isnt this quite magical?
your exercise
the exercise is to write a function called func_test
that gets a function as a parameter and tests it using the tests in the functions docstreing
def func_test(func):
- func_test should use the
func.__doc__
to get the docstring of the function to test - lines with ‘»>’ are what needs to be evaluated (hint: use
eval
for a MUCH simpler solution) - lines afer ‘»>’ that don’t start with ‘»>’ are the expected result
func_test
should return a dictionary with the number of failed tests, and number of tests ran- try to mimic the output of the
doctest
module - there’s a simple code to test your
func_test
below
### useful example of doctest usage
def my_func(x, y, z):
"""
>>> my_func(1, 2, 3)
5
>>> my_func('hello ', 3, 'world')
hello hello hello world
>>> my_func(0, 0, 0)
what happens when things are wrong?
"""
return x * y + z
import doctest
doctest.testmod()
def _print_failure(example, expected, got):
print("**********************************************************************")
print("Failed example:")
print('\t', example)
print('Expected:')
print('\t', expected)
print('Got:')
print('\t', got)
def func_test(func):
doc = func.__doc__
prev_line_eval = None
tests_ran = 0
tests_failed = 0
for line in doc.splitlines():
line = line.strip()
if line.startswith('>>>'):
prev_line_eval = line[3:]
result = str(eval(prev_line_eval))
elif prev_line_eval:
tests_ran += 1
if result != line:
_print_failure(prev_line_eval, line, result)
tests_failed +=1
prev_line_eval = None
print("**********************************************************************")
return {"failed" : tests_failed, "attempted" : tests_ran}
### useful: test your 'func_test' function
result = func_test(my_func)
assert result['failed'] == 1
assert result['attempted'] == 3
2. Game of life
python has been used by a lot of game engines as a way to ‘script’ the engine. in this example, we have written an incredibly simple game called ‘Conway’s game of life’ 1.
fun fact: this game is is Turing complete. which means that anything that could be calculated, can be calculated using this game. In fact, several different programmable computer architectures have been implemented in Conway’s Life, including a pattern that simulates Tetris.
The game consists of an infinite 2d board on which cells live or die.
The rules of the game are simple:
- Any live cell with fewer than two live neighbours dies, as if by underpopulation.
- Any live cell with two or three live neighbours lives on to the next generation.
- Any live cell with more than three live neighbours dies, as if by overpopulation.
- Any dead cell with three live neighbours becomes a live cell, as if by reproduction.
the file game-of-life.py
contains a full implementation of the game. go ahead and run it now
>> python game-of-life.py
Your task
-
add a custom rule engine to the game
to do this you have to edit the file
game-of-life.py
you find in this directory and implement two methods that are currently unimplemented:- implement the
read_custom_rules()
function - implement the
apply_custom_rules()
function
- implement the
-
look at the
apply_default_rules()
function, and implement the default rules of the game as two rule filesrule-1.txt
andrule-2.txt
-
invent new rules or modify the a rules by adding more
rule-xyz.txt
files and without changing thegame-of-life.py
file
HINTS:
- both of the functions you need to implement have a handy
TODO
comment to help you with your task- apart from implementing these functions, no other code needs to be modified
- here’s how rule #1 and rule #3 can be implemented together as a custom rule in a file called
rule-1.txt
if grid[i, j] == ON: if (total_neighbours < 2) or (total_neighbours > 3): result = OFF
- a solution can be found in
game-of-life.solution.py
The bundled game of life code is based on this awesome implementation 2