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.

129 lines
3.7 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. len_rows = len(rows)
  19. assert(len_rows != 0)
  20. len_cols = len(cols)
  21. assert(len_cols != 0)
  22. def print_result(model):
  23. print(" " + ''.join(cols) + " "*5 + ''.join(cols))
  24. for i in range(len_rows):
  25. print(rows[i] + " " + ''.join(playground[i]) + " >>> ", end='')
  26. for j in range(len_cols):
  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(len_rows):
  36. print(rows[i] + " ", end='')
  37. for j in range(len_cols):
  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. solver = Solver()
  47. cells = [[None for j in range(len_cols)] for i in range(len_rows)]
  48. def get_possible_tents_in_col(col):
  49. possible_tent_positions = []
  50. for row in range(len_rows):
  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(len_cols):
  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, len_rows)):
  63. for q in range(max(j-1, 0), min(j+2, len_cols)):
  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, len_rows - 1)]:
  70. if p == i: continue
  71. tree_pos.append(cells[p][j])
  72. for q in [max(j-1, 0), min(j+1, len_cols - 1)]:
  73. if q == j: continue
  74. tree_pos.append(cells[i][q])
  75. return tree_pos
  76. # TODO
  77. # Cell entries need to be represented by a Z3 variable
  78. for i in range(len_rows):
  79. for j in range(len_cols):
  80. # your code goes here...
  81. # TODO
  82. # Bound/restrict the values of the cells according to the input
  83. if playground[i][j] == EMPTY:
  84. # your code goes here...
  85. else:
  86. # your code goes here...
  87. # TODO
  88. # The sums of tents per row/column must match the amounts given in the input
  89. for j in range(len_cols):
  90. # your code goes here...
  91. for i in range(len_rows):
  92. # your code goes here...
  93. for i in range(len_rows):
  94. for j in range(len_cols):
  95. if playground[i][j] == "T": continue
  96. tree_constraint = Bool("False")
  97. # TODO
  98. # A tent needs to be next to a tree
  99. # Incrementally build up the tree_constraint ...
  100. for possible_tree in get_tree_neighbours(i, j):
  101. # your code goes here...
  102. # ... and add it to the solver
  103. # TODO
  104. # A tent must not be next to another tent
  105. for neighbour in get_neighbours(i, j):
  106. # your code goes here...
  107. res = solver.check()
  108. if res == unsat:
  109. print("UNSAT")
  110. print_forest()
  111. else:
  112. m = solver.model()
  113. print_result(m)