Advent of code - Day 3

Day 3 instructions

Part 1

Read in data into a pandas dataframe.

import pandas as pd
import numpy as np

df = pd.read_csv('day3input.txt',delimiter=' ', skip_blank_lines=True,header=None)
df.head()
0 1 2 3
0 #1 @ 387,801: 11x22
1 #2 @ 101,301: 19x14
2 #3 @ 472,755: 11x16
3 #4 @ 518,720: 23x17
4 #5 @ 481,939: 29x20
  • Strip column 2 of its trailing colon, split the column on the comma into x_space and y_space.
  • Split column 3 into x_length and y_length by the ‘x’ inbetween the to values.
df['x_space'], df['y_space'] = df[2].str.strip(':').str.split(',',1).str
df['x_length'], df['y_length'] = df[3].str.split('x',1).str

df.head()
0 1 2 3 x_space y_space x_length y_length
0 #1 @ 387,801: 11x22 387 801 11 22
1 #2 @ 101,301: 19x14 101 301 19 14
2 #3 @ 472,755: 11x16 472 755 11 16
3 #4 @ 518,720: 23x17 518 720 23 17
4 #5 @ 481,939: 29x20 481 939 29 20
  • Drop unnecessary columns
  • Change datatypes to integers
df.drop(columns=[0,1,2,3],inplace=True)
df = df.astype(int)

df.head()
x_space y_space x_length y_length
0 387 801 11 22
1 101 301 19 14
2 472 755 11 16
3 518 720 23 17
4 481 939 29 20

Find max x and y coordinates for mapping out fabric.

max_x = df['x_space'].max() + df['x_length'].max()
max_y = df['y_space'].max() + df['y_length'].max()

print('Max x value : {}'.format(max_x))
print('Max y value : {}'.format(max_y))
Max x value : 1016
Max y value : 1012

Initialise array of zeros of dimensions (max_x, max_y) representing the fabric.

fabric = np.zeros((max_x,max_y))

For each row in the dataframe:

  • Read values for x, y, x_length and y_length
  • Initialize array of ones of dimensions (x_length, y_length) representing the size of the claim.
  • Add the claim array onto the fabric array at the corresponding coordinates
for i in range(len(df)):
    x, y, x_length, y_length = df.loc[i,:]
    claim = np.ones((x_length, y_length))
    fabric[x:x+x_length, y:y+y_length] += claim

Fabric representation and mapping example:

sample = np.zeros((5,5))
sample
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])
sample_claim = np.ones((2,3))
sample_claim
array([[1., 1., 1.],
       [1., 1., 1.]])
sample[0:2, 1:4] += sample_claim
sample
array([[0., 1., 1., 1., 0.],
       [0., 1., 1., 1., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])

Find counts of overlapping claims.

unique, counts = np.unique(fabric,return_counts=True)
print(sorted(zip(unique, counts)))
[(0.0, 679490), (1.0, 233398), (2.0, 85755), (3.0, 22904), (4.0, 5526), (5.0, 931), (6.0, 172), (7.0, 16)]

Find total that is overlapping with at least one other claim.

total_double_matched = counts[2:].sum()
print('Total double matched : {}'.format(total_double_matched))
Total double matched : 115304

Part 2 - Find the only claim with no overlap

We already have an array holding the fabric, with all the claims added in the correct place.

import matplotlib.pyplot as plt

plt.figure(figsize=(12,12))
plt.title('Visual representation of fabric')
plt.xlabel('x-coordinates')
plt.ylabel('y-coordinates')
plt.imshow(fabric)
plt.colorbar()
plt.show()

png

So to find the claim that does not overlap we need to loop through the claims again, checking whether the claim (array of ones) is equal to the fabric at the coordinates of the claim.

for i in range(len(df)):
    x, y, x_length, y_length = df.loc[i,:]
    claim = np.ones((x_length, y_length))
    if np.array_equal(fabric[x:x+x_length, y:y+y_length], claim):
        print('Thats the one! :\n', df.loc[i,:])
Thats the one! :
 x_space     336
y_space     615
x_length     28
y_length     21
Name: 274, dtype: int64

Name : 274 is the entry we are looking for, my answer is 275 because we deleted the index column earlier and pandas dataframes index from 0 and not 1.

Updated: