2015-10-09 14 views
8

Jest ta gra na iOS i Andriod o nazwie Puzzle numer 9 (Nie jestem w żaden sposób związany z twórcami). Zaczynasz od siatki 3x3, w której liczby od 1 do 9 są losowo umieszczane na planszy. Następnie łączymy sąsiednie liczby (śledzenie ścieżki), aby dodać do 9. Ostateczny węzeł na ścieżce staje się 9, a wszystkie inne liczby zwiększają się o 1. Łączymy te same wielokrotności 9 razem, gdy węzeł końcowy staje się dwa razy większy od liczby a początkowy węzeł powraca do jednego. Na przykład, jeśli zaczniesz zJak zrobić skuteczny solver dla Puzzle numer 9

1 2 3 
5 4 6 
7 8 9 

można zacząć 2-3-4 i skończyć z

1 3 4 
5 9 6 
7 8 9 

a następnie połączyć dwa 9 za

1 3 4 
5 1 6 
7 8 18 

The cel gra ma osiągnąć 1152. Zasadniczo jest to 2048, ale bez elementów stochastycznych. Gra kończy się, gdy zabraknie numerów, które sumują się do 9, na przykład

8 7 6 
5 5 5 
9 1 72 

napisałem prosty przeszukiwanie w głąb na python działa dla niektórych zagadek, ale zabrakło pamięci do innych łamigłówek:

import sys 
import Queue 

conf = "213 547 689" 
grid1 = [] 
for y in conf.split(): 
    for x in y: 
     grid1.append(int(x)) 

a = [] 
explored = set() 
sol = Queue.LifoQueue() 

def tostr(node): 
    s = '' 
    for i in range(0,9): 
     s += str(node[i]) + ' ' 
    return s 

def printsol(): 
    while not sol.empty(): 
     print sol.get()   

def same(x, y, grid): 
    for n in neighbors(y): 
     ng = grid[:] 
     if grid[n] == x and n != y: 
      if x == 576: 
       printsol() 
       sys.exit() 
      ng[n] = 2*x 
      ng[y] = 1 
      sol.put(tostr(ng)) 
      same(2*x, n, ng) 
      solve(ng, grid) 
      sol.get() 
      ng[n] = 1 
      ng[y] = 2*x 
      sol.put(tostr(ng)) 
      same(2*x, y, ng) 
      solve(ng, grid) 
      sol.get() 

##succeeding functions are edited versions of Boggle solver from http://stackoverflow.com/questions/746082/how-to-find-list-of-possible-words-from-a-letter-matrix-boggle-solver 
def solve(grid2, grid1): 
    for i in range(0,9): 
     if grid2[i] < 9 and tostr(grid2) not in explored: 
      for result in extending(grid2[i], (i,), grid2): 
       newgrid = grid2[:] 
       y = len(result) - 1 
       for j in range(0, y): 
        newgrid[result[j]] += 1 
       newgrid[result[y]] = 9 
       sol.put(tostr(newgrid)) 
       if tostr(newgrid) not in explored: 
        same(9, result[y], newgrid) 
        solve(newgrid, grid2) 
       sol.get() 
    explored.add(tostr(grid2)) 

def extending(add, path, grid2): 
    if add == 9: 
     yield path 
    for n in neighbors(path[-1]): 
     if n not in path: 
      add1 = add + grid2[n] 
      if add1 <= 9: 
       for result in extending(add1, path + (n,), grid2): 
        yield result 

def neighbors(n): 
    for nx in range(max(0, n%3-1), min(n%3+2, 3)): 
     for ny in range(max(0, n/3-1), min(n/3+2, 3)): 
      yield ny*3+nx 

sol.put(tostr(grid1)) 
solve(grid1, grid1) 

W jaki sposób zwiększasz wydajność? Jeśli nie to, jaka byłaby dobra heurystyka dla świadomego wyszukiwania? Zastanawiałem się nad absolutną różnicą średniej liczby na tablicy od pewnej liczby, ale jaka byłaby dobra liczba?

+0

"łączysz sąsiednie numery". jak definiujesz "sąsiednie"? czy masz to, gdy mają wspólną krawędź lub bok? – svs

+0

'Łączysz te same wielokrotności 9'. czy dozwolone są tylko sąsiednie elementy? – svs

+0

możesz prześledzić ścieżkę i numery muszą być jakoś połączone (powyżej, poniżej, po lewej, prawej, po przekątnej) i te same wielokrotności 9 muszą być w sąsiedztwie również – Bruha

Odpowiedz

-1

Kwestia jest dość prosta: system DFS przejdzie jedną ścieżkę do momentu jej zakończenia. W ten sposób otrzymasz ogromny zestaw discovered zawierający wysokie wartości, które nigdy nie zostaną użyte. Zamiast tego użyj BFS lub A *.

+0

, ale co to jest dobra heurystyka? – Bruha

+0

@Bruha najprostszym byłoby po prostu użyć liczby sposobów łączenia liczb do 9 lub wielokrotności 9, aby porównać różne stany. możesz wziąć pod uwagę sumę liczb w stanie. Będziesz musiał trochę eksperymentować z ważeniem pojedynczych wartości/dodawać inne wartości w celu zoptymalizowania heurystyki – Paul

0

pisałem coś jakiś czas temu i opublikował je tutaj: http://sourceforge.net/p/puzzlenumber9

swoim rodzaju o poszukiwaniu brute-force, ale sortowania opcje zwrócone na każdej głębokości, jak również ograniczyć głębokość zrobić to szybciej. Po prostu nie pamiętam, jak sortuję i ograniczam głębokość, LOL. (Przyjrzę się kodowi i dodam, że później, gdy mam czas ... Myślę, że kod pobiera właśnie ustaloną małą liczbę wyników na każdej głębokości, gdzie ostatni bieg miał najwyższą sumę.)

Pamiętam, że po odczuciu satysfakcji, że program zwraca rozwiązanie, wejście na ścieżkę porusza się jeden po drugim na urządzeniu wydawało się dość nudne :)

To co podoba mi się w tym kodzie to to, że został przypadkowo połączony w zasadzie "wykonywać pracę" bez wysiłku w poszukiwaniu najbardziej zwięzłego i skutecznego podejścia. Szczególnie podoba mi się długa lista case ix of, ikonologicznie przeciwstawiająca się uproszczeniom funkcjonalnym.

kod Haskell:

{-# OPTIONS_GHC -O2 #-} 
import Data.List (sortBy,nubBy) 
import Data.Ord (compare) 
import System.Time 

main = do 
    putStrLn "Puzzle Number 9 Solver Copyright May 2015 alhambra1" 
    putStrLn "\nEnter 'e' at any time to exit" 
    putStrLn "\nEnter target number" 
    target <- getLine 
    if null target 
     then main 
     else if head target == 'e'  
       then return()   
       else do 
         putStrLn "Enter number of moves at each choice point (density, 3 to 6 recommended)" 
         density <- getLine 
         if null density 
          then main 
          else if head density == 'e'  
            then return()   
            else do 
             putStrLn "Enter board numbers separated by spaces" 
             board <- getLine 
             if null board 
              then main 
              else if head board == 'e'  
                then return()   
                else do 
                 putStrLn "" 
                 time1 <- getClockTime 
                 let b = map (\x -> read x :: Int) (take 9 $ words board) 
                  t = read (head (words target)) :: Int 
                  d = read (head (words density)) :: Int 
                 print (map reverse $ reverse $ head $ take 1 $ f t b [] d) 
                 time2 <- getClockTime 
                 putStrLn "" 
                 print (timeDiffToString $ diffClockTimes time2 time1) 
                 putStrLn "" 
                 exit 

exit = do 
    putStrLn "Enter 'a' to start again or 'e' to exit" 
    line <- getLine 
    if null line 
     then exit 
      else if head line == 'a' 
        then do putStrLn "" 
          main 
          else if head line == 'e' 
            then return() 
            else exit 

f target board paths toTake 
    | not (null hasTarget) = [(((\(x,y,z)-> z) . head $ hasTarget):paths)] 
    | null ms    = [] 
    | otherwise   = do (s,bd,idxs) <- take toTake (sortBy (\(x,y,z) (x',y',z') -> compare x' x) ms') 
           f target bd (idxs:paths) toTake 
where hasTarget = filter ((==target) . (\(x,y,z)-> x)) ms 
     ms = moves board 
     ms' = nubBy (\(x,y,z) (x',y',z') -> let a = drop 1 (init z) 
               b = drop 1 (init z') 
              in if not (null a) && not (null b) 
               then a == b 
               else False) ms 

moves board = do j <- [1..9] 
       let num = board !! (j - 1) 
        board' = (take (j - 1) board) ++ [num + 1] ++ (drop j board) 
       moves' j board' num [j] 0 num 
where moves' ix board s idxs prev next 
     | (s == 9 || multiple) && (length idxs > 1) = [(s,board',idxs)] 
     | s > 9 && mod s 9 /= 0 = [] 
     | otherwise = case ix of 
      1 -> if elem 2 idxs then [] else moves' 2 board' (s + b) (2:idxs) next b 
       ++ (if elem 4 idxs then [] else moves' 4 board' (s + d) (4:idxs) next d) 
       ++ (if elem 5 idxs then [] else moves' 5 board' (s + e) (5:idxs) next e) 
      2 -> if elem 1 idxs then [] else moves' 1 board' (s + a) (1:idxs) next a 
       ++ (if elem 3 idxs then [] else moves' 3 board' (s + c) (3:idxs) next c) 
       ++ (if elem 4 idxs then [] else moves' 4 board' (s + d) (4:idxs) next d) 
       ++ (if elem 5 idxs then [] else moves' 5 board' (s + e) (5:idxs) next e) 
       ++ (if elem 6 idxs then [] else moves' 6 board' (s + f) (6:idxs) next f) 
      3 -> if elem 2 idxs then [] else moves' 2 board' (s + b) (2:idxs) next b 
       ++ (if elem 5 idxs then [] else moves' 5 board' (s + e) (5:idxs) next e) 
       ++ (if elem 6 idxs then [] else moves' 6 board' (s + f) (6:idxs) next f) 
      4 -> if elem 1 idxs then [] else moves' 1 board' (s + a) (1:idxs) next a 
       ++ (if elem 2 idxs then [] else moves' 2 board' (s + b) (2:idxs) next b) 
       ++ (if elem 5 idxs then [] else moves' 5 board' (s + e) (5:idxs) next e) 
       ++ (if elem 7 idxs then [] else moves' 7 board' (s + g) (7:idxs) next g) 
       ++ (if elem 8 idxs then [] else moves' 8 board' (s + h) (8:idxs) next h) 
      5 -> if elem 1 idxs then [] else moves' 1 board' (s + a) (1:idxs) next a 
       ++ (if elem 2 idxs then [] else moves' 2 board' (s + b) (2:idxs) next b) 
       ++ (if elem 3 idxs then [] else moves' 3 board' (s + c) (3:idxs) next c) 
       ++ (if elem 4 idxs then [] else moves' 4 board' (s + d) (4:idxs) next d) 
       ++ (if elem 6 idxs then [] else moves' 6 board' (s + f) (6:idxs) next f) 
       ++ (if elem 7 idxs then [] else moves' 7 board' (s + g) (7:idxs) next g) 
       ++ (if elem 8 idxs then [] else moves' 8 board' (s + h) (8:idxs) next h) 
       ++ (if elem 9 idxs then [] else moves' 9 board' (s + i) (9:idxs) next i) 
      6 -> if elem 2 idxs then [] else moves' 2 board' (s + b) (2:idxs) next b 
       ++ (if elem 3 idxs then [] else moves' 3 board' (s + c) (3:idxs) next c) 
       ++ (if elem 5 idxs then [] else moves' 5 board' (s + e) (5:idxs) next e) 
       ++ (if elem 8 idxs then [] else moves' 8 board' (s + h) (8:idxs) next h) 
       ++ (if elem 9 idxs then [] else moves' 9 board' (s + i) (9:idxs) next i) 
      7 -> if elem 4 idxs then [] else moves' 4 board' (s + d) (4:idxs) next d 
       ++ (if elem 5 idxs then [] else moves' 5 board' (s + e) (5:idxs) next e) 
       ++ (if elem 8 idxs then [] else moves' 8 board' (s + h) (8:idxs) next h) 
      8 -> if elem 4 idxs then [] else moves' 4 board' (s + d) (4:idxs) next d 
       ++ (if elem 5 idxs then [] else moves' 5 board' (s + e) (5:idxs) next e) 
       ++ (if elem 6 idxs then [] else moves' 6 board' (s + f) (6:idxs) next f) 
       ++ (if elem 7 idxs then [] else moves' 7 board' (s + g) (7:idxs) next g) 
       ++ (if elem 9 idxs then [] else moves' 9 board' (s + i) (9:idxs) next i) 
      9 -> if elem 5 idxs then [] else moves' 5 board' (s + e) (5:idxs) next e 
       ++ (if elem 6 idxs then [] else moves' 6 board' (s + f) (6:idxs) next f) 
       ++ (if elem 8 idxs then [] else moves' 8 board' (s + h) (8:idxs) next h) 
      where multiple = length idxs == 2 && prev == next && mod s 9 == 0 
       [a,b,c,d,e,f,g,h,i] = board 
       board' = if s == 9 
          then (take (headIdxs - 1) board) ++ [9] ++ (drop headIdxs board) 
          else if multiple 
            then board'' 
            else (take (headIdxs - 1) board) ++ [next + 1] ++ (drop headIdxs board) 
       board'' = map (\(x,y) -> if x == headIdxs then y * 2 else if x == last idxs then 1 else y) (zip [1..] board) 
       headIdxs = head idxs 
1

Celem gry jest dotarcie 1152

udało mi się to zrobić! Oto przykładowe wyniki wyszukiwania.W pierwszym wierszu trzy liczby to: wynik stanu, głębokość wykresu i maksymalny element z macierzy. Na kolejnych trzech jest macierzą sama:

... 
-577 246 576 
    36 288 9 
    1 1 576 
144 36 72 

-577 245 576 
    36 288 18 
    18 1 576 
144 9 72 

-577 249 576 
    1 288 9 
    1 288 576 
    1 1 1 

-577 245 576 
    36 288 1 
    18 18 576 
144 9 72 

-577 250 576 
    1 1 9 
    1 576 576 
    1 1 1 

-1153 251 1152 
    1 1 9 
    1 1 1152 
    1 1 1 

-1153 251 1152 
    1 1 9 
    1 1152 1 
    1 1 1 

-577 250 576 
    1 576 9 
    1 1 576 
    1 1 1 

-1153 251 1152 
    1 1 9 
    1 1 1152 
    1 1 1 

-1153 251 1152 
    1 1152 9 
    1 1 1 
    1 1 1 
... 

Jak widać, aby uzyskać wynik trzeba zbadać dość głęboko. Weź również pod uwagę, że współczynnik rozgałęzienia jest bardzo duży i możesz zauważyć, że problem stanowi wyzwanie. Musisz wykonać ~ ruchów, aby uzyskać wynik . Zakładając, że zabierze Ci to sekund na ruch, będziesz grać w grę dla 40min !!!

To, co zrobiłem, przypisałem wynik dla każdego węzła/stanu, a podczas eksploracji utrzymywałem tylko najwyższe stany/stany: . Zapewni to, że będziemy eksplorować tylko odpowiednie węzły. Pozostało więc zaprojektowanie funkcji score/heurystyki. Oto co wynik funkcje Próbowałem:

  • maksymalna elementu z macierzy
  • głębokość węzła
  • suma elementów macierzy
  • score który opowiada o ile elementy podzielna przez 9 IS sąsiednim elementem jest podzielna przez 9
  • liczby odrębnych elementów w macierzy
  • liczby odrębnych elementów w macierzy powyżej 9
  • liczba różnych elementów w macierzy poniżej 2
  • wynik, który mówi o ile elementy podzielna przez 9 jest sąsiedni element, który jest również podzielna przez 9, a jej dwa razy mniejszej

Za pomocą prostych heurystyk mogli budować bardziej złożony. W rezultacie otrzymałem heurystykę, która jest sumą tylko pierwszego i ostatniego z wyżej wymienionej listy. Zbieranie bardziej restrykcyjnych heurystyk utrudnia wyszukiwanie. Oto kod (Python 3):

import random 
from queue import PriorityQueue 


dx = [0, 0, -1, -1, -1, 1, 1, 1] 
dy = [-1, 1, -1, 0, 1, -1, 0, 1] 


class State: 
    def __init__(self, a, depth): 
     self.depth = depth 
     if len(a) == 9: 
      self.a = (tuple(a[:3]), tuple(a[3:6]), tuple(a[6:])) 
     if len(a) == 3: 
      self.a = tuple(map(tuple, a)) 

    @staticmethod 
    def check(i): 
     return 0 <= i < 3 

    def get_9_moves(self): 
     ans = [] 
     for i in range(3): 
      for j in range(3): 
       if self.a[i][j] % 9 == 0: 

        for k in range(len(dx)): 
         ni, nj = i + dx[k], j + dy[k] 
         if State.check(ni) and State.check(nj): 
          if self.a[ni][nj] % 9 == 0 and \ 
           self.a[i][j] == self.a[ni][nj]: 
           ans.append(((i, j), (ni, nj))) 
     return ans 

    def get_sum_moves_rec(self, i, j, cur_sum, cur_cells, ans): 
     if cur_sum > 9: 
      return 
     if cur_sum == 9 and len(cur_cells) > 1: 
      ans.append(tuple(cur_cells)) 
     for k in range(len(dx)): 
      ni, nj = i + dx[k], j + dy[k] 
      pair = (ni, nj) 
      if self.check(ni) and self.check(nj) and pair not in cur_cells: 
       cur_cells.append(pair) 
       self.get_sum_moves_rec(ni, nj, cur_sum + self.a[ni][nj], cur_cells, ans) 
       cur_cells.pop() 

    def get_sum_moves(self): 
     ans = [] 
     for i in range(3): 
      for j in range(3): 
       self.get_sum_moves_rec(i, j, self.a[i][j], [(i, j)], ans) 
     return ans 

    def get_neighbours(self): 
     neighbours = [] 
     moves = self.get_sum_moves() 
     for move in moves: 
      a = list(map(list, self.a)) 
      for i in range(len(move)): 
       x, y = move[i] 
       if i == len(move)-1: 
        a[x][y] = 9 
       else: 
        a[x][y] += 1 
      neighbours.append(State(a, self.depth+1)) 
     moves = self.get_9_moves() 
     for move in moves: 
      a = list(map(list, self.a)) 
      a[move[0][0]][move[0][1]] = 1 
      a[move[1][0]][move[1][1]] *= 2 
      neighbours.append(State(a, self.depth+1)) 
     return neighbours 

    def get_value(self): 
     return max(map(max, self.a)) 

    # 576 
    def get_score0(self): 
     return -self.get_value() 

    def get_score1(self): 
     ans = 0 
     for i in range(3): 
      for j in range(3): 
       if self.a[i][j] % 9 == 0: 
        ans += 1 
     return ans 

    # 36 
    def get_score2(self): 
     ans = 0 
     for i in range(3): 
      for j in range(3): 
       if self.a[i][j] < 9: 
        ans += 1 
     return ans 

    # achieves 1152 but rather slow 
    def get_score3(self): 
     return -self.depth 

    # 36 
    def get_score4(self): 
     ans = 0 
     for i in range(3): 
      for j in range(3): 
       if self.a[i][j] == 1: 
        ans += 1 
     return ans 

    # 288 
    def get_score5(self): 
     return -sum(map(sum, self.a)) 

    def get_score6(self): 
     t = [] 
     for i in range(3): 
      for j in range(3): 
       if self.a[i][j] % 9 == 0: 
        t.append((self.a[i][j], (i, j))) 
     t.sort(reverse=True) 
     ans = 0 
     for i in range(len(t) - 1): 
      pairi = t[i][1] 
      pairj = t[i+1][1] 

      if abs(pairi[0]-pairj[0]) <= 1 and abs(pairi[1]-pairj[1]) <= 1: 
       ans += 1 
      break 
     return -ans 

    def get_score7(self): 
     t = [] 
     for i in range(3): 
      for j in range(3): 
       if self.a[i][j] % 9 == 0: 
        t.append(self.a[i][j]) 
     t.sort(reverse=True) 
     ans = 0 
     for i in range(len(t) - 1): 

      if t[i] // t[i+1] == 2: 
       ans += 1 
      break 
     return -ans 

    def get_score8(self): 
     t = [] 
     for e in self.a: 
      t.extend(e) 
     return len(list(filter(lambda x: x >= 9,t))) 

    def get_score9(self): 
     t = [] 
     for e in self.a: 
      t.extend(e) 
     return len(list(filter(lambda x: x <= 2,t))) 

    def get_score10(self): 
     t = [] 
     for e in self.a: 
      t.extend(e) 
     return len(set(filter(lambda x: x >= 9,t))) 



    def get_score_mix(self): 
     # achieves 1152 
     return self.get_score0() + self.get_score6() 

    def __repr__(self): 
     ans = '' 
     for i in range(3): 
      for j in range(3): 
       ans += '{0:4d} '.format(self.a[i][j]) 
      ans += '\n' 
     return ans 

    def __hash__(self): 
     return hash(self.a) 

    def __lt__(self, other): 
     # hash(self) < hash(other) 
     pass 


class Solver: 

    @staticmethod 
    def strategy1(s): 
     visited = set() 
     while True: 
      # print(s) 
      neighbours = s.get_neighbours() 
      if len(neighbours) == 0: 
       break 
      ns = None 
      for i in range(30): 
       ns = random.choice(neighbours) 
       if not ns in visited: 
        s = ns 
        break 
      if ns is None: 
       break 
     print(s.get_value()) 

    @staticmethod 
    def strategy2(s): 
     visited = set() 
     max_depth = 6 
     max_value = 0 
     calls = 0 

     def dfs(state, depth): 
      # print(state) 
      nonlocal max_value, calls 

      calls += 1 
      if depth > max_depth: 
       return 
      if state in visited: 
       return 
      visited.add(state) 
      max_value = max(max_value, s.get_value()) 

      for new_state in state.get_neighbours(): 
       dfs(new_state, depth + 1) 

     dfs(s, 0) 
     print(max_value) 
     print(calls) 

    @staticmethod 
    def strategy3(s): 

     visited = set() 
     pq = PriorityQueue(maxsize=1000) 
     pq.put((0, s)) 
     visited.add(s) 
     max_value = 0 

     while not pq.empty(): 
      score, state = pq.get() 
      # print(' score0 score1 score2 score3 score4 score5 score6 score7 score8 score9 score10') 
      # print('{0:7d} {1:7d} {2:7d} {3:7d} {4:7d} {5:7d} {6:7d} {7:7d} {8:7d} {9:7d} {10:7d}'.format(state.get_score0(), state.get_score1(), state.get_score2(), 
      #                        state.get_score3(), state.get_score4(), state.get_score5(), 
      #                        state.get_score6(), state.get_score7(), state.get_score8(), 
      #                        state.get_score9(), state.get_score10())) 
      print(score, state.depth, state.get_value()) 
      print(state) 
      max_value = max(max_value, state.get_value()) 

      for new_state in state.get_neighbours(): 
       # print(random.randint(0, 10)) 
       if new_state not in visited: 
        visited.add(new_state) 
        pq._put((new_state.get_score_mix(), new_state)) 
     print(max_value) 


start = list(range(1, 10)) 
random.shuffle(start) 
s = State(start, 0) 
Solver.strategy3(s) 
# s = State([1, 1, 18, 18, 18, 36, 18 , 18, 2 ], 0) 
# print(s) 
# 
# for n in s.get_neighbours(): 
#  print(n) 

Co dalej?

Ponieważ procedura nie jest bardzo wydajna (znalezienie odpowiedzi zajmuje około 1 minuty), można spróbować znaleźć lepszą heurystykę, która byłaby przydatna do wyszukiwania. Wygląda na to, że powinny być bardzo luźne, próbując wymodelować wymóg, w przeciwnym razie zepsułoby to wyszukiwanie.

+0

Czy używasz maksymalnego rozmiaru pqueue, aby ograniczyć liczbę opcji, które próbujesz, jednocześnie znajdując bliskie optymalne rozwiązanie? Jeśli tak, mógłbym spróbować. Po prostu ustawiłem moje na nieskończone, ale wtedy biorę pierwsze znalezione rozwiązanie, bez względu na to ile kroków to zajmie. Podoba mi się również twoja metoda "get_sum_moves". :) –

+0

@CalebMauer tak, ustawiono maksymalny rozmiar kolejki, aby ograniczyć użycie pamięci i eksplorację czasu. – svs

0
  • Głębokość najpierw - Najpierw należy ocenić większą głębokość. Znacznie zmniejsza zużycie pamięci i szybciej rozwiązuje problem. W Puzzle numer 9 istnieje górna granica liczby ruchów potrzebnych do rozwiązania, więc pierwsza głębokość jest bezpieczna w użyciu dla tego problemu.
  • Suma wszystkich liczb mniej niż 9 - Wolisz, aby więcej numerów działało, aby nie znaleźć się w stanie ze wszystkimi.
  • Użyj zestawu do śledzenia poprzednich stanów. - Użyj zestawu, aby śledzić, które stany zostały odwiedzone. Zmniejsza czas uruchamiania.

Zrobiłem program w języku Python, aby rozwiązać ten problem, a jedyną prawdziwą inteligencją w takiej kolejności, w jakiej próbuje on przenosić, są te dwie rzeczy. Najgorszy czas na rozwiązanie zajmuje około 30 sekund. Średnia jest bardziej podobna do 3.

Głębokie pierwsze wyszukiwanie w połączeniu ze zbiorem śmieci Pythona utrzymywały zużycie pamięci poniżej 50 MB.