-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
559 additions
and
10 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,11 @@ | ||
package org.advent; | ||
|
||
import org.advent.day18.Day18; | ||
import org.advent.day19.Day19; | ||
|
||
public class Main { | ||
|
||
public static void main(String[] args) { | ||
new Day18().run(); | ||
new Day19().run(); | ||
} | ||
|
||
} |
4 changes: 3 additions & 1 deletion
4
src/main/java/org/advent/utils/Crucible.java → src/main/java/org/advent/day17/Crucible.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.advent.day19; | ||
|
||
import org.advent.utils.ClasspathFileReader; | ||
|
||
public class Day19 implements Runnable { | ||
|
||
@Override | ||
public void run() { | ||
var lines = new ClasspathFileReader().readAllLines("day19.input"); | ||
System.out.println(new Day19Part1().solve(lines)); | ||
System.out.println(new Day19Part2().solve(lines)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package org.advent.day19; | ||
|
||
import io.vavr.Tuple; | ||
import org.apache.commons.lang3.StringUtils; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import static io.vavr.collection.List.ofAll; | ||
import static java.util.Objects.requireNonNull; | ||
import static java.util.function.Function.identity; | ||
import static java.util.stream.Collectors.toMap; | ||
import static org.advent.utils.StringUtils.parseSections; | ||
import static org.advent.utils.StringUtils.readLines; | ||
|
||
public class Day19Part1 { | ||
|
||
public Number solve(List<String> lines) { | ||
var sections = parseSections(lines); | ||
var workflowMap = createWorkflowMap(sections.getFirst()); | ||
var parts = readLines(sections.getLast()).stream() | ||
.map(Part::parse) | ||
.toList(); | ||
|
||
return ofAll(parts.stream() | ||
.map(part -> Tuple.of(part, runPartThroughWorkflows(part, workflowMap))) | ||
.filter(tuple -> tuple._2.contains("A")) | ||
.map(tuple -> tuple._1.calculateChristmasRating())) | ||
.sum(); | ||
} | ||
|
||
public Map<String, Workflow> createWorkflowMap(String lines) { | ||
return readLines(lines).stream() | ||
.map(Workflow::parse) | ||
.collect(toMap(Workflow::name, identity())); | ||
} | ||
|
||
public List<String> runPartThroughWorkflows(Part part, Map<String, Workflow> workflowMap) { | ||
var workflowName = "in"; | ||
var path = new ArrayList<String>(); | ||
path.add(workflowName); | ||
|
||
while (true) { | ||
var workflow = requireNonNull(workflowMap.get(workflowName)); | ||
for (var rule : workflow.rules()) { | ||
if (evaluateCondition(rule.condition(), part)) { | ||
if ("A".equals(rule.destination()) || "R".equals(rule.destination())) { | ||
path.add(rule.destination()); | ||
return path; | ||
|
||
} else { | ||
workflowName = rule.destination(); | ||
path.add(workflowName); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
public boolean evaluateCondition(String condition, Part part) { | ||
if (StringUtils.isBlank(condition)) { | ||
return true; | ||
} | ||
|
||
var isLt = condition.contains("<"); | ||
String[] parts = condition.split(isLt ? "<" : ">"); | ||
String lhs = parts[0]; | ||
int rhs = Integer.parseInt(parts[1]); | ||
|
||
return switch (lhs) { | ||
case "x" -> isLt ? part.x() < rhs : part.x() > rhs; | ||
case "m" -> isLt ? part.m() < rhs : part.m() > rhs; | ||
case "a" -> isLt ? part.a() < rhs : part.a() > rhs; | ||
case "s" -> isLt ? part.s() < rhs : part.s() > rhs; | ||
default -> throw new IllegalArgumentException("Invalid condition format"); | ||
}; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package org.advent.day19; | ||
|
||
import io.vavr.Tuple; | ||
import io.vavr.Tuple2; | ||
import org.advent.utils.MathUtils; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
|
||
import static io.vavr.collection.HashMap.of; | ||
import static org.advent.utils.StringUtils.parseSections; | ||
|
||
public class Day19Part2 extends Day19Part1 { | ||
|
||
public Number solve(List<String> lines) { | ||
var sections = parseSections(lines); | ||
var workflowMap = createWorkflowMap(sections.getFirst()); | ||
return countAcceptedCombinations( | ||
of( | ||
'x', Tuple.of(1, 4000), | ||
'm', Tuple.of(1, 4000), | ||
'a', Tuple.of(1, 4000), | ||
's', Tuple.of(1, 4000) | ||
), | ||
workflowMap, | ||
"in" | ||
); | ||
} | ||
|
||
public long countAcceptedCombinations( | ||
io.vavr.collection.Map<Character, Tuple2<Integer, Integer>> christmasRanges, | ||
Map<String, Workflow> workflowMap, | ||
String startingWorkflowName) { | ||
if ("R".equals(startingWorkflowName)) { | ||
return 0L; | ||
} | ||
|
||
if ("A".equals(startingWorkflowName)) { | ||
return christmasRanges.values() | ||
.map(range -> range._2 - range._1 + 1) | ||
.product() | ||
.longValue(); | ||
} | ||
|
||
var workflow = workflowMap.get(startingWorkflowName); | ||
var count = 0L; | ||
for (var rule : workflow.rules()) { | ||
var range = christmasRanges.get(rule.conditionLHS()).getOrNull(); | ||
|
||
// Last rule, no condition, just go to destination | ||
if (rule.conditionOperator() == null) { | ||
count += countAcceptedCombinations(christmasRanges, workflowMap, rule.destination()); | ||
continue; | ||
} | ||
|
||
char operator = rule.conditionOperator(); | ||
var rhs = Optional.ofNullable(rule.conditionRHS()); | ||
if (operator == '<') { | ||
var matchedRange = MathUtils.intersectRange(range, Tuple.of(range._1, rhs.orElse(0) - 1)); | ||
var unmatchedRange = Tuple.of(matchedRange._2 + 1, range._2); | ||
count += countAcceptedCombinations( | ||
christmasRanges.put(rule.conditionLHS(), matchedRange), | ||
workflowMap, | ||
rule.destination()); | ||
christmasRanges = christmasRanges.put(rule.conditionLHS(), unmatchedRange); | ||
continue; | ||
} | ||
|
||
// operator == '>' | ||
var matchedRange = MathUtils.intersectRange(range, Tuple.of(rhs.orElse(0) + 1, range._2)); | ||
var unmatchedRange = Tuple.of(range._1, matchedRange._1 - 1); | ||
count += countAcceptedCombinations( | ||
christmasRanges.put(rule.conditionLHS(), matchedRange), | ||
workflowMap, | ||
rule.destination()); | ||
christmasRanges = christmasRanges.put(rule.conditionLHS(), unmatchedRange); | ||
} | ||
|
||
return count; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.advent.day19; | ||
|
||
public record Part(int x, int m, int a, int s) { | ||
|
||
public int calculateChristmasRating() { | ||
return x + m + a + s; // 🎄 | ||
} | ||
|
||
public static Part parse(String line) { | ||
var values = line.substring(1, line.length() - 1).split(","); | ||
var x = Integer.parseInt(values[0].split("=")[1]); | ||
var m = Integer.parseInt(values[1].split("=")[1]); | ||
var a = Integer.parseInt(values[2].split("=")[1]); | ||
var s = Integer.parseInt(values[3].split("=")[1]); | ||
return new Part(x, m, a, s); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package org.advent.day19; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
import static java.util.stream.Collectors.toList; | ||
|
||
public record Workflow(String name, List<WorkflowRule> rules) { | ||
|
||
public static Workflow parse(String line) { | ||
var parts = line.split("\\{"); | ||
var name = parts[0]; | ||
var rules = Arrays.stream(parts[1].substring(0, parts[1].length() - 1).split(",")) | ||
.map(WorkflowRule::parse) | ||
.collect(toList()); | ||
return new Workflow(name, rules); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package org.advent.day19; | ||
|
||
public record WorkflowRule(String condition, String destination) { | ||
|
||
public static WorkflowRule parse(String rule) { | ||
var ruleParts = rule.split(":"); | ||
return new WorkflowRule(ruleParts.length > 1 ? ruleParts[0] : null, ruleParts[ruleParts.length - 1]); | ||
} | ||
|
||
public Character conditionLHS() { | ||
return condition == null ? null : condition.charAt(0); | ||
} | ||
|
||
public Character conditionOperator() { | ||
return condition == null ? null : condition.charAt(1); | ||
} | ||
|
||
public Integer conditionRHS() { | ||
return condition == null ? null : Integer.parseInt(condition.substring(2)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 5 additions & 1 deletion
6
...t/java/org/advent/utils/CrucibleTest.java → ...t/java/org/advent/day17/CrucibleTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.