-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLinked_Table_module.py
More file actions
226 lines (191 loc) · 8.6 KB
/
Linked_Table_module.py
File metadata and controls
226 lines (191 loc) · 8.6 KB
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
from typing import Optional
class LinkedTableNode:
def __init__(self, state: bool = False, hooked: Optional[set["LinkedTableNode"]] = None) -> None:
self.hooked: set["LinkedTableNode"] = set()
if hooked is not None and len(hooked) <= 8:
for node in hooked:
node.hook(self)
elif hooked is not None:
raise ValueError("The set of hooked nodes is too large")
self.state: bool = state
def hook(self, new: "LinkedTableNode") -> None:
self.hooked.add(new)
new.hooked.add(self)
def __len__(self):
return self.hooked.__len__()
class LinkedTableCoordSystem:
def __init__(self,
origin: LinkedTableNode,
up: LinkedTableNode,
left: LinkedTableNode):
self.up: LinkedTableNode = up
self.left: LinkedTableNode = left
self.origin: LinkedTableNode = origin
def __getitem__(self, coordinates: tuple[int]) -> LinkedTableNode:
pass # TODO coordinate getter system
def create_even_base() -> set[LinkedTableNode]:
base_tiles = []
for i in range(4):
base_tiles.append(LinkedTableNode())
for i in range(1, 4):
base_tiles[0].hook(base_tiles[i])
for i in (1, 2):
base_tiles[3].hook(base_tiles[i])
base_tiles[1].hook(base_tiles[2])
return set(base_tiles)
def create_odd_base() -> set[LinkedTableNode]:
edges = []
corners = []
for i in range(4):
current_edge = LinkedTableNode()
current_corner = LinkedTableNode()
current_corner.hook(current_edge)
if i > 0:
current_edge.hook(corners[i - 1])
current_edge.hook(edges[i-1])
if i == 3:
current_corner.hook(edges[0])
current_edge.hook(edges[0])
edges.append(current_edge)
corners.append(current_corner)
surroundings: set[LinkedTableNode] = set(edges).union(set(corners))
center = LinkedTableNode(hooked=surroundings)
surroundings.add(center)
return surroundings
def create_square(side_length: int) -> tuple[LinkedTableCoordSystem, set[LinkedTableNode]]:
if side_length % 2 == 0:
base: set[LinkedTableNode] = create_even_base()
origin: LinkedTableNode = next(iter(base)) # select an element from the base set
up: LinkedTableNode = next(iter(origin.hooked))
right: LinkedTableNode = next(iter(origin.hooked.intersection(up.hooked)))
side_length -= 2
else:
base: set[LinkedTableNode] = create_odd_base()
edges: set[LinkedTableNode] = set()
for node in base:
match len(node):
case 8:
origin: LinkedTableNode = node
case 5:
edges.add(node)
up: LinkedTableNode = next(iter(edges))
right: LinkedTableNode = next(iter(edges.intersection(up.hooked)))
side_length -= 3
while side_length > 0:
expand(base)
side_length -= 2
# TODO Link edges
return LinkedTableCoordSystem(origin, up, right), base
def expand_corner(corner: LinkedTableNode) -> list[LinkedTableNode]:
new_corner = LinkedTableNode()
new_intermediary_edge_0 = LinkedTableNode()
new_intermediary_edge_1 = LinkedTableNode()
new_final_edge_0 = LinkedTableNode()
new_final_edge_1 = LinkedTableNode()
edges_to_hook_intermediary: list[LinkedTableNode] = []
for potential_edge in corner.hooked:
if len(potential_edge) == 5:
edges_to_hook_intermediary.append(potential_edge)
edges_to_hook_final: list[LinkedTableNode] = []
for intermediary in edges_to_hook_intermediary:
for node in intermediary.hooked:
if len(node) == 5 and node not in edges_to_hook_intermediary:
edges_to_hook_final.append(node)
break
new_corner.hook(corner)
new_corner.hook(new_intermediary_edge_0)
new_corner.hook(new_intermediary_edge_1)
new_intermediary_edge_0.hook(corner)
new_intermediary_edge_1.hook(corner)
new_intermediary_edge_0.hook(edges_to_hook_intermediary[0])
new_intermediary_edge_1.hook(edges_to_hook_intermediary[1])
new_intermediary_edge_0.hook(new_final_edge_0)
new_intermediary_edge_1.hook(new_final_edge_1)
new_final_edge_0.hook(corner)
new_final_edge_1.hook(corner)
new_final_edge_0.hook(edges_to_hook_intermediary[0])
new_final_edge_1.hook(edges_to_hook_intermediary[1])
new_final_edge_0.hook(edges_to_hook_final[0])
new_final_edge_1.hook(edges_to_hook_final[1])
# I know this can be done with a loop, but it makes more sense in my mind like this,
# and I would certainly make dumb mistakes if I made it a loop
return [new_corner, new_final_edge_0, new_final_edge_1]
def expand_along(edge: LinkedTableNode) -> Optional[set[LinkedTableNode]]:
node_under_current: Optional[LinkedTableNode] = None
node_under_next: Optional[LinkedTableNode] = None
if 4 not in {len(x) for x in edge.hooked}:
for node in edge.hooked:
if len(node) == 7:
if node_under_current is not None:
raise ValueError("base structure invalid: too many 7-neighbour adjacencies")
node_under_current = node
if len(node) == 6:
if node_under_next is not None:
raise ValueError("base structure invalid: too many 6-neighbour adjacencies")
node_under_next = node
if node_under_next is not None and node_under_current is not None:
break
node_after_next: Optional[LinkedTableNode] = None
for node in node_under_next.hooked:
if len(node) == 5:
node_after_next = node
break
if node_after_next is None:
for node in node_under_next.hooked:
if len(node) == 6:
node_after_next = node
break
else:
raise ValueError("Invalid links in base table.")
node_under_other_end: Optional[LinkedTableNode] = None
node_other_end: Optional[LinkedTableNode] = None
for node in node_after_next.hooked:
if len(node) == 7:
node_under_other_end = node
if len(node) == 4:
node_other_end = node
if node_under_other_end is not None and node_other_end is not None:
break
else:
raise ValueError("Invalid links in base table")
adjacent_node = LinkedTableNode(hooked={node_under_current,
node_under_next,
node_after_next,
edge})
closing_node = LinkedTableNode(hooked={node_under_next,
node_after_next,
node_under_other_end,
node_other_end,
adjacent_node})
return {adjacent_node, closing_node}
else:
return {LinkedTableNode(hooked={edge, node_under_current, node_under_next, node_after_next})}
else: # the current edge has a 4-adjacency neighbour, meaning it is at the end of the line.
for node in edge.hooked:
if len(node) == 7:
if node_under_current is not None:
raise ValueError("base structure invalid: too many 7-neighbour adjacencies")
node_under_current = node
if len(node) == 4:
if node_under_next is not None:
raise ValueError("base structure invalid: too many 6-neighbour adjacencies")
node_under_next = node
if node_under_next is not None and node_under_current is not None:
break
LinkedTableNode(hooked={edge, node_under_current, node_under_next})
return None
def expand(base: set[LinkedTableNode]) -> set[LinkedTableNode]:
corners: set[LinkedTableNode] = set()
for potential_corner in base:
if len(potential_corner) == 3:
corners.add(potential_corner)
if len(corners) != 4:
raise ValueError("Provided base is invalid: does not have exactly 4 corners")
start_corner = next(iter(corners))
start_expanded = expand_corner(start_corner)
pass # TODO Expansion logic, must stop right on top of the 2 corners that are nearest to start_corner.
if __name__ == "__main__":
a = create_odd_base()
print(len(a))
b = expand(a)
print(len(a), len(b))