Advent of Code: Day #11 - Seating System

12th of December 2020 |

5 - 6 minutes

Introduction

I was super busy yesterday so sorry this is late! The code is not the best optimised and I would like to go over it again in the future but it does work.

Task One

Today we are given a Game of Life-esque problem to model the seating in the waiting area. We are asked to apply the rules described and return the total amount of occupied seats.

Reading in the data

The input data is a map describing the layout of the seating area, a L character represents an empty chair, # an occupied one and . represents the floor. I read this data into a multidimensional array so I can access the data using an x, y index. seat = seats[y][x]

Python Copy
def read_data(path):
dataset = []
with open(path) as f:
for line in f.readlines():
dataset.append(list(line.rstrip()))

return dataset

The Solution

To solve this I iterated over all of the seats and calculated the neighbors of the current seat. I then applied the rules and updated the seat as necessary. The solution is a bit slow, mainly because of the deepcopy every complete iteration.

Python Copy
def task_one(seatplan):
def query(y, x):
if y < 0 or x < 0 or y > height-1 or x > width-1:
return "."
return seats[y][x]

width = len(seatplan[0])
height = len(seatplan)
seats = []

while seats != seatplan:
seats = deepcopy(seatplan)
for y in range(height):
for x in range(width):
current_seat = query(y, x)
neighbours = [query(y-1, x-1), query(y-1, x), query(y-1, x+1),
query(y, x-1), query(y, x+1),
query(y+1, x-1), query(y+1, x), query(y+1, x+1)]

occupied = [seat for seat in neighbours if seat == "#"]
if current_seat == "L" and "#" not in neighbours:
seatplan[y][x] = "#"
elif current_seat == "#" and len(occupied) >= 4:
seatplan[y][x] = "L"

return len([seat for row in seatplan for seat in row if seat == "#"])

Task Two

The Solution

Task two had us consider the first seat in the line of view from the current seat not just the ones adjacent. I do this by just checking spots until we find one that is not just floor.

Python Copy
def task_two(seatplan):
def query(y, x):
if y < 0 or x < 0 or y > height - 1 or x > width - 1:
return "L"
return old_seats[y][x]

width = len(seatplan[0])
height = len(seatplan)
seats = deepcopy(seatplan)
old_seats = deepcopy(seatplan)
old_seats_new = deepcopy(seatplan)
last = False

coeffs = [
[-1, -1], [-1, 0], [-1, +1],
[0, -1], [0, +1],
[+1, -1], [+1, 0], [+1, +1]
]

while True:
for y in range(height):
for x in range(width):
old_seats_new[y][x] = seats[y][x]

current_seat = query(y, x)

neighbours = [None, None, None,
None, None,
None, None, None]
c = 1
while any(seat is None for seat in neighbours):
for i, (a, b) in enumerate(coeffs):
seat = query(y - a * c, x - b * c)
if neighbours[i] is None and seat != ".":
neighbours[i] = seat
c += 1

if current_seat == "L" and "#" not in neighbours:
seats[y][x] = "#"
elif current_seat == "#" and len(["#" for seat in neighbours if seat == "#"]) >= 5:
seats[y][x] = "L"

old_seats = old_seats_new
if seats == old_seats and last:
break
last = seats == old_seats
return len([1 for row in seats for seat in row if seat == "#"])

Leaderboard Code: 353270-1fc6ef28

Github Repository A link to the github repo containing all the days.

main.py A direct download of the main.py script

3.1Kb