Advertisement
Guest User

Untitled

a guest
Dec 11th, 2020
646
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.40 KB | None | 0 0
  1. import logging
  2. from typing import List
  3. from collections import Counter
  4. import copy
  5.  
  6. logging.basicConfig(level=logging.INFO)
  7.  
  8.  
  9. def read_input(filename: str):
  10.     seats: List(str) = []
  11.     with open(filename, 'r') as f:
  12.         for line in f:
  13.             line = line.rstrip()
  14.             seats.append(list(line))
  15.     return seats
  16.  
  17.  
  18. def neighbors(row, col, seats):
  19.     max_col = len(seats[0])
  20.     max_row = len(seats)
  21.     neighbors = [(row - 1, col - 1), (row - 1, col), (row - 1, col + 1),
  22.                 (row, col - 1),                      (row, col + 1),
  23.                 (row + 1, col - 1),  (row + 1, col), (row + 1, col + 1)]
  24.     return list(filter(lambda p: p[0] >= 0 and p[0] < max_row and p[1] >= 0 and p[1] < max_col, neighbors))
  25.  
  26. def occupy(row, col, seats):
  27.     seats[row][col] = '#'
  28.  
  29. def unoccupy(row, col, seats):
  30.     seats[row][col] = 'L'
  31.  
  32. def occupied_neighbors(row, col, seats):
  33.     n = neighbors(row, col, seats)
  34.     return list(filter(lambda x: seats[x[0]][x[1]] == '#', n))
  35.  
  36.  
  37. def solution_1(seats):
  38.     loop = 0
  39.     seatcopy = copy.deepcopy(seats)
  40.     while True:
  41.         loop += 1
  42.         changed = False
  43.         for rownum, row in enumerate(seats):
  44.             for col, status in enumerate(row):
  45.                 num_occupied_neighbors = len(occupied_neighbors(rownum, col, seats))
  46.                 if status == 'L' and num_occupied_neighbors == 0:
  47.                     occupy(rownum, col, seatcopy)
  48.                     changed = True
  49.                 elif status == '#' and num_occupied_neighbors >= 4:
  50.                     unoccupy(rownum, col, seatcopy)
  51.                     changed = True
  52.         logging.debug(f'{seatcopy}')
  53.         seats = copy.deepcopy(seatcopy)
  54.         if not changed:
  55.             break
  56.     logging.debug(f'Broke the loop at {loop}')
  57.     count = 0
  58.     for row in seats:
  59.         count += Counter(row)['#']
  60.     return count
  61.  
  62. ####### Part 2 ########
  63. def visible_seats(row, col, seats):
  64.     logging.debug(f'processing {row, col}')
  65.     directions = {
  66.         'NW': lambda row, col, delta: (row - delta, col - delta),
  67.         'N': lambda row, col, delta: (row - delta, col),
  68.         'NE': lambda row, col, delta: (row - delta, col + delta),
  69.         'W': lambda row, col, delta: (row, col - delta),
  70.         'E': lambda row, col, delta: (row, col + delta),
  71.         'SW': lambda row, col, delta: (row + delta, col - delta),
  72.         'S': lambda row, col, delta: (row + delta, col),
  73.         'SE': lambda row, col, delta: (row + delta, col + delta),
  74.     }
  75.  
  76.     def is_valid(row, col):
  77.         max_col = len(seats[0])
  78.         max_row = len(seats)
  79.         return row in range(0, max_row) and col in range(0, max_col)
  80.  
  81.     visible = []
  82.     delta = 1
  83.     while dirs := list(directions):
  84.         logging.debug(f'processing {delta} delta')
  85.         for d in dirs:
  86.             nr, nc = directions[d](row, col, delta)
  87.             if not is_valid(nr, nc):
  88.                 del directions[d] # Hit the row or column boundary
  89.             elif seats[nr][nc] == 'L':
  90.                 del directions[d] # Our view in this direction is an empty seat
  91.             elif seats[nr][nc] == '#':
  92.                 visible.append((nr, nc))
  93.                 del directions[d] # Our view in this direction is an occupied seat
  94.         delta += 1
  95.     return visible
  96.  
  97.  
  98. def solution_2(seats):
  99.     loop = 0
  100.     seatcopy = copy.deepcopy(seats)
  101.     while True:
  102.         loop += 1
  103.         changed = False
  104.         for rownum, row in enumerate(seats):
  105.             for col, status in enumerate(row):
  106.                 viscount = len(visible_seats(rownum, col, seats))
  107.                 logging.debug(f'Viscount={viscount} for {rownum, col}')
  108.                 if status == 'L' and viscount == 0:
  109.                     occupy(rownum, col, seatcopy)
  110.                     changed = True
  111.                 elif status == '#' and viscount >= 5:
  112.                     unoccupy(rownum, col, seatcopy)
  113.                     changed = True
  114.         logging.debug(f'{seatcopy}')
  115.         seats = copy.deepcopy(seatcopy)
  116.         if not changed:
  117.             break
  118.     logging.debug(f'Broke the loop at {loop}')
  119.     count = 0
  120.     for row in seats:
  121.         count += Counter(row)['#']
  122.     return count
  123.    
  124.  
  125. # main
  126. if __name__ == '__main__':
  127.     seats = read_input('input.txt')
  128.     result_1 = solution_1(seats)
  129.     result_2 = solution_2(seats)
  130.     print(f'Result = {result_1}') # 2470
  131.     print(f'Result2 = {result_2}')
  132.  
  133.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement