Advent of Code 2020: Day 3 – Toboggan Trajectory

When I read the description for day 3 od the Advent of Code, I thought it was asking me to create some kind of pathfinding algorithm. The idea behind this challenge is to figure out how many trees you will hit while skiing down a grid.

You should go check out the description so that you will understand the problem.

!!! SPOILERS AHEAD !!!

You should stop reading if you haven’t solved this puzzle yet!

Part 1

This first portion of the challenge is about figuring out how many trees you end up hitting. Your slope looks something like this:

..##.......
#...#...#..
.#....#..#.
..#.#...#.#
.#...##..#.
..#.##.....
.#.#.#....#
.#........#
#.##...#...
#...##....#
.#..#...#.#

Your input file tells you how to travel down the slope. So line one might say you travel 3 right, and 2 down while line 2 might say you only go right 1, down 1. Trees are marked using the “#”.

I ended up brute-forcing the answer:

def detect_trees(data: list, right: int = 3, down: int = 1) -> int:
    pos = 0
    trees = 0
    first_row = True
    for line in data[::down]:
        line = line * 100

        if pos != 0:
            char = line[:pos][-1]

        if first_row:
            pos += right+1
            first_row = False
            continue
        else:
            pos += right

        if char == "#":
            trees += 1

    print(f"Number of trees: {trees}")
    return trees

While I know this isn’t great code, or even efficient, my goal is solving the puzzle quickly and basically placing on a private leaderboard or two.

Anyway, what I do here is loop over the lines in the data file and change my position accordingly. I use a little hack to tell me if I’m on the first row or not which helps me start where I want to.

Every time the last character I land on is a “#”, I add to my tree counter. This worked quite well overall, even if it is a pretty lame solution.

Part 2

Part 2 is very similar except that this time, you take the answer for each slope and multiply the answers together. For that, I create a new function that and called my function above using the provided slopes.

def multiply_slopes(data: list) -> int:
    first = detect_trees(data, right=1, down=1)
    second = detect_trees(data, right=3, down=1)
    third = detect_trees(data, right=5, down=1)
    fourth = detect_trees(data, right=7, down=1)
    fifth = detect_trees(data, right=1, down=2)
    multiplied = first * second * third * fourth * fifth
    print(f'Slopes multiplied: {multiplied}')
    return multiplied

Then I multiplied the result, printed it out and returned it. In retrospect, I could have use math.prod() here to do the multiplication step and made the code slightly less.

Other Solutions

Matt Harrison (author and professional Python trainer) is doing a video walk through of each of the days of Advent of Code. He is including lots of tips about Python along the way. You should check those videos out here as the price goes up the most videos are added.

I have also learned after writing my solution that I could have used the modulus operator to make the whole thing simpler:

That guy solved the challenge in less than 3 minutes! I like the brevity of the solution, although it’s not something I would have thought of.