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.

146 lines
4.1 KiB

  1. # coding: utf-8
  2. import os, sys
  3. from z3 import *
  4. from itertools import combinations
  5. pretty_print = True
  6. # get the playground information
  7. if len(sys.argv) != 2:
  8. print("Usage: python3 seating-arrangement.py <wedding-file>")
  9. sys.exit(0)
  10. def faulty_line(line, num):
  11. print("Faulty input at line " + str(num) + ". Ignoring '" + line + "'")
  12. # data structures prepared for you
  13. guests = set()
  14. friends = []
  15. foes = []
  16. longest_name_len = 0
  17. def add_to_guest_list(a,b=None):
  18. guests.add(a)
  19. if b != None:
  20. guests.add(b)
  21. def longest_name(a,b=None):
  22. global longest_name_len
  23. if len(a) > longest_name_len: longest_name_len = len(a)
  24. if b != None and len(b) > longest_name_len : longest_name_len = len(b)
  25. solver = Solver()
  26. ################################### Parse Guests and Constraints ####################################
  27. Guest = DeclareSort("Guest")
  28. with open(sys.argv[1]) as f:
  29. wedding = f.read()
  30. wedding = wedding.strip().split("\n")
  31. linenum = 0
  32. for line in wedding:
  33. linenum += 1
  34. if line[0] == '#':
  35. continue
  36. if line.rstrip():
  37. info = line.split(" ")
  38. if len(info) == 1:
  39. guest = Const(info[0], Guest)
  40. add_to_guest_list()
  41. longest_name(info[0])
  42. continue
  43. if len(info) != 3:
  44. faulty_line(line, linenum)
  45. continue
  46. longest_name(info[0], info[2])
  47. if info[1] == "dislikes":
  48. first_guest = Const(info[0], Guest)
  49. second_guest = Const(info[2], Guest)
  50. add_to_guest_list(first_guest, second_guest)
  51. # TODO add the pair of guests as foes
  52. elif info[1] == "likes":
  53. first_guest = Const(info[0], Guest)
  54. second_guest = Const(info[2], Guest)
  55. add_to_guest_list(first_guest, second_guest)
  56. # TODO add pair of guests as friends
  57. else:
  58. faulty_line(line, linenum)
  59. continue
  60. ################################### Wedding Guests ####################################
  61. def neigbours(a, b):
  62. pass
  63. # all guests must be seated at the big table
  64. # no two guests should sit on the same position (hint: use combinations)
  65. # friends should be neigbours
  66. # foes should not be neigbours
  67. # check satisfiability
  68. res = solver.check()
  69. if res != sat:
  70. print("unsat")
  71. sys.exit(1)
  72. m = solver.model()
  73. ################################################################################
  74. arrangement = ["" for guest in range(len(guests))]
  75. for guest in guests:
  76. arrangement[m.evaluate(position(guest),model_completion=True).as_long()] = guest.decl().name()
  77. def print_table():
  78. side_length = round(len(guests)/4)
  79. top = arrangement[0:side_length]
  80. right = arrangement[side_length:2*side_length]
  81. bottom = arrangement[2*side_length:3*side_length]
  82. left = arrangement[3*side_length:]
  83. while len(left) < len(right):
  84. left.append("")
  85. while len(right) < len(left):
  86. right.append("")
  87. table_line_length = longest_name_len + 1
  88. print("\n")
  89. top_row = ""
  90. top_row += (longest_name_len + 1) * " "
  91. for top_guest in top:
  92. top_row += top_guest + " "
  93. table_line_length += len(top_guest) + 1
  94. print(top_row)
  95. print((longest_name_len + 1) * " " + table_line_length * "-")
  96. first_element = True
  97. for left_guest, right_guest in zip(reversed(left), right):
  98. row = ""
  99. if not first_element:
  100. row += longest_name_len * " "
  101. row += "|" + ">"* (table_line_length) + "|"
  102. print(row)
  103. row = ""
  104. else:
  105. first_element = False
  106. row += left_guest.rjust(longest_name_len) + "|" + "<"* (table_line_length) + "|" + right_guest
  107. print(row)
  108. print((longest_name_len + 1) * " " + table_line_length * "-")
  109. bottom_row = ""
  110. bottom_row += (longest_name_len + 1) * " "
  111. for bottom_guest in reversed(bottom):
  112. bottom_row += bottom_guest + " "
  113. print(bottom_row)
  114. print("\n")
  115. if(pretty_print):
  116. print_table()
  117. print("Seating plan:")
  118. print(arrangement)