199 lines
6.8 KiB
Python
199 lines
6.8 KiB
Python
from typing import Union
|
|
import operator
|
|
|
|
from interpreter.dataStructures import direction, position, codel
|
|
|
|
def getDP(directionPointer: int) -> str:
|
|
"""
|
|
Finds the correct direction pointer string
|
|
:param directionPointer: Input direction pointer
|
|
:return: direction pointer string
|
|
"""
|
|
if directionPointer == 0:
|
|
return 'r'
|
|
if directionPointer == 1:
|
|
return 'd'
|
|
if directionPointer == 2:
|
|
return 'l'
|
|
return 'u'
|
|
|
|
|
|
def getCC(codelChooser: int) -> str:
|
|
"""
|
|
finds the correct codel chooser direction string
|
|
:param codelChooser: input codel chooser
|
|
:return: codel chooser direction string
|
|
"""
|
|
if codelChooser == 0:
|
|
return 'l'
|
|
return 'r'
|
|
|
|
|
|
def getArrow(direction: direction) -> str:
|
|
"""
|
|
Returns the Unicode arrow from the direction
|
|
:param direction: Input direction
|
|
:return: Unicode arrow string
|
|
"""
|
|
if direction.pointers[0] == 0:
|
|
if direction.pointers[1] == 0:
|
|
return "\u2197"
|
|
if direction.pointers[1] == 1:
|
|
return "\u2198"
|
|
return ""
|
|
|
|
if direction.pointers[0] == 1:
|
|
if direction.pointers[1] == 0:
|
|
return "\u2198"
|
|
if direction.pointers[1] == 1:
|
|
return "\u2199"
|
|
return ""
|
|
|
|
if direction.pointers[0] == 2:
|
|
if direction.pointers[1] == 0:
|
|
return "\u2199"
|
|
if direction.pointers[1] == 1:
|
|
return "\u2196"
|
|
return ""
|
|
|
|
if direction.pointers[0] == 3:
|
|
if direction.pointers[1] == 0:
|
|
return "\u2196"
|
|
if direction.pointers[1] == 1:
|
|
return "\u2197"
|
|
return ""
|
|
return ""
|
|
|
|
|
|
def flipCC(codelChooser: int) -> int:
|
|
"""
|
|
Flips the codelChooser 0 -> 1, 1 -> 0
|
|
:param codelChooser: unflipped codelChooser
|
|
:return: flipped codelChooser
|
|
"""
|
|
return int(not codelChooser)
|
|
|
|
|
|
def flipDP(directionPointer: int) -> int:
|
|
"""
|
|
Cycles the directionpointer 0 -> 1, 1 -> 2, 2 -> 3, 3 -> 0
|
|
:param directionPointer: unflipped directionPointer
|
|
:return: new DirectionPointer
|
|
"""
|
|
if directionPointer != 3:
|
|
return directionPointer + 1
|
|
return 0
|
|
|
|
def flipDPInvert(directionPointer: int, count = 0) -> int:
|
|
if count >= 0:
|
|
return directionPointer
|
|
else:
|
|
if directionPointer != 0:
|
|
return flipDPInvert(directionPointer - 1, count + 1)
|
|
return flipDPInvert(3, count + 1)
|
|
|
|
def flip(inputDirection: direction) -> direction:
|
|
"""
|
|
Chooses what part of the general pointer to flip, by DP%2 == CC rule, providing the following flow:
|
|
(0,0) -> (0,1)
|
|
(0,1) -> (1,1)
|
|
(1,1) -> (1,0)
|
|
(1,0) -> (2,0)
|
|
(2,0) -> (2,1)
|
|
(2,1) -> (3,1)
|
|
(3,1) -> (3,0)
|
|
(3,0) -> (0,0)
|
|
:param inputDirection: Original state of the pointers
|
|
:return: Tuple of ints containing new pointers
|
|
"""
|
|
if inputDirection.pointers[0] % 2 == inputDirection.pointers[1]:
|
|
return direction((inputDirection.pointers[0], flipCC(inputDirection.pointers[1])))
|
|
return direction((flipDP(inputDirection.pointers[0]), inputDirection.pointers[1]))
|
|
|
|
|
|
def getNextPosition(startPosition: position, directionPointer: int) -> Union[position, KeyError]:
|
|
"""
|
|
Finds next position along the direction pointer
|
|
:param startPosition: start position
|
|
:param directionPointer: direction pointer
|
|
:return: next position
|
|
"""
|
|
if directionPointer == 0:
|
|
return position((startPosition.coords[0] + 1, startPosition.coords[1]))
|
|
if directionPointer == 1:
|
|
return position((startPosition.coords[0], startPosition.coords[1] + 1))
|
|
if directionPointer == 2:
|
|
return position((startPosition.coords[0] - 1, startPosition.coords[1]))
|
|
if directionPointer == 3:
|
|
return position((startPosition.coords[0], startPosition.coords[1] - 1))
|
|
return KeyError("Given key {} is no valid Direction Pointer (0, 1, 2, or 3)".format(directionPointer))
|
|
|
|
|
|
def getPreviousPosition(startPosition: position, directionPointer: int) -> position:
|
|
"""
|
|
Inverts the directionPointer, and finds the next position
|
|
:param startPosition: Input position
|
|
:param directionPointer: Input directionpointer
|
|
:return: Previous position
|
|
"""
|
|
if directionPointer == 0:
|
|
return getNextPosition(startPosition, 2)
|
|
if directionPointer == 1:
|
|
return getNextPosition(startPosition, 3)
|
|
if directionPointer == 2:
|
|
return getNextPosition(startPosition, 0)
|
|
return getNextPosition(startPosition, 1)
|
|
|
|
|
|
def findEdge(inputCodel: codel, inputDirection: direction) -> Union[position, bool]:
|
|
"""
|
|
Finds the edge of the codel according to the direction pointer and the codel chooser
|
|
:param inputCodel: Set of adjacent positions with the same color
|
|
:param pointers: Tuple where pointers[0] = DP and pointers[1] = CC
|
|
:return: Position within the codel that is adjacent to the next pixel to go to
|
|
"""
|
|
dp = inputDirection.pointers[0]
|
|
cc = inputDirection.pointers[1]
|
|
|
|
# Right side
|
|
if dp == 0:
|
|
edgePosition = max(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[0])
|
|
maxValues = list(filter(lambda lambdaPos: lambdaPos.coords[0] == edgePosition.coords[0], inputCodel.codel))
|
|
if cc == 0:
|
|
# -> ^ Right and up
|
|
return min(maxValues, key=lambda lambdaPos: lambdaPos.coords[1])
|
|
else:
|
|
# -> V Right and down
|
|
return max(maxValues, key=lambda lambdaPos: lambdaPos.coords[1])
|
|
# Bottom side
|
|
elif dp == 1:
|
|
edgePosition = max(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[1])
|
|
maxValues = list(filter(lambda lambdaPos: lambdaPos.coords[1] == edgePosition.coords[1], inputCodel.codel))
|
|
if cc == 0:
|
|
# V -> Down and right
|
|
return max(maxValues, key=lambda lambaPos: lambaPos.coords[0])
|
|
else:
|
|
# V <- Down and left
|
|
return min(maxValues, key=lambda lambdaPos: lambdaPos.coords[0])
|
|
# Left side
|
|
elif dp == 2:
|
|
edgePosition = min(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[0])
|
|
minValues = list(filter(lambda lambdaPos: lambdaPos.coords[0] == edgePosition.coords[0], inputCodel.codel))
|
|
if cc == 0:
|
|
# <- V Left and down
|
|
return max(minValues, key=lambda lambaPos: lambaPos.coords[1])
|
|
else:
|
|
# <- ^ left and up
|
|
return min(minValues, key=lambda lambdaPos: lambdaPos.coords[1])
|
|
|
|
# Top side
|
|
else: # dp == 3
|
|
edgePosition = min(inputCodel.codel, key=lambda lambdaPos: lambdaPos.coords[1])
|
|
maxValues = list(filter(lambda lambdaPos: lambdaPos.coords[1] == edgePosition.coords[1], inputCodel.codel))
|
|
if cc == 0:
|
|
# ^ <- Up and left
|
|
return min(maxValues, key=lambda lambaPos: lambaPos.coords[0])
|
|
else:
|
|
# ^ -> Up and right
|
|
return max(maxValues, key=lambda lambdaPos: lambdaPos.coords[0])
|