Advertisement
Guest User

edgematch

a guest
Jan 30th, 2015
234
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.11 KB | None | 0 0
  1. import string
  2. import itertools
  3. import time
  4.  
  5. orientations = "NESW"
  6.  
  7. def solve(gridsize, tiles, tileletters):
  8.     solution = next(solutions(gridsize, tiles))
  9.     print ' '.join([tileletters[tile] + orientation
  10.                     for tile, orientation in solution])
  11.  
  12. def solutions(gridsize, tiles):
  13.     return eval(compile_solutions(gridsize))(tiles)
  14.  
  15. def compile_solutions(gridsize):
  16.     def compile_for(vars):
  17.         return "for %s in candidates(tiles, [%s])" %\
  18.             (vars[-1], ",".join(vars[:-1]))
  19.  
  20.     def compile_if(vars):
  21.         pos = len(vars)-1
  22.         if pos == 0:
  23.             return ""
  24.         elif pos < gridsize:
  25.             return "if mleftof(%s,%s)" % (vars[pos-1], vars[pos])
  26.         elif pos % gridsize == 0:
  27.             return "if mabove(%s,%s)" % (vars[pos-gridsize], vars[pos])
  28.         else:
  29.             return "if mleftof(%s,%s) and mabove(%s,%s)" %\
  30.                 (vars[pos-1], vars[pos], vars[pos-gridsize], vars[pos])
  31.  
  32.     def compile_clause(vars):
  33.         return " ".join([compile_for(vars), compile_if(vars)])
  34.  
  35.     vars = ["p" + str(pos) for pos in range(gridsize**2)]
  36.     body = "(" + "(" + ",".join(vars) + ")\n" +\
  37.            "\n".join([compile_clause(list(itertools.islice(vars, pos+1)))
  38.                       for pos in range(len(vars))]) + ")"
  39.     return "lambda tiles : %s" % body
  40.  
  41. def candidates(tiles, places):
  42.     remaining = tiles.difference([tile for tile, _ in places])
  43.     return itertools.product(remaining, orientations)
  44.  
  45. def match(edge1, edge2):
  46.     return string.swapcase(edge1) == edge2
  47.  
  48. def mleftof(p1, p2):
  49.     return match(rightedge(p1), leftedge(p2))
  50.  
  51. def mabove(p1, p2):
  52.     return match(bottomedge(p1), topedge(p2))
  53.  
  54. def edge(n, place):
  55.     (tile, orien) = place
  56.     return tile[n-orientations.index(orien)]
  57.  
  58. def topedge(p): return edge(0, p)
  59. def rightedge(p): return edge(1, p)
  60. def bottomedge(p): return edge(2, p)
  61. def leftedge(p): return edge(3, p)
  62.  
  63. def from_file(filename, sep='\n'):
  64.     return file(filename).read().strip().split(sep)
  65.  
  66. def read_puzzle(filename):
  67.     input = from_file(filename)
  68.     gridsize = int(input[0])
  69.     tiles = input[1:]
  70.     tileletters = dict(zip(tiles, string.ascii_uppercase))
  71.     return gridsize, set(tiles), tileletters
  72.  
  73. def timedcall(fn, *args):
  74.     start = time.clock()
  75.     result = fn(*args)
  76.     t = time.clock()-start
  77.     print '(%.2f seconds)\n' % t
  78.     return (result, t)
  79.  
  80. def test():
  81.     assert mleftof(("ycKC", "N"), ("mMyC", "N"))
  82.     assert not mleftof(("ycKC", "N"), ("mMyC", "E"))
  83.  
  84.     assert mabove(("ycKC", "N"), ("kKcY", "N"))
  85.     assert not mabove(("ycKC", "N"), ("kKcY", "E"))
  86.  
  87.     assert topedge(("kKcY", "N")) == "k"
  88.     assert topedge(("kKcY", "E")) == "Y"
  89.     assert topedge(("kKcY", "S")) == "c"
  90.     assert topedge(("kKcY", "W")) == "K"
  91.  
  92.     assert match("A", "a")
  93.     assert match("a", "A")
  94.     assert not match("A", "A")
  95.     assert not match("a", "a")
  96.  
  97.     print "All tests pass."
  98.  
  99. if __name__ == '__main__':
  100.     test()
  101.     timedcall(solve, *read_puzzle("input3.txt"))
  102.     timedcall(solve, *read_puzzle("input4.txt"))
  103.     timedcall(solve, *read_puzzle("input5.txt"))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement