Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 721dc53

Browse filesBrowse files
committed
Day 8
1 parent 6ec140f commit 721dc53
Copy full SHA for 721dc53

File tree

Expand file treeCollapse file tree

2 files changed

+235
-0
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+235
-0
lines changed

‎src/test/java/com/macasaet/Day08.java

Copy file name to clipboard
+225Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
package com.macasaet;
2+
3+
import java.util.*;
4+
import java.util.stream.Collectors;
5+
import java.util.stream.Stream;
6+
import java.util.stream.StreamSupport;
7+
8+
import org.junit.jupiter.api.Test;
9+
10+
/**
11+
* --- Day 8: Seven Segment Search ---
12+
*/
13+
public class Day08 {
14+
15+
protected Stream<String> getInput() {
16+
return StreamSupport
17+
.stream(new LineSpliterator("day-08.txt"),
18+
false);
19+
}
20+
21+
public record Digit(List<Character> segments) {
22+
public Digit decode(final Map<Character, Character> map) {
23+
return new Digit(segments().stream()
24+
.map(map::get)
25+
.collect(Collectors.toUnmodifiableList()));
26+
}
27+
28+
public int asInt() {
29+
if (segments().size() == 6 && hasSegments('a', 'b', 'c', 'e', 'f', 'g')) { // FIXME use on/off mechanism
30+
return 0;
31+
} else if (segments().size() == 2 && hasSegments('c', 'f')) {
32+
return 1;
33+
} else if (segments().size() == 5 && hasSegments('a', 'c', 'd', 'e', 'g')) {
34+
return 2;
35+
} else if (segments().size() == 5 && hasSegments('a', 'c', 'd', 'f', 'g')) {
36+
return 3;
37+
} else if (segments().size() == 4 && hasSegments('b', 'c', 'd', 'f')) {
38+
return 4;
39+
} else if (segments().size() == 5 && hasSegments('a', 'b', 'd', 'f', 'g')) {
40+
return 5;
41+
} else if (segments().size() == 6 && hasSegments('a', 'b', 'd', 'e', 'f', 'g')) {
42+
return 6;
43+
} else if (segments().size() == 3 && hasSegments('a', 'c', 'f')) {
44+
return 7;
45+
} else if (segments().size() == 7 && hasSegments('a', 'b', 'c', 'd', 'e', 'f', 'g')) {
46+
return 8;
47+
} else if (segments().size() == 6 && hasSegments('a', 'b', 'c', 'd', 'f', 'g')) {
48+
return 9;
49+
}
50+
throw new IllegalStateException("Invalid Digit: " + this);
51+
}
52+
53+
public boolean hasSegments(final char... segments) {
54+
for (final var segment : segments) {
55+
if (!hasSegment(segment)) {
56+
return false;
57+
}
58+
}
59+
return true;
60+
}
61+
62+
public boolean hasSegment(final char segment) {
63+
return segments().contains(segment);
64+
}
65+
66+
public static Digit parse(final String string) {
67+
final var array = string.toCharArray();
68+
final var list = new ArrayList<Character>(array.length);
69+
for (final var c : array) {
70+
list.add(c);
71+
}
72+
return new Digit(Collections.unmodifiableList(list));
73+
}
74+
}
75+
76+
public static record Entry(List<Digit> uniqueSignalPatterns, List<Digit> outputValue) {
77+
78+
public int decodeOutput() {
79+
final var map = buildDecodingMap();
80+
final StringBuilder builder = new StringBuilder();
81+
for (final var outputDigit : outputValue()) {
82+
final var decodedDigit = outputDigit.decode(map);
83+
final int digit = decodedDigit.asInt();
84+
builder.append(digit);
85+
}
86+
final String stringInt = builder.toString();
87+
return Integer.parseInt(stringInt);
88+
}
89+
90+
protected SortedSet<Character> getDigitSegmentsWithCount(final int n) {
91+
return uniqueSignalPatterns().stream()
92+
.filter(digit -> digit.segments().size() == n)
93+
.findFirst()
94+
.get()
95+
.segments()
96+
.stream()
97+
.collect(TreeSet::new, SortedSet::add, SortedSet::addAll);
98+
}
99+
100+
protected Set<Digit> getDigitsWithCount(final int n) { // TODO return stream
101+
return uniqueSignalPatterns()
102+
.stream()
103+
.filter(digit -> digit.segments().size() == n).collect(Collectors.toUnmodifiableSet());
104+
}
105+
106+
public Map<Character, Character> buildDecodingMap() {
107+
final var encodingMap = buildEncodingMap();
108+
final var result = new HashMap<Character, Character>();
109+
for(final var entry : encodingMap.entrySet()) {
110+
result.put(entry.getValue(), entry.getKey());
111+
}
112+
return Collections.unmodifiableMap(result);
113+
}
114+
115+
public Map<Character, Character> buildEncodingMap() {
116+
final var map = new HashMap<Character, Character>();
117+
final var oneSegments = getDigitSegmentsWithCount(2);
118+
final var sevenSegments = getDigitSegmentsWithCount(3);
119+
final var fourSegments = getDigitSegmentsWithCount(4);
120+
final var eightSegments = getDigitSegmentsWithCount(7);
121+
final var aMapping = sevenSegments.stream().filter(c -> !oneSegments.contains(c)).findFirst().get();
122+
map.put('a', aMapping);
123+
124+
final var zeroSixNine = getDigitsWithCount(6);
125+
var zsnSegments = zeroSixNine.stream().flatMap(digit -> digit.segments().stream()).collect(Collectors.toList());
126+
zsnSegments.removeIf(sevenSegments::contains);
127+
zsnSegments.removeIf(fourSegments::contains);
128+
final var sssMap = new HashMap<Character, Integer>();
129+
for (final var c : zsnSegments) {
130+
sssMap.compute(c, (_key, old) -> old == null ? 1 : old + 1);
131+
}
132+
if(sssMap.size() != 2) {
133+
throw new IllegalStateException("More segments for 0, 6, 9 encountered: " + sssMap);
134+
}
135+
for (final var entry : sssMap.entrySet()) {
136+
if (entry.getValue() == 3) {
137+
map.put('g', entry.getKey());
138+
} else if (entry.getValue() == 2) {
139+
map.put('e', entry.getKey());
140+
} else {
141+
throw new IllegalStateException();
142+
}
143+
}
144+
145+
final var twoFiveThree = getDigitsWithCount(5);
146+
var tftSegments = twoFiveThree.stream().flatMap(digit -> digit.segments.stream()).collect(Collectors.toList());
147+
tftSegments.removeIf(sevenSegments::contains);
148+
tftSegments.removeIf(candidate -> candidate.equals(map.get('e')));
149+
tftSegments.removeIf(candidate -> candidate.equals(map.get('g')));
150+
final var tftCounts = new HashMap<Character, Integer>();
151+
for(final var c : tftSegments) {
152+
tftCounts.compute(c, (_key, old) -> old == null ? 1 : old + 1);
153+
}
154+
for(final var entry : tftCounts.entrySet()) {
155+
if(entry.getValue() == 3) {
156+
map.put('d', entry.getKey());
157+
} else if(entry.getValue() == 1) {
158+
map.put('b', entry.getKey());
159+
} else {
160+
throw new IllegalStateException();
161+
}
162+
}
163+
164+
zsnSegments = zeroSixNine.stream().flatMap(digit -> digit.segments().stream()).collect(Collectors.toList());
165+
zsnSegments.removeIf(candidate -> candidate.equals(map.get('a')));
166+
zsnSegments.removeIf(candidate -> candidate.equals(map.get('b')));
167+
zsnSegments.removeIf(candidate -> candidate.equals(map.get('d')));
168+
zsnSegments.removeIf(candidate -> candidate.equals(map.get('e')));
169+
zsnSegments.removeIf(candidate -> candidate.equals(map.get('g')));
170+
final var zsnCounts = new HashMap<Character, Integer>();
171+
for(final var c : zsnSegments) {
172+
zsnCounts.compute(c, (_key, old) -> old == null ? 1 : old + 1);
173+
}
174+
for(final var entry : zsnCounts.entrySet()) {
175+
if(entry.getValue() == 2) {
176+
map.put('c', entry.getKey());
177+
} else if( entry.getValue() == 3) {
178+
map.put('f', entry.getKey());
179+
} else {
180+
throw new IllegalStateException();
181+
}
182+
}
183+
184+
return map;
185+
}
186+
187+
public static Entry parse(final String string) {
188+
final var components = string.split(" \\| ");
189+
final var uniqueSignalPatterns = components[0].split(" ");
190+
final var outputValue = components[1].split(" ");
191+
192+
return new Entry(Arrays.stream(uniqueSignalPatterns)
193+
.map(Digit::parse)
194+
.collect(Collectors.toUnmodifiableList()),
195+
Arrays.stream(outputValue)
196+
.map(Digit::parse)
197+
.collect(Collectors.toUnmodifiableList()));
198+
}
199+
200+
}
201+
202+
@Test
203+
public final void part1() {
204+
final var result = getInput()
205+
.map(Entry::parse)
206+
.flatMap(entry -> entry.outputValue().stream())
207+
.filter(digit -> {
208+
final var segments = digit.segments();
209+
final var numSegments = segments.size();
210+
return numSegments == 2 || numSegments == 4 || numSegments == 3 || numSegments == 7;
211+
})
212+
.count();
213+
System.out.println("Part 1: " + result);
214+
}
215+
216+
@Test
217+
public final void part2() {
218+
final var result = getInput()
219+
.map(Entry::parse)
220+
.mapToInt(Entry::decodeOutput).sum();
221+
222+
System.out.println("Part 2: " + result);
223+
}
224+
225+
}

‎src/test/resources/sample/day-08.txt

Copy file name to clipboard
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
2+
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
3+
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
4+
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
5+
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
6+
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
7+
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
8+
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
9+
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
10+
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.