Original story Original story: [I tried to simulate the probability of a bingo game with Python] (http://qiita.com/elzup/items/d532ffa1d326fbf75d01) Original story: [I tried to fix "I tried to simulate the probability of a bingo game with Python"] (http://qiita.com/t2y/items/8584b77b3fe02dd2ce63)
I still don't know how to write a doc block, so I'll study
One of the features of Python is doctest. If you combine the document of how to use the function with a simple test, it may be two birds with one stone.
If you modify the logic of the original code so as not to mess with it, the doctest of the modified code is not good, but if you try to develop while writing the doctest, the perspective of the position to use will expand and it will be easy to use naturally. You can implement functions and modules.
While writing doctest, if you develop it interactively, it will be easy to debug, it will be an easy-to-use API, and I wanted to say that it can be used as a document as it is, but I could not write appropriate sample code, so revenge.
I tried to make it easier to understand the purpose of doctest.
__repr__
, you don't need debug output function ( __repr__
* seems to be used in print function etc. when * __str__
* is not defined)As an aside, I've been wondering if I could write the card number generation process more clearly from yesterday, and I was a little happy when I used * reduce *.
def _generate(self):
def sampling(k=5):
for i in range(k):
yield sample(range(15 * i + 1, 15 * (i + 1) + 1), k)
return reduce(add, sampling())
I would be happy if I could convey this kind of atmosphere.
# -*- coding: utf-8 -*-
from functools import reduce
from operator import add
from random import sample
class Card:
""" 75-ball Bingo Card
The middle square is designated a "FREE" space.
The columns are labeled as follows.
"B": (numbers 1–15)
"I": (numbers 16–30)
"N": (numbers 31–45)
"G": (numbers 46–60)
"O": (numbers 61–75)
http://en.wikipedia.org/wiki/Bingo_card
>>> data = [ # for testing use
... 1, 2, 3, 4, 5,
... 6, 7, 8, 9, 10,
... 11, 12, 13, 14, 15,
... 16, 17, 18, 19, 20,
... 21, 22, 23, 24, 25,
... ]
>>> card = Card(data)
>>> len(card.numbers)
25
>>> card.numbers[12]
True
>>> card.is_bingo
False
>>> print(card)
1 2 3 4 5
6 7 8 9 10
11 12 o 14 15
16 17 18 19 20
21 22 23 24 25
Show 'o' when giving number is found
>>> card.set_number(14)
>>> print(card)
1 2 3 4 5
6 7 8 9 10
11 12 o o 15
16 17 18 19 20
21 22 23 24 25
Check bingo giving number to the card.
>>> card.set_number(35) # have no effect if number not in card.numbers
>>> card.set_number(1)
>>> card.set_number(7)
>>> card.set_number(19)
>>> card.is_bingo
False
>>> card.set_number(25)
>>> card.is_bingo
True
>>> print(card)
o 2 3 4 5
6 o 8 9 10
11 12 o o 15
16 17 18 o 20
21 22 23 24 o
"""
def __init__(self, numbers=None):
self.numbers = self._generate() if numbers is None else numbers
self.numbers[12] = True
self.is_bingo = False
def __repr__(self):
ascii_card = ''
for i in range(int(len(self.numbers) / 5)):
for num in self.numbers[5 * i:5 * (i + 1)]:
if num is True:
num = 'o'
elif num is False:
num = 'x'
ascii_card += '{0:>3s}'.format(str(num))
ascii_card += '\n'
return ascii_card[:-1]
def _generate(self):
def sampling(k=5):
for i in range(k):
yield sample(range(15 * i + 1, 15 * (i + 1) + 1), k)
return reduce(add, sampling())
def set_number(self, number):
if number not in self.numbers:
return
self.numbers[self.numbers.index(number)] = True
if not self.is_bingo:
self.check_bingo()
def check_bingo(self):
def check(start, stop, step=1):
return all(map(lambda x: x is True, self.numbers[start:stop:step]))
if self.numbers.count(True) < 5:
return
for i in range(5):
if check(i * 5, (i + 1) * 5): # horizontal
self.is_bingo = True
return
for i in range(5):
if check(i, i + 21, 5): # vertical
self.is_bingo = True
return
if check(0, 25, 6) or check(4, 21, 4): # skew
self.is_bingo = True
return
Run doctest like this.
$ python -m doctest Bingo_kai2.py #If no error is displayed, the test is correct
$ python -m doctest Bingo_kai2.py -v #Redundant mode
Recommended Posts