Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import logging
- from typing import List
- from collections import Counter
- import copy
- logging.basicConfig(level=logging.INFO)
- def read_input(filename: str):
- seats: List(str) = []
- with open(filename, 'r') as f:
- for line in f:
- line = line.rstrip()
- seats.append(list(line))
- return seats
- def neighbors(row, col, seats):
- max_col = len(seats[0])
- max_row = len(seats)
- neighbors = [(row - 1, col - 1), (row - 1, col), (row - 1, col + 1),
- (row, col - 1), (row, col + 1),
- (row + 1, col - 1), (row + 1, col), (row + 1, col + 1)]
- return list(filter(lambda p: p[0] >= 0 and p[0] < max_row and p[1] >= 0 and p[1] < max_col, neighbors))
- def occupy(row, col, seats):
- seats[row][col] = '#'
- def unoccupy(row, col, seats):
- seats[row][col] = 'L'
- def occupied_neighbors(row, col, seats):
- n = neighbors(row, col, seats)
- return list(filter(lambda x: seats[x[0]][x[1]] == '#', n))
- def solution_1(seats):
- loop = 0
- seatcopy = copy.deepcopy(seats)
- while True:
- loop += 1
- changed = False
- for rownum, row in enumerate(seats):
- for col, status in enumerate(row):
- num_occupied_neighbors = len(occupied_neighbors(rownum, col, seats))
- if status == 'L' and num_occupied_neighbors == 0:
- occupy(rownum, col, seatcopy)
- changed = True
- elif status == '#' and num_occupied_neighbors >= 4:
- unoccupy(rownum, col, seatcopy)
- changed = True
- logging.debug(f'{seatcopy}')
- seats = copy.deepcopy(seatcopy)
- if not changed:
- break
- logging.debug(f'Broke the loop at {loop}')
- count = 0
- for row in seats:
- count += Counter(row)['#']
- return count
- ####### Part 2 ########
- def visible_seats(row, col, seats):
- logging.debug(f'processing {row, col}')
- directions = {
- 'NW': lambda row, col, delta: (row - delta, col - delta),
- 'N': lambda row, col, delta: (row - delta, col),
- 'NE': lambda row, col, delta: (row - delta, col + delta),
- 'W': lambda row, col, delta: (row, col - delta),
- 'E': lambda row, col, delta: (row, col + delta),
- 'SW': lambda row, col, delta: (row + delta, col - delta),
- 'S': lambda row, col, delta: (row + delta, col),
- 'SE': lambda row, col, delta: (row + delta, col + delta),
- }
- def is_valid(row, col):
- max_col = len(seats[0])
- max_row = len(seats)
- return row in range(0, max_row) and col in range(0, max_col)
- visible = []
- delta = 1
- while dirs := list(directions):
- logging.debug(f'processing {delta} delta')
- for d in dirs:
- nr, nc = directions[d](row, col, delta)
- if not is_valid(nr, nc):
- del directions[d] # Hit the row or column boundary
- elif seats[nr][nc] == 'L':
- del directions[d] # Our view in this direction is an empty seat
- elif seats[nr][nc] == '#':
- visible.append((nr, nc))
- del directions[d] # Our view in this direction is an occupied seat
- delta += 1
- return visible
- def solution_2(seats):
- loop = 0
- seatcopy = copy.deepcopy(seats)
- while True:
- loop += 1
- changed = False
- for rownum, row in enumerate(seats):
- for col, status in enumerate(row):
- viscount = len(visible_seats(rownum, col, seats))
- logging.debug(f'Viscount={viscount} for {rownum, col}')
- if status == 'L' and viscount == 0:
- occupy(rownum, col, seatcopy)
- changed = True
- elif status == '#' and viscount >= 5:
- unoccupy(rownum, col, seatcopy)
- changed = True
- logging.debug(f'{seatcopy}')
- seats = copy.deepcopy(seatcopy)
- if not changed:
- break
- logging.debug(f'Broke the loop at {loop}')
- count = 0
- for row in seats:
- count += Counter(row)['#']
- return count
- # main
- if __name__ == '__main__':
- seats = read_input('input.txt')
- result_1 = solution_1(seats)
- result_2 = solution_2(seats)
- print(f'Result = {result_1}') # 2470
- print(f'Result2 = {result_2}')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement