script_ok_1.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. '''
  2. @author: olivier.massot, 2019
  3. '''
  4. import heapq
  5. import itertools
  6. import sys
  7. def log(x):
  8. print(x, file=sys.stderr)
  9. # Cells
  10. BLUEBERRIES_CRATE = "B"
  11. ICE_CREAM_CRATE = "I"
  12. WINDOW = "W"
  13. EMPTY_TABLE = "#"
  14. DISHWASHER = "D"
  15. FLOOR_CELL = "."
  16. # Items
  17. NONE = "NONE"
  18. DISH = "DISH"
  19. ICE_CREAM = "ICE_CREAM"
  20. BLUEBERRIES = "BLUEBERRIES"
  21. location = {DISH: DISHWASHER,
  22. ICE_CREAM: ICE_CREAM_CRATE,
  23. BLUEBERRIES: BLUEBERRIES_CRATE,
  24. WINDOW: WINDOW}
  25. class Base():
  26. def __repr__(self):
  27. return f"<{self.__class__.__name__}: {self.__dict__}>"
  28. class Customer(Base):
  29. def __init__(self, item, award):
  30. self.item = item
  31. self.award = int(award)
  32. class Cook(Base):
  33. def __init__(self, x, y, item):
  34. self.x = int(x)
  35. self.y = int(y)
  36. self.item = item
  37. self.order = ""
  38. @property
  39. def pos(self):
  40. return (self.x, self.y)
  41. def use(self, x, y, msg=""):
  42. print("USE", x, y, msg)
  43. def move(self, x, y):
  44. print("MOVE", x, y)
  45. class Table(Base):
  46. def __init__(self, x, y, item):
  47. self.x = int(x)
  48. self.y = int(y)
  49. self.item = item
  50. class Oven(Base):
  51. def __init__(self, contents, timer):
  52. self.contents = contents
  53. self.timer = int(timer)
  54. class NoPathFound(Exception):
  55. pass
  56. class PathNode(tuple):
  57. def __new__(self, x, y, parent=None):
  58. n = tuple.__new__(self, (x, y))
  59. n.parent = parent
  60. n.cost = 0
  61. return n
  62. class Grid(Base):
  63. def __init__(self, cells):
  64. self.cells = cells
  65. def at(self, x, y):
  66. return self.cells[y][x]
  67. def is_in(self, x, y):
  68. try:
  69. self.at(x, y)
  70. return True
  71. except IndexError:
  72. return False
  73. def flatten(self):
  74. return [(x, y, c) for y, row in enumerate(self.cells) for x, c in enumerate(row)]
  75. def where_are(self, content):
  76. return [(x, y) for x, y, c in self.flatten() if c == content]
  77. def is_passable(self, x, y):
  78. return self.at(x, y) in (FLOOR_CELL, "0", "1")
  79. def closest(self, from_, content):
  80. return min(self.where_are(content), key=lambda k: (abs(from_[0] - k[0]) + abs(from_[1] - k[1])))
  81. def neighbors(self, x, y):
  82. return [(xn, yn) for xn, yn in [(x - 1, y - 1), (x, y - 1), (x + 1, y - 1), \
  83. (x - 1, y), (x + 1, y) , \
  84. (x - 1, y + 1), (x, y + 1), (x + 1, y + 1)]
  85. if self.is_in(xn, yn)]
  86. def path_to(self, origin, target):
  87. nodes = []
  88. origin = PathNode(*origin)
  89. heapq.heappush(nodes, (0, origin))
  90. while nodes:
  91. current = heapq.heappop(nodes)[1]
  92. if current == target:
  93. break
  94. for x, y in self.neighbors(*current):
  95. node = PathNode(x, y, current)
  96. if not self.is_passable(*node):
  97. continue
  98. node.cost = current.cost + 1
  99. priority = node.cost + (abs(node[0] - target[0]) + abs(node[1] - target[1]))
  100. heapq.heappush(nodes, (priority, node))
  101. else:
  102. raise NoPathFound("no path were found to the targetted location {}".format(target))
  103. result = [target]
  104. while current != origin:
  105. result.append(tuple(current))
  106. current = current.parent
  107. result.append(origin)
  108. result.reverse()
  109. return result
  110. # input vars
  111. num_all_customers = int(input())
  112. all_customers = [Customer(*input().split()) for _ in range(num_all_customers)]
  113. grid = Grid([list(input()) for i in range(7)])
  114. log(f"{num_all_customers} customers: {all_customers}")
  115. log(f"grid: {grid}")
  116. while True:
  117. turns_remaining = int(input())
  118. player = Cook(*input().split())
  119. log(f"*** player: {player}")
  120. partner = Cook(*input().split())
  121. log(f"*** partner: {partner}")
  122. num_tables_with_items = int(input()) # the number of tables in the kitchen that currently hold an item
  123. tables = [Table(*input().split()) for _ in range(num_tables_with_items)]
  124. log(f"*** tables: {tables}")
  125. oven = Oven(*input().split())
  126. log(f"*** oven: {oven}")
  127. num_customers = int(input()) # the number of customers currently waiting for food
  128. customers = [Customer(*input().split()) for _ in range(num_customers)]
  129. log(f"*** customers: {customers}")
  130. ### SCRIPT
  131. # if no current order, take the most beneficial
  132. if not player.order:
  133. queue = sorted(customers, reverse=True, key=lambda x: x.award)
  134. # what is my partner doing?
  135. player.order = queue[0].item
  136. log(f'>>> new order taken: {player.order}')
  137. todo = player.order.split('-')
  138. log(f"todo: {todo}")
  139. next_task = next([t for t in todo if not t in player.item], WINDOW)
  140. if next_task == WINDOW:
  141. player.order, todo = [], []
  142. log(f"next_task: {next_task}")
  143. target = location[next_task]
  144. log(f"target: {target}")
  145. closest = grid.closest(player.pos, target)
  146. log(f"closest: {closest}")
  147. player.use(*closest)