def evaluate(individual): corners_perm = individual[0] edges_perm = individual[1] inner_perm = individual[2] idx = 0 for i, j in board.enumerate_corners(): board.board[i][j] = PieceRef(puzzle_def.corners[corners_perm[idx]], 0, i, j) idx += 1 idx = 0 for i, j in board.enumerate_edges(): board.board[i][j] = PieceRef(puzzle_def.edges[edges_perm[idx]], 0, i, j) idx += 1 idx = 0 for i, j in board.enumerate_inner(): board.board[i][j] = PieceRef(puzzle_def.inner[inner_perm[idx]], 0, i, j) idx += 1 board.fix_orientation() board.heuristic_orientation() return board.evaluate(),
def step(self): if not self.unplaced: # nothing to place, solved probably... return random.shuffle(self.unplaced) max_score = None max_i = None max_j = None max_tile = None max_ref = None max_dir = None max_rem = [] tile = self.unplaced.popleft() if tile.type == TYPE_CORNER: coll = self.board.enumerate_corners() elif tile.type == TYPE_EDGE: coll = self.board.enumerate_edges() else: coll = self.board.enumerate_inner() for i, j in coll: curr = 0 if self.board.board[i][j]: curr = self.board.evaluate_piece(i, j) ref = PieceRef(tile, 0, i, j) for dir in self.orientations[i][j]: ref.dir = dir score, rem = self.check_piece_score(ref, i, j) score -= curr if max_score is None or score > max_score: max_score = score max_i = i max_j = j max_ref = ref max_dir = dir max_tile = tile max_rem = rem if self.board.board[max_i][max_j]: self.unplaced.append(self.board.board[max_i][max_j].piece_def) self.board.board[max_i][max_j] = None self.board.board[max_i][max_j] = max_ref self.board.board[max_i][max_j].dir = max_dir for i, j in max_rem: self.unplaced.append(self.board.board[i][j].piece_def) self.board.board[i][j] = None print(f"Placing {max_ref.piece_def.id} at {max_i},{max_j}") pass
def put_piece(self, i, j, piece_def, dir): # TODO remove currently placed piece in given position ref = PieceRef(piece_def, dir, i, j) self.board[i][j] = ref if piece_def.id in self.board_by_id: raise Exception( f"ID {piece_def.id} to be placed already on the board!") self.board_by_id[piece_def.id] = ref
def __init__(self, board, enable_finalizing=True, constraint_reducing=True, connecting=False, pieces_map=None, find_all=False, grid_file=None, rotations_file=None): # pre-calculated factorials self.fact = [math.factorial(i) for i in range(4 * 256 + 1)] # 4 times for each rotation self.enable_finalizing = enable_finalizing self.constraint_reducing = constraint_reducing self.connecting = connecting self.find_all = find_all self.grid_file = grid_file self.grid_scores = None self.finalizing_threshold = 90 self.counter = 0 self.placed_best = 0 self.board = board self.unvisited = dict() self.backtrack_to = 0 self.state = self.SEARCHING for i in range(self.board.puzzle_def.height): for j in range(self.board.puzzle_def.width): if not pieces_map or (i, j) in pieces_map: self.unvisited[i, j] = 0 self.visited = list() self.placed_ids = set() # self.unplaced_ids = set() self.unplaced_corners_ids = set() self.unplaced_corners = set() rotations = None if rotations_file is not None: rotations = {} with open(rotations_file) as f: for line in f.readlines(): id, dir = line.split(",") rotations[int(id)] = int(dir) for piece in self.board.puzzle_def.corners: if rotations is not None: self.unplaced_corners.add( PieceRef(piece, rotations[piece.id], 0, 0)) else: for dir in range(4): self.unplaced_corners.add(PieceRef(piece, dir, 0, 0)) self.unplaced_corners_ids.add(piece.id) self.unplaced_edges = set() self.unplaced_edges_ids = set() for piece in self.board.puzzle_def.edges: if rotations is not None: self.unplaced_edges.add( PieceRef(piece, rotations[piece.id], 0, 0)) else: for dir in range(4): self.unplaced_edges.add(PieceRef(piece, dir, 0, 0)) self.unplaced_edges_ids.add(piece.id) self.unplaced_inner = set() self.unplaced_inner_ids = set() for piece in self.board.puzzle_def.inner: if rotations is not None: self.unplaced_inner.add( PieceRef(piece, rotations[piece.id], 0, 0)) else: for dir in range(4): self.unplaced_inner.add(PieceRef(piece, dir, 0, 0)) self.unplaced_inner_ids.add(piece.id) self.forbidden = {} for i in range(self.board.puzzle_def.height): for j in range(self.board.puzzle_def.width): self.forbidden[i, j] = dict() self.backtracked_position = None self.explored = [0] * len(self.board.puzzle_def.all) self.explored_max = self.fact[4] \ * self.fact[len(self.board.puzzle_def.edges)] \ * self.fact[len(self.board.puzzle_def.inner)] \ * (4 ** len(self.board.puzzle_def.inner)) # pre-place hints for hint in self.board.puzzle_def.hints: id = hint[2] self.placed_ids.add(id) piece_def = self.board.puzzle_def.all[id] i, j = hint[0], hint[1] ref = PieceRef(piece_def, 0, i, j) self.board.board[i][j] = ref if hint[3] != -1: ref.dir = hint[3] if id in self.unplaced_corners_ids: self.unplaced_corners_ids.remove(id) if id in self.unplaced_edges_ids: self.unplaced_edges_ids.remove(id) if id in self.unplaced_inner_ids: self.unplaced_inner_ids.remove(id) to_remove = set() for piece in self.unplaced_corners: if piece.piece_def.id == id: to_remove.add(piece) for piece in to_remove: self.unplaced_corners.remove(piece) to_remove = set() for piece in self.unplaced_edges: if piece.piece_def.id == id: to_remove.add(piece) for piece in to_remove: self.unplaced_edges.remove(piece) to_remove = set() for piece in self.unplaced_inner: if piece.piece_def.id == id: to_remove.add(piece) for piece in to_remove: self.unplaced_inner.remove(piece) if (i, j) in self.unvisited: del self.unvisited[i, j] self.visited.append((i, j)) self.board.marks[i][j] = id if self.grid_file: self.grid_scores = dict() with open(self.grid_file, "r") as f: for line in f.readlines(): fields = line.strip().split(",") for i, field in enumerate(fields): fields[i] = int(field) self.grid_scores[fields[0], fields[1]] = fields[2] self.board.fix_orientation()
def __init__(self, board, positions, fix_smaller=False): self.counter = 0 self.board = board self.fix_smaller = fix_smaller self.unvisited = dict() self.last_found = None x = 4 for i, j in positions: self.unvisited[i, j] = 0 self.visited = list() self.placed_ids = set() self.unplaced_ids = set() self.unplaced_corners = set() for piece in self.board.puzzle_def.corners: for dir in range(4): self.unplaced_corners.add(PieceRef(piece, dir, 0, 0)) self.unplaced_edges = set() for piece in self.board.puzzle_def.edges: for dir in range(4): self.unplaced_edges.add(PieceRef(piece, dir, 0, 0)) self.unplaced_inner = set() for piece in self.board.puzzle_def.inner: for dir in range(4): self.unplaced_inner.add(PieceRef(piece, dir, 0, 0)) self.forbidden = {} for i in range(self.board.puzzle_def.height): for j in range(self.board.puzzle_def.width): self.forbidden[i, j] = set() self.backtracked_position = None # pre-place hints self.hints_count = len(self.board.puzzle_def.hints) for hint in self.board.puzzle_def.hints: id = hint[2] self.placed_ids.add(id) piece_def = self.board.puzzle_def.all[id] i, j = hint[0], hint[1] ref = PieceRef(piece_def, 0, i, j) self.board.board[i][j] = ref if hint[3] != -1: ref.dir = hint[3] to_remove = set() for piece in self.unplaced_corners: if piece.piece_def.id == id: to_remove.add(piece) for piece in to_remove: self.unplaced_corners.remove(piece) to_remove = set() for piece in self.unplaced_edges: if piece.piece_def.id == id: to_remove.add(piece) for piece in to_remove: self.unplaced_edges.remove(piece) to_remove = set() for piece in self.unplaced_inner: if piece.piece_def.id == id: to_remove.add(piece) for piece in to_remove: self.unplaced_inner.remove(piece) if (i, j) in self.unvisited: del self.unvisited[i, j] self.visited.append((i, j)) self.board.marks[i][j] = id self.board.fix_orientation()
type=str, required=True, default=None, help='Rotations file output') args = parser.parse_args() puzzle_def = PuzzleDefinition() puzzle_def.load(args.conf, args.load) board = board.Board(puzzle_def) # place hints for hint in board.puzzle_def.hints: id = hint[2] piece_def = board.puzzle_def.all[id] i, j = hint[0], hint[1] ref = PieceRef(piece_def, 0, i, j) board.board[i][j] = ref if hint[3] != -1: ref.dir = hint[3] board.marks[i][j] = id board.fix_orientation() with open(args.save, "w") as out: for i in range(board.puzzle_def.height): for j in range(board.puzzle_def.width): out.write( f"{board.board[i][j].piece_def.id}, {board.board[i][j].dir}\n" )