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

Completed Year 2022 Day 10 part 1

parent 8b1b9ebc
No related branches found
No related tags found
No related merge requests found
......@@ -8,6 +8,7 @@
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
......@@ -41,6 +42,7 @@ upper limit of the size of the set.
- [The solution](src/main/java/edu/unl/cse/bohn/year2022/Day2.java)
The subproblems for both parts are
- Score a single round
- Determine which hand is played by each player; adjust score based on "my" hand
- Determine the outcome of the round; adjust score based on the outcome
......@@ -62,6 +64,7 @@ Where we parameterized the commonality on Day 1, today we'll simply extract the
### Part 1
The subproblems are
- Determine an item's priority
- For each knapsack, determine which items are in each compartment
- Assume an even non-zero number of items
......@@ -73,10 +76,12 @@ The subproblems are
### 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
- ~~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*}
......@@ -97,6 +102,7 @@ Both problems involve finding a singular common character -- one among two strin
### 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
......@@ -127,6 +133,7 @@ We've hit the first puzzle whose input will require a little creativity when par
### Part 1
The subproblems are
- Separate the initial conditions from the subsequent instructions
- Assume there is exactly one blank line between them
- Represent the stacks
......@@ -136,7 +143,8 @@ The subproblems are
- Assume the stack numbers are in-order (*i.e.*, the last index tells us how many there are)
- Can we assume there are only a single-digit number of stacks?
- Assume all crates are of the form "[?]"
- Part of that is an assumption that a crate can be represented with a single character -- and I'm going to further
- Part of that is an assumption that a crate can be represented with a single character -- and I'm going to
further
assume it's not ' '
- Assume an empty space atop a stack is of the form " "
- Assume exactly one space between stacks
......@@ -167,6 +175,7 @@ techniques should be used.
### Part 1
The subproblems are
- Identify the first sequence of four unique characters in a string
- Assume there is such a sequence
- Determine when a sequence of four characters contain duplicates
......@@ -189,6 +198,7 @@ This is straight-forward -- I just need to parameterize the helper method that l
### Part 1
The subproblems are
- Parse the input
- Based on the responses to commands, determine the size of each directory
- The size of a "leaf" directory that has no subdirectories is the sum of the sizes of its files
......@@ -200,11 +210,13 @@ Many of these problems can be mapped to a simpler problem.
I think the reason I'm so tempted to create a model of the directory structure is because the description of the
structure is coming in BFS, but determining the directory sizes would best be done DFS.
It looks like the puzzle input has fewer than 200 directories. YOLO. So, add to the subproblems:
- Build a model of the directory tree
### Part 2
The new subproblems are
- Determine how much space needs to be freed
- Find the smallest directory whose size is greater than that amount
......@@ -224,6 +236,7 @@ it will serve both parts.
### Part 1
The subproblems are
- Determine the tree heights
- Determine whether a tree is visible
- From the right or left
......@@ -233,6 +246,7 @@ The subproblems are
### Part 2
The subproblems are
- Determine the tree heights
- Determine the scenic score for each tree
- For each tree, determine the distance, in each direction, to the next tree that is at least as tall
......@@ -258,6 +272,7 @@ Well... I'm going to take the part 2 code in a (very) slightly different directi
### Part 1
The subproblems are
- Determine whether the head and tail are touching
- Determine what direction the tail should move
- Both of the previous subproblems include the subproblem of finding the distance between the head and tail along each
......@@ -275,5 +290,41 @@ We'll replace the explicit `head` and `tail` with an array of `Position`s.
## Day 10
- [The problem](https://adventofcode.com/2022/day/10)
- [The solution](src/main/java/edu/unl/cse/bohn/year2022/Day10.java),
including [the computer](src/main/java/edu/unl/cse/bohn/year2022/computer)
It looks like it's time to start building this year's "computer."
### Part 1
The subproblems are
- Parse the input
- Process no-ops (advance the cycle counter by one)
- Process addition (update the accumulator and advance the cycle counter by 2)
- Determine the "signal strength" at cycle 40n+20
- I've already determined in the larger sample that there are an odd number of no-ops within the first 20
instructions, which means that the signal strength might be measured in the middle of an instruction (*i.e*, we
cannot simply advance the cycle counter by 2 for addition)
- Yes, I realize the instructions *also* make this pretty clear
Looking at the "computer," it needs to
- Do the parsing and processing, described above
- Advance to a specific clock cycle, which may be in the middle of an instruction
- Presumably, if the "program" has terminated, then there's no expectation of advancing to that clock cycle
- Report the signal strength
An interesting twist: the signal strength we're looking for is the signal strength ***during*** the clock cycle -- not
before, not after.
That means that the clock cycle has advanced, but the accumulator hasn't updated.
### Part 2
...
## Day 11
(coming soon)
package edu.unl.cse.bohn.year2022;
import edu.unl.cse.bohn.Puzzle;
import edu.unl.cse.bohn.year2022.computer.Computer;
import java.util.List;
@SuppressWarnings("unused")
public class Day10 extends Puzzle {
public static final int INITIAL_CYCLE_FOR_MEASUREMENT = 20;
public static final int MEASUREMENT_STEP = 40;
public Day10(boolean isProductionReady) {
super(isProductionReady);
// sampleData = """
// noop
// addx 3
// addx -5""";
sampleData = muchLargerSampleData;
}
private Computer computer = new Computer();
@Override
public long computePart1(List<String> data) {
computer = new Computer();
computer.addInstructions(data);
int sumOfSignalStrengths = 0;
int i = 0;
do {
// System.out.println(computer);
sumOfSignalStrengths += computer.getSignalStrengthDuringPreviousCycle();
}
while (i < 6 && computer.advanceToCycle(INITIAL_CYCLE_FOR_MEASUREMENT + MEASUREMENT_STEP * i++));
return sumOfSignalStrengths;
}
@Override
public long computePart2(List<String> data) {
computer = new Computer();
computer.addInstructions(data);
return 0;
}
String muchLargerSampleData = """
addx 15
addx -11
addx 6
addx -3
addx 5
addx -1
addx -8
addx 13
addx 4
noop
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx -35
addx 1
addx 24
addx -19
addx 1
addx 16
addx -11
noop
noop
addx 21
addx -15
noop
noop
addx -3
addx 9
addx 1
addx -3
addx 8
addx 1
addx 5
noop
noop
noop
noop
noop
addx -36
noop
addx 1
addx 7
noop
noop
noop
addx 2
addx 6
noop
noop
noop
noop
noop
addx 1
noop
noop
addx 7
addx 1
noop
addx -13
addx 13
addx 7
noop
addx 1
addx -33
noop
noop
noop
addx 2
noop
noop
noop
addx 8
noop
addx -1
addx 2
addx 1
noop
addx 17
addx -9
addx 1
addx 1
addx -3
addx 11
noop
noop
addx 1
noop
addx 1
noop
noop
addx -13
addx -19
addx 1
addx 3
addx 26
addx -30
addx 12
addx -1
addx 3
addx 1
noop
noop
noop
addx -9
addx 18
addx 1
addx 2
noop
noop
addx 9
noop
noop
noop
addx -1
addx 2
addx -37
addx 1
addx 3
noop
addx 15
addx -21
addx 22
addx -6
addx 1
noop
addx 2
addx 1
noop
addx -10
noop
noop
addx 20
addx 1
addx 2
addx 2
addx -6
addx -11
noop
noop
noop""";
}
package edu.unl.cse.bohn.year2022.computer;
public class AddX implements Instruction {
private final int operand;
public AddX(int operand) {
this.operand = operand;
}
@Override
public int getDuration() {
return 2;
}
@Override
public void execute(Computer.Context context) {
context.advanceClock(getDuration());
context.setRX(context.getRX() + operand);
}
@Override
public String toString() {
return "addx " + operand;
}
}
package edu.unl.cse.bohn.year2022.computer;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
public class Computer {
private final Context context;
private final Deque<Instruction> instructions;
private int reportedCycleNumber;
private int signalStrength;
public Computer() {
context = new Context();
instructions = new LinkedList<>();
reportedCycleNumber = 0;
signalStrength = 0;
}
public void addInstruction(String instruction) {
String[] instructionFields = instruction.strip().split(" ");
// if there are too many instructions, I might want to use reflection, but for now,
// I think a switch assignment will do nicely
instructions.addLast(switch (instructionFields[0]) {
case "noop" -> new Noop();
case "addx" -> new AddX(Integer.parseInt(instructionFields[1]));
default -> throw new IllegalArgumentException("Unrecognized instruction " + instruction);
});
}
public void addInstructions(List<String> instructions) {
instructions.forEach(this::addInstruction);
}
@SuppressWarnings("unused")
public void flushInstructions() {
instructions.clear();
}
private boolean instructionsAreAvailable() {
return instructions.isEmpty();
}
private int getCycle() {
return reportedCycleNumber;
}
private void setSignalStrengthForNextCycle() {
signalStrength = (getCycle() + 1) * context.rX;
}
public int getSignalStrengthDuringPreviousCycle() {
return signalStrength;
}
/**
* Advances the computer to the specified clock cycle, executing instructions along the way.
* If all instructions are exhausted before reaching the specified clock cycle, then the computer will stop
* early (because there are no instructions to execute).
*
* @param cycleNumber The clock cycle to advance to
* @return <code>true</code> if the computer reached the specified clock cycle,
* <code>false</code> if the computer stopped early
* @throws IllegalArgumentException if <code>clockNumber</code> is earlier than the current clock cycle
*/
public boolean advanceToCycle(int cycleNumber) {
if (cycleNumber < reportedCycleNumber) {
throw new IllegalArgumentException("Cannot turn back time. The current cycle number is "
+ reportedCycleNumber + " and the requested cycle is " + cycleNumber + ".");
}
while (!instructionsAreAvailable() && reportedCycleNumber < cycleNumber) {
if (context.clockCycle + instructions.getFirst().getDuration() > cycleNumber) {
// if executing the next instruction would advance the clock too far
reportedCycleNumber = cycleNumber - 1;
setSignalStrengthForNextCycle();
reportedCycleNumber++;
} else {
Instruction nextInstruction = instructions.removeFirst();
reportedCycleNumber = context.clockCycle + nextInstruction.getDuration() - 1;
setSignalStrengthForNextCycle();
nextInstruction.execute(context);
reportedCycleNumber++;
}
}
return reportedCycleNumber == cycleNumber;
}
public String toString() {
return "reported cycle: " + getCycle() + " (actual " + context.clockCycle + ")" + "\tRX: " + context.rX + "\t"
+ (instructionsAreAvailable() ? "--idle--" : (context.clockCycle == getCycle() ? " next" : "current")
+ " instruction: `" + instructions.getFirst() + "`")
+ "\tsignal strength during previous cycle: " + getSignalStrengthDuringPreviousCycle();
}
/**
* A convenient way to pass values by reference to the instructions
*/
static class Context {
private int clockCycle;
private int rX; // the accumulator, register rX (a/o Day 10, the only register)
private Context() {
clockCycle = 0;
rX = 1;
}
void advanceClock(int additionalCycles) {
if (additionalCycles < 0) {
throw new IllegalArgumentException("Cannot turn back time. `additionalCycles` (" + additionalCycles
+ ") must be non-negative.");
}
clockCycle += additionalCycles;
}
int getRX() {
return rX;
}
void setRX(int newValue) {
rX = newValue;
}
}
}
package edu.unl.cse.bohn.year2022.computer;
public interface Instruction {
int getDuration();
void execute(Computer.Context context);
}
package edu.unl.cse.bohn.year2022.computer;
public class Noop implements Instruction {
@Override
public int getDuration() {
return 1;
}
@Override
public void execute(Computer.Context context) {
context.advanceClock(getDuration());
}
@Override
public String toString() {
return "noop";
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment