Skip to content

Commit ec8786c

Browse files
committed
Advent of Code 2021 - Day 8
1 parent daf6939 commit ec8786c

File tree

6 files changed

+517
-4
lines changed

6 files changed

+517
-4
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ Last year I ran a [cruise log for my 25 days competing in the Advent of Code](ht
2424
- [The Advent of Code 2021 Day 4 log, playing myself](https://www.codingnagger.com/2021/12/04/the-advent-of-code-2021-day-4-log-playing-myself/)
2525
- [The Advent of Code 2021 Day 5 log, pointless points](https://www.codingnagger.com/2021/12/05/the-advent-of-code-2021-day-5-log-pointless-points/)
2626
- [The Advent of Code 2021 Day 6 log, plenty of fish](https://www.codingnagger.com/2021/12/06/the-advent-of-code-2021-day-6-log-plenty-of-fish/)
27-
- [The Advent of Code 2021 Day 7 log, return of the crab](https://www.codingnagger.com/2021/12/07/the-advent-of-code-2021-day-7-log-return-of-the-crab/)
27+
- [The Advent of Code 2021 Day 7 log, return of the crab](https://www.codingnagger.com/2021/12/07/the-advent-of-code-2021-day-7-log-return-of-the-crab/)
28+
- [The Advent of Code 2021 Day 8, Bruteforce for the win](https://www.codingnagger.com/2021/12/08/the-advent-of-code-2021-day-8-bruteforce-for-the-win/)

src/main/java/com/codingnagger/App.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.codingnagger;
22

3-
import com.codingnagger.days.*;
3+
import com.codingnagger.days.Day;
4+
import com.codingnagger.days.Day8;
45
import com.codingnagger.utils.InputLoader;
56

67
import java.io.IOException;
@@ -13,9 +14,9 @@ public class App {
1314
public static void main(String[] args) throws IOException {
1415
System.out.println("Advent of Code 2021");
1516

16-
List<String> input = InputLoader.Load("day7.txt");
17+
List<String> input = InputLoader.Load("day8.txt");
1718

18-
Day day = new Day7();
19+
Day day = new Day8();
1920

2021
System.out.println("Part 1:");
2122
System.out.println(day.partOne(input));
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package com.codingnagger.days;
2+
3+
import java.util.Arrays;
4+
import java.util.Collection;
5+
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
import java.util.stream.Collectors;
9+
10+
public class Day8 implements Day {
11+
public static Map<Integer, Character> simpleDigitCandidatesBySize = createSimpleDigitDefinitions();
12+
13+
public static Map<Integer, Character> createSimpleDigitDefinitions() {
14+
HashMap<Integer, Character> digitDefinition = new HashMap<>();
15+
digitDefinition.put(2, '1');
16+
digitDefinition.put(4, '4');
17+
digitDefinition.put(3, '7');
18+
digitDefinition.put(7, '8');
19+
return digitDefinition;
20+
}
21+
22+
public static List<SevenSegmentDisplay> parse(List<String> input) {
23+
return input.stream().map(Day8::parseEntry).collect(Collectors.toList());
24+
}
25+
26+
public static SevenSegmentDisplay parseEntry(String entry) {
27+
String[] entryParts = entry.split(" \\| ");
28+
return new SevenSegmentDisplay(Arrays.asList(entryParts[0].split(" ")), Arrays.asList(entryParts[1].split(" ")));
29+
}
30+
31+
@Override
32+
public String partOne(List<String> input) {
33+
List<SevenSegmentDisplay> displays = parse(input);
34+
35+
return "" + displays.stream()
36+
.map(d -> d.digits)
37+
.flatMap(Collection::stream)
38+
.filter(d -> simpleDigitCandidatesBySize.containsKey(d.length()))
39+
.count();
40+
}
41+
42+
@Override
43+
public String partTwo(List<String> input) {
44+
return "" + input.stream().map(Day8::parseEntry).mapToInt(e -> e.output()).sum();
45+
}
46+
47+
static class SevenSegmentDisplay {
48+
List<String> signalPatterns;
49+
List<String> digits;
50+
Map<String, Character> foundDigits;
51+
Map<Character, String> digitPatterns;
52+
Map<Character, Character> segmentMap;
53+
54+
public SevenSegmentDisplay(List<String> signalPatterns, List<String> digits) {
55+
this.signalPatterns = signalPatterns;
56+
this.digits = digits;
57+
}
58+
59+
public String determineOutput() {
60+
return digits.stream().map(this::getMatchingDigit).collect(Collectors.joining(""));
61+
}
62+
63+
public int output() {
64+
findDigits();
65+
return Integer.parseInt(determineOutput());
66+
}
67+
68+
private String getMatchingDigit(String test) {
69+
return foundDigits.entrySet().stream()
70+
.filter(d -> {
71+
char[] a = d.getKey().toCharArray();
72+
char[] b = test.toCharArray();
73+
74+
Arrays.sort(a);
75+
Arrays.sort(b);
76+
77+
return Arrays.equals(a, b);
78+
})
79+
.map(d -> d.getValue() + "")
80+
.findFirst()
81+
.get();
82+
}
83+
84+
public char getDigit(String pattern) {
85+
return foundDigits.get(pattern);
86+
}
87+
88+
public void findDigits() {
89+
foundDigits = new HashMap<>();
90+
digitPatterns = new HashMap<>();
91+
92+
for (String pattern : signalPatterns) {
93+
if (simpleDigitCandidatesBySize.containsKey(pattern.length())) {
94+
foundDigits.put(pattern, simpleDigitCandidatesBySize.get(pattern.length()));
95+
digitPatterns.put(simpleDigitCandidatesBySize.get(pattern.length()), pattern);
96+
}
97+
}
98+
99+
segmentMap = findSegments();
100+
101+
List<String> patternsToFind = signalPatterns.stream().filter(p -> !foundDigits.containsKey(p)).collect(Collectors.toList());
102+
103+
foundDigits.put(patternsToFind.stream().filter(this::isZero).findFirst().get(), '0');
104+
foundDigits.put(patternsToFind.stream().filter(this::isTwo).findFirst().get(), '2');
105+
foundDigits.put(patternsToFind.stream().filter(this::isThree).findFirst().get(), '3');
106+
foundDigits.put(patternsToFind.stream().filter(this::isFive).findFirst().get(), '5');
107+
foundDigits.put(patternsToFind.stream().filter(this::isSix).findFirst().get(), '6');
108+
foundDigits.put(patternsToFind.stream().filter(this::isNine).findFirst().get(), '9');
109+
}
110+
111+
private boolean isNine(String s) {
112+
return s.length() == 6 && matches("a,b,c,d,f,g", s);
113+
}
114+
115+
private boolean isSix(String s) {
116+
return s.length() == 6 && matches("a,b,d,e,f,g", s);
117+
}
118+
119+
private boolean isFive(String s) {
120+
return s.length() == 5 && matches("a,b,d,f,g", s);
121+
}
122+
123+
private boolean isThree(String s) {
124+
return s.length() == 5 && matches("a,c,d,f,g", s);
125+
}
126+
127+
private boolean isTwo(String s) {
128+
return s.length() == 5 && matches("a,c,d,e,g", s);
129+
}
130+
131+
private boolean matches(String csvValue, String test) {
132+
return Arrays.stream(csvValue.split(",")).map(c -> segmentMap.get(c.charAt(0))).allMatch(c -> containsChar(test, c));
133+
}
134+
135+
private boolean isZero(String s) {
136+
return s.length() == 6 && matches("a,b,c,e,f,g", s);
137+
}
138+
139+
public Map<Character, Character> findSegments() {
140+
HashMap<Character, Character> segments = new HashMap<>();
141+
142+
char[] partsOfOne = digitPatterns.get('1').toCharArray();
143+
144+
if (isC(partsOfOne[0])) {
145+
segments.put('c', partsOfOne[0]);
146+
segments.put('f', partsOfOne[1]);
147+
} else {
148+
segments.put('c', partsOfOne[1]);
149+
segments.put('f', partsOfOne[0]);
150+
}
151+
152+
char a = digitPatterns.get('7').replace("" + partsOfOne[0], "").replace("" + partsOfOne[1], "").charAt(0);
153+
154+
segments.put('a', a);
155+
156+
char[] partsOfEight = digitPatterns.get('8').toCharArray();
157+
158+
for (char c : partsOfEight) {
159+
if (isD(c)) {
160+
segments.put('d', c);
161+
} else if (isE(c)) {
162+
segments.put('e', c);
163+
} else if (isG(c)) {
164+
segments.put('g', c);
165+
}
166+
}
167+
168+
for (char c : partsOfEight) {
169+
if (segments.containsValue(c)) {
170+
continue;
171+
}
172+
173+
segments.put('b', c);
174+
}
175+
176+
return segments;
177+
}
178+
179+
private boolean isG(char c) {
180+
return containsChar(digitPatterns.get('8'), c) &&
181+
!containsChar(digitPatterns.get('1'), c) &&
182+
!containsChar(digitPatterns.get('4'), c) &&
183+
!containsChar(digitPatterns.get('7'), c) &&
184+
countAppearancesPatternsWithLength(c, 6) == 3 &&
185+
countAppearancesPatternsWithLength(c, 5) == 3;
186+
}
187+
188+
private boolean isE(char c) {
189+
return containsChar(digitPatterns.get('8'), c) &&
190+
countAppearancesPatternsWithLength(c, 6) == 2 &&
191+
countAppearancesPatternsWithLength(c, 5) == 1;
192+
}
193+
194+
private boolean isD(char c) {
195+
return containsChar(digitPatterns.get('8'), c) &&
196+
countAppearancesPatternsWithLength(c, 6) == 2 &&
197+
countAppearancesPatternsWithLength(c, 5) == 3;
198+
}
199+
200+
private boolean isC(char c) {
201+
return containsChar(digitPatterns.get('1'), c) &&
202+
countAppearancesPatternsWithLength(c, 6) == 2 &&
203+
countAppearancesPatternsWithLength(c, 5) == 2;
204+
}
205+
206+
private boolean containsChar(String value, char test) {
207+
return value.contains(test + "");
208+
}
209+
210+
private long countAppearancesPatternsWithLength(char c, int length) {
211+
return signalPatterns.stream()
212+
.filter(p -> p.length() == length)
213+
.filter(p -> containsChar(p, c))
214+
.count();
215+
}
216+
}
217+
}

0 commit comments

Comments
 (0)