9 filename=(len(sys.argv) > 1) and sys.argv[1] or "37_26_seats.txt"
 
  11 base_states=[list(s.rstrip()) for s in open(filename, "r")]
 
  12 states=copy.deepcopy(base_states)
 
  14 def get_adjacent_seats(states, y, x, seat_map):
 
  21     if y >= len(states)-1:
 
  29     if x >= len(states[y])-1:
 
  32     for check_y in range(start_y, end_y+1):
 
  33         for check_x in range(start_x, end_x+1):
 
  34             if check_y == y and check_x == x:
 
  36             if states[check_y][check_x] == "#":
 
  41 def get_nearest_seats(states, y, x, seat_map):
 
  43     for seat in seat_map[y][x]:
 
  44         if states[seat[0]][seat[1]] == "#":
 
  49 def calc_nearest_seats(states):
 
  51     for y,row in enumerate(states):
 
  52         for x,seat in enumerate(row):
 
  53             # only do anything if the seat is a seat
 
  57             for check_y,other_row in enumerate(states):
 
  58                 for check_x,other_seat in enumerate(other_row):
 
  59                     # only do anything if the seat is a seat
 
  63                     if check_x == x and check_y == y:
 
  65                     if abs(check_x - x) == abs(check_y - y):
 
  66                         # this is one of the four diagonals
 
  67                         if check_x > x and check_y > y:
 
  68                             # down and right, getting further away
 
  69                             # so if we've got a value ignore, other
 
  71                             if 'dr' not in daseats:
 
  72                                 daseats['dr']=[check_y,check_x]
 
  73                         elif check_x > x and check_y < y:
 
  74                             # up and right, getting closer
 
  75                             daseats['ur']=[check_y,check_x]
 
  76                         elif check_x < x and check_y < y:
 
  77                             # up and left, getting closer, so always replace
 
  78                             daseats['ul']=[check_y,check_x]
 
  79                         elif check_x < x and check_y > y:
 
  80                             # down and left getting further away
 
  81                             if 'dl' not in daseats:
 
  82                                 daseats['dl']=[check_y,check_x]
 
  83                     elif check_x > x and check_y == y:
 
  84                         # heading right, getting further away
 
  85                         # so if we've got a value ingore, other
 
  87                         if 'r' not in daseats:
 
  88                             daseats['r']=[check_y,check_x]
 
  89                     elif check_x < x and check_y == y:
 
  90                         # heading left, getting closer
 
  91                         daseats['l']=[check_y,check_x]
 
  92                     elif check_y > y and check_x == x:
 
  93                         # heading down, getting further away
 
  94                         if 'd' not in daseats:
 
  95                             daseats['d']=[check_y,check_x]
 
  96                     elif check_y < y and check_x == x:
 
  98                         daseats['u']=[check_y,check_x]
 
 100                 seats[y]={x: [seat for seat in daseats.values()]}
 
 101             seats[y][x]=[seats for seats in daseats.values()]
 
 106 def apply_rules(states, check=get_adjacent_seats, max_people=4, seat_map=None):
 
 107     new_states=copy.deepcopy(states)
 
 109     for y in range(0, len(states)):
 
 110         for x in range(0, len(states[0])):
 
 111             if states[y][x] == ".":
 
 113             adj_seats=check(states, y, x, seat_map)
 
 114             if states[y][x] == 'L' and adj_seats == 0:
 
 116             elif states[y][x] == '#' and adj_seats >= max_people:
 
 121 def get_seats(states):
 
 122     return ''.join([''.join(s) for s in states])
 
 124 def print_layout(states, indent_string=""):
 
 126         print(indent_string, ''.join(line))
 
 130 previous_seats=get_seats(states)
 
 131 states=apply_rules(states)
 
 132 seats=get_seats(states)
 
 134 while seats!=previous_seats:
 
 135     states=apply_rules(states)
 
 137     seats=get_seats(states)
 
 140 print("  Final state:")
 
 141 print_layout(states, "  ")
 
 142 print("  Occupied: {}".format(seats.count('#')))
 
 145 states=copy.deepcopy(base_states)
 
 146 seat_map=calc_nearest_seats(states)
 
 148 previous_seats=get_seats(states)
 
 149 states=apply_rules(states,get_nearest_seats,5,seat_map)
 
 150 seats=get_seats(states)
 
 152 while seats!=previous_seats:
 
 153     states=apply_rules(states,get_nearest_seats,5,seat_map)
 
 155     seats=get_seats(states)
 
 158 print("  Final state:")
 
 159 print_layout(states, "  ")
 
 160 print("  Occupied: {}".format(seats.count('#')))