Skip to content
Snippets Groups Projects
Commit ea526372 authored by Christopher Bohn's avatar Christopher Bohn :thinking:
Browse files

Completed Year 2022 Day 11 part 1. Still working on part 2.

parent 88dc41c1
No related branches found
No related tags found
No related merge requests found
......@@ -333,5 +333,72 @@ I'm revisiting the signal strength code.
## Day 11
- [The problem](https://adventofcode.com/2022/day/11)
- [The solution](src/main/java/edu/unl/cse/bohn/year2022/Day11.java)
Oof. This is a long description. Probably because the input is so verbose, and then you have the exmaple.
### Part 1
The subproblems are
- Parse the input to obtain, for each monkey, its
- starting items -- not only the value (worry level), but also the order
- relationship between the new and old worry levels
- after examining the input, all operations appear to be addition or multiplication, and the first operand is
always the old value
- test operation and the true/false target monkeys
- after examining the input, all tests are whether the worry level is divisible by some integer
-
- Determine which monkey will throw an item next
- Reduce an item's worry level immediately before it is thrown
- Track how many (probably non-unique) items a monkey inspects across the many rounds
- Determine the two most active monkeys after 20 rounds
### Part 2
The part 2 description seems to be forecasting that the `Monkey` class will be used and modified again in the coming
day(s).
If that happens, then I'll move `Monkey` to be an outer class instead of an inner class.
For now, I just need to modify it so that the boredom modification is optional.
### Refactoring
Since parts 1 & 2 differ only in whether to use the boredom modification and the number of rounds,
I can create a parameterized method.
### Possible misinterpretation
It looks like part 2 isn't saying to abandon the divisor *now* to replace the modifier later;
I guess we're supposed to figure out the new modifier for of part 2.
That is more interesting, to say the least.
Both the description and my code (without a boredom modifier) agree that after 1 round:
```
Monkey 0 inspected items 2 times.
Monkey 1 inspected items 4 times.
Monkey 2 inspected items 3 times.
Monkey 3 inspected items 6 times.
```
but after 20, the description says
```
Monkey 0 inspected items 99 times.
Monkey 1 inspected items 97 times.
Monkey 2 inspected items 8 times.
Monkey 3 inspected items 103 times.
```
but my code (without a boredom modifier) says
```
Monkey 0 inspected items 96 times.
Monkey 1 inspected items 100 times.
Monkey 2 inspected items 7 times.
Monkey 3 inspected items 103 times.
```
I wonder if this suggests the final pre-throw modifier is history based; that is, no modifier on the first inspection,
but then the monkey gets a little bored at something it's seen before.
## Day 12
(coming soon)
package edu.unl.cse.bohn.year2022;
import edu.unl.cse.bohn.Puzzle;
import java.util.*;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
@SuppressWarnings("unused")
public class Day11 extends Puzzle {
public Day11(boolean isProductionReady) {
super(isProductionReady);
sampleData = """
Monkey 0:
Starting items: 79, 98
Operation: new = old * 19
Test: divisible by 23
If true: throw to monkey 2
If false: throw to monkey 3
Monkey 1:
Starting items: 54, 65, 75, 74
Operation: new = old + 6
Test: divisible by 19
If true: throw to monkey 2
If false: throw to monkey 0
Monkey 2:
Starting items: 79, 60, 97
Operation: new = old * old
Test: divisible by 13
If true: throw to monkey 1
If false: throw to monkey 3
Monkey 3:
Starting items: 74
Operation: new = old + 3
Test: divisible by 17
If true: throw to monkey 0
If false: throw to monkey 1""";
}
@Override
public long computePart1(List<String> data) {
//noinspection MagicNumber
return measureMonkeyBusiness(data, 20, true);
}
@Override
public long computePart2(List<String> data) {
measureMonkeyBusiness(data, 1, false);
System.out.println();
//noinspection MagicNumber
return measureMonkeyBusiness(data, 20, false);
}
private static long measureMonkeyBusiness(List<String> data, int numberOfRounds, boolean useBoredomModifier) {
List<Monkey> monkeys = new LinkedList<>();
Monkey.clearMonkeys();
Monkey.setTerse();
if (useBoredomModifier) {
Monkey.setBoredomModification();
} else {
Monkey.clearBoredomModification();
}
int monkeyNumber = 0;
while (monkeyNumber * 7 < data.size()) {
monkeys.add(Monkey.createMonkey(data.subList(monkeyNumber * 7, monkeyNumber * 7 + 6)));
monkeyNumber++;
}
for (int i = 0; i < numberOfRounds; i++) {
for (Monkey monkey : monkeys) {
monkey.throwItems();
}
}
// Monkey.printMonkeys();
Monkey.setVerbose();
LinkedList<Integer> inspectionCounts = new LinkedList<>();
for (Monkey monkey: monkeys) {
inspectionCounts.add(monkey.getNumberOfInspections());
}
inspectionCounts.sort(Integer::compareTo);
return (long) inspectionCounts.removeLast() * (long) inspectionCounts.removeLast();
}
private static class Monkey {
public static final int BOREDOM_DIVISOR = 3;
private static boolean useBoredomModifier = true;
private static boolean verbose = false;
private static final List<Monkey> monkeys = new LinkedList<>();
private final int monkeyNumber;
private final List<Integer> items;
private final UnaryOperator<Integer> worryLevelModifier;
private final int testDivisor;
private final Map<Boolean, Integer> targetMonkeys;
private int inspectionCount;
public static void setVerbose() {
verbose = true;
}
public static void setTerse() {
verbose = false;
}
public static void setBoredomModification() {
useBoredomModifier = true;
}
public static void clearBoredomModification() {
useBoredomModifier = false;
}
public static void printMonkeys() {
for (Monkey monkey : monkeys) {
System.out.println("Monkey " + monkey.getMonkeyNumber() + ": " + monkey.getItems());
}
}
public static Monkey createMonkey(List<String> description) {
// >Monkey 0:
int intendedMonkeyNumber = Integer.parseInt(description.get(0).strip().split(" ")[1].split(":")[0]);
// > Starting items: 79, 98
String[] itemStrings = description.get(1).split(":")[1].strip().split(", ");
List<Integer> items = Arrays.stream(itemStrings)
.map(Integer::parseInt)
.collect(Collectors.toCollection(LinkedList::new));
// > Operation: new = old * 19
String operator = description.get(2).strip().split(" ")[4];
String operand = description.get(2).strip().split(" ")[5];
UnaryOperator<Integer> worryLevelModifier = switch (operator) {
case "+" -> operand.equals("old") ? (n -> n + n) : (n -> n + Integer.parseInt(operand));
case "*" -> operand.equals("old") ? (n -> n * n) : (n -> n * Integer.parseInt(operand));
default -> throw new UnsupportedOperationException("Unhandled operator: " + operator);
};
// > Test: divisible by 23
int testDivisor = Integer.parseInt(description.get(3).strip().split(" ")[3]);
// > If true: throw to monkey 2
Map<Boolean, Integer> targetMonkeys = new HashMap<>();
targetMonkeys.put(true, Integer.parseInt(description.get(4).strip().split(" ")[5]));
// > If false: throw to monkey 3
targetMonkeys.put(false, Integer.parseInt(description.get(5).strip().split(" ")[5]));
Monkey monkey = new Monkey(items, worryLevelModifier, testDivisor, targetMonkeys);
if (monkey.getMonkeyNumber() != intendedMonkeyNumber) {
System.err.println("[WARNING] expected to create monkey " + intendedMonkeyNumber
+ " but created monkey " + monkey.getMonkeyNumber());
}
if (monkey.getMonkeyNumber() != monkeys.size()) {
System.err.println("[WARNING] monkey " + monkey.getMonkeyNumber() + " will be placed in position "
+ monkeys.size() + " in the list.");
}
if (verbose) {
System.out.println(monkey);
}
monkeys.add(monkey);
return monkey;
}
public static void clearMonkeys() {
monkeys.clear();
}
private Monkey(List<Integer> items, UnaryOperator<Integer> worryLevelModifier,
int testDivisor, Map<Boolean, Integer> targetMonkeys) {
this.monkeyNumber = monkeys.size();
this.items = items;
this.worryLevelModifier = worryLevelModifier;
this.testDivisor = testDivisor;
this.targetMonkeys = targetMonkeys;
this.inspectionCount = 0;
}
private int getMonkeyNumber() {
return monkeyNumber;
}
private List<Integer> getItems() {
return Collections.unmodifiableList(items);
}
public int getNumberOfInspections() {
if (verbose) {
System.out.println("Monkey " + monkeyNumber + " inspected items " + inspectionCount + " times.");
}
return inspectionCount;
}
public void throwItems() {
if (verbose) {
System.out.println("Monkey: " + monkeyNumber);
}
items.forEach(this::throwItem);
items.clear(); // probably should remove each item in `throwItem()` but that could screw with the iterator
}
private void throwItem(Integer item) {
inspectionCount++;
int worryLevel = item;
if (verbose) {
System.out.println(" Monkey inspects an item with a worry level of " + worryLevel + ".");
}
worryLevel = worryLevelModifier.apply(worryLevel);
if (verbose) {
System.out.println(" Worry level is modified by (" + worryLevelModifier
+ ") to " + worryLevel + ".");
}
worryLevel = useBoredomModifier ? worryLevel / BOREDOM_DIVISOR : worryLevel;
boolean worryLevelIsDivisibleByTestDivisor = worryLevel % testDivisor == 0;
if (verbose) {
if (useBoredomModifier) {
System.out.println(" Monkey gets bored with item. Worry level is divided by "
+ BOREDOM_DIVISOR + " to " + worryLevel + ".");
} else {
System.out.println(" Monkey doesn't get bored with item. Worry level remains "
+ worryLevel + ".");
}
System.out.println(" Current worry level is "
+ (worryLevelIsDivisibleByTestDivisor ? "" : "not ")
+ "divisible by " + testDivisor + ".");
System.out.println(" Item with worry level " + worryLevel
+ " is thrown to monkey " + targetMonkeys.get(worryLevelIsDivisibleByTestDivisor) + ".");
}
monkeys.get(targetMonkeys.get(worryLevelIsDivisibleByTestDivisor)).receiveItem(worryLevel);
}
private void receiveItem(Integer item) {
items.add(item);
}
@Override
public String toString() {
return "Monkey " + monkeyNumber
+ System.lineSeparator() + " Items: " + items
+ System.lineSeparator() + " Operation: " + worryLevelModifier
+ System.lineSeparator() + " Test: divisible by " + testDivisor
+ System.lineSeparator() + " If true: throw to monkey " + targetMonkeys.get(true)
+ System.lineSeparator() + " If false: throw to monkey " + targetMonkeys.get(false);
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment