Advertisement
franji

Sudoku arr(tuple) fork()

Apr 25th, 2018
343
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.42 KB | None | 0 0
  1. import os
  2. import sys
  3.  
  4. game = """
  5. _ _ 4  _ _ _  _ 5 7
  6. 2 _ _  _ _ _  8 _ _
  7. 3 9 _  5 _ _  _ _ 6
  8.  
  9. _ 1 _  4 7 5  9 _ _
  10. _ _ _  _ 3 _  _ _ _
  11. _ _ 5  2 1 8  _ 3 _
  12.  
  13. 7 _ _  _ _ 9  _ 4 8
  14. _ _ 9  _ _ _  _ _ 3
  15. 1 8 _  _ _ _  2 _ _
  16. """
  17.  
  18. game1='''
  19. _ _ _ _ 6 1 _ _ 5
  20. _ 3 _ _ _ _ _ _ 9
  21. _ 4 _ _ _ 3 1 _ _
  22.  
  23. 7 8 _ 3 _ _ _ 5 2
  24. _ _ 2 _ _ _ 9 _ _
  25. 5 9 _ _ _ 8 _ 1 6
  26.  
  27. _ _ 7 1 _ _ _ 9 _
  28. 6 _ _ _ _ _ _ 7 _
  29. 9 _ _ 6 2 _ _ _ _
  30. '''
  31.  
  32.  
  33. game_test='''
  34. _ 2 3 4 5 6 7 8 9
  35. _ 5 _ _ _ _ _ _ _
  36. _ 6 _ _ _ _ _ _ _
  37.  
  38. _ 3 _ _ _ _ _ _ _
  39. _ 4 _ _ _ _ _ _ _
  40. _ 7 _ _ _ _ _ _ _
  41.  
  42. _ 8 _ _ _ _ 2 3 4
  43. _ 9 _ _ _ _ 5 6 7
  44. _ _ _ _ _ _ 8 9 _
  45. '''
  46.  
  47.  
  48.  
  49. def BoardFromInput(game):
  50.   res = [[]]
  51.   for ch in game:
  52.     item = None
  53.     if ch.isdigit():
  54.       item = [True, int(ch)]
  55.     elif ch == '_':
  56.       item = [False, None]
  57.    
  58.     if item:
  59.       if len(res[-1]) >= 9:
  60.         res.append([])
  61.       res[-1].append(item)
  62.   if len(res) != 9 or len(res[-1]) != 9:
  63.     print "ERROR - illegal Suduko input"
  64.   return res
  65.  
  66.  
  67. def PrintBoard(board):
  68.   for (li, line) in enumerate(board):
  69.     if li % 3 == 0:
  70.        print "-" * 47
  71.     for (ci, (isset, num)) in enumerate(line):
  72.       if ci % 3 == 0:
  73.         print " | ",
  74.       if num:
  75.         print num, " ",
  76.       else:
  77.         print "_", " ",
  78.     print
  79.   print "-" * 47
  80.  
  81.  
  82. def InLine(n, board, line):
  83.   for isset, num in board[line]:
  84.     if n == num:
  85.       return True
  86.   return False
  87.  
  88. def InCol(n, board, col):
  89.   for line in board:
  90.     isset, num = line[col]
  91.     if n == num:
  92.       return True
  93.   return False
  94.  
  95. def InSq(n, board, line, col):
  96.   sqY = line / 3
  97.   sqX = col / 3
  98.   for l in xrange(sqY * 3, sqY * 3 + 3):
  99.     for c in xrange(sqX * 3, sqX * 3 + 3):
  100.       isset, num = board[l][c]
  101.       if n == num:
  102.         return True
  103.   return False
  104.  
  105.  
  106. def _test():
  107.   board = BoardFromInput(game_test)
  108.   assert InLine(2, board, 0)
  109.   assert not InLine(1, board, 0)
  110.   assert InCol(2, board, 1)
  111.   assert not InCol(1, board, 1)
  112.   assert InSq(2, board, 8, 8)
  113.   assert not InSq(1, board, 8, 8)
  114.  
  115.  
  116. def validate_game(game):
  117.   board = BoardFromInput(game)
  118.   for l in xrange(9):
  119.     for c in xrange(9):
  120.       if not board[l][c][0]:
  121.         continue  # skip the free cells
  122.       v = board[l][c][1]
  123.       board[l][c][0] = False
  124.       board[l][c][1] = None
  125.       #print "line=", l , "col=", c, "num=", v
  126.       assert not InLine(v, board, l)
  127.       assert not InCol(v, board, c)
  128.       assert not InSq(v, board, l, c)
  129.       # restore
  130.       board[l][c][0] = True
  131.       board[l][c][1] = v
  132.  
  133.  
  134. def SolveFork(board, i , use_fork=False, childs_set = None):
  135.     """Call Solve(board, i).
  136.    if use_fork=False - just call it and return its value
  137.    when use_fork==True - open a child process to run Solve()
  138.    and at the parent - add the child's pid to childs_set and return False.
  139.    """
  140.     if not use_fork:
  141.         return Solve(board, i)
  142.     # using fork
  143.     child_pid = os.fork()
  144.     if child_pid == 0:
  145.         # inside child process
  146.         solved = Solve(board, i)
  147.         if solved:
  148.             sys.exit(1)
  149.         else:
  150.             sys.exit(0)
  151.     else:
  152.         childs_set.add(child_pid)
  153.     return False
  154.  
  155.  
  156. def Solve(board, i):
  157.   #PrintBoard(board)
  158.   #raw_input(">>>")
  159.   if i >= 9 * 9:
  160.     print "SOLUTION:"
  161.     PrintBoard(board)
  162.     return True
  163.   line = i / 9
  164.   col = i % 9
  165.   if board[line][col][0]:
  166.     return Solve(board, i + 1)
  167.   childs = set()
  168.   for n in range(1,10):
  169.     board[line][col][1] = None
  170.     line_bad = InLine(n, board, line)
  171.     row_bad = InCol(n, board, col)
  172.     sq_bad = InSq(n, board, line, col)
  173.     #print "line_bad", line_bad, "row", row_bad, "sq", sq_bad
  174.     if line_bad or row_bad or sq_bad:
  175.       continue
  176.     board[line][col][1] = n
  177.     use_fork = i < 2
  178.     solved = SolveFork(board, i + 1, use_fork=use_fork, childs_set=childs)
  179.     if solved:
  180.         return True
  181.     board[line][col][1] = None
  182.   # after starting all child processes
  183.   # wait for them to end
  184.   # NOte that if for was NOT used - childs={} and False is returned here
  185.   solved = False
  186.   while childs:
  187.       finished_pid, exit_status = os.wait()
  188.       # print "DEBUG finished_pid = ", finished_pid, exit_status
  189.       childs.remove(finished_pid)
  190.       if exit_status > 0:
  191.           solved = True
  192.   return solved
  193.  
  194.  
  195. validate_game(game1)
  196. board = BoardFromInput(game1)
  197. print "SUDUKO:"
  198. PrintBoard(board)
  199.  
  200. if Solve(board, 0):
  201.   print "SOLUTION:"
  202.   #PrintBoard(board)
  203. else:
  204.   print "NO SOUTION"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement