You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
3.3 KiB

  1. # coding: utf-8
  2. import os, sys
  3. from z3 import *
  4. # get the playground information
  5. if len(sys.argv) != 2:
  6. print("Usage: python3 trees_and_tents.py <forest-file>")
  7. EMPTY = "?"
  8. TREE = 2
  9. if len(sys.argv) == 2:
  10. fname = sys.argv[1]
  11. with open(fname) as f:
  12. playground = f.read()
  13. cols = [col for col in playground.strip().split("\n")[0][1:]]
  14. rows = [row[0] for row in playground.strip().split("\n")[1:]]
  15. playground = [[EMPTY if x == EMPTY else x for x in row[1:]]
  16. for row in playground.strip().split("\n")[1:]]
  17. # get the playground size
  18. size_y = len(rows)
  19. assert(size_y != 0)
  20. size_x = len(cols)
  21. assert(size_x != 0)
  22. def print_result(model):
  23. print(" " + ''.join(cols) + " "*5 + ''.join(cols))
  24. for i in range(size_y):
  25. print(rows[i] + " " + ''.join(playground[i]) + " >>> ", end='')
  26. for j in range(size_x):
  27. cell = model[cells[i][j]].as_long()
  28. if cell != TREE:
  29. print(cell, end='')
  30. elif cell == TREE:
  31. print("T", end='')
  32. print()
  33. def print_forest():
  34. print(" " + ''.join(cols))
  35. for i in range(size_y):
  36. print(rows[i] + " ", end='')
  37. for j in range(size_x):
  38. cell = playground[i][j]
  39. if cell != TREE:
  40. print(cell, end='')
  41. elif cell == TREE:
  42. print("T", end='')
  43. print()
  44. ################################# Trees and Tents ##################################
  45. # create the solver
  46. cells = [[None for j in range(size_x)] for i in range(size_y)]
  47. solver = Solver()
  48. def get_possible_tents_in_col(col):
  49. possible_tent_positions = []
  50. for row in range(size_y):
  51. if playground[row][col] != "T":
  52. possible_tent_positions.append(cells[row][col])
  53. return possible_tent_positions
  54. def get_possible_tents_in_row(row):
  55. possible_tent_positions = []
  56. for col in range(size_x):
  57. if playground[row][col] != "T":
  58. possible_tent_positions.append(cells[row][col])
  59. return possible_tent_positions
  60. def get_neighbours(i, j):
  61. cs = []
  62. for p in range(max(i-1, 0), min(i+2, size_y)):
  63. for q in range(max(j-1, 0), min(j+2, size_x)):
  64. if p == i and q == j: continue
  65. cs.append(cells[p][q])
  66. return cs
  67. def get_tree_neighbours(i, j):
  68. tree_pos = []
  69. for p in [max(i-1, 0), min(i+1, size_y - 1)]:
  70. if p == i: continue
  71. tree_pos.append(cells[p][j])
  72. for q in [max(j-1, 0), min(j+1, size_x - 1)]:
  73. if q == j: continue
  74. tree_pos.append(cells[i][q])
  75. return tree_pos
  76. # TODO Cell entries need to be represented by a Z3 variable
  77. # TODO Bound/restrict the values of the cells according to the input
  78. # TODO The sums of tents per row/column must match the amounts given in the input
  79. for i in range(size_y):
  80. for j in range(size_x):
  81. if playground[i][j] == "T":
  82. # TODO A tent needs to be next to a tree
  83. # Incrementally build up the tree_constraint ...
  84. tree_constraint = False
  85. for possible_tent in get_tree_neighbours(i, j):
  86. pass
  87. else:
  88. neighbours = get_neighbours(i, j)
  89. # TODO A tent must not be next to another tent
  90. res = solver.check()
  91. if res == unsat:
  92. print("UNSAT")
  93. print_forest()
  94. else:
  95. m = solver.model()
  96. print(m)
  97. print_result(m)