Skip to content

Instantly share code, notes, and snippets.

@JackKell
Created November 30, 2019 00:16
Show Gist options
  • Save JackKell/7e305d84da889d473a106e8abecd2ed7 to your computer and use it in GitHub Desktop.
Save JackKell/7e305d84da889d473a106e8abecd2ed7 to your computer and use it in GitHub Desktop.
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