Skip to content

Instantly share code, notes, and snippets.

@davidselassie
Last active September 23, 2016 22:06
Show Gist options
  • Save davidselassie/5232966587c1b9d9ee4e539ac129a604 to your computer and use it in GitHub Desktop.
Save davidselassie/5232966587c1b9d9ee4e539ac129a604 to your computer and use it in GitHub Desktop.
Encapsulating encoded score
LETTER_OFFSET = ord('a')
ROUND_LENGTH = 25
def _letter_to_index(a):
"""Return the index of a letter.
>>> _letter_to_index('q')
16
>>> _letter_to_index('z')
Traceback (most recent call last):
...
ValueError: can't decode letter 'z'
"""
i = ord(a.lower()) - LETTER_OFFSET
if i < 0 or i >= ROUND_LENGTH:
raise ValueError("can't decode letter {!r}".format(a))
return i
def _index_to_letter(i):
"""Return the letter at an index.
>>> _index_to_letter(16)
'q'
>>> _index_to_letter(25)
Traceback (most recent call last):
...
ValueError: can't encode index 25
"""
if i < 0 or i >= ROUND_LENGTH:
raise ValueError("can't encode index {!r}".format(i))
return chr(i + LETTER_OFFSET)
def _encode_hit_miss_list(l):
"""Encode a list of hits booleans as a packed string.
The packed string will contain a unique letter for each shot missed.
'a' is missing the first shot, 'y' the last shot.
>>> l = [True for _ in range(ROUND_LENGTH)]
>>> l[0] = False
>>> l[16] = False
>>> l[24] = False
>>> _encode_hit_miss_list(l)
'aqy'
>>> _encode_hit_miss_list([])
Traceback (most recent call last):
...
ValueError: can't encode incomplete hit list; len 0 instead of 25
"""
if len(l) != ROUND_LENGTH:
raise ValueError("can't encode incomplete hit list; len {!r} instead "
"of {!r}".format(len(l), ROUND_LENGTH))
letter_list = [
_index_to_letter(i)
for i, hit_miss
in enumerate(l)
if not hit_miss
]
return ''.join(letter_list)
def _decode_hit_miss_list(encoded_miss_str):
"""Decode a packed string into a list of hit booleans.
The packed string will contain a unique letter for each shot missed.
'a' is missing the first shot, 'y' the last shot.
>>> l = _decode_hit_miss_list('aqy')
>>> [i for i, hit_miss in enumerate(l) if not hit_miss]
[0, 16, 24]
"""
hit_list = [True for _ in range(ROUND_LENGTH)]
for letter in encoded_miss_str:
index = _letter_to_index(letter)
hit_list[index] = False
return hit_list
class Round:
"""A single round."""
def __init__(self):
self._encoded_misses = ''
def get_hit_miss_list(self):
"""Get the saved list of shots. False shots are missed.
>>> round = Round()
>>> round._encoded_misses = 'aqy'
>>> l = round.get_hit_miss_list()
>>> [i for i, hit_miss in enumerate(l) if not hit_miss]
[0, 16, 24]
"""
return _decode_hit_miss_list(self._encoded_misses)
def set_hit_miss_list(self, l):
"""Set the saved list of shots. False shots are missed.
>>> round = Round()
>>> l = [True for _ in range(ROUND_LENGTH)]
>>> l[0] = False
>>> l[16] = False
>>> l[24] = False
>>> round.set_hit_miss_list(l)
>>> round._encoded_misses
'aqy'
"""
self._encoded_misses = _encode_hit_miss_list(l)
@davidselassie
Copy link
Author

The functions _encode_hit_miss_list() and _decode_hit_miss_list() encapsulate the way that the misses are actually stored in the DB. You could also imagine writing functions to facilitate searching here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment