Created
November 30, 2019 00:16
-
-
Save JackKell/7e305d84da889d473a106e8abecd2ed7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from enum import Enum | |
from copy import deepcopy | |
from typing import List, Tuple, Union, Set | |
class ActionType(Enum): | |
MOVE_UP = 0 | |
MOVE_RIGHT = 1 | |
MOVE_LEFT = 2 | |
MOVE_DOWN = 3 | |
CLEAN = 4 | |
NONE = 5 | |
class CellState(Enum): | |
DIRTY = 'd' | |
CLEAN = '-' | |
BOT = 'b' | |
NOT_VISIBLE = 'o' | |
class CleaningRobot(object): | |
downOffsets: set = {(-1, 1), (0, 1), (1, 1)} | |
upOffsets: set = {(-1, -1), (0, -1), (1, -1)} | |
rightOffsets: set = {(1, -1), (1, 0), (1, 1)} | |
leftOffsets: set = {(-1, 1), (0, 1), (1, 1)} | |
adjacentOffsets: set = downOffsets.union(upOffsets).union(rightOffsets).union(leftOffsets) | |
def __init__(self, startRowIndex, startColumnIndex, sensorBoardState): | |
self._rows: int = len(sensorBoardState) | |
self._cols: int = len(sensorBoardState[0]) | |
self._rowIndex: int = startRowIndex | |
self._colIndex: int = startColumnIndex | |
self._lastActionType: ActionType = ActionType.NONE | |
self._board: List[List[chr]] = deepcopy(sensorBoardState) | |
self._dirtyCells: Set[Tuple[int, int]] = set() | |
self._sensorBoardState = sensorBoardState | |
def tick(self, sensorBoardState): | |
self._scanCells(sensorBoardState) | |
if self._hasCellsToClean(): | |
if self._isCurrentCellDirty(): | |
self._clean() | |
return | |
nearestDirtyCellPosition = self._getNearestDirtyCellPosition() | |
self._moveTowards(nearestDirtyCellPosition) | |
# else move towards an unvisited cell, maybe the largest grouping | |
# else idle | |
pass | |
def _scanCells(self, sensorBoardState): | |
if self._lastActionType == ActionType.MOVE_RIGHT and self._rowIndex < self._cols - 1: | |
self._scanOffsets(sensorBoardState, CleaningRobot.rightOffsets) | |
elif self._lastActionType == ActionType.MOVE_LEFT and self._rowIndex > 0: | |
self._scanOffsets(sensorBoardState, CleaningRobot.leftOffsets) | |
elif self._lastActionType == ActionType.MOVE_UP and self._colIndex > 0: | |
self._scanOffsets(sensorBoardState, CleaningRobot.upOffsets) | |
elif self._lastActionType == ActionType.MOVE_DOWN and self._colIndex < self._rows - 1: | |
self._scanOffsets(sensorBoardState, CleaningRobot.downOffsets) | |
elif self._lastActionType == ActionType.CLEAN: | |
# if we cleaned last time then there are no new tiles to scan | |
return | |
elif self._lastActionType == ActionType.NONE: | |
self._scanOffsets(sensorBoardState, CleaningRobot.adjacentOffsets) | |
else: | |
raise Exception("_lastMove is set to unsupported move type" + str(self._lastActionType)) | |
def _hasCellsToClean(self): | |
return len(self._dirtyCells) > 0 | |
def _getNearestDirtyCellPosition(self) -> Tuple[int, int]: | |
pass | |
def _getNearestUnvisitedCellPosition(self) -> Tuple[int, int]: | |
pass | |
def _isPositionInBounds(self, xIndex, yIndex) -> bool: | |
return 0 <= xIndex < self._cols and 0 <= yIndex < self._rows | |
def _isCurrentCellDirty(self) -> bool: | |
return self._board[self._rowIndex][self._colIndex] == CellState.DIRTY.value | |
def _moveRight(self) -> None: | |
print("RIGHT") | |
self._lastActionType = ActionType.MOVE_RIGHT | |
self._rowIndex += 1 | |
def _moveLeft(self) -> None: | |
print("LEFT") | |
self._lastActionType = ActionType.MOVE_LEFT | |
self._rowIndex -= 1 | |
def _moveUp(self) -> None: | |
print("UP") | |
self._lastActionType = ActionType.MOVE_UP | |
self._colIndex -= 1 | |
def _moveDown(self) -> None: | |
print("DOWN") | |
self._lastActionType = ActionType.MOVE_DOWN | |
self._colIndex += 1 | |
def _clean(self) -> None: | |
print("CLEAN") | |
self._lastActionType = ActionType.CLEAN | |
self._dirtyCells.remove((self._rowIndex, self._colIndex)) | |
self._board[self._rowIndex][self._colIndex] = CellState.CLEAN.value | |
def _scanOffsets(self, sensorBoardState, offsets: Set[Tuple[int, int]]) -> None: | |
for rowOffset, colOffset in offsets: | |
cellColIndex, cellRowIndex = self._rowIndex + rowOffset, self._colIndex + colOffset | |
if self._isPositionInBounds(cellColIndex, cellRowIndex): | |
cellState = sensorBoardState[cellRowIndex][cellColIndex] | |
self._board[cellRowIndex][cellColIndex] = cellState | |
if cellState == CellState.DIRTY.value: | |
self._dirtyCells.add((cellColIndex, cellRowIndex)) | |
def _moveTowards(self, nearestDirtyCellPosition: Tuple[int, int]) -> None: | |
pass | |
isFirstMove: bool = True | |
robot: Union[CleaningRobot, None] = None | |
def next_move(posX, posY, board): | |
global robot, isFirstMove | |
if isFirstMove: | |
isFirstMove = False | |
robot = CleaningRobot(posX, posY, board) | |
robot.tick(board) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment