def get_target_positions(self): """Gibt ein dict zurück, dass alle bis auf das letzte Element der zu lösenden Reihe auf ihre gewünschte Position abbildet""" l = list(self.s[0]) d = dict() for i in l[:-2]: d.update({i: puz.get_position(self.s, i)}) # besondere Position für den Vorletzten d.update({l[-2]: tuple(np.array(puz.get_position(self.s, l[-2])) + (0, 1))}) return d
def manhattan_dist_sum(p, tiles = None): if not tiles: tiles = p.flat solved = puzzle.solved(p) s = 0 for t in tiles: s_pos = puzzle.get_position(p, t) t_pos = puzzle.get_position(solved, t) s += u.manhattan_distance(*s_pos, *t_pos) return s
def solve_last(self): # log.info("solving last:\n{}",format(self.p)) """Löst die letzten beiden Elemente, womit dann die ganze Reihe gelöst ist""" r, d, l, u = (0, 1), (1, 0), (0, -1), (-1, 0) final_lst_pos = puz.get_position(self.s, self.s[0][-1]) lst_pos = self.lst_pos() # 1. Fall: 4 ist über der 3 und beide werden zusammen 'reinrotiert' -> fertig if all(lst_pos == np.array(final_lst_pos) + d): pa = PosAction((0, len(self.s[0]) - 2), [r, d]) locked = self.locked.union({self.lst_pos()}) self.exec_pa(pa, locked) # 2. Fall: 3 und 4 sind vertauscht -> Überführung in 3. Fall elif all(lst_pos == np.array(final_lst_pos) + l): pa = PosAction((1, len(self.s[0]) - 2), [u]) self.exec_pa(pa, self.locked) self.solve_last() # 3. Fall: Überführung in 1. Fall elif (all(lst_pos == np.array(final_lst_pos) + (1, -1)) and all(puz.empty_position(self.p) == np.array(final_lst_pos) + l)): pa = PosAction(puz.empty_position(self.p), [r, d, d, l, u, u, r, d, l, u, r, d, d, l, u, r, d]) self.exec_pa(pa, set()) self.solve_last() # 4. Fall (default): Die 4 ist irgendwo anders -> Überführung in 1. else: self.p, acts = move_one_tile(self.p, self.s[0][-1], tuple(np.array(final_lst_pos) + d), self.locked) self._moves += acts self.solve_last()
def solve_but_last(self): """Löst die ersten n-2 der obersten Reihe und bringt den n-1ten in eine geeignete Position um ihn zusammen mit dem n-ten zu lösen (z.B.: '12.3')""" d = self.get_target_positions() for i in sorted(d): log.info("solving element {}".format(i)) self.p, acts = move_one_tile(self.p, i, d[i], self.locked) self._moves += acts self.locked.add(puz.get_position(self.p, i))
def move_one_tile(p, tile, target_position, locked): """tile wird an position bewegt unter Berücksichtigung der locked Tiles tile: ein int locked: set von Positionen (Tupeln)""" start_position = puz.get_position(p, tile) path = a_star(p.shape[0], start_position, target_position, locked) # print(path) pos_actions = coords_to_pos_actions(path) # print(pos_actions) actions = [] for a in pos_actions: # print("Meta-Action", a.start_position, a.actions) # print(p) p, acts = a.execute(p, locked) actions += acts return p, actions
def stl_pos(self): """Gibt die aktuelle Position des vorletzten zu lösenden Elements zurück""" stl = self.s[0][-2] return puz.get_position(self.p, stl)
def lst_pos(self): """Gibt die aktuelle Position des letzten zu lösenden Elements zurück""" last = self.s[0][-1] return puz.get_position(self.p, last)