bananabread100
BAN USERAnother Python implementation. I've focused on clarity & explicitness (in other words, this won't win code golf). Docstrings, PEP 8 & 257, etc.
#!/usr/bin/env python
import string
from collections import namedtuple
from itertools import izip_longest, tee
VALUES = string.lowercase
NUM_ROWS = 5
# Using a namedtuple for readability & ease of debugging.
Coords = namedtuple("Coordinates", "x y")
def rows(iterable, n, fillvalue=None):
"""Generator function that yields a single row of the matrix."""
args = [iter(iterable)] * n
results = izip_longest(fillvalue=fillvalue, *args)
for row in results:
yield [i for i in row if i]
def positions_dict():
"""Returns a dictionary mapping characters to coordinates."""
lookup = {}
for i, row in enumerate(rows(VALUES, NUM_ROWS)):
for j, elem in enumerate(row):
lookup[elem] = Coords(j, i)
return lookup
def node_cmp(start, next_move):
"""Returns a list of 'instructions' for moving around the graph.
Precedence is given to 'Up' and 'Left' moves since there is a
constraint on the x-axis. 'z' being on a row by itself will create
weirdness with strings like 'zxz' or 'xzx'.
"""
instrs = []
if start.y > next_move.y:
instrs += ["Up"] * (start.y - next_move.y)
if start.x > next_move.x:
instrs += ["Left"] * (start.x - next_move.x)
if start.y < next_move.y:
instrs += ["Down"] * (next_move.y - start.y)
if start.x < next_move.x:
instrs += ["Right"] * (next_move.x - start.x)
return instrs
def pairwise(iterable):
"""Returns a list of coordinate pairs. This enables windowing over
the set of coordinates to consider them two at a time.
Example:
>> pairwise('dogs')
[('d', 'o'), ('o', 'g'), ('g', 's')]
"""
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def main(target):
target = target.lower()
positions = positions_dict()
coords = [positions[i] for i in target]
instrs = []
# If our first letter isn't 'a', we need to inject the coordinates for that
# letter at the head of the list. Otherwise, we need to make sure our first
# instruction is 'OK'.
if target[0] != 'a':
coords.insert(0, positions['a'])
else:
instrs += ['OK']
for pair in pairwise(coords):
instrs += node_cmp(*pair)
instrs.append('OK')
return instrs
if __name__ == "__main__":
import sys
from pprint import pprint
try:
word = sys.argv[1]
except IndexError:
raise IndexError("You need to provide a word to build.")
[pprint(i) for i in main(word)]
I think there's actually a bug in your implementation here. The string ``zyz`` does something weird:
- bananabread100 December 01, 2013DDDDDOURRRROULLLLDO
By my reckoning this works out to "zyu"
Also the string ``azyaz`` turns out strange:
ODDDDDOURRRROUUUUULLLLOUDDDDDO
That last "U" takes the "cursor" off the grid.
I think what it is is that you've got the "z" node's coordinates wrong or something.