''' @author: olivier.massot, 2019 ''' import heapq import itertools import sys def log(x): print(x, file=sys.stderr) # Cells BLUEBERRIES_CRATE = "B" ICE_CREAM_CRATE = "I" WINDOW = "W" EMPTY_TABLE = "#" DISHWASHER = "D" FLOOR_CELL = "." # Items NONE = "NONE" DISH = "DISH" ICE_CREAM = "ICE_CREAM" BLUEBERRIES = "BLUEBERRIES" location = {DISH: DISHWASHER, ICE_CREAM: ICE_CREAM_CRATE, BLUEBERRIES: BLUEBERRIES_CRATE, WINDOW: WINDOW} class Base(): def __repr__(self): return f"<{self.__class__.__name__}: {self.__dict__}>" class Customer(Base): def __init__(self, item, award): self.item = item self.award = int(award) class Cook(Base): def __init__(self, x, y, item): self.x = int(x) self.y = int(y) self.item = item self.order = "" @property def pos(self): return (self.x, self.y) def use(self, x, y, msg=""): print("USE", x, y, msg) def move(self, x, y): print("MOVE", x, y) class Table(Base): def __init__(self, x, y, item): self.x = int(x) self.y = int(y) self.item = item class Oven(Base): def __init__(self, contents, timer): self.contents = contents self.timer = int(timer) class NoPathFound(Exception): pass class PathNode(tuple): def __new__(self, x, y, parent=None): n = tuple.__new__(self, (x, y)) n.parent = parent n.cost = 0 return n class Grid(Base): def __init__(self, cells): self.cells = cells def at(self, x, y): return self.cells[y][x] def is_in(self, x, y): try: self.at(x, y) return True except IndexError: return False def flatten(self): return [(x, y, c) for y, row in enumerate(self.cells) for x, c in enumerate(row)] def where_are(self, content): return [(x, y) for x, y, c in self.flatten() if c == content] def is_passable(self, x, y): return self.at(x, y) in (FLOOR_CELL, "0", "1") def closest(self, from_, content): return min(self.where_are(content), key=lambda k: (abs(from_[0] - k[0]) + abs(from_[1] - k[1]))) def neighbors(self, x, y): return [(xn, yn) for xn, yn in [(x - 1, y - 1), (x, y - 1), (x + 1, y - 1), \ (x - 1, y), (x + 1, y) , \ (x - 1, y + 1), (x, y + 1), (x + 1, y + 1)] if self.is_in(xn, yn)] def path_to(self, origin, target): nodes = [] origin = PathNode(*origin) heapq.heappush(nodes, (0, origin)) while nodes: current = heapq.heappop(nodes)[1] if current == target: break for x, y in self.neighbors(*current): node = PathNode(x, y, current) if not self.is_passable(*node): continue node.cost = current.cost + 1 priority = node.cost + (abs(node[0] - target[0]) + abs(node[1] - target[1])) heapq.heappush(nodes, (priority, node)) else: raise NoPathFound("no path were found to the targetted location {}".format(target)) result = [target] while current != origin: result.append(tuple(current)) current = current.parent result.append(origin) result.reverse() return result # input vars num_all_customers = int(input()) all_customers = [Customer(*input().split()) for _ in range(num_all_customers)] grid = Grid([list(input()) for i in range(7)]) log(f"{num_all_customers} customers: {all_customers}") log(f"grid: {grid}") while True: turns_remaining = int(input()) player = Cook(*input().split()) log(f"*** player: {player}") partner = Cook(*input().split()) log(f"*** partner: {partner}") num_tables_with_items = int(input()) # the number of tables in the kitchen that currently hold an item tables = [Table(*input().split()) for _ in range(num_tables_with_items)] log(f"*** tables: {tables}") oven = Oven(*input().split()) log(f"*** oven: {oven}") num_customers = int(input()) # the number of customers currently waiting for food customers = [Customer(*input().split()) for _ in range(num_customers)] log(f"*** customers: {customers}") ### SCRIPT # if no current order, take the most beneficial if not player.order: queue = sorted(customers, reverse=True, key=lambda x: x.award) # what is my partner doing? player.order = queue[0].item log(f'>>> new order taken: {player.order}') todo = player.order.split('-') log(f"todo: {todo}") next_task = next([t for t in todo if not t in player.item], WINDOW) if next_task == WINDOW: player.order, todo = [], [] log(f"next_task: {next_task}") target = location[next_task] log(f"target: {target}") closest = grid.closest(player.pos, target) log(f"closest: {closest}") player.use(*closest)