Source code for hammoudeh_puzzle.best_buddy_placer

"""
This contains classes that will be used by the best buddy placer technique developed by Zayd Hammoudeh
as an extension of Paikin and Tal's solver.
"""

from hammoudeh_puzzle.puzzle_piece import PuzzlePieceSide


[docs]class BestBuddyPlacerCollection(object): """ A container object used to store all the data used by the best buddy placer. """ def __init__(self): # Store the location of the open locations self._open_locations = {} # Depending on the number of best buddies, you are placed in a different tier of dictionary self._multiside_open_slots_lists = [None for _ in xrange(0, PuzzlePieceSide.get_numb_sides())]
[docs] def update_open_slot(self, puzzle_location, side, neighbor_side_info): """ When a piece is placed, some set of adjacent slots will need to be updated. This performs that neighbor updating. Args: puzzle_location (PuzzleLocation): Unique location of the open slot side (PuzzlePieceSide): Side of the open slot where neighbor information is going to be added. neighbor_side_info (NeighborSidePair): Information regarding the piece neighbor """ location_key = puzzle_location.key # Get the number of neighbors for the piece to be updated numb_neighbors = self._open_locations.get(location_key, None) # If this location does not exist, add it. if numb_neighbors is None: self._add_open_slot(puzzle_location, side, neighbor_side_info) return # Get the open slot and update the specified side # noinspection PyTypeChecker open_slot = self._multiside_open_slots_lists[numb_neighbors - 1][location_key] open_slot.update_side_neighbor_info(side, neighbor_side_info) # Update the containers storing the open slot information self._put_slot_into_dictionaries(open_slot)
[docs] def get_open_slot_dictionary(self, numb_neighbors): """ Gets all the open slots with the specified number of neighbors. Args: numb_neighbors (int): Number of neighbors adjacent to the set of open slots Returns (dict): Dictionary containing the open slots in the puzzles with the specified number of neighbors. """ return self._multiside_open_slots_lists[numb_neighbors - 1]
def _put_slot_into_dictionaries(self, open_slot): """ Puts an open slot into the dictionaries storing the slot information. Args: open_slot (MultisidePuzzleOpenSlot): Multiside slot information to add to the internal dictionary data structures. """ loc_key = open_slot.location.key self._open_locations[loc_key] = open_slot.numb_neighbors # Delete the entry from the lower level open slot list if(self._multiside_open_slots_lists[open_slot.numb_neighbors - 2] is not None and self._multiside_open_slots_lists[open_slot.numb_neighbors - 2].get(loc_key, None) is not None): del self._multiside_open_slots_lists[open_slot.numb_neighbors - 2][loc_key] # Add the entry to the next level open slot list if self._multiside_open_slots_lists[open_slot.numb_neighbors - 1] is not None: slot_dictionary = self._multiside_open_slots_lists[open_slot.numb_neighbors - 1] slot_dictionary[loc_key] = open_slot else: slot_dictionary = {loc_key: open_slot} self._multiside_open_slots_lists[open_slot.numb_neighbors - 1] = slot_dictionary def _add_open_slot(self, puzzle_location, adjacent_side, neighbor_side_info): """ Creates a new open slot and Args: puzzle_location (PuzzleLocation): neighbor_side_info (List[(side, NeighborSidePair)]): List of all neighbor sides. """ # Create a new open slot new_open_slot = MultisidePuzzleOpenSlot(puzzle_location) new_open_slot.update_side_neighbor_info(adjacent_side, neighbor_side_info) # Add the open slot to the dictionaries self._put_slot_into_dictionaries(new_open_slot)
[docs] def remove_open_slot(self, piece_location): """ After a piece is placed, this function updates the data structures in teh best buddy placer to reflect this is no longer an open slot. Args: piece_location (PuzzleLocation): Location (both (row, column) and puzzle ID) where the last piece was placed """ # Get the number of neighbors for the puzzle piece numb_neighbors = self._open_locations.get(piece_location.key, None) if numb_neighbors is None: return # Delete the piece from the diction del self._open_locations[piece_location.key] # noinspection PyTypeChecker del self._multiside_open_slots_lists[numb_neighbors - 1][piece_location.key]
[docs]class MultisidePuzzleOpenSlot(object): """ Represents a single open slot in a puzzle being solved. """ def __init__(self, puzzle_location): """ Args: puzzle_location (PuzzleLocation): Puzzle location information in the PuzzleLocation class format. """ self._puzzle_location = puzzle_location self._neighbor_side_list = [None] * PuzzlePieceSide.get_numb_sides() self._numb_neighbors = 0
[docs] def update_side_neighbor_info(self, side, neighbor_side_info): """ Updates the side neighbor information for a piece. Args: side (PuzzlePieceSide): Side of the open slot of interest neighbor_side_info (NeighborSidePair): Information on the neighbor including the side of the neighbor that is adjacent to this piece. """ # Can only update a side once for now. assert self._neighbor_side_list[side.value] is None # Update the neighbor list and increment the number of neighbors. self._neighbor_side_list[side.value] = neighbor_side_info self._numb_neighbors += 1
[docs] def get_neighbor_info(self, open_slot_side): """ Gets the neighbor identification number of a neighboring piece. Args: open_slot_side (PuzzlePieceSide): Side of the open slot Returns (NeighborSidePair): If the piece has a neighbor on the specified side, it returns a NeighborSidePair containing the neighbor id and the neighbor's side. """ return self._neighbor_side_list[open_slot_side.value]
@property def location(self): """ Returns the actual location of the open slot. Returns (PuzzleLocation): Location of the open slot """ return self._puzzle_location @property def numb_neighbors(self): """ Determines the number of neighbors (i.e. pieces) directly adjacent to this open location. Returns(int): Number neighbors for this open slot. """ return self._numb_neighbors @property def key(self): """ Gets the key of a MultisidePuzzleOpenSlot object. Returns (str): Unique key for a multisided open slot """ return self._puzzle_location.key