-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerator.py
executable file
·119 lines (94 loc) · 3.03 KB
/
generator.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
118
119
#!/usr/bin/env python
import sys
import random
import argparse
def make_puzzle(s, solvable, iterations):
def swap_empty(p):
idx = p.index(0)
poss = []
if idx % s > 0:
poss.append(idx - 1)
if idx % s < s - 1:
poss.append(idx + 1)
if idx / s > 0 and idx - s >= 0:
poss.append(idx - s)
if idx / s < s - 1:
poss.append(idx + s)
swi = random.choice(poss)
p[idx] = p[swi]
p[swi] = 0
p = make_goal(s)
for i in range(iterations):
swap_empty(p)
if not solvable:
if p[0] == 0 or p[1] == 0:
p[-1], p[-2] = p[-2], p[-1]
else:
p[0], p[1] = p[1], p[0]
return p
def make_goal(s):
ts = s * s
puzzle = [-1 for i in range(ts)]
cur = 1
x = 0
ix = 1
y = 0
iy = 0
while True:
puzzle[x + y * s] = cur
if cur == 0:
break
cur += 1
if x + ix == s or x + ix < 0 or (ix != 0 and puzzle[x + ix + y * s] != -1):
iy = ix
ix = 0
elif y + iy == s or y + iy < 0 or (iy != 0 and puzzle[x + (y + iy) * s] != -1):
ix = -iy
iy = 0
x += ix
y += iy
if cur == s * s:
cur = 0
return puzzle
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("size", type=int, help="Size of the puzzle's side. Must be >3.")
parser.add_argument("-s", "--solvable", action="store_true", default=False,
help="Forces generation of a solvable puzzle. Overrides -u.")
parser.add_argument("-u", "--unsolvable", action="store_true", default=False,
help="Forces generation of an unsolvable puzzle")
parser.add_argument("-i", "--iterations", type=int, default=10000, help="Number of passes")
args = parser.parse_args()
random.seed()
if args.solvable and args.unsolvable:
print("Can't be both solvable AND unsolvable, dummy !")
sys.exit(1)
if args.size < 3:
print("Can't generate a puzzle with size lower than 2. It says so in the help. Dummy.")
sys.exit(1)
if not args.solvable and not args.unsolvable:
solv = random.choice([True, False])
elif args.solvable:
solv = True
elif args.unsolvable:
solv = False
s = args.size
puzzle = make_puzzle(s, solvable=solv, iterations=args.iterations)
w = len(str(s * s))
print("# This puzzle is %s" % ("solvable" if solv else "unsolvable"))
print("%d" % s)
print()
for y in range(s):
for x in range(s):
print("%s" % (str(puzzle[x + y * s]).rjust(w))),
print()
class Node:
instances = 0
def __init__(self, puzzle, g=0, h=0, f=0):
self.puzzle = puzzle
self.f = f
self.g = g
self.h = h
self.parent = None
def __repr__(self): return f"< f-score={self.f}, puzzle: {self.puzzle}, g-score={self.g} >"
def __eq__(self, other): return self.puzzle == other.puzzle