-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
148 lines (116 loc) · 3.67 KB
/
main.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
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
import sys
import time
import typing as t
from dataclasses import dataclass
from functools import reduce
from operator import mul
from enum import Enum, auto
from solver import (
Cube, rotate, generate_cube, CubeAddError,
get_all_cubes, get_all_rotates, cube_rotation, print_c, Fragment
)
from data import figures as figures_
def to_fragment(name, fragment_coords):
base, *others = fragment_coords
mx, my, mz = base
return Fragment(
name=name,
coords=tuple((x - mx, y - my, z - mz) for x, y, z in others)
)
class MsgTypes(Enum):
VARIANTS = auto()
PROGRESS = auto()
FOUNDED = auto()
END = auto()
TOTAL = auto()
@dataclass
class Msg:
type: MsgTypes
payload: t.Any | None
def __iter__(self):
return iter((self.type, self.payload))
def calculate(figures):
def send(msg_type, msg):
return Msg(msg_type, msg)
base, *others = figures
e_cube = Cube(generate_cube(3))
base_cubes = list(get_all_cubes(e_cube, base))
base_cubes_ = []
cbs = set()
for base_c in base_cubes:
if base_c in cbs:
continue
base_cubes_.append(base_c)
for rotations in get_all_rotates():
rotated = cube_rotation(base_c, rotations)
cbs.add(rotated)
cubes_set = []
for fig in others:
current_set = set()
for rotations in get_all_rotates():
rotated = rotate(fig, rotations)
for c in get_all_cubes(e_cube, rotated):
current_set.add(c)
cubes_set.append(current_set)
common_time = time.time()
cubes_set.insert(0, base_cubes_)
count = 0
counts = [len(c_set) for c_set in cubes_set] + [1]
all_solutions = reduce(mul, counts)
sols_c = [reduce(mul, counts[cp:]) for cp in range(len(counts))]
yield send(MsgTypes.VARIANTS, all_solutions)
tasks = [(e_cube, cube, 0) for cube in cubes_set[0]]
while tasks:
cube, new_cube, pos = tasks.pop()
try:
pos += 1
cube = cube + new_cube
if pos == len(figures):
yield send(MsgTypes.FOUNDED, cube)
count += 1
continue
tasks.extend((cube, new_cube, pos) for new_cube in cubes_set[pos])
yield send(MsgTypes.PROGRESS, count)
except CubeAddError:
count += sols_c[pos]
yield send(MsgTypes.PROGRESS, count)
yield send(MsgTypes.TOTAL, time.time() - common_time)
yield send(MsgTypes.END, None)
colors = [
"#fcb33d", "#ffe7bf", "#fadaa4", "#ffd58f", "#fac670", "#ffbd52",
]
colors = colors * 10
def consumer_(gen):
count_variants = None
results = []
for msgtype, value in gen:
match msgtype:
case MsgTypes.VARIANTS:
count_variants = value
print(f'Всего вариантов: {value}')
continue
case MsgTypes.PROGRESS:
progress = int(value / count_variants * 50)
sys.stdout.write(f"\rПрогресс: ·{'>' * progress}{' ' * (50 - progress)}·")
sys.stdout.flush()
continue
case MsgTypes.FOUNDED:
results.append(value)
continue
case MsgTypes.TOTAL:
print(f'\nЗатрачено {value:.3} sec')
continue
case MsgTypes.END:
for res in results:
print("\nНайдено решение:\n")
print_c(res)
return
def main():
try:
consumer_(
calculate(figures_)
)
except StopIteration:
pass
if __name__ == '__main__':
main()