From 8e24234f5393eb84515207fa1e8ca0dfe86aea9c Mon Sep 17 00:00:00 2001 From: Christopher Bohn <bohn@unl.edu> Date: Sun, 12 Dec 2021 17:16:02 -0600 Subject: [PATCH] Day 5 complete --- 2021/README.md | 16 ++- 2021/src/main/java/edu/unl/cse/bohn/Main.java | 4 +- .../main/java/edu/unl/cse/bohn/Puzzle.java | 7 +- .../java/edu/unl/cse/bohn/year2021/Day1.java | 5 +- .../java/edu/unl/cse/bohn/year2021/Day2.java | 5 +- .../java/edu/unl/cse/bohn/year2021/Day3.java | 5 +- .../java/edu/unl/cse/bohn/year2021/Day4.java | 5 +- .../java/edu/unl/cse/bohn/year2021/Day5.java | 108 ++++++++++++++++++ 8 files changed, 138 insertions(+), 17 deletions(-) create mode 100644 2021/src/main/java/edu/unl/cse/bohn/year2021/Day5.java diff --git a/2021/README.md b/2021/README.md index 9f4b90a..7290326 100644 --- a/2021/README.md +++ b/2021/README.md @@ -21,4 +21,18 @@ masks are cool. This problem is a little more interesting since there are two stringly types in the data, and one of them (the Bingo cards) requires a delimiter between instances. Defining a custom class to represent Bingo cards simplifies the -post-parsing problem. \ No newline at end of file +post-parsing problem. + +## Day 5 + +This is a pretty straight-forward problem. The only real challenge is that there +are two significant sub-problems: computing the line segments and computing the +vent map. I suppose an alternative approach would be to compute the y=mx+b form +of the lines and algebraically determining their intersections. + +I definitely need to get into the habit of thinking about computationally +less-complex approaches. The straight-forward design I came up with for Day 5 is +O(num_lines * num_rows * num_columns); the algebraic approach would be +O(num_lines^2), so not too much of a big deal on this problem. But (I'm sure) +there will be some problems whose straight-forward solution are a tad +intractable. \ No newline at end of file diff --git a/2021/src/main/java/edu/unl/cse/bohn/Main.java b/2021/src/main/java/edu/unl/cse/bohn/Main.java index f2d082f..c1a7573 100644 --- a/2021/src/main/java/edu/unl/cse/bohn/Main.java +++ b/2021/src/main/java/edu/unl/cse/bohn/Main.java @@ -21,13 +21,13 @@ public class Main { Integer.toString(calendar.get(Calendar.YEAR)), scanner)); int day = Integer.parseInt(getUserInput("Enter puzzle day", Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)), scanner)); + boolean useProductionData = getUserInput("Use sample data (Y/N)?", "Y", scanner).toUpperCase().charAt(0) != 'Y'; scanner.close(); ImportData dataSource = new ImportData(apiKey, year, day); String className = Main.class.getPackageName() + ".year" + year + ".Day" + day; Puzzle puzzle = null; try { - puzzle = (Puzzle)Class.forName(className).getConstructors()[0] - .newInstance(); + puzzle = (Puzzle)Class.forName(className).getConstructors()[0].newInstance(useProductionData); } catch (ClassNotFoundException classNotFoundException) { System.err.println("Could not find class " + className); System.exit(1); diff --git a/2021/src/main/java/edu/unl/cse/bohn/Puzzle.java b/2021/src/main/java/edu/unl/cse/bohn/Puzzle.java index ef977db..b8e5910 100644 --- a/2021/src/main/java/edu/unl/cse/bohn/Puzzle.java +++ b/2021/src/main/java/edu/unl/cse/bohn/Puzzle.java @@ -4,9 +4,12 @@ import java.io.IOException; import java.util.List; public abstract class Puzzle { - protected Integer day = null; protected String sampleData = ""; - protected boolean isProductionReady = false; + protected boolean isProductionReady; + + public Puzzle(boolean isProductionReady) { + this.isProductionReady = isProductionReady; + } public abstract int computePart1(List<String> data); public abstract int computePart2(List<String> data); diff --git a/2021/src/main/java/edu/unl/cse/bohn/year2021/Day1.java b/2021/src/main/java/edu/unl/cse/bohn/year2021/Day1.java index a19ed99..e1b1be5 100644 --- a/2021/src/main/java/edu/unl/cse/bohn/year2021/Day1.java +++ b/2021/src/main/java/edu/unl/cse/bohn/year2021/Day1.java @@ -9,8 +9,8 @@ import java.util.List; public class Day1 extends Puzzle { private List<Integer> depths; - public Day1() { - day = 1; + public Day1(boolean isProductionReady) { + super(isProductionReady); sampleData = """ 199 200 @@ -22,7 +22,6 @@ public class Day1 extends Puzzle { 269 260 263"""; - isProductionReady = true; } private int countIncreases(List<Integer> values) { diff --git a/2021/src/main/java/edu/unl/cse/bohn/year2021/Day2.java b/2021/src/main/java/edu/unl/cse/bohn/year2021/Day2.java index 43ef3f3..92585ee 100644 --- a/2021/src/main/java/edu/unl/cse/bohn/year2021/Day2.java +++ b/2021/src/main/java/edu/unl/cse/bohn/year2021/Day2.java @@ -16,8 +16,8 @@ public class Day2 extends Puzzle { @SuppressWarnings("FieldCanBeLocal") private int aim; - public Day2() { - day = 2; + public Day2(boolean isProductionReady) { + super(isProductionReady); sampleData = """ forward 5 down 5 @@ -25,7 +25,6 @@ public class Day2 extends Puzzle { up 3 down 8 forward 2"""; - isProductionReady = true; } @Override diff --git a/2021/src/main/java/edu/unl/cse/bohn/year2021/Day3.java b/2021/src/main/java/edu/unl/cse/bohn/year2021/Day3.java index 292ead5..fa94aab 100644 --- a/2021/src/main/java/edu/unl/cse/bohn/year2021/Day3.java +++ b/2021/src/main/java/edu/unl/cse/bohn/year2021/Day3.java @@ -12,8 +12,8 @@ public class Day3 extends Puzzle { private int reportLength; private int[] ones, zeroes; - public Day3() { - day = 3; + public Day3(boolean isProductionReady) { + super(isProductionReady); sampleData = """ 00100 11110 @@ -27,7 +27,6 @@ public class Day3 extends Puzzle { 11001 00010 01010"""; - isProductionReady = true; } @Override diff --git a/2021/src/main/java/edu/unl/cse/bohn/year2021/Day4.java b/2021/src/main/java/edu/unl/cse/bohn/year2021/Day4.java index 27b1ee3..46fa1c2 100644 --- a/2021/src/main/java/edu/unl/cse/bohn/year2021/Day4.java +++ b/2021/src/main/java/edu/unl/cse/bohn/year2021/Day4.java @@ -13,8 +13,8 @@ public class Day4 extends Puzzle { private List<Integer> numbers; private List<BingoCard> cards; - public Day4() { - day = 4; + public Day4(boolean isProductionReady) { + super(isProductionReady); sampleData = """ 7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 @@ -35,7 +35,6 @@ public class Day4 extends Puzzle { 18 8 23 26 20 22 11 13 6 5 2 0 12 3 7"""; - isProductionReady = true; } private void parseData(List<String> data) { diff --git a/2021/src/main/java/edu/unl/cse/bohn/year2021/Day5.java b/2021/src/main/java/edu/unl/cse/bohn/year2021/Day5.java new file mode 100644 index 0000000..21a443d --- /dev/null +++ b/2021/src/main/java/edu/unl/cse/bohn/year2021/Day5.java @@ -0,0 +1,108 @@ +package edu.unl.cse.bohn.year2021; + +import edu.unl.cse.bohn.Puzzle; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +@SuppressWarnings("unused") +public class Day5 extends Puzzle { + public record Point(int x, int y) { + } + + List<List<Point>> lineSegments; + int greatestX, greatestY; + + public Day5(boolean isProductionReady) { + super(isProductionReady); + sampleData = """ + 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"""; + } + + private void parseData(List<String> data, boolean considerDiagonals) { + greatestX = greatestY = 0; + lineSegments = new LinkedList<>(); + for (String datum : data) { + List<Point> lineSegment = new LinkedList<>(); + String[] endPoints = datum.split(" -> "); + String[] point = endPoints[0].split(","); + int x1 = Integer.parseInt(point[0]); + int y1 = Integer.parseInt(point[1]); + point = endPoints[1].split(","); + int x2 = Integer.parseInt(point[0]); + int y2 = Integer.parseInt(point[1]); + greatestX = Integer.max(greatestX, Integer.max(x1, x2)); + greatestY = Integer.max(greatestY, Integer.max(y1, y2)); + if (x1 == x2) { // vertical line + int yMin = Integer.min(y1, y2); + int yMax = Integer.max(y1, y2); + for (int y = yMin; y <= yMax; y++) { + lineSegment.add(new Point(x1, y)); + } + } else if (y1 == y2) { // horizontal line + int xMin = Integer.min(x1, x2); + int xMax = Integer.max(x1, x2); + for (int x = xMin; x <= xMax; x++) { + lineSegment.add(new Point(x, y1)); + } + } else if (considerDiagonals) { + int y = y1; + if (x1 < x2) { + for (int x = x1; x <= x2; x++) { + lineSegment.add(new Point(x,y)); + y = y1 < y2 ? y+1 : y-1; + } + } else { + for (int x = x1; x >= x2; x--) { + lineSegment.add(new Point(x,y)); + y = y1 < y2 ? y+1 : y-1; + } + } + } + lineSegments.add(lineSegment); + } + } + + private int countIntersectingVentLines() { + int[][] ventMap = new int[greatestX + 1][greatestY + 1]; + for (int[] row : ventMap) { + Arrays.fill(row, 0); + } + for (List<Point> lineSegment : lineSegments) { + for (Point point : lineSegment) { + ventMap[point.x()][point.y()]++; + } + } + int numberOfIntersections = 0; + for (int x = 0; x <= greatestX; x++) { + for (int y = 0; y <= greatestY; y++) { + if (ventMap[x][y] > 1) { + numberOfIntersections++; + } + } + } + return numberOfIntersections; + } + + @Override + public int computePart1(List<String> data) { + parseData(data, false); + return countIntersectingVentLines(); + } + + @Override + public int computePart2(List<String> data) { + parseData(data, true); + return countIntersectingVentLines(); + } +} -- GitLab