Advent of Code — Day 3

Joby Ingram-Dodd
5 min readDec 5, 2020
Photo by Roman Synkevych on Unsplash

DAY 1, DAY 2

Welcome back to day 3 of my Advent of Code walkthroughs, I found this one to be quite a bit tougher then the 2 days before and was beginning to worry I would never make day 25. However I got there in the end and a little help from my fellow students at Strive School made all the difference.

Part 1

The challenge today was to navigate a toboggan down a slope and count the number of trees we hit on the way. To do this I was given a ‘map’ and a step pattern of how to travel across the map. Each line of the map was a string with a repeating pattern, something like this;-

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

The ‘.’ represented empty snow and the ‘#’ represented the trees. The step pattern I had was to move 1 down and 3 right (everyone gets different data), starting at the top left I had to navigate down the map all the way to the bottom some 320 lines later, counting trees hit. In the instructions each line is described repeating, which is important as you will see.

My first approach was to keep moving right until I got out of range then start at index 0 again however this was not working. Reaching out for help I was lucky to get help from a Strive Student who suggested multiplying the lines to repeat the pattern and avoid out of index errors. This worked a treat. So it was then just a case of stepping through each line and shifting across 3, then check if it was a tree and update the tree counter. Here is the code.

map_lines = mapData.split("\n")
cp = 0
tree_count = 0
right = 3
def multiLine(l):
line = l*100
return MakeMove(line)


def MakeMove(l):
global cp
#look at the line and move accross 3
cp += right
pos = cp
if l[pos] == "#":
return True
else:
return False
for l in map_lines:
global tree_count
index = map_lines.index(l)
if index != 0:
if multiLine(l):
tree_count += 1

Lets break this down a little at the top I have 3 global variables and the orginal data (map) split into lines. These are cp which is the current position from left to right then we have tree_count which is our counter to count the trees and we have right which is the number of steps to move right each time.

map_lines = mapData.split("\n")
cp = 0
tree_count = 0
right = 3

Then we get into the functions I have defined, the first one to look at is MakeMove (I know the convention for python is to name functions with underscore rather then camel case but old swift habits die hard), the function actually makes the move on the map and checks to see if it is a tree.

def MakeMove(l):
global cp
#look at the line and move accross
cp += right
pos = cp
if l[pos] == "#":
return True
else:
return False

The function takes the line on the map as an input, which is a string, we then take the current position (cp) and add the number of steps (right) to it. This gives us the new position (pos), and using this position as an index we can use an if statement to check if the character at that position is a tree (#). If it is return true if not return false.

The next function is multiLine (camel case again) which as the name suggests multiplies the line solving our out of index issues.

def multiLine(l):
line = l*100
return MakeMove(line)

We then pass the extra long line into the MakeMove function and check for trees. The return passes back up the chain.

Lastly we have a for loop to go through all the lines on the map, passing each line into the multiLine function

for l in map_lines:
global tree_count
index = map_lines.index(l)
if index != 0:
if multiLine(l):
tree_count += 1

I brought tree_count in as a global variable so I can update the counter, I also used index to check we were not on the first line, as we only want to check lines after the first. I could have done this in the for loop using in range but I thought this made more sense.

Finally print the result.

print(tree_count)

Part 2

Part 2 added some complexity as always, we now had to test 4 different runs down the map and multiply the results together. For me I had these to check

Right 1, down 1.

Right 3, down 1. (This is the slope you already checked.)

Right 5, down 1.

Right 7, down 1.

Right 1, down 2

For the ones which were down 1 it was just a case of changing the right variable in the code for part 1 and noting the result, pretty simple. However the last sequence in the list was 2 down which required some tweaks to the code, here is the new code.

map_lines = mapData.split("\n")
cp = 1
tree_count = 0
right = 1
def multiLine(l):
line = l*100
if x ==1:
return MakeMove(line)

def MakeMove(l):
global cp
#look at the line and move accross 3
cp += right
pos = cp
if l[pos] == "#":
return True
else:
return False
for l in map_lines:
global tree_count
index = map_lines.index(l)
if index != 0 and index % 2 == 0:
if multiLine(l):
tree_count += 1

The changes are made are in 2 places, firstly I added ‘ and index % 2 == 0' to my if statement in the for loop. By checking if the index was divisible by 2 meant I only checked every other line for trees. I expected this to be the only change I needed but it produced the wrong result. After lots of head scratching and checking everything twice, I changed cp to 1 as its initial value which fixed the issue.

Then just multiply the 4 results and we are all done.

Day 3 took me much longer then it should have, as in the end it’s pretty simple, hopefully day 4 clicks quicker.

--

--