Compare commits
2 Commits
21b9ce7ad7
...
f3a6257cd4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3a6257cd4 | ||
|
|
52142da3f3 |
@@ -15,16 +15,8 @@ class BruteForceSolver:
|
|||||||
self.game.set_direction(x, y, Direction.UP)
|
self.game.set_direction(x, y, Direction.UP)
|
||||||
|
|
||||||
def solve(self) -> Generator[None]:
|
def solve(self) -> Generator[None]:
|
||||||
attempts = 0
|
|
||||||
required = 4 ** (self.game.width * self.game.height)
|
|
||||||
while not self.game.solved():
|
while not self.game.solved():
|
||||||
yield
|
yield
|
||||||
attempts += 1
|
|
||||||
|
|
||||||
print(
|
|
||||||
f"{attempts:0>{len(str(required))}}/{required} ({attempts / required * 100}%) ",
|
|
||||||
end="\r",
|
|
||||||
)
|
|
||||||
self.game.turn_cw(0, 0)
|
self.game.turn_cw(0, 0)
|
||||||
for prev, curr in pairwise(
|
for prev, curr in pairwise(
|
||||||
chain(
|
chain(
|
||||||
|
|||||||
24
src/algorithms/profile.py
Normal file
24
src/algorithms/profile.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import time
|
||||||
|
from multiprocessing import Pool
|
||||||
|
|
||||||
|
from src.algorithms.bruteforce import BruteForceSolver
|
||||||
|
from src.net import NetGame
|
||||||
|
|
||||||
|
|
||||||
|
def test_run() -> float:
|
||||||
|
game = NetGame(3, 3)
|
||||||
|
solver = BruteForceSolver(game)
|
||||||
|
a = time.perf_counter()
|
||||||
|
for _ in solver.solve():
|
||||||
|
pass
|
||||||
|
b = time.perf_counter()
|
||||||
|
return b - a
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
total = 0
|
||||||
|
with Pool() as p:
|
||||||
|
processes = [p.apply_async(test_run) for _ in range(100)]
|
||||||
|
for proc in processes:
|
||||||
|
total += proc.get()
|
||||||
|
print(total)
|
||||||
122
src/algorithms/wfc.py
Normal file
122
src/algorithms/wfc.py
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
from netTypes import Direction, PieceType
|
||||||
|
from src.net import NetGame
|
||||||
|
|
||||||
|
|
||||||
|
class WFCSolver:
|
||||||
|
game: NetGame
|
||||||
|
observed: list[list[bool]]
|
||||||
|
possible_connections: list[list[set[Direction]]]
|
||||||
|
|
||||||
|
def __init__(self, game: NetGame) -> None:
|
||||||
|
self.game = game
|
||||||
|
self.observed = [[False] * self.game.width for _ in range(self.game.height)]
|
||||||
|
self.possible_connections = [
|
||||||
|
[
|
||||||
|
{Direction.UP, Direction.RIGHT, Direction.DOWN, Direction.LEFT}
|
||||||
|
for _ in range(self.game.width)
|
||||||
|
]
|
||||||
|
for _ in range(self.game.width)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Es kann nicht mit dem Rand des Feldes eine Verbindung bestehen
|
||||||
|
for column in self.possible_connections:
|
||||||
|
column[0].remove(Direction.UP)
|
||||||
|
column[-1].remove(Direction.DOWN)
|
||||||
|
|
||||||
|
for i in range(len(self.possible_connections[0])):
|
||||||
|
self.possible_connections[0][i].remove(Direction.LEFT)
|
||||||
|
|
||||||
|
for i in range(len(self.possible_connections[-1])):
|
||||||
|
self.possible_connections[-1][i].remove(Direction.RIGHT)
|
||||||
|
|
||||||
|
def get_possible_directions(self, x: int, y: int) -> set[Direction]:
|
||||||
|
ptype = self.game.get_piece(x, y).type
|
||||||
|
dirs = self.possible_connections[x][y]
|
||||||
|
if ptype == PieceType.NODE:
|
||||||
|
return dirs
|
||||||
|
elif ptype == PieceType.CORNER:
|
||||||
|
possible: set[Direction] = set()
|
||||||
|
if dirs.union({Direction.UP, Direction.RIGHT}):
|
||||||
|
possible.add(Direction.UP)
|
||||||
|
if dirs.union({Direction.RIGHT, Direction.DOWN}):
|
||||||
|
possible.add(Direction.RIGHT)
|
||||||
|
if dirs.union({Direction.DOWN, Direction.LEFT}):
|
||||||
|
possible.add(Direction.DOWN)
|
||||||
|
if dirs.union({Direction.LEFT, Direction.UP}):
|
||||||
|
possible.add(Direction.LEFT)
|
||||||
|
return possible
|
||||||
|
elif ptype == PieceType.STRAIGHT:
|
||||||
|
if len(dirs) == 4:
|
||||||
|
return dirs
|
||||||
|
elif {Direction.UP, Direction.DOWN}.issubset(dirs):
|
||||||
|
return {Direction.UP}
|
||||||
|
elif {Direction.LEFT, Direction.RIGHT}.issubset(dirs):
|
||||||
|
return {Direction.RIGHT}
|
||||||
|
else:
|
||||||
|
return set()
|
||||||
|
else:
|
||||||
|
if len(dirs) == 4:
|
||||||
|
return dirs
|
||||||
|
elif len(dirs) == 3:
|
||||||
|
not_connected = (
|
||||||
|
{Direction.UP, Direction.DOWN, Direction.LEFT, Direction.RIGHT}
|
||||||
|
.difference(dirs)
|
||||||
|
.pop()
|
||||||
|
)
|
||||||
|
return {Direction((not_connected + 2) % 4)}
|
||||||
|
else:
|
||||||
|
return set()
|
||||||
|
|
||||||
|
def get_possible_direction_count(self, x: int, y: int) -> int:
|
||||||
|
ptype = self.game.get_piece(x, y).type
|
||||||
|
connectable = self.possible_connections[x][y]
|
||||||
|
camount = len(connectable)
|
||||||
|
if camount == 4:
|
||||||
|
return 4
|
||||||
|
if ptype == PieceType.NODE:
|
||||||
|
return camount
|
||||||
|
elif ptype == PieceType.CORNER:
|
||||||
|
if camount == 3:
|
||||||
|
return 2
|
||||||
|
elif (
|
||||||
|
camount == 2
|
||||||
|
and connectable != {Direction.UP, Direction.DOWN}
|
||||||
|
and connectable != {Direction.LEFT, Direction.RIGHT}
|
||||||
|
): # 2 nicht-gegenüberliegende seiten
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
elif ptype == PieceType.STRAIGHT:
|
||||||
|
if camount == 4:
|
||||||
|
return 4
|
||||||
|
elif (
|
||||||
|
camount == 3
|
||||||
|
or connectable == {Direction.UP, Direction.DOWN}
|
||||||
|
or connectable == {Direction.LEFT, Direction.RIGHT}
|
||||||
|
):
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
else: # T-JUNCTION
|
||||||
|
if camount == 4:
|
||||||
|
return 4
|
||||||
|
elif camount == 3:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def solve(self) -> None:
|
||||||
|
coordinates = list(
|
||||||
|
((i, j) for i in range(self.game.width) for j in range(self.game.height))
|
||||||
|
)
|
||||||
|
while not self.game.solved():
|
||||||
|
(x, y) = min(
|
||||||
|
coordinates, key=lambda t: self.get_possible_direction_count(*t)
|
||||||
|
)
|
||||||
|
if self.get_possible_direction_count(x, y) == 0:
|
||||||
|
raise NotImplementedError(
|
||||||
|
"Irgendwo eine falsche Richtung gewählt, muss diese Logik noch schreiben"
|
||||||
|
)
|
||||||
|
direction = self.get_possible_directions(x, y).pop()
|
||||||
|
self.game.set_direction(x, y, direction)
|
||||||
|
# TODO: Nachbaren updaten
|
||||||
Reference in New Issue
Block a user