90 lines
2.5 KiB
Python
90 lines
2.5 KiB
Python
from dataclasses import dataclass
|
|
from copy import deepcopy
|
|
|
|
|
|
@dataclass
|
|
class Coordinate:
|
|
x: int
|
|
y: int
|
|
|
|
def __add__(self, other):
|
|
return self.__class__(
|
|
self.x+other.x,
|
|
self.y+other.y
|
|
)
|
|
|
|
|
|
class Identicon:
|
|
WIDTH = 17
|
|
HEIGHT = 9
|
|
SYMBOLS = ' .o+=*BOX@%&#/^'
|
|
START_SYMBOL = 'S'
|
|
END_SYMBOL = 'E'
|
|
BISHOP_START = Coordinate(8, 4)
|
|
|
|
MOVES = {
|
|
0: Coordinate(-1, -1), # 00 ↖
|
|
1: Coordinate( 1, -1), # 01 ↗
|
|
2: Coordinate(-1, 1), # 10 ↙
|
|
3: Coordinate( 1, 1), # 11 ↘
|
|
}
|
|
|
|
def __init__(self, data):
|
|
self._data = data
|
|
self._grid = [[0] * self.WIDTH for _ in range(self.HEIGHT)]
|
|
self._bishop_position = deepcopy(self.BISHOP_START)
|
|
self._end_position = None
|
|
|
|
def calculate(self):
|
|
for command in self._get_commands():
|
|
self._execute(command)
|
|
self._end_position = self._bishop_position
|
|
|
|
def _get_commands(self):
|
|
commands = []
|
|
for octet in self._data:
|
|
commands.extend([
|
|
octet & 0b11, # 00 00 00 [00]
|
|
(octet >> 2) & 0b11, # 00 00 [00] 00
|
|
(octet >> 4) & 0b11, # 00 [00] 00 00
|
|
(octet >> 6) & 0b11, # [00] 00 00 00
|
|
])
|
|
return commands
|
|
|
|
def _execute(self, command):
|
|
move = self.MOVES[command]
|
|
self._bishop_position = self._ensure_within_grid_borders(self._bishop_position + move)
|
|
self._increment_current_position()
|
|
|
|
def _ensure_within_grid_borders(self, coordinate: Coordinate):
|
|
coordinate.x = max(0, min(self.WIDTH-1, coordinate.x))
|
|
coordinate.y = max(0, min(self.HEIGHT-1, coordinate.y))
|
|
return coordinate
|
|
|
|
def _increment_current_position(self):
|
|
self._grid[self._bishop_position.y][self._bishop_position.x] += 1
|
|
|
|
def __str__(self):
|
|
icon = self._header+'\n'
|
|
for y, row in enumerate(self._grid):
|
|
icon += '|'
|
|
for x, cell in enumerate(row):
|
|
icon += self._determine_symbol(Coordinate(x, y), cell)
|
|
icon += '|\n'
|
|
icon += self._header
|
|
|
|
return icon
|
|
|
|
@property
|
|
def _header(self):
|
|
return f'+{self.WIDTH*"-"}+'
|
|
|
|
def _determine_symbol(self, coordinate, cell):
|
|
symbol = self.SYMBOLS[min(cell, len(self.SYMBOLS)-1)]
|
|
if coordinate == self.BISHOP_START:
|
|
symbol = self.START_SYMBOL
|
|
elif coordinate == self._end_position:
|
|
symbol = self.END_SYMBOL
|
|
|
|
return symbol
|