diff options
-rw-r--r-- | .coverage | 1 | ||||
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | levels/level_5_slimes/level_5.22.yaml | 31 | ||||
-rwxr-xr-x | solver.py | 60 | ||||
-rw-r--r-- | tests_solver/test_solver.py | 2 |
5 files changed, 45 insertions, 50 deletions
diff --git a/.coverage b/.coverage deleted file mode 100644 index 6686567..0000000 --- a/.coverage +++ /dev/null @@ -1 +0,0 @@ -!coverage.py: This is a private format, don't read it directly!{"lines":{"/home/storage/Games/kana_quest/kana_quest_solver/solver.py":[5,17,18,20,21,23,25,27,29,45,48,51,30,31,35,38,54,56,58,69,79,108,143,150,173,192,195,204,212,219,246,255,258,265,274,308,312,320,329,339,347,357,366,391,39,42,43,61,62,63,64,65,66,67,46,80,205,207,210,81,83,84,85,86,87,88,82,90,91,93,94,95,96,92,98,99,100,105,106,109,110,111,112,70,71,72,73,74,75,76,113,114,213,215,217,115,267,268,269,49,270,266,40,116,118,119,120,121,117,123,124,125,126,127,128,129,130,131,132,134,135,136,137,138,139,140,220,222,228,229,230,231,233,236,237,239,242,243,244,141,259,193,174,175,176,177,178,144,145,146,147,148,179,181,182,151,152,154,155,156,157,159,160,161,162,158,164,165,167,208,168,171,183,184,185,186,187,188,169,313,315,317,206,316,170,166,180,189,261,262,276,277,278,279,280,281,282,283,284,275,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,304,305,260,309,101,102,103,240,104,247,248,249,252,250,253,358,359,330,321,322,323,324,325,326,331,196,197,198,199,200,202,332,334,335,336,223,224,225,226,333,360,361,362,363]}}
\ No newline at end of file @@ -2,3 +2,4 @@ __pycache__ *.pyc *.swp *.cache +.coverage diff --git a/levels/level_5_slimes/level_5.22.yaml b/levels/level_5_slimes/level_5.22.yaml new file mode 100644 index 0000000..8969f35 --- /dev/null +++ b/levels/level_5_slimes/level_5.22.yaml @@ -0,0 +1,31 @@ +# kana quest grid level 5.22 +size: [7, 4] +max_actions: 19 +#max_actions: 22 +target_score: 9 +grid: [ + [ar_d, ki ], [ar_d, null], [void, null], [slim, u ], [slim, o ], [void, null], [void, null], + [ar_u, null], [norm, null], [norm, null], [norm, null], [norm, null], [norm, null], [ar_l, si ], + [norm, null], [ar_d, null], [norm, null], [norm, null], [norm, null], [norm, null], [ar_l, nu ], + [ar_u, null], [ar_u, sa ], [ar_u, 'no'], [ar_u, he ], [ar_u, ku ], [froz, ho ], [froz, ka ], +] +# The kana 'no' need to be protected else the program convert it into False... + +# Too big to be run completly, some solutions: +#KanaGrid (cnt: 19, score: 9): +# |∧ ∧||∨ ∨| |~ u~| +# | ||∧sa∧||<so<|| || || || | +# |∨ki∨||[ka]||∧no∧||<nu<||∧ku∧|| || | +# |∧ ∧||∨ ∨||[ho]||∧he∧|| || || | +#================================================================================ +#KanaGrid (cnt: 19, score: 9): +# |∧ ∧||∨ ∨| |~ u~| +# |[ka]||∧sa∧||<so<|| || || || | +# |∨ki∨|| ||∧no∧||<nu<||∧ku∧|| || | +# |∧ ∧||∨ ∨||[ho]||∧he∧|| || || | +#================================================================================ +#KanaGrid (cnt: 19, score: 9): +# |∨ki∨||[ka]| |~ u~| +# |∧ ∧||∧sa∧||<so<|| || || || | +# | ||∨ ∨||∧no∧||<nu<||∧ku∧|| || | +# |∧ ∧||∨ ∨||[ho]||∧he∧|| || || | @@ -14,15 +14,13 @@ Options: --print Display only the original (unresolved) grid ''' -#import copy +import copy import os import pickle import time -#import zlib import docopt import yaml -import numpy class Kana: @@ -82,11 +80,7 @@ class KanaGrid: self.width = size[0] self.height = size[1] - #self.grid = grid - if type(grid) is list: - self.grid = numpy.array(grid) - else: - self.grid = grid + self.grid = copy.copy(grid) self.action_count = action_count self.score = score self.myst_count = myst_count @@ -95,15 +89,12 @@ class KanaGrid: def copy(self): new_grid = KanaGrid( (self.width, self.height), - None, - #self.grid.copy(), - #copy.copy(self.grid), + grid=self.grid, action_count=self.action_count, score=self.score, myst_count=self.myst_count, parent=self.parent, ) - new_grid.grid = self.grid.copy() return new_grid def is_swappable(self, pos1, pos2): @@ -234,19 +225,8 @@ class KanaGrid: # the bare minimum equal to 1. self.score, self.myst_count = self.longest_chain() - def get_tuple(self): - #data = ''.join(( - # str(self.width), - # str(self.height), - # str(self.grid), - # str(self.action_count), - # )) - #return zlib.crc32(data.encode('utf8')) - #return hash((self.width, self.height, str(self.grid), self.action_count)) - #my_tuple = (self.width, self.height, str(self.grid.all()), self.action_count) - #my_tuple = (self.width, self.height, str(self.grid.all()), self.action_count) - #print(f'my_tuple: {my_tuple}, hash {hash(my_tuple)}') - return (self.width, self.height, tuple(self.grid), self.action_count) + def get_grid_hashable(self): + return tuple(self.grid) def get_kana(self, pos): if pos[0] < 0 or pos[0] >= self.width: @@ -279,8 +259,6 @@ class KanaGrid: vect = (pos2[0] - pos1[0], pos2[1] - pos1[1]) while self.is_swappable(pos_src, pos_dst): - #print("swap between src %s (%s) dst %s (%s)" - # % (kana_src, pos_src, kana_dst, pos_dst)) self.set_kana(pos_src, kana_dst) self.set_kana(pos_dst, kana_src) @@ -400,9 +378,6 @@ def generate_possible_grids(kanagrid): for x in range(kanagrid.width): for action_type in KanaGrid.actions: new_grid = kanagrid.action((x, y), action_type) - #if new_grid: # and new_grid.grid != kanagrid.grid: # syntax in numpy ? - #if new_grid and not (new_grid.grid == kanagrid.grid).all(): # and new_grid.grid != kanagrid.grid: # syntax in numpy ? - #if new_grid and not numpy.array_equal(new_grid.grid, kanagrid.grid): if new_grid: # better perf to have only new_grid is None check and not # comparison if move has given same grid as having exact @@ -412,22 +387,22 @@ def generate_possible_grids(kanagrid): yield (x, y), action_type, new_grid -def generate_all_possible_grids(grid, taboos, max_actions): +def generate_all_possible_grids(grid, bests, max_actions): for pos, action_type, new_grid in generate_possible_grids(grid): - grid_hash = new_grid.get_tuple() - if grid_hash in taboos: + key = new_grid.get_grid_hashable() + if key in bests and bests[key].action_count <= new_grid.action_count: continue - taboos.add(grid_hash) + bests[key] = new_grid new_grid.parent = grid if new_grid.action_count >= max_actions: yield new_grid continue - yield from generate_all_possible_grids(new_grid, taboos, max_actions) + yield from generate_all_possible_grids(new_grid, bests, max_actions) def search_all_solution(kanagrid, target_score, max_actions): - taboos = set() - generator = generate_all_possible_grids(kanagrid, taboos=taboos, max_actions=max_actions) + bests = {} + generator = generate_all_possible_grids(kanagrid, bests=bests, max_actions=max_actions) for grid in generator: grid.update_score() if grid.score >= target_score and grid.myst_count == 0: @@ -448,16 +423,6 @@ def repr_grid_with_parents(grid): return '\n'.join(reversed(items)) -#def print_score_over(node, target_score): -# node.grid.update_score() -# if node.grid.score >= target_score: -# print("="*80) -# print(node_repr_with_parents(node)) -# return -# for child in node.children: -# print_score_over(child, target_score) - - def main(): args = docopt.docopt(__doc__) @@ -516,6 +481,5 @@ def main(): print(f'time taken to calculate: {hours:02d}:{minutes:02d}:{seconds:02d}') - if __name__ == '__main__': main() diff --git a/tests_solver/test_solver.py b/tests_solver/test_solver.py index 808804e..a1a0e67 100644 --- a/tests_solver/test_solver.py +++ b/tests_solver/test_solver.py @@ -15,7 +15,6 @@ def test_is_swappable(): [Kana("froz", "su"), Kana("norm", "su")], [Kana("norm", "su"), Kana("norm" )], [Kana("norm" ), Kana("froz", "su")], - [Kana("norm" ), Kana("norm" )], ] for swappable_grid in swappable_grids: @@ -26,6 +25,7 @@ def test_is_swappable(): not_swappable_grids = [ [Kana("norm", "su"), Kana("rock", "su")], [Kana("froz", "su"), Kana("froz", "su")], + [Kana("norm" ), Kana("norm" )], ] for not_swappable_grid in not_swappable_grids: |