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 execute(self, p, locked): """p: das Feld auf dem die Aktion ausgeführt werden soll locked: eine Menge von Positionen die nicht bewegt werden dürfen. Die erste Position die durch die Aktion betreten wird, wird autoamtisch gelockt""" log.debug("executing PosAction; start: {}, actions: {}".format(self.start_position, self.actions)) l = locked.copy() l.add(self.locked_position()) # die erste Position wird automatisch gelockt! path = a_star(p.shape[0], puz.empty_position(p), self.start_position, l) assert path, "PosAction not executable, starting position not reachable" init_actions = coords_to_actions(path) # log.info("moving into start pos., path: {}".format(init_actions)) p = puz.apply_actions(p, init_actions) p = puz.apply_actions(p, self.actions) return p, init_actions + self.actions