Advertisement
Ricky_Demer

3 Queens & 3 Knights can't cover

Jun 15th, 2014
286
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.79 KB | None | 0 0
  1. from itertools import product
  2.  
  3.  
  4.  
  5.  
  6. def rotate(queens):
  7.     return ((7-queens[0][1],queens[0][0]),(7-queens[1][1],queens[1][0]),(7-queens[2][1],queens[2][0]))
  8.  
  9. def reflect(queens):
  10.     return ((7-queens[0][0],queens[0][1]),(7-queens[1][0],queens[1][1]),(7-queens[2][0],queens[2][1]))
  11.  
  12. def canonicalize(queens):
  13.     current = queens
  14.     minq = sorted(queens)
  15.     for ctr in range(3):
  16.         current = rotate(current)
  17.         minq = min(sorted(current),minq)
  18.     current = reflect(queens)
  19.     minq = min(sorted(current),minq)
  20.     for ctr in range(3):
  21.         current = rotate(current)
  22.         minq = min(sorted(current),minq)
  23.     return minq
  24.  
  25. def iscoveredby(square,queens):
  26.     x,y = square
  27.     for queen in queens:
  28.         if queen[0] == x or queen[1] == y or abs(queen[0]-x) == abs(queen[1]-y):
  29.             return True
  30.     return False
  31.  
  32. def coverenough(queens):
  33.     if sum([int(iscoveredby(sq,queens)) for sq in [[0,2],[0,5],[2,0],[2,7],[5,0],[5,7],[7,2],[7,5]]]) < 5:
  34.         return False
  35.     return True
  36.  
  37. def coveredbyknightat(square):
  38.     x,y = square
  39.     gridmoves = [[x-2,y-1],[x-2,y+1],[x-1,y-2],[x-1,y+2],[x+1,y-2],[x+1,y+2],[x+2,y-1],[x+2,y+1]]
  40.     return [(x,y)]+[(w,z) for [w,z] in gridmoves if 0 <= w < 8 and 0 <= z < 8]
  41.  
  42. def centrality(square):
  43.     return len(coveredbyknightat(square))
  44.  
  45.  
  46. def stillcoveredby(square,queens,knights):
  47.     cbklist = coveredbyknightat(square)
  48.     for knight in knights:
  49.         if knight in cbklist:
  50.             return True
  51.     if square in queens:
  52.         return True
  53.     x,y = square
  54.     for queen in queens:
  55.         if queen[0] < x and x-queen[0] == y-queen[1]:
  56.             interposed = False
  57.             for i in range(1,x-queen[0]):
  58.                 if (queen[0]+i,queen[1]+i) in knights:
  59.                     interposed = True
  60.             if not interposed:
  61.                 return True
  62.         if queen[0] == x and queen[1] < y:
  63.             interposed = False
  64.             for i in range(1,y-queen[1]):
  65.                 if (queen[0],queen[1]+i) in knights:
  66.                     interposed = True
  67.             if not interposed:
  68.                 return True
  69.         if x < queen[0] and queen[0]-x == y-queen[1]:
  70.             interposed = False
  71.             for i in range(1,queen[0]):
  72.                 if (x+i,y-i) in knights:
  73.                     interposed = True
  74.             if not interposed:
  75.                 return True
  76.         if x < queen[0] and queen[1] == y:
  77.             interposed = False
  78.             for i in range(1,queen[0]-x):
  79.                 if (x+i,y) in knights:
  80.                     interposed = True
  81.             if not interposed:
  82.                 return True
  83.         if x < queen[0] and queen[0]-x == queen[1]-y:
  84.             interposed = False
  85.             for i in range(1,queen[0]-x):
  86.                 if (x+i,y+i) in knights:
  87.                     interposed = True
  88.             if not interposed:
  89.                 return True
  90.         if queen[0] == x and y < queen[1]:
  91.             interposed = False
  92.             for i in range(1,queen[1]-y):
  93.                 if (x,y+i) in knights:
  94.                     interposed = True
  95.             if not interposed:
  96.                 return True
  97.         if queen[0] < x and x-queen[0] == queen[1]-y:
  98.             interposed = False
  99.             for i in range(1,x-queen[0]):
  100.                 if (x-i,y+i) in knights:
  101.                     interposed = True
  102.             if not interposed:
  103.                 return True
  104.         if queen[0] < x and queen[1] == y:
  105.             interposed = False
  106.             for i in range(1,queen[0]-x):
  107.                 if (queen[0]+i,queen[1]) in knights:
  108.                     interposed = True
  109.             if not interposed:
  110.                 return False
  111.     return False
  112.  
  113. #  I am aware of the "for else" construction; I just wanted to make it more clear what was happening.
  114.  
  115.            
  116. def actuallyworks(queens,knights):
  117.     if len(sorted(set(queens+knights))) != len(queens)+len(knights):
  118.         return False
  119.     for sq in product(range(8),range(8)):
  120.         if not stillcoveredby(sq,queens,knights):
  121.             return False
  122.     return True
  123.  
  124.  
  125.  
  126. candidates = set()
  127. for queen0x in range(4):
  128.     for queen0y in range(queen0x+1):
  129.         for queen1x in range(8):
  130.             for queen1y in range(8):
  131.                 for queen2x in range(8):
  132.                     for queen2y in range(8):
  133.                         queens = ((queen0x,queen0y),(queen1x,queen1y),(queen2x,queen2y))
  134.                         if (queens[0] != queens[1]) and (queens[0] != queens[2]) and (queens[1] != queens[2]) and coverenough(queens):
  135.                             candidates.add(tuple(canonicalize(queens)))
  136. squaresfromoutside = sorted(product(range(8),range(8)),key=centrality)
  137. theremightbeasolution = False
  138. for queens in candidates:
  139.     notcoveredbyqueens = [sq for sq in squaresfromoutside if not iscoveredby(sq,queens)]
  140.     if len(notcoveredbyqueens) == 0:
  141.         theremightbeasolution = True
  142.         break
  143.     for knight0 in coveredbyknightat(notcoveredbyqueens[0]):
  144.         firstnotcovered = [sq for sq in notcoveredbyqueens if sq not in coveredbyknightat(knight0)]
  145.         if len(firstnotcovered) == 0:
  146.             theremightbeasolution = True
  147.             break
  148.         for knight1 in coveredbyknightat(firstnotcovered[0]):
  149.             secondnotcovered = [sq for sq in firstnotcovered if sq not in coveredbyknightat(knight1)]
  150.             if len(secondnotcovered) == 0:
  151.                 theremightbeasolution = True
  152.                 break
  153.             for knight2 in coveredbyknightat(secondnotcovered[0]):
  154.                 thirdnotcovered = [sq for sq in secondnotcovered if sq not in coveredbyknightat(knight2)]
  155.                 if len(thirdnotcovered) == 0 and actuallyworks(queens,(knight0,knight1,knight2)):
  156.                     theremightbeasolution = True
  157. print(theremightbeasolution)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement