← Home

Advent of Code 2020 Day 11



This year’s Advent of Code’s day 11 challenge – Seating System was a type of cellular automata task where one needed to model the eventual seating positions of individuals who are waiting to board a ferry.

To create our visualizations first we generate a new, random initial seating layout based off of the AoC examples

def generate_layout(rows, columns):
    chars = ['L', '.']
    layout = []
    for _ in range(rows):
        column = []
        for _ in range(columns):
            column.append(random.choice(chars))
        layout.append(row)
    return(layout)

this returns a two dimensional array like

[
    ['.', '.', '.', 'L', '.', 'L', '.', 'L', '.', 'L'],
    ['.', 'L', 'L', 'L', 'L', 'L', 'L', '.', '.', '.'],
    ['.', '.', 'L', 'L', '.', 'L', 'L', 'L', 'L', 'L'],
    ['L', 'L', 'L', '.', 'L', 'L', 'L', 'L', 'L', '.'],
    ['.', '.', 'L', 'L', '.', 'L', '.', '.', 'L', 'L'],
    ['L', '.', 'L', 'L', '.', 'L', 'L', '.', 'L', 'L'],
    ['L', '.', '.', 'L', '.', 'L', '.', 'L', 'L', 'L'],
    ['.', 'L', 'L', '.', '.', '.', '.', 'L', '.', 'L'],
    ['.', '.', 'L', '.', 'L', 'L', 'L', '.', '.', '.'],
    ['L', 'L', 'L', '.', 'L', 'L', '.', '.', 'L', 'L']
]

next we have print_layout() which gives us a nicer representation of our seats

def print_layout(seat_array):
    layout = ""
    for column in seat_array:
        c = ""
        for seat in column:
          c += seat
        layout += '\n' + c
    return(layout)
...L.L.L.L
.LLLLLL...
..LL.LLLLL
LLL.LLLLL.
..LL.L..LL
L.LL.LL.LL
L..L.L.LLL
.LL....L.L
..L.LLL...
LLL.LL..LL

The fun thing about this function is that is gives us lot of flexibility in how we represent this data. For example we can draw our seats using unicode block elements.

def print_layout(seat_array):
    layout = ""
    for column in seat_array:
        c = ""
        for seat in column:
            if seat == '.': c += ' '
            if seat == '#': c += '▓'
            if seat == 'L': c += '▒'
        layout += '\n' + c
    return(layout)
 ▓ ░▓▓░▓ ▓
▓ ░ ░░ ░ ▓
▓ ░     ░
░ ░▓ ░   ░
▓░ ░░ ▓▓░▓
░▓▓  ░▓░
 ░░ ░ ░░▓
▓▓  ░▓
    ░░ ▓░░
    ▓░  ░▓

Then we can create an animation of our generated layouts reaching equilibrium

while True:
  os.system('clear')

  rows, columns = os.popen('stty size', 'r').read().split()
  layout = generate_layout(int(columns), int(rows))
  seats = model_seats(layout)

  occupied_seat_counts = [0]
  while True:
    seats = model_seats(seats) # model the next seat layout

    layout = print_layout(seats)
    print(layout, flush=True) # display our new seat layout

    occupied_seats = layout.count('▓') # this should be whichever
                                       # char you use to represent
                                       # occupied seats
    if occupied_seats == occupied_seat_counts[-1]:
      break # if the number of occupied seats has not changed since
            # the previous run break and start on new seating layout
    else:
      occupied_seat_counts.append(occupied_seats)

You can see the full code and run it in your browser.