-
Notifications
You must be signed in to change notification settings - Fork 0
/
filter.py
147 lines (105 loc) · 3.83 KB
/
filter.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
from functools import lru_cache
from grid import is_connected
from grid import boundary
from grid import corners
from grid import _boundary_lengths
from debug import debug
def _filter_chiral(minos):
for mino in minos:
if mino == mino.reflect_vert(): continue
if mino == mino.reflect_horiz(): continue
if mino == mino.reflect_diag(): continue
if mino == mino.reflect_skew(): continue
yield mino
def _filter_one_sided(minos, sort=True):
"""
Remove rotations in set of minos (with history).
"""
vis = set() # visited mino rotation families
for mino in minos:
# If we haven't seen a rotation of this mino before,
# add its rotations to the visisted list
if mino not in vis:
mino_rots = mino.rotations()
vis.update(mino_rots)
# Add the (maximal rotation of the) mino
yield max(mino_rots) if sort else mino
def _filter_one_sided_mem(minos):
"""
Remove rotations in set of minos (without history).
hyp: minos has no duplicates
"""
for mino in minos:
if mino < mino.rotate_left(): continue
if mino < mino.rotate_half(): continue
if mino < mino.rotate_right(): continue
# If this mino is maximum amoung its rotations, output it
yield mino
def _filter_free(minos, sort=True):
"""
Remove rotations and reflections in the set of minos (with history).
"""
vis = set() # visited transformation families
for mino in minos:
# If we haven't seen a rotation or reflection of this mino before,
# add its transforms to the visisted list
if mino not in vis:
mino_trans = mino.transforms()
vis.update(mino_trans)
# Add the (maximal transform of the) mino
yield max(mino_trans) if sort else mino
def _filter_free_mem(minos):
"""
Remove rotations and reflections in the set of minos (without history).
hyp: minos has no duplicates
"""
for mino in minos:
if mino < mino.rotate_left(): continue
if mino < mino.rotate_half(): continue
if mino < mino.rotate_right(): continue
if mino < mino.reflect_vert(): continue
if mino < mino.reflect_horiz(): continue
if mino < mino.reflect_diag(): continue
if mino < mino.reflect_skew(): continue
# If this mino is maximum amoung its transformations, output it
yield mino
@lru_cache(maxsize=None)
def whole_grid ( h, w ) :
return set((x,y) for x in range(-1,h+1) for y in range(-1,w+1))
@lru_cache(maxsize=None)
def has_topological_property ( condition ) :
def _cnd ( mino ) :
antimino = whole_grid(mino.height, mino.width) - mino.cells
return condition(antimino)
return _cnd
def _filter_holes ( condition , minos ) :
return filter(has_topological_property(condition), minos)
def _filter_without_holes ( minos ) :
"""
Check if outside of polyomino is connected. If not, there is a hole.
"""
return _filter_holes(is_connected, minos)
def _filter_with_holes ( minos ) :
"""
Check if outside of polyomino is disconnected. If it is, there is no hole.
"""
return _filter_holes(lambda x : not is_connected(x), minos)
def _filter_with_odd_side_lengths ( minos ):
for mino in minos:
debug('polyomino')
debug('=========')
debug(mino)
debug('=========')
debug(mino.cells)
b = boundary(mino.cells, mino.origin)
debug(b)
c = corners(b)
debug(c)
if all(map(lambda x: x % 2, _boundary_lengths(c))):
debug('OK')
debug('polyomino')
debug('=========')
debug(mino)
debug('=========')
yield mino
debug('#####################################')