-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathutil.py
More file actions
84 lines (75 loc) · 3.17 KB
/
util.py
File metadata and controls
84 lines (75 loc) · 3.17 KB
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/local/bin/python3
'''Utility functions'''
from typing import TypeVar, Dict, Iterable, Callable
from framework import get_plank, Move, Peg, Plank, Board, Tuple, List
# types
KeyType = TypeVar('KeyType')
ValueType = TypeVar('ValueType')
Solution = Iterable[Move]
RiverCrossingCharacter = str
RiverCrossingSolution = str
PegTranslator = Dict[Peg, RiverCrossingCharacter]
RiverCrossingCharacterTranslator = Dict[RiverCrossingCharacter, Peg]
def invert_dictionary(mapping: Dict[KeyType, ValueType]) -> Dict[ValueType, KeyType]:
'''
Inverts a dictionary
from https://stackoverflow.com/a/483833/
'''
return {v: k for k, v in mapping.items()}
def convert_to_rc_solution(solution: Solution, translator: PegTranslator,
starting_person_position: Peg) -> RiverCrossingSolution:
'''
Takes a solution, a translator from pegs to RC characters,
...and a peg number for the starting person position,
...and returns the River Crossing solution string for that solution.
'''
def plank_converter(plank: Plank) -> str:
ans = ""
for peg in plank:
ans += translator[peg].upper()
return "".join(sorted(ans))
ans = ""
person_position = starting_person_position
for move_type, peg in solution:
if move_type == "walk":
person_position = peg
elif move_type == "grab":
ans += plank_converter(get_plank(peg, person_position)) + '-'
elif move_type == "place":
ans += plank_converter(get_plank(peg, person_position)) + ' '
else:
raise ValueError("Unrecognized move type {}".format(move_type))
return ans.strip()
class SolutionStepper: # pylint: disable=too-few-public-methods
'''
Class for stepping through River Crossing solution strings -
Helpful for debugging
'''
def __init__(self, base_board_creator: Callable[[], Board],
solution_string: RiverCrossingSolution,
translator: RiverCrossingCharacterTranslator):
'''
Takes a function that creates a board when called with no parameters
...and a River Crossing solution string,
...and a translator from pegs to RC solution characters
'''
# when called, creates the board after 0 steps
self.base_board_creator = base_board_creator
solution_string = solution_string.strip().upper()
self.moves: List[Tuple[Plank, Plank]] = solution_string.split() # type: ignore
self.moves = [move.split('-') for move in self.moves] # type: ignore
self.moves = [tuple([get_plank(*[translator[peg] for peg in plank]) # type: ignore
for plank in move])
for move in self.moves]
def get_puzzle_at_step(self, step: int) -> Board:
'''
Returns the puzzle after doing the given amount of steps
...from the River Crossing string
'''
ans = self.base_board_creator()
for index in range(step):
grab_plank, place_plank = self.moves[index]
ans.remove_plank(grab_plank)
ans.add_plank(place_plank)
ans.person_position = place_plank[0]
return ans