Skip to content

Commit

Permalink
aoc 2017 day 7 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
TheCK committed Dec 11, 2024
1 parent 5a4a7d2 commit c349296
Show file tree
Hide file tree
Showing 7 changed files with 1,140 additions and 21 deletions.
4 changes: 2 additions & 2 deletions adventofcode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@
[20162402tests]: src/test/java/org/ck/adventofcode/year2016/Day24Test.java
[20162501tests]: src/test/java/org/ck/adventofcode/year2016/Day25Test.java

# 2017 (15/16)
# 2017 (16/16)

| # | Name | Solution | Test |
|---------:|---------------------------------------------------------------------|:------------------------------------:|:---------------------------------:|
Expand All @@ -423,7 +423,7 @@
| 20170601 | [Day 6: Memory Reallocation][20170601] | ✅[💾][20170601solution] | ✅[💾][20170601tests] |
| 20170602 | [Day 6: Memory Reallocation - Part 2][20170602] | ✅[💾][20170602solution] | ✅[💾][20170602tests] |
| 20170701 | [Day 7: Recursive Circus][20170701] | ✅[💾][20170701solution] | ✅[💾][20170701tests] |
| 20170702 | [Day 7: Recursive Circus - Part 2][20170702] | [💾][20170702solution] | [💾][20170702tests] |
| 20170702 | [Day 7: Recursive Circus - Part 2][20170702] | ✅[💾][20170702solution] | ✅[💾][20170702tests] |
| 20170801 | [Day 8: I Heard You Like Registers][20170801] | ✅[💾][20170801solution] | ✅[💾][20170801tests] |
| 20170802 | [Day 8: I Heard You Like Registers - Part 2][20170802] | ✅[💾][20170802solution] | ✅[💾][20170802tests] |

Expand Down
103 changes: 86 additions & 17 deletions adventofcode/src/main/java/org/ck/adventofcode/year2017/Day07.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package org.ck.adventofcode.year2017;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.*;
import java.util.function.BiFunction;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand All @@ -19,42 +17,113 @@
id = 20170702,
name = "Day 7: Recursive Circus - Part 2",
url = "https://adventofcode.com/2017/day/7#part2",
category = "2017",
solved = false)
category = "2017")
public class Day07 extends AOCSolution {
private static final Pattern LINE_PATTERN =
Pattern.compile("(?<name>\\w+) \\((?<weight>\\d+)\\) ?(-> (?<above>[\\w, ]+))?");

@Override
protected void runPartOne(final Scanner in) {
final List<Program> programs = new ArrayList<>();
run(in, (programs, first) -> first);
}

@Override
protected void runPartTwo(final Scanner in) {
run(in, (programs, first) -> String.valueOf(Day07.findDifference(programs, first).newWeight()));
}

private void run(
final Scanner in, final BiFunction<Map<String, Program>, String, String> getResult) {
final Map<String, Program> programs = new HashMap<>();

while (in.hasNextLine()) {
final Matcher matcher = LINE_PATTERN.matcher(in.nextLine());

if (matcher.find()) {
if (matcher.group("above") == null) {
programs.add(
programs.put(
matcher.group("name"),
new Program(
matcher.group("name"), Integer.parseInt(matcher.group("weight")), new String[0]));
matcher.group("name"), Integer.parseInt(matcher.group("weight")), List.of()));
} else {
programs.add(
programs.put(
matcher.group("name"),
new Program(
matcher.group("name"),
Integer.parseInt(matcher.group("weight")),
matcher.group("above").split(", ")));
Arrays.asList(matcher.group("above").split(", "))));
}
}
}

final List<String> names = programs.stream().map(Program::name).collect(Collectors.toList());
programs.forEach(program -> Arrays.stream(program.above()).forEach(names::remove));
final Set<String> names = new HashSet<>(programs.keySet());
programs.values().forEach(program -> program.above().forEach(names::remove));

print(names.get(0));
print(getResult.apply(programs, names.stream().findFirst().orElseThrow()));
}

@Override
protected void runPartTwo(final Scanner in) {}
/**
* this code assumes that the affected node has more than one neighbour, otherwise the decision
* would have to happen one level up
*/
private static Result findDifference(final Map<String, Program> programs, final String current) {
final Program program = programs.get(current);
final List<String> aboveList = program.above();

if (aboveList.isEmpty()) {
return new WeightResult(program.weight());
}

final Map<String, Result> results =
aboveList.stream()
.collect(Collectors.toMap(above -> above, above -> findDifference(programs, above)));

final Optional<Result> maybeNewWeightResult =
results.values().stream().filter(NewWeightResult.class::isInstance).findFirst();

if (maybeNewWeightResult.isPresent()) {
return maybeNewWeightResult.get();
}

final LongSummaryStatistics stats =
results.values().stream().mapToLong(Result::weight).summaryStatistics();
final long difference = stats.getMax() - stats.getMin();

if (difference == 0) {
return new WeightResult(program.weight() + stats.getMin() * stats.getCount());
}

final String oddProgramName =
results.entrySet().stream()
.collect(Collectors.groupingBy(e -> e.getValue().weight(), Collectors.toList()))
.values()
.stream()
.filter(list -> list.size() == 1)
.map(list -> list.getFirst().getKey())
.findFirst()
.orElseThrow();

final long oddProgramWeight = programs.get(oddProgramName).weight();

return new NewWeightResult(
stats.getMax() == results.get(oddProgramName).weight()
? oddProgramWeight - difference
: oddProgramWeight + difference);
}

private sealed interface Result permits NewWeightResult, WeightResult {
default long newWeight() {
throw new UnsupportedOperationException();
}

default long weight() {
throw new UnsupportedOperationException();
}
}

private record NewWeightResult(long newWeight) implements Result {}

private record WeightResult(long weight) implements Result {}

private record Program(String name, int weight, String[] above) {}
private record Program(String name, int weight, List<String> above) {}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.ck.adventofcode.year2017;

import org.ck.adventofcode.util.BaseAOCTest;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

Expand All @@ -14,7 +13,6 @@ void testOne(String name) throws Exception {

@ParameterizedTest
@ValueSource(strings = {"02", "02a"})
@Disabled
void testTwo(String name) throws Exception {
runTest(new Day07()::partTwo, "day07/%s".formatted(name));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
529
Loading

0 comments on commit c349296

Please sign in to comment.