1
1
package com .github .saser .adventofcode .year2016 .day10 ;
2
2
3
+ import java .io .BufferedReader ;
3
4
import java .io .Reader ;
5
+ import java .util .HashMap ;
6
+ import java .util .HashSet ;
7
+ import java .util .LinkedList ;
8
+ import java .util .List ;
9
+ import java .util .Map ;
10
+ import java .util .Objects ;
11
+ import java .util .regex .Pattern ;
4
12
5
13
import com .github .saser .adventofcode .Result ;
6
14
@@ -14,6 +22,128 @@ public static Result part2(Reader r) {
14
22
}
15
23
16
24
private static Result solve (Reader r , int part ) {
25
+ var network = Network .parse (r );
26
+ var paths = network .flow ();
27
+ if (part == 1 ) {
28
+ var visited61 = new HashSet <>(paths .get (61 ));
29
+ var visited17 = new HashSet <>(paths .get (17 ));
30
+ visited61 .retainAll (visited17 );
31
+ var bot = visited61 .iterator ().next ();
32
+ return Result .ok (Integer .toString (bot ));
33
+ }
17
34
return Result .err ("not implemented yet" );
18
35
}
36
+
37
+ private static class Network {
38
+ public final Map <Integer , Sink > sources ;
39
+ public final Map <Integer , Sink > highSinks ;
40
+ public final Map <Integer , Sink > lowSinks ;
41
+
42
+ public Network (Map <Integer , Sink > sources , Map <Integer , Sink > highSinks , Map <Integer , Sink > lowSinks ) {
43
+ this .sources = sources ;
44
+ this .highSinks = highSinks ;
45
+ this .lowSinks = lowSinks ;
46
+ }
47
+
48
+ public static Network parse (Reader r ) {
49
+ var sources = new HashMap <Integer , Sink >();
50
+ var highSinks = new HashMap <Integer , Sink >();
51
+ var lowSinks = new HashMap <Integer , Sink >();
52
+ var br = new BufferedReader (r );
53
+ var it = br .lines ().iterator ();
54
+ var sourceRE = Pattern .compile ("value (\\ d+) goes to bot (\\ d+)" );
55
+ var highLowRE = Pattern .compile ("bot (\\ d+) gives (low|high) to (output|bot) (\\ d+) and (low|high) to (output|bot) (\\ d+)" );
56
+ while (it .hasNext ()) {
57
+ var line = it .next ();
58
+ var sourceMatcher = sourceRE .matcher (line );
59
+ if (sourceMatcher .matches ()) {
60
+ var value = Integer .parseInt (sourceMatcher .group (1 ));
61
+ var bot = Integer .parseInt (sourceMatcher .group (2 ));
62
+ sources .put (value , new Sink (bot , false ));
63
+ continue ;
64
+ }
65
+ var highLowMatcher = highLowRE .matcher (line );
66
+ if (highLowMatcher .matches ()) {
67
+ var sourceBot = Integer .parseInt (highLowMatcher .group (1 ));
68
+ var isLow1 = highLowMatcher .group (2 ).equals ("low" );
69
+ var isOutput1 = highLowMatcher .group (3 ).equals ("output" );
70
+ var number1 = Integer .parseInt (highLowMatcher .group (4 ));
71
+ (isLow1 ? lowSinks : highSinks ).put (sourceBot , new Sink (number1 , isOutput1 ));
72
+ var isLow2 = highLowMatcher .group (5 ).equals ("low" );
73
+ var isOutput2 = highLowMatcher .group (6 ).equals ("output" );
74
+ var number2 = Integer .parseInt (highLowMatcher .group (7 ));
75
+ (isLow2 ? lowSinks : highSinks ).put (sourceBot , new Sink (number2 , isOutput2 ));
76
+ continue ;
77
+ }
78
+ throw new IllegalArgumentException (String .format ("invalid line: %s" , line ));
79
+ }
80
+ return new Network (sources , highSinks , lowSinks );
81
+ }
82
+
83
+ public Map <Integer , List <Integer >> flow () {
84
+ var q = new LinkedList <Pair <Integer , Sink >>();
85
+ for (var entry : this .sources .entrySet ()) {
86
+ q .add (new Pair <>(entry .getKey (), entry .getValue ()));
87
+ }
88
+ var paths = new HashMap <Integer , List <Integer >>();
89
+ var held = new HashMap <Integer , Integer >();
90
+ while (!q .isEmpty ()) {
91
+ var entry = q .removeFirst ();
92
+ var value = entry .first ;
93
+ var sink = entry .second ;
94
+ if (!paths .containsKey (value )) {
95
+ paths .put (value , new LinkedList <>());
96
+ }
97
+ paths .get (value ).add (sink .target );
98
+ if (sink .isOutput ) {
99
+ continue ;
100
+ }
101
+ var bot = sink .target ;
102
+ if (!held .containsKey (bot )) {
103
+ held .put (bot , value );
104
+ continue ;
105
+ }
106
+ var current = held .get (bot );
107
+ var low = Math .min (current , value );
108
+ var high = Math .max (current , value );
109
+ q .addLast (new Pair <>(low , lowSinks .get (bot )));
110
+ q .addLast (new Pair <>(high , highSinks .get (bot )));
111
+ }
112
+ return paths ;
113
+ }
114
+
115
+ private static class Pair <T1 , T2 > {
116
+ public final T1 first ;
117
+ public final T2 second ;
118
+
119
+ public Pair (T1 first , T2 second ) {
120
+ this .first = first ;
121
+ this .second = second ;
122
+ }
123
+
124
+ @ Override
125
+ public boolean equals (Object o ) {
126
+ if (this == o ) return true ;
127
+ if (o == null || getClass () != o .getClass ()) return false ;
128
+ Pair <?, ?> pair = (Pair <?, ?>) o ;
129
+ return first .equals (pair .first ) &&
130
+ second .equals (pair .second );
131
+ }
132
+
133
+ @ Override
134
+ public int hashCode () {
135
+ return Objects .hash (first , second );
136
+ }
137
+ }
138
+ }
139
+
140
+ private static class Sink {
141
+ public final int target ;
142
+ public final boolean isOutput ;
143
+
144
+ public Sink (int target , boolean isOutput ) {
145
+ this .target = target ;
146
+ this .isOutput = isOutput ;
147
+ }
148
+ }
19
149
}
0 commit comments