#!/usr/bin/env python3 #(height, width) import random as rnd import os # import sys import itertools from enum import Enum import time import math from queue import PriorityQueue as pq from intervaltree import IntervalTree as itree # DEBUG=True DEBUG=False class SquareType(Enum): AISLE = 0 SEAT = 1 WALL = 2 height=0 width=0 grid=[] # entries=[(3,0)] entries=[(0,3)] # entries=[(7,3),(7,43)] # entries=[(7,3)] tickTaken = 0 passengers = None class GridSquare: #typ: SquareType def __init__(self, typ): self.typ = typ #occupAtTick is an interval tree, stores intervals where the gridSquare is occupied #intervals are [a,b), a nice sane choice #values are individuals self.occupAtTick = itree() class Passenger: #dest and curr are both 2-tuples def __init__(self, dest, curr): self.dest = dest self.curr = curr self.inter = None #Path is composed of tuples: (pos, t) self.path = [] def __str__(self): return "(%s|%s)" % (dest, curr) def mooreNeighbourhood(pos): return [i for i in [(pos[0]+1, pos[1]), (pos[0], pos[1]+1), (pos[0]-1, pos[1]), (pos[0], pos[1]-1)] if i[0] >= 0 and i[1] >= 0 and i[0] < height and i[1] < width] def findPath(passenger, pid, currTick): global passengers global grid #used when moving into seats afterTick = 0 dest = passenger.inter #Element format: (Tick at time of movement, Position, Time stayed in previous square) q = pq() time=[[10**10 for x in range(0,width)] for y in range(0,height)] prev=[[None for x in range(0,width)] for y in range(0,height)] time[passenger.curr[0]][passenger.curr[1]]=currTick q.put((currTick, passenger.curr, 1)) while not q.empty(): u = q.get() if u[1] == dest: grid[u[1][0]][u[1][1]].occupAtTick.addi(u[0],u[0]+3,pid) afterTick = u[0]+2 # passenger.path.append((u[1], u[0])) u=prev[u[1][0]][u[1][1]] while prev[u[1][0]][u[1][1]] != None: grid[u[1][0]][u[1][1]].occupAtTick.addi(u[0],u[0]+u[2],pid) # passenger.path.append((u[1], u[0])) u=prev[u[1][0]][u[1][1]] # passenger.path.append((passenger.curr, currTick)) break #The Art of Standing Still q.put((u[0] + 1, u[1], 1)) for x in mooreNeighbourhood(u[1]): alt = 0 if grid[x[0]][x[1]].typ == SquareType.SEAT: if ( not (grid[u[1][0]][u[1][1]].typ == SquareType.AISLE and u[1][1] != x[1]) and len(grid[x[0]][x[1]].occupAtTick[u[0]:u[0]+5-1]) == 0): alt = time[u[1][0]][u[1][1]] + 5 if alt < time[x[0]][x[1]]: time[x[0]][x[1]] = alt prev[x[0]][x[1]] = u q.put((alt, x, 5)) else: continue elif grid[x[0]][x[1]].typ == SquareType.AISLE: if len(grid[x[0]][x[1]].occupAtTick[u[0]+1:u[0]+1+1]) == 0: alt = time[u[1][0]][u[1][1]] + 1 if alt < time[x[0]][x[1]]: time[x[0]][x[1]] = alt prev[x[0]][x[1]] = u q.put((alt, x, 1)) else: continue else: continue #Supposed to do the big shuffly once they get to the aisle in front of their seat, doesn't work for innermost? dest = passenger.dest moveDir = None if dest[0] > passenger.inter[0]: moveDir = -1 else: moveDir = 1 mDone=False while not mDone: mDone = True u=passenger.dest while u != passenger.inter: occup = list(grid[u[0]+moveDir][u[1]].occupAtTick[afterTick:afterTick+5]) if len(occup) != 0: if (moveDir == 1 and passengers[occup[0][2]].dest < u) or (moveDir == -1 and passengers[occup[0][2]].dest > u): mDone=False occup2 = list(grid[u[0]][u[1]].occupAtTick[afterTick:afterTick+5]) if len(occup2) != 0: grid[u[0]+moveDir][u[1]].occupAtTick.addi(occup[0][0], afterTick, occup[0][2]) grid[u[0]+moveDir][u[1]].occupAtTick.remove(occup[0]) grid[u[0]][u[1]].occupAtTick.addi(occup2[0][0], afterTick, occup2[0][2]) grid[u[0]][u[1]].occupAtTick.remove(occup2[0]) grid[u[0]+moveDir][u[1]].occupAtTick.addi(afterTick,10**11,occup2[0][2]) grid[u[0]][u[1]].occupAtTick.addi(afterTick,10**11,occup[0][2]) else: grid[u[0]+moveDir][u[1]].occupAtTick.addi(occup[0][0], afterTick, occup[0][2]) grid[u[0]+moveDir][u[1]].occupAtTick.remove(occup[0]) grid[u[0]][u[1]].occupAtTick.addi(afterTick,10**11,occup[0][2]) u = (u[0] + moveDir, u[1]) afterTick+=4 def printPath(p): print("inter: " + str(p.inter)) print("dest: " + str(p.dest)) for x in p.path: print(str(x[0]) + ": " + str(grid[x[0][0]][x[0][1]].occupAtTick[x[1]])) btime = 3 #passengers board every btime ticks delay = 0.01 #Precomputation of all paths, later code is just output functionality def compute(): global btime global passengers global tickTaken tick=0 toadd=0 #genderequality #blm #blessed #syria for (i, prsn) in enumerate(passengers): for e in entries: if toadd < len(passengers) and len(grid[e[0]][e[1]].occupAtTick[tick]) == 0: prsn.curr = (e[0], e[1]) findPath(prsn, i, tick) if DEBUG: print("calculating: " + str(i)) tick += btime toadd += 1 else: tick += 1 for row in grid: for x in row: # print(x.occupAtTick) if len(x.occupAtTick) != 0: # print("list(x.occupAtTick.items)[-1][0]: " + str(list(x.occupAtTick.items())[-1][0])) tickTaken = max(tickTaken, list(x.occupAtTick.items())[-1][0]) print("Time Taken: " + str(tickTaken)) def tick(t): done=True global btime global delay # print grid if DEBUG: print(chr(0x3000), end="") print(chr(0x3000), end="") for x in range(0, width): if x % 10 == 0: print(chr(0xFF10 + int(x / 10)), end="") else: print(chr(0x3000), end="") print() print(chr(0x3000), end="") print(chr(0x3000), end="") for x in range(0, width): print(chr(0xFF10 + (x % 10)), end="") print() for (i, row) in enumerate(grid): if i % 10 == 0: print(chr(0xFF10 + int(i / 10)), end="") else: print(chr(0x3000), end="") print(chr(0xFF10 + (i % 10)), end="") for guy in row: if len(guy.occupAtTick[t]) != 0: print(chr(0x20000 + list(guy.occupAtTick[t])[0][2]), end="") elif guy.typ == SquareType.SEAT: print(":", end="") elif guy.typ == SquareType.WALL: print("W", end="") else: print("_", end="") print() print("---") printPath(passengers[2]) if DEBUG: # time.sleep(1.0) # time.sleep(0.5) # time.sleep(0.1) time.sleep(0.05) # time.sleep(0.02) # time.sleep(0.01) # time.sleep(0.001) os.system("clear") def init(): global height global width global grid global passengers passengers = [] arrFile = open("figure2.txt") height=int(arrFile.readline()) width=int(arrFile.readline()) print(height) print(width) grid = [[GridSquare(SquareType.AISLE) for x in range(0,width)] for y in range(0,height)] for y in range(0,height): for x in range(0,width+1): char = arrFile.read(1); match char: case 'S': grid[y][x].typ = SquareType.SEAT passengers.append(Passenger((y,x),(-1,-1))) case 'W': grid[y][x].typ = SquareType.WALL case '.': grid[y][x].typ = SquareType.AISLE for x in passengers: sign=(-1)**rnd.randint(0,1) for i in range(1,7): inc = (-1)**i * sign * math.floor((i+1)/2) if (inc + x.dest[0] > 0) and (inc + x.dest[0] < height) and (grid[x.dest[0]+inc][x.dest[1]].typ == SquareType.AISLE): x.inter=(inc + x.dest[0], x.dest[1]) break def run(end): t = 0 while t < end: tick(t) t += 1 def main(): global passengers #boarding order # seediter = int(sys.argv[1]) for seediter in range(55,2000): init() print("Seed: " + str(seediter)) rnd.seed(seediter) # passengers.reverse() rnd.shuffle(passengers) compute() # run(tickTaken) if __name__ == "__main__": main()