diff --git a/2022/README.md b/2022/README.md
index a081fdf5cbca4d05ffbbeff11d10abb919d28fd1..5c62a28bbe635b67efc851268ab3a0c3e79b33b5 100644
--- a/2022/README.md
+++ b/2022/README.md
@@ -63,6 +63,23 @@ The subproblems are
     - *Aha!* one of the knapsacks in the sample data has 'L' as a common item, twice
 - Sum the priorities of all the "common items"
 
+### Part 2
+
+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*}
+  - 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"
+- Sum the priorities of all the "triplet items"
+
+### Refactoring opportunity
+
+Both problems involve finding a singular common character -- one among two strings, the other among three.
+
 #Day 4
 
 (coming soon)
diff --git a/2022/src/main/java/edu/unl/cse/bohn/year2022/Day3.java b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day3.java
index 2e21cef5ccda4ba9174058b92b54e5e751967478..5cceef2e445845f0c09d35f38abdfcb322d2980e 100644
--- a/2022/src/main/java/edu/unl/cse/bohn/year2022/Day3.java
+++ b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day3.java
@@ -2,8 +2,7 @@ package edu.unl.cse.bohn.year2022;
 
 import edu.unl.cse.bohn.Puzzle;
 
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
 
 @SuppressWarnings("unused")
 public class Day3 extends Puzzle {
@@ -37,51 +36,72 @@ public class Day3 extends Puzzle {
 
     @Override
     public long computePart2(List<String> data) {
-        return 0;
+        long prioritySum = 0;
+        if (data.size() % 3 != 0) {
+            throw new IllegalArgumentException("The number of knapsacks (" + data.size() + ") is not divisible by three.");
+        }
+        for (int i = 0; i < data.size(); i += 3) {
+            char commonItem = getCommonItem(data.get(i), data.get(i + 1), data.get(i + 2));
+            prioritySum += getPriority(commonItem);
+        }
+        return prioritySum;
     }
 
     private char getCommonItem(String firstCompartment, String secondCompartment) {
+        return getCommonItem(firstCompartment, secondCompartment, null);
+    }
+
+    private char getCommonItem(String firstCollection, String secondCollection, String thirdCollection) {
         Character commonItem = null;
-        List<Character> firstCompartmentItems = firstCompartment.chars().sorted().mapToObj(c -> (char) c).toList();
-        List<Character> secondCompartmentItems = secondCompartment.chars().sorted().mapToObj(c -> (char) c).toList();
-        Iterator<Character> firstCompartmentIterator = firstCompartmentItems.iterator();
-        Iterator<Character> secondCompartmentIterator = secondCompartmentItems.iterator();
+        List<Character> firstItems = firstCollection.chars().sorted().mapToObj(c -> (char) c).toList();
+        List<Character> secondItems = secondCollection.chars().sorted().mapToObj(c -> (char) c).toList();
+        List<Character> thirdItems = (thirdCollection == null) ?
+                List.copyOf(secondItems) : thirdCollection.chars().sorted().mapToObj(c -> (char) c).toList();
+        Iterator<Character> firstIterator = firstItems.iterator();
+        Iterator<Character> secondIterator = secondItems.iterator();
+        Iterator<Character> thirdIterator = thirdItems.iterator();
         Character firstItem = null;
         Character secondItem = null;
-        // with the items sorted, we will advance through the items until we reach the end one of the compartments
-        while (firstCompartmentIterator.hasNext() || secondCompartmentIterator.hasNext()) {
-            firstItem = (firstItem == null && firstCompartmentIterator.hasNext()) ?
-                    firstCompartmentIterator.next() : firstItem;
-            secondItem = (secondItem == null && secondCompartmentIterator.hasNext()) ?
-                    secondCompartmentIterator.next() : secondItem;
-            if (commonItem == null && (firstItem == null || secondItem == null)) {
-                throw new IllegalArgumentException("Reached the end of a compartment among "
-                        + firstCompartment + " and " + secondCompartment + " without finding a common item.");
-            }
-            else if (firstItem == secondItem) {
+        Character thirdItem = null;
+        // with the items sorted, we will advance through the items until we reach the end of the compartments
+        while (firstIterator.hasNext() || secondIterator.hasNext() || thirdIterator.hasNext()) {
+            firstItem = (firstItem == null && firstIterator.hasNext()) ?
+                    firstIterator.next() : firstItem;
+            secondItem = (secondItem == null && secondIterator.hasNext()) ?
+                    secondIterator.next() : secondItem;
+            thirdItem = (thirdItem == null && thirdIterator.hasNext()) ?
+                    thirdIterator.next() : thirdItem;
+            if (commonItem == null && (firstItem == null || secondItem == null || thirdItem == null)) {
+                throw new IllegalArgumentException("Reached the end of a compartment among {" + firstCollection + " " +
+                        secondCollection + " " + thirdCollection + " without finding a common item.");
+            } else if (firstItem == secondItem && secondItem == thirdItem) {
                 if (commonItem == null || commonItem == firstItem) {
                     commonItem = firstItem;
                     firstItem = null;
                     secondItem = null;
+                    thirdItem = null;
                 } else {
                     throw new IllegalStateException("Found a common item (" + firstItem + ") when one already exists " +
-                            "(" + commonItem + ") for compartments " + firstCompartment + " and " + secondCompartment);
+                            "(" + commonItem + ") among {" + firstCollection + " " + secondCollection + " " +
+                            thirdCollection + "}");
                 }
-            } else if (firstItem != null && secondItem != null) {
-                if (firstItem < secondItem) {
+            } else if (firstItem != null && secondItem != null && thirdItem != null) {
+                if (firstItem < secondItem || firstItem < thirdItem) {
                     firstItem = null;
-                } else {
+                } else if (secondItem < thirdItem) {
                     secondItem = null;
+                } else {
+                    thirdItem = null;
                 }
-            } else {    // if we've gotten this far with a null item, then we just need to exhaust the remaining string
+            } else {    // if we've gotten this far with a null item, then we just need to exhaust the remaining strings
                 firstItem = null;
                 secondItem = null;
+                thirdItem = null;
             }
         }
         if (commonItem == null) {
-            throw new IllegalArgumentException("No common item found among "
-                    + firstCompartment + " and " + secondCompartment);
-//                    + firstCompartmentItems + " and " + secondCompartmentItems);
+            throw new IllegalArgumentException("No common item found among {"
+                    + firstCollection + " " + secondCollection + " " + thirdCollection + "}");
         }
         return commonItem;
     }