summaryrefslogtreecommitdiffstats
path: root/aoc
diff options
context:
space:
mode:
Diffstat (limited to 'aoc')
-rw-r--r--aoc/datastructures.py68
-rw-r--r--aoc/mixins.py20
-rw-r--r--aoc/tests/__init__.py0
-rw-r--r--aoc/tests/test_datastructures.py16
4 files changed, 104 insertions, 0 deletions
diff --git a/aoc/datastructures.py b/aoc/datastructures.py
index 81a68e4..244aa1e 100644
--- a/aoc/datastructures.py
+++ b/aoc/datastructures.py
@@ -1,5 +1,6 @@
1# -*- coding: utf-8 -*- 1# -*- coding: utf-8 -*-
2from collections import namedtuple 2from collections import namedtuple
3from typing import Iterator
3 4
4 5
5class Coordinate(namedtuple("Coordinate", ["x", "y"])): 6class Coordinate(namedtuple("Coordinate", ["x", "y"])):
@@ -28,3 +29,70 @@ class Coordinate(namedtuple("Coordinate", ["x", "y"])):
28 px, 29 px,
29 py, 30 py,
30 ) 31 )
32
33 def neighbours(self, no_diagonal: bool = False) -> Iterator["Coordinate"]:
34 if no_diagonal:
35 yield self + Coordinate(-1, 0),
36 yield self + Coordinate(1, 0),
37 yield self + Coordinate(0, -1),
38 yield self + Coordinate(0, 1),
39 else:
40 for dy in range(self.y - 1, self.y + 2):
41 for dx in range(self.x - 1, self.x + 2):
42 if dy == self.y and dx == self.x:
43 continue
44
45 yield Coordinate(dx, dy)
46
47
48class Coordinate3(namedtuple("Coordinate3", ["x", "y", "z"])):
49 def __sub__(self, other: "Coordinate3") -> "Coordinate3":
50 return Coordinate3(self.x - other.x, self.y - other.y, self.z - other.z)
51
52 def __add__(self, other: "Coordinate3") -> "Coordinate3":
53 return Coordinate3(self.x + other.x, self.y + other.y, self.z + other.z)
54
55 def manhattan_distance(self, other: "Coordinate3") -> int:
56 return abs(self.x - other.x) + abs(self.y - other.y) + abs(self.z - other.z)
57
58 @property
59 def polarity(self) -> "Coordinate3":
60 try:
61 px = abs(self.x) / self.x
62 except ZeroDivisionError:
63 px = 0
64
65 try:
66 py = abs(self.y) / self.y
67 except ZeroDivisionError:
68 py = 0
69
70 try:
71 pz = abs(self.z) / self.z
72 except ZeroDivisionError:
73 pz = 0
74
75 return Coordinate3(
76 px,
77 py,
78 pz,
79 )
80
81 def neighbours(self, no_diagonal: bool = False) -> Iterator["Coordinate3"]:
82 if no_diagonal:
83 yield self + Coordinate3(-1, 0, 0)
84 yield self + Coordinate3(1, 0, 0)
85 yield self + Coordinate3(0, -1, 0)
86 yield self + Coordinate3(0, 1, 0)
87 yield self + Coordinate3(0, 0, -1)
88 yield self + Coordinate3(0, 0, 1)
89 else:
90 for dz in range(self.z - 1, self.z + 2):
91 for dy in range(self.y - 1, self.y + 2):
92 for dx in range(self.x - 1, self.x + 2):
93 coordinate = Coordinate3(dx, dy, dz)
94
95 if dy == self.y and dx == self.x:
96 continue
97
98 yield coordinate
diff --git a/aoc/mixins.py b/aoc/mixins.py
index faeb3eb..5986b6e 100644
--- a/aoc/mixins.py
+++ b/aoc/mixins.py
@@ -55,3 +55,23 @@ class AStarMixin(Generic[Node]):
55 55
56 if neighbour not in open_nodes: 56 if neighbour not in open_nodes:
57 open_nodes.add(neighbour) 57 open_nodes.add(neighbour)
58
59
60class BreathFirstSearchMixin(Generic[Node]):
61 @staticmethod
62 def bfs(
63 start: Node, neighbours: Callable[[Node], Iterator[Node]]
64 ) -> Iterator[Node]:
65 queue = [start]
66 searched = set()
67
68 while len(queue):
69 item = queue.pop(0)
70
71 for neighbour in neighbours(item):
72 if neighbour not in searched and neighbour not in set(queue):
73 queue.append(neighbour)
74
75 searched.add(item)
76
77 yield item
diff --git a/aoc/tests/__init__.py b/aoc/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/aoc/tests/__init__.py
diff --git a/aoc/tests/test_datastructures.py b/aoc/tests/test_datastructures.py
new file mode 100644
index 0000000..a7965f5
--- /dev/null
+++ b/aoc/tests/test_datastructures.py
@@ -0,0 +1,16 @@
1# -*- coding: utf-8 -*-
2from aoc.datastructures import Coordinate3
3
4
5class TestCoordinate3:
6 def test_neighbours_nodiagonal(self):
7 coordinate = Coordinate3(0, 0, 0)
8
9 assert set(coordinate.neighbours(True)) == {
10 Coordinate3(-1, 0, 0),
11 Coordinate3(1, 0, 0),
12 Coordinate3(0, -1, 0),
13 Coordinate3(0, 1, 0),
14 Coordinate3(0, 0, -1),
15 Coordinate3(0, 0, 1),
16 }