commit 701f17d49b19b0e40a6a97340ba1d0082fa0b357
parent 075009958b22571e49d7903fb3637c55d6fc44d9
Author: Eamon Caddigan <eamon.caddigan@gmail.com>
Date: Sun, 5 Dec 2021 19:48:22 -0500
Solution to day 5, part 2
Diffstat:
A | day05_part2.py | | | 71 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 71 insertions(+), 0 deletions(-)
diff --git a/day05_part2.py b/day05_part2.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+"""Advent of Code 2021, day 5 (part 2): considering the diagonal lines."""
+
+import numpy as np
+from utils import get_puzzle_input
+from day05_part1 import (convert_input_to_df,
+ count_point_coverage,
+ count_danger_points)
+
+def find_points_x(x_1, y_1, x_2, y_2):
+ """Given a line segment's start and end coordinates, return a numby array
+ of x coordinates for the points along segment"""
+ # This is easy because we're only dealing with horizontal and vertical
+ # lines (for now)
+ if x_1 > x_2:
+ line_array = np.arange(x_1, x_2 - 1, -1)
+ elif x_1 < x_2:
+ line_array = np.arange(x_1, x_2 + 1, 1)
+ else:
+ line_array = np.repeat(x_1, abs(y_2 - y_1) + 1)
+ return line_array
+
+def find_points_y(x_1, y_1, x_2, y_2):
+ """Given a line segment's start and end coordinates, return a numby array
+ of x coordinates for the points along segment"""
+ return find_points_x(x_1=y_1, y_1=x_1, x_2=y_2, y_2=x_2)
+
+def find_line_points(endpoints_df):
+ """Given a df with the start and end coordinates of the line segments, add
+ new columns, `x` and `y`, that give the coordinates of all points covered
+ by the line (note that line data will be dropped but indices are
+ retained)"""
+ # I don't love that I'm copy-pasting so much of the code from Part 1, but
+ # one thing I have consciously avoided is refactoring Part 1 after Part 2
+ # is revealed to me. Not sure why I care about that but I do!
+ return (
+ endpoints_df
+ .assign(x=lambda df: [find_points_x(*x[1].to_list()) \
+ for x in df[['x1', 'y1', 'x2', 'y2']].iterrows()],
+ y=lambda df: [find_points_y(*x[1].to_list()) \
+ for x in df[['x1', 'y1', 'x2', 'y2']].iterrows()])
+ .explode(['x', 'y'])
+ .drop(columns=['x1', 'y1', 'x2', 'y2'])
+ )
+
+def solve_puzzle(input_string):
+ """Return the numeric solution to the puzzle"""
+ return count_danger_points(
+ count_point_coverage(
+ find_line_points(
+ convert_input_to_df(input_string)
+ )
+ )
+ )
+
+if __name__ == "__main__":
+ assert solve_puzzle(
+ "\n".join(("0,9 -> 5,9",
+ "8,0 -> 0,8",
+ "9,4 -> 3,4",
+ "2,2 -> 2,1",
+ "7,0 -> 7,4",
+ "6,4 -> 2,0",
+ "0,9 -> 2,9",
+ "3,4 -> 1,4",
+ "0,0 -> 8,8",
+ "5,5 -> 8,2",
+ "\n"))) == 12
+
+ print("Number of points to avoid (including the diagnoal lines now):",
+ solve_puzzle(get_puzzle_input(5)))