-
Notifications
You must be signed in to change notification settings - Fork 31
/
Canvas.py
117 lines (100 loc) · 3.6 KB
/
Canvas.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# A custom class to create an ASCII-art canvas, similar to 05AB1E's
from enum import Enum
class Direction(Enum):
# Enum class for directions
UP = 0
UP_RIGHT = 1
RIGHT = 2
DOWN_RIGHT = 3
DOWN = 4
DOWN_LEFT = 5
LEFT = 6
UP_LEFT = 7
def to_x(dir):
return [0, 1, 1, 1, 0, -1, -1, -1][dir.value]
def to_y(dir):
return [-1, -1, 0, 1, 1, 1, 0, -1][dir.value]
class Canvas:
def __init__(self, filler=" "):
# Canvas is a list of rows
self.filler = filler
self.canvas = [[filler]]
self.x = 0
self.y = 0
self.start_x = 0
self.start_y = 0
def extend(self, length, dir):
if dir == Direction.RIGHT:
for item in self.canvas:
item.extend([self.filler] * length)
elif dir == Direction.DOWN:
for _ in range(length):
self.canvas.append([self.filler] * len(self.canvas[0]))
elif dir == Direction.LEFT:
for item, index in enumerate(self.canvas):
self.canvas[item] = [self.filler] * length + index
self.x += length
self.start_x += length
elif dir == Direction.UP:
for _ in range(length):
self.canvas = [
[self.filler] * len(self.canvas[0])
] + self.canvas
self.y += length
self.start_y += length
def draw_line(self, dir, length, text):
final_y = self.y + Direction.to_y(dir) * (length - 1)
if final_y < 0:
self.extend(-final_y, Direction.UP)
final_y = 0
elif final_y >= len(self.canvas):
self.extend(final_y - len(self.canvas) + 1, Direction.DOWN)
final_y = len(self.canvas) - 1
final_x = self.x + Direction.to_x(dir) * (length - 1)
if final_x < 0:
self.extend(-final_x, Direction.LEFT)
final_x = 0
elif final_x >= len(self.canvas[0]):
self.extend(final_x - len(self.canvas[0]) + 1, Direction.RIGHT)
final_x = len(self.canvas[0]) - 1
for i in range(length):
self.canvas[self.y + Direction.to_y(dir) * i][
self.x + Direction.to_x(dir) * i
] = text[i % len(text)]
self.x = final_x
self.y = final_y
def draw(self, dirs, lengths, text):
dirs = Canvas.replace_patterns(dirs)
maxl = max(len(lengths), len(dirs))
lsum = None
for i in range(maxl):
if dirs[i % len(dirs)] == 8:
self.x = self.start_x
self.y = self.start_y
continue
l = lengths[i % len(lengths)]
if lsum == None:
self.draw_line(Direction(dirs[i % len(dirs)]), l, text)
lsum = 1
else:
self.x += Direction.to_x(Direction(dirs[i % len(dirs)]))
self.y += Direction.to_y(Direction(dirs[i % len(dirs)]))
t = text[lsum % len(text) :] + text[: lsum % len(text)]
self.draw_line(Direction(dirs[i % len(dirs)]), l - 1, t)
lsum += l - 1
def __str__(self):
return "\n".join(["".join(row) for row in self.canvas])
def replace_patterns(dirs):
res = []
for dir in dirs:
res += {
"+": [0, 4, 2, 6, 4, 0, 6, 2],
"x": [1, 5, 3, 7, 5, 1, 7, 3],
"]": [2, 4, 6],
"[": [6, 4, 2],
"<": [5, 3],
">": [3, 5],
"v": [3, 1],
"^": [1, 3],
}.get(dir, [dir])
return res