diff options
Diffstat (limited to 'solver.py')
-rwxr-xr-x | solver.py | 87 |
1 files changed, 45 insertions, 42 deletions
@@ -20,10 +20,8 @@ import yaml class Kana: - types_without_kana = ('void', 'empt', 'fblk') - types_valid_for_chain = ('norm', 'froz', 'rock', 'ar_u', 'ar_l', 'ar_d', 'ar_r') - types_with_kana = types_valid_for_chain + ('myst', ) - types_all = types_with_kana + types_without_kana + types = ('void', 'norm', 'froz', 'rock', 'myst', + 'ar_u', 'ar_l', 'ar_d', 'ar_r') def __init__(self, type_name, kana=None): self.type_name = type_name @@ -31,10 +29,12 @@ class Kana: #print(type_name) #print(kana) - assert type_name in self.types_all - if type_name in self.types_with_kana: - assert kana[0] in ('k', 's', 'n', 'h', 't', 'm') - assert kana[1] in ('a', 'i', 'u', 'e', 'o') + assert type_name in self.types + + # missing yet: 'n' and 'y...' and 'w...' are not we all vowels + if kana: + assert kana[0] in 'kstnhmryw' + assert kana[1] in 'aiueo' def __repr__(self): return "%s(%s)" % (self.type_name, self.kana) @@ -47,14 +47,16 @@ kana_void = Kana('void') class KanaGrid: - def __init__(self, size, grid, action_count=0, score=0, parent=None): + def __init__(self, size, grid, + action_count=0, score=0, myst_count=0, parent=None): self.width = size[0] self.height = size[1] self.grid = grid self.action_count = action_count self.score = score - self.parent = None + self.myst_count = myst_count + self.parent = parent def copy(self): return KanaGrid( @@ -62,21 +64,20 @@ class KanaGrid: copy.copy(self.grid), action_count=self.action_count, score=self.score, + myst_count=self.myst_count, parent=self.parent, - ) + ) def is_swappable(self, pos1, pos2): kana1 = self.get_kana(pos1) kana2 = self.get_kana(pos2) table_ok = { - 'norm': ('norm', 'empt', 'froz', 'fblk', 'ar_u', 'ar_r', 'ar_d', 'ar_l'), - 'empt': ('norm', 'froz', 'fblk', 'ar_u', 'ar_r', 'ar_d', 'ar_l'), - 'froz': ('norm', 'empt', 'ar_u', 'ar_r', 'ar_d', 'ar_l'), - 'fblk': ('norm', 'empt', 'ar_u', 'ar_r', 'ar_d', 'ar_l'), - 'ar_u': ('norm', 'empt', 'froz', 'fblk', 'ar_d' ), - 'ar_r': ('norm', 'empt', 'froz', 'fblk', 'ar_l'), - 'ar_d': ('norm', 'empt', 'froz', 'fblk', 'ar_u' ), - 'ar_l': ('norm', 'empt', 'froz', 'fblk', 'ar_r' ), + 'norm': ('norm', 'froz', 'ar_u', 'ar_r', 'ar_d', 'ar_l'), + 'froz': ('norm', 'ar_u', 'ar_r', 'ar_d', 'ar_l'), + 'ar_u': ('norm', 'froz', 'ar_d' ), + 'ar_r': ('norm', 'froz', 'ar_l'), + 'ar_d': ('norm', 'froz', 'ar_u' ), + 'ar_l': ('norm', 'froz', 'ar_r' ), } if kana1.type_name in table_ok: if kana2.type_name in table_ok[kana1.type_name]: @@ -123,13 +124,16 @@ class KanaGrid: for y in range(self.height): for x in range(self.width): kana = self.get_kana((x, y)) - if kana.type_name in Kana.types_valid_for_chain: + if kana.kana: yield (x, y) def populate_chain(self, pos1, chain_positions): + myst_count = 0 if pos1 in chain_positions: - return + return myst_count kana1 = self.get_kana(pos1) + if kana1.type_name == 'myst': + myst_count += 1 chain_positions.add(pos1) pos2_list = [ (pos1[0], pos1[1]-1), # up @@ -141,27 +145,32 @@ class KanaGrid: if pos2 in chain_positions: continue kana2 = self.get_kana(pos2) - if kana2.type_name in Kana.types_valid_for_chain: + if kana2.kana: if is_kana_compatible(kana1, kana2): - self.populate_chain(pos2, chain_positions) + myst_count += self.populate_chain(pos2, chain_positions) + return myst_count def longest_chain(self): already_evaluated_pos = set() highest_length = 0 highest_length_chain = 0 + highest_myst_count = 0 for pos in self.generate_valid_pos_for_chain(): if pos in already_evaluated_pos: continue chain = set() - self.populate_chain(pos, chain) + myst_count = self.populate_chain(pos, chain) already_evaluated_pos = already_evaluated_pos.union(chain) + if myst_count > highest_myst_count: + highest_myst_count = myst_count if highest_length < len(chain): highest_length = len(chain) highest_length_chain = chain - return highest_length #, highest_length_chain # easy to add if needed + return highest_length, highest_myst_count + #, highest_length_chain # easy to add if needed def update_score(self): - self.score = self.longest_chain() + self.score, self.myst_count = self.longest_chain() def get_hash(self): data = ''.join(( @@ -244,14 +253,14 @@ class KanaGrid: def repr_grid(grid, grid_size): indicator_map = { + 'norm': (' ', ' '), + 'froz': ('\x1b[36m[', ']\x1b[0m'), + 'rock': (' \x1b[1;40m', '\x1b[0m '), + 'myst': ('\x1b[33m?', '?\x1b[0m'), 'ar_u': ('\x1b[30m∧\x1b[0m', '\x1b[30m∧\x1b[0m'), 'ar_r': ('\x1b[30m>\x1b[0m', '\x1b[30m>\x1b[0m'), 'ar_d': ('\x1b[30m∨\x1b[0m', '\x1b[30m∨\x1b[0m'), 'ar_l': ('\x1b[30m<\x1b[0m', '\x1b[30m<\x1b[0m'), - 'froz': (' \x1b[36m', '\x1b[0m '), - 'fblk': (' \x1b[36m[]', '\x1b[0m '), - 'rock': (' \x1b[1;40m', '\x1b[0m '), - 'myst': ('\x1b[33m?', '?\x1b[0m'), } lines = [] kana_iter = iter(grid) @@ -260,23 +269,17 @@ def repr_grid(grid, grid_size): for x in range(grid_size[0]): kana = next(kana_iter) tname = kana.type_name + kkana = kana.kana + if not kkana: + kkana = ' ' if tname == 'void': line += ' ' - elif tname == 'empt': - line += '| |' - elif tname == 'fblk': - line += '|%s%s|' % ( - indicator_map[tname][0], - indicator_map[tname][1], - ) elif tname in indicator_map: line += '|%s%s%s|' % ( indicator_map[tname][0], - kana.kana, + kkana, indicator_map[tname][1], ) - elif kana.type_name in Kana.types_with_kana: - line += '| %s |' % kana.kana lines.append(line) return '\n'.join(lines) @@ -298,7 +301,7 @@ def generate_possible_grids(kanagrid): new_grid = kanagrid.action((x, y), action_type) #if new_grid and new_grid.grid != kanagrid.grid: # yield (x, y), action_type, new_grid - if new_grid is not None: + if new_grid is not None and new_grid.grid != kanagrid.grid: yield (x, y), action_type, new_grid # debug test @@ -350,7 +353,7 @@ def main(): generate_all_possible_grids(kanagrid, grids=grids, max_actions=max_actions) for grid in grids.values(): grid.update_score() - if grid.score >= target_score: + if grid.score >= target_score and grid.myst_count == 0: print("="*80) if args['-p']: print(repr_grid_with_parents(grid)) |