Skip to content

Riddle 1: Crossing zeroes

First the headers

#headers
from sys import argv
import itertools as it
from pandas import DataFrame
import plotly.express as px

Then reading the input into a neat list

#reading
with open(argv[1]) as f:
    lines : [(chr, int)] = [ ( line[0], int(line[1:]) ) for line in f.read().split('\n')[0:-1] ]

A neat plotting function

#plot
# Make 0 the midpoint for a nicer graph
y = [ point if point < 50 else point - 100 for point in y ]

# yss are slices for our animation
yss = [ y[0:i] for i in range(1,len(y),100)]
yss.append(y)

# fill in all the data necessary for the slices
all_points = [[ (i, y, "Hit" if y == 0 else "Miss", len(ys)) for i, y in enumerate(ys)  ] for ys in yss]
# Add point to first slice to include color
all_points.append([(0,-50,"Hit",1)])

# Make a list from a list-of-lists
all_points = it.chain.from_iterable(all_points)

# Dataframe for plotly
df = DataFrame(data=all_points, columns=("x","y","color", "iteration"))

fig = px.scatter(df, x="x", y="y", animation_frame="iteration", color="color", range_y=[-50,50], range_x=[0,len(y)])
fig.write_html("docs/output/1afig.html", include_plotlyjs="cdn")

Bringing it all together

file: 1a.py
<<headers>>
<<reading>>
y = [50]

for dir, distance in lines:
    match dir:
        case 'L':
            y.append((y[-1] - distance+100)%100)
        case 'R':
            y.append((y[-1] + distance+100)%100)
<<plot>>
<<count>>

Let's show the visualization:

Lets count and write our zeroes:

#count
hits = [1 for point in y if point == 0]
with open("docs/output/1a.txt","w") as f:
    f.write(f"{len(hits)}")

That gives us our answer for the first part:

Answer 1a
969

For the second part, we also need to take crossings into account, that changes things a bit, lets generate the data differently and not use modulo

#part2
y = [50]

for dir, distance in lines:
    match dir:
        case 'L':
            y.append(y[-1] - distance)
        case 'R':
            y.append(y[-1] + distance)

Now lets visualize that data, and where it crosses anywhere where mod(100) is zero

#plot2
#create our animation frames
yss = [ y[0:i] for i in range(1,len(y),100)]
yss.append(y)

# Add extra info to our dataframes
all_points = [[ (i, y, len(ys)) for i, y in enumerate(ys)  ] for ys in yss]

# make a list from a list of lists
all_points = it.chain.from_iterable(all_points)

df = DataFrame(data=all_points, columns=("x","y", "iteration"))

fig = px.line(df, x="x", y="y", animation_frame="iteration", range_y=[min(y),max(y)], range_x=[0,len(y)])
fig.write_html("docs/output/1bfig.html", include_plotlyjs="cdn")

Putting it all together

file: 1b.py
<<headers>>
<<reading>>
<<part2>>
<<plot2>>
<<findcrossings>>

As you can see it crosses the "modulo(100) == 0" point quite a few times, lets find those points, naively:

#findcrossings
crossings = 0
# take pairs of points
for i in range(1,len(y)):
    # are we going up or down?
    dir = 1 if y[i] > y[i-1] else -1
    #iterate over all numbers between the pair
    for j in range(y[i-1],y[i], dir):
        if j%100 == 0:
            crossings = crossings + 1
with open("docs/output/1b.txt","w") as f:
    f.write(f"{crossings}")

Which gives us the answer:

Answer 1b
5887