From aa15b69dd8fd09e19e78c2c10753100e5e426094 Mon Sep 17 00:00:00 2001 From: vg Date: Tue, 19 May 2020 20:30:09 +0200 Subject: reduce memory consumption by always using same kanas --- solver.py | 56 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/solver.py b/solver.py index 8498f66..df62f64 100755 --- a/solver.py +++ b/solver.py @@ -17,6 +17,7 @@ Options: import copy import os import pickle +import time import zlib import docopt @@ -28,6 +29,8 @@ class Kana: 'ar_u', 'ar_r', 'ar_d', 'ar_l') slime_merge_types = ('norm', 'froz', 'ar_u', 'ar_r', 'ar_d', 'ar_l') + cache = {} + def __init__(self, type_name, kana=None): self.type_name = type_name self.kana = kana @@ -44,6 +47,13 @@ class Kana: assert kana[0] in 'kstnhmryw' assert kana[1] in 'aiueo' + def create(type_name, kana=None): + key = (type_name, kana) + if key in Kana.cache: + return Kana.cache[key] + new_kana = Kana.cache[key] = Kana(type_name, kana) + return new_kana + def dump(self): 'return a list representing the members of this Kana' return [self.type_name, self.kana] @@ -54,7 +64,8 @@ class Kana: def __eq__(self, other): return self.type_name == other.type_name and self.kana == other.kana -kana_void = Kana('void') + +kana_void = Kana.create('void') class KanaGrid: @@ -95,6 +106,12 @@ class KanaGrid: } if kana1.type_name in table_ok: if kana2.type_name in table_ok[kana1.type_name]: + + # early return for empty norm to empty norm + if kana1.type_name == kana2.type_name == 'norm' \ + and kana1.kana is kana2.kana is None: + return False + ar_vect_ok = { 'ar_u': ( 0, -1), 'ar_l': (-1, 0), @@ -117,7 +134,7 @@ class KanaGrid: if kana.type_name == 'myst': new_grid = self.copy() new_grid.action_count += 1 - new_grid.set_kana(pos, Kana('norm', kana.kana)) + new_grid.set_kana(pos, Kana.create('norm', kana.kana)) return new_grid elif action_type in ('up', 'right', 'down', 'left'): pos_map = { @@ -130,10 +147,13 @@ class KanaGrid: if kana.type_name == 'slim': kana2 = self.get_kana(pos_dest) if kana2.type_name in Kana.slime_merge_types and kana2.kana: + # early return for slime merging for same vowel + if kana2.kana[1] == kana.kana[0]: + return new_grid = self.copy() new_grid.action_count += 1 - new_kana1 = Kana('void') - new_kana2 = Kana( + new_kana1 = kana_void + new_kana2 = Kana.create( kana2.type_name, kana2.kana[0] + kana.kana[0], ) @@ -196,7 +216,10 @@ class KanaGrid: #, highest_length_chain # easy to add if needed def update_score(self): - self.score, self.myst_count = self.longest_chain() + if not self.score: + # if self.score == 0 calculate the score as the score is always at + # the bare minimum equal to 1. + self.score, self.myst_count = self.longest_chain() def get_hash(self): data = ''.join(( @@ -221,6 +244,7 @@ class KanaGrid: elif pos[1] < 0 or pos[1] >= self.height: return self.grid[pos[0]+pos[1]*self.width] = kana + self.score = 0 def swap_kana(self, pos1, pos2): kana_dst = self.get_kana(pos2) @@ -250,12 +274,10 @@ class KanaGrid: kana_dst = self.get_kana(pos_dst) def load(input_dict): - grid = [] - for serialized_kana in input_dict['grid']: - if serialized_kana[0] == 'void': - grid.append(kana_void) - else: - grid.append(Kana(serialized_kana[0], serialized_kana[1])) + grid = [ + Kana.create(serialized_kana[0], serialized_kana[1]) + for serialized_kana in input_dict['grid'] + ] params = { 'size': input_dict['size'], 'grid': grid, @@ -425,11 +447,12 @@ def main(): if args['--print']: return + solver_start_time = int(time.time()) mtime = os.path.getmtime cache_file = '%s.cache' % grid_fn if os.path.exists(cache_file) and mtime(cache_file) >= mtime(grid_fn): - print('DEBUG: USING CACHED VERSION') + print(f'Using cached version from {cache_file}') with open(cache_file, 'rb') as stream: cached_version = pickle.load(stream) generator = get_solutions_from_cache(cached_version) @@ -455,6 +478,15 @@ def main(): with open(cache_file, 'wb') as stream: pickle.dump(cache_generation, stream) + solver_stop_time = int(time.time()) + solver_delta_time = solver_stop_time - solver_start_time + hours = solver_delta_time // 3600 + minutes = (solver_delta_time // 60) % 60 + seconds = solver_delta_time % 60 + + print(f'time taken to calculate: {hours:02d}:{minutes:02d}:{seconds:02d}') + + if __name__ == '__main__': main() -- cgit v1.2.3