def test_equals(self): location = Location(1, 2) bombs = 3 first = State(location, bombs) second = State(location, bombs) self.assertEqual(first, second) second.bombs += 1 self.assertNotEqual(first, second)
def next_state(self, state): if not self.in_range(state.location): return for next_location in state.location.neighborhood(): if not self.in_range(next_location): continue if self[next_location].is_wall and state.bombs > 0: yield State(next_location, state.bombs - 1) elif not self[next_location].is_wall: yield State(next_location, state.bombs)
def get_info(locations, final_state): info = SearchInfo() info.final_state = final_state states = [State(location, 0) for location in locations] states = [None] + states for i in range(1, len(states)): info.add(state=states[i], parent=states[i - 1], distance=(i - 1)) return info
def test_empty(self): map_ = ["..", ".."] labyrinth = Labyrinth3d([map_, map_]) info = self.get_info([Location(0, 0, 0), Location(1, 0, 0), Location(1, 1, 0), Location(1, 1, 1)], State(Location(1, 1, 1), 0)) expected = ['X.', 'XX', '', '..', '.X'] self.assertEqual(find_path(labyrinth, info), expected)
def test_easy(self): map_ = [[".#", "#."], ["..", ".."]] labyrinth = Labyrinth3d(map_) info = self.get_info([Location(0, 0, 0), Location(0, 0, 1), Location(0, 1, 1), Location(1, 1, 1), Location(1, 1, 0)], State(Location(1, 1, 0), 0)) solve_info = solve(labyrinth, Location(0, 0, 0), Location(1, 1, 0), 0) path = find_path(labyrinth, solve_info) expected = find_path(labyrinth, info) self.assertEqual(path, expected)
def test_empty(self): map_ = ["...", "...", "..."] labyrinth = Labyrinth3d([map_, map_]) info = self.get_info([Location(0, 0, 0), Location(0, 0, 1), Location(0, 1, 1), Location(0, 2, 1), Location(1, 2, 1), Location(2, 2, 1)], State(Location(2, 2, 1), 0)) solve_info = solve(labyrinth, Location(0, 0, 0), Location(2, 2, 1), 0) path = find_path(labyrinth, solve_info) expected = find_path(labyrinth, info) self.assertEqual(path, expected)
def test_next_state(self): map_ = ["...", "#.#", "###"] labyrinth = Labyrinth(map_) location = Location(1, 1) out_of_range_location = Location(0, 4) state = State(out_of_range_location, 1) self.check_next_state(labyrinth, state, []) expected_next_states = [State(Location(0, 1), 1), State(Location(1, 0), 0), State(Location(1, 2), 0), State(Location(2, 1), 0)] state = State(location, 1) self.check_next_state(labyrinth, state, expected_next_states) state = State(Location(0, 0), 1) self.check_next_state(labyrinth, state, expected_next_states[0:2])
def solve(labyrinth, start, end, bombs): """Find path from start to end in labyrinth with bombs""" start_state = State(start, bombs) info = SearchInfo() heap = [] heappush(heap, (bombs, 0, start_state)) info.add(state=start_state, parent=None, distance=0) while len(heap) != 0: current = heappop(heap)[2] if current.location == end: info.final_state = current return info for state in labyrinth.next_state(current): if state not in info.used: info.add(state=state, parent=current, distance=info.dist[current] + 1) heappush(heap, (-state.bombs, info.dist[state], state)) return None
def test_bombs(self): map_ = [["....", "####", "...."], ["####", "....", "####"]] labyrinth = Labyrinth3d(map_) info = self.get_info([Location(0, 0, 0), Location(1, 0, 0), Location(1, 0, 1), Location(1, 1, 1), Location(1, 2, 1), Location(2, 2, 1)], State(Location(2, 2, 1), 0)) expected = ["X...", "B###", "....", '', "####", "XXX.", "##B#"] self.assertEqual(find_path(labyrinth, info), expected)
def test_init(self): location = Location(1, 1) bombs = 10 state = State(location, bombs) self.assertEqual(state.location, location) self.assertEqual(state.bombs, bombs)
def test_lt(self): first = State(Location(1, 2), 3) second = State(Location(1, 2), 4) self.assertLess(first, second)
def test_hash(self): location = Location(1, 2) bombs = 3 first = State(location, bombs) second = State(location, bombs) self.assertEqual(hash(first), hash(second))
def test_str(self): state = State(Location(1, 2), 3) self.assertEqual(str(state), "State: Location: 1 2 0. Count of bombs: 3")