-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathDay7.java
146 lines (123 loc) · 4.04 KB
/
Day7.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package com.sbaars.adventofcode.year17.days;
import com.sbaars.adventofcode.year17.Day2017;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Day7 extends Day2017 {
private static class Program {
String name;
int weight;
List<Program> children = new ArrayList<>();
Program parent;
Program(String name, int weight) {
this.name = name;
this.weight = weight;
}
int getTotalWeight() {
return weight + children.stream().mapToInt(Program::getTotalWeight).sum();
}
}
private Map<String, Program> buildTree(String[] lines) {
Map<String, Program> programs = new HashMap<>();
Pattern pattern = Pattern.compile("(\\w+)\\s+\\((\\d+)\\)(?:\\s+->\\s+(.*))?");
// First pass: create all programs
for (String line : lines) {
Matcher m = pattern.matcher(line);
if (m.find()) {
String name = m.group(1);
int weight = Integer.parseInt(m.group(2));
programs.put(name, new Program(name, weight));
}
}
// Second pass: build relationships
for (String line : lines) {
Matcher m = pattern.matcher(line);
if (m.find()) {
Program program = programs.get(m.group(1));
String children = m.group(3);
if (children != null) {
for (String childName : children.split(",\\s+")) {
Program child = programs.get(childName);
program.children.add(child);
child.parent = program;
}
}
}
}
return programs;
}
private int findCorrectWeight(Program root) {
// Check if any children are unbalanced
for (Program child : root.children) {
int result = findCorrectWeight(child);
if (result != -1) {
return result;
}
}
// Check if this node's children are balanced
if (!root.children.isEmpty()) {
Map<Integer, List<Program>> weightGroups = new HashMap<>();
for (Program child : root.children) {
weightGroups.computeIfAbsent(child.getTotalWeight(), k -> new ArrayList<>()).add(child);
}
if (weightGroups.size() == 2) {
// Find the odd one out
Map.Entry<Integer, List<Program>> wrongEntry = null;
Map.Entry<Integer, List<Program>> correctEntry = null;
for (Map.Entry<Integer, List<Program>> entry : weightGroups.entrySet()) {
if (entry.getValue().size() == 1) {
wrongEntry = entry;
} else {
correctEntry = entry;
}
}
if (wrongEntry != null && correctEntry != null) {
Program wrongProgram = wrongEntry.getValue().get(0);
int difference = wrongEntry.getKey() - correctEntry.getKey();
return wrongProgram.weight - difference;
}
}
}
return -1;
}
public Day7() {
super(7);
}
public static void main(String[] args) {
new Day7().printParts();
}
@Override
public Object part1() {
String[] lines = dayStrings();
Set<String> allPrograms = new HashSet<>();
Set<String> childPrograms = new HashSet<>();
Pattern pattern = Pattern.compile("(\\w+)\\s+\\(\\d+\\)(?:\\s+->\\s+(.*))?");
for (String line : lines) {
Matcher m = pattern.matcher(line);
if (m.find()) {
String program = m.group(1);
allPrograms.add(program);
String children = m.group(2);
if (children != null) {
for (String child : children.split(",\\s+")) {
childPrograms.add(child);
}
}
}
}
// The root program is the only one that is not a child of any other program
allPrograms.removeAll(childPrograms);
return allPrograms.iterator().next();
}
@Override
public Object part2() {
String[] lines = dayStrings();
Map<String, Program> programs = buildTree(lines);
// Find root program
Program root = programs.values().stream()
.filter(p -> p.parent == null)
.findFirst()
.orElseThrow();
return findCorrectWeight(root);
}
}