From 853e33ccdb997d4996fcd5a290be12c1a919d7d0 Mon Sep 17 00:00:00 2001
From: Christopher Bohn <bohn@unl.edu>
Date: Sun, 4 Dec 2022 08:50:20 -0600
Subject: [PATCH] Completed Year 2022 Day 4

---
 2022/README.md                                | 57 ++++++++++++++----
 .../java/edu/unl/cse/bohn/year2022/Day4.java  | 59 +++++++++++++++++++
 2 files changed, 106 insertions(+), 10 deletions(-)
 create mode 100644 2022/src/main/java/edu/unl/cse/bohn/year2022/Day4.java

diff --git a/2022/README.md b/2022/README.md
index 5c62a28..808f8f3 100644
--- a/2022/README.md
+++ b/2022/README.md
@@ -5,20 +5,25 @@
 - [The problem](https://adventofcode.com/2022/day/1)
 - [The solution](src/main/java/edu/unl/cse/bohn/year2022/Day1.java)
 
-I like the first few days' problems -- they're simple enough that they make great computational thinking examples for my 100-level students.
+I like the first few days' problems -- they're simple enough that they make great computational thinking examples for my
+100-level students.
 Breaking the problem down into subproblems:
 - Keep track of how many calories an elf is carrying
 - Detect when we've reach the end of the list of items that elf is carrying
 - Convert strings to integers
-- Of the elves considered so far, keep track of the number of calories being carried by the elf who is carrying the most calories (or the three elves who are carrying the most calories)
+- Of the elves considered so far, keep track of the number of calories being carried by the elf who is carrying the most
+- calories (or the three elves who are carrying the most calories)
 - Update that count when we've finished with an elf
-  - For part 1, we must determine whether the most-recent elf is carrying more calories than the maximum among the previous elves
-  - For part 2, we must determine whether the most-recent elf is carrying more calories than any of the previous top-three
+  - For part 1, we must determine whether the most-recent elf is carrying more calories than the maximum among the 
+  - previous elves
+  - For part 2, we must determine whether the most-recent elf is carrying more calories than any of the previous 
+  - top-three
 - Produce the result
   - For part 1, the result is the maximum number of calories being carried by any one elf
   - For part 2, the result is the sum of the number of calories being carried by the top three
 
-While I wouldn't expect my students to be able to provide solutions in quite so few lines as I did -- we don't teach the Java streams API in CS1 -- they could definitely do this problem.
+While I wouldn't expect my students to be able to provide solutions in quite so few lines as I did -- we don't teach the
+Java streams API in CS1 -- they could definitely do this problem.
 The only wrinkle is that a blank line isn't the *only* way to reach the end of an elf's list.
 
 ### Refactoring opportunity
@@ -27,7 +32,8 @@ Parts 1 & 2 differ only in how many "maximum" elves we're tracking and, conseque
 My part 2 solution used a set that can never grow to more than 3 items because we're tracking the top three elves.
 Part 1 can be thought of as a degenerate case of tracking the top "one" elf;
 this suggests that it can be solved with a set that can never grow to more than 1 item.
-Which means we can use the same solution for both parts, parameterized by the top "number" of elves, which becomes the upper limit of the size of the set.
+Which means we can use the same solution for both parts, parameterized by the top "number" of elves, which becomes the 
+upper limit of the size of the set.
 
 ## Day 2
 
@@ -44,7 +50,8 @@ Seems pretty straight-forward.
 
 ### Refactoring opportunity
 
-Parts 1 & 2 differ in whether we determine the outcome based off of "my" hand, or whether we determine "my" hand based off of the outcome.
+Parts 1 & 2 differ in whether we determine the outcome based off of "my" hand, or whether we determine "my" hand based 
+o ff of the outcome.
 Where we parameterized the commonality on Day 1, today we'll simply extract the commonality into a helper method.
 
 ## Day 3
@@ -69,8 +76,10 @@ The subproblems are
 - Determine an item's priority (solved from part 1)
 - ~~Determine which items are present in exactly three knapsacks~~
   - ~~Determine which knapsacks each item is in~~
-  - ~~I'm not sure that it matters, but what if a "triplet item" occurs multiple times in a knapsack; is it no longer a "triplet item"? We probably could check by finding out if an elf is in more than one triplet.~~
-- Looks like I misread the problem statement originally. It seems that we don't need to find the triplets; the triplets appear in order in the data, knapsacks {*i*, *i+1*, *i+2*}
+  - ~~I'm not sure that it matters, but what if a "triplet item" occurs multiple times in a knapsack; is it no longer a 
+    "triplet item"? We probably could check by finding out if an elf is in more than one triplet.~~
+- Looks like I misread the problem statement originally. It seems that we don't need to find the triplets; the triplets 
+  appear in order in the data, knapsacks {*i*, *i+1*, *i+2*}
   - Assume the number of knapsacks is divisible by 3
   - Determine which item is common in each triplet
     - Assume each triplet has exactly one "triplet item"
@@ -80,7 +89,35 @@ The subproblems are
 
 Both problems involve finding a singular common character -- one among two strings, the other among three.
 
-#Day 4
+## Day 4
+
+- [The problem](https://adventofcode.com/2022/day/4)
+- [The solution](src/main/java/edu/unl/cse/bohn/year2022/Day4.java)
+
+### Part 1
+
+The subproblems are
+- Determine which sections each elf is responsible for
+  - Determining the minimum and maximum section numbers should be sufficient
+- For each pair, determine if one elf's section range is fully covered by the other's
+  - Comparing the minimums and maximums should be sufficient
+- Count the number of such pairs
+
+Seems straight-forward enough.
+
+### Part 2
+
+The subproblems are substantially the same. The only difference is that instead of checking for complete overlap, we're
+checking for any overlap -- we just need to change the comparison.
+
+### Refactoring opportunity
+
+As noted, the only difference between parts 1 & 2 is how the comparison happens.
+I must be spending too much time with C, because my first instinct was to create a function pointer and then create a
+function for each of the two ways to compare.
+No, the thing to do is to extract the common part out into a helper method.
+
+## Day 5
 
 (coming soon)
 
diff --git a/2022/src/main/java/edu/unl/cse/bohn/year2022/Day4.java b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day4.java
new file mode 100644
index 0000000..4483432
--- /dev/null
+++ b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day4.java
@@ -0,0 +1,59 @@
+package edu.unl.cse.bohn.year2022;
+
+import edu.unl.cse.bohn.Puzzle;
+
+import java.util.List;
+
+@SuppressWarnings("unused")
+public class Day4 extends Puzzle {
+    public Day4(boolean isProductionReady) {
+        super(isProductionReady);
+        sampleData = """
+                2-4,6-8
+                2-3,4-5
+                5-7,7-9
+                2-8,3-7
+                6-6,4-6
+                2-6,4-8""";
+    }
+
+    @Override
+    public long computePart1(List<String> data) {
+        long overlappingElfCount = 0;
+        for (String datum : data) {
+            int[] minima = new int[2];
+            int[] maxima = new int[2];
+            getExtrema(datum, minima, maxima);
+            if ((minima[0] >= minima[1] && maxima[0] <= maxima[1]) ||
+                    (minima[1] >= minima[0] && maxima[1] <= maxima[0])) {
+                overlappingElfCount++;
+            }
+        }
+        return overlappingElfCount;
+    }
+
+    @Override
+    public long computePart2(List<String> data) {
+        long overlappingElfCount = 0;
+        for (String datum : data) {
+            int[] minima = new int[2];
+            int[] maxima = new int[2];
+            getExtrema(datum, minima, maxima);
+            if ((minima[0] >= minima[1] && minima[0] <= maxima[1]) ||       // lower-end of elf 1 falls in elf 2's range
+                    (maxima[0] >= minima[1] && maxima[0] <= maxima[1]) ||   // upper-end of elf 1 falls in elf 2's range
+                    (minima[1] >= minima[0] && minima[1] <= maxima[0]) ||   // lower-end of elf 2 falls in elf 1's range
+                    (maxima[1] >= minima[0] && maxima[1] <= maxima[0])) {   // upper-end of elf 2 falls in elf 1's range
+                overlappingElfCount++;
+            }
+        }
+        return overlappingElfCount;
+    }
+
+    private static void getExtrema(String datum, int[] minima, int[] maxima) {
+        String[] sections = datum.split(",");
+        for (int i = 0; i < sections.length; i++) {
+            minima[i] = Integer.parseInt(sections[i].split("-")[0]);
+            maxima[i] = Integer.parseInt(sections[i].split("-")[1]);
+        }
+    }
+}
-- 
GitLab