1
1
package com .sbaars .adventofcode .year16 .days ;
2
2
3
3
import com .sbaars .adventofcode .year16 .Day2016 ;
4
- import java .util .Map ;
5
- import java .util .Arrays ;
4
+ import java .util .*;
6
5
import java .util .stream .Collectors ;
7
6
8
7
public class Day4 extends Day2016 {
9
-
10
8
public Day4 () {
11
9
super (4 );
12
10
}
@@ -15,44 +13,65 @@ public static void main(String[] args) {
15
13
new Day4 ().printParts ();
16
14
}
17
15
18
- private boolean isRealRoom (String name , String checksum ) {
19
- // Remove dashes and count letter frequencies
20
- Map <Character , Long > freq = name .replace ("-" , "" ).chars ()
21
- .mapToObj (c -> (char ) c )
22
- .collect (Collectors .groupingBy (c -> c , Collectors .counting ()));
23
-
24
- // Get top 5 most common letters, breaking ties alphabetically
25
- String calculatedChecksum = freq .entrySet ().stream ()
26
- .sorted ((a , b ) -> {
27
- int freqCompare = b .getValue ().compareTo (a .getValue ());
28
- return freqCompare != 0 ? freqCompare : a .getKey ().compareTo (b .getKey ());
29
- })
30
- .limit (5 )
31
- .map (e -> String .valueOf (e .getKey ()))
32
- .collect (Collectors .joining ());
16
+ private record Room (String name , int sectorId , String checksum ) {
17
+ public boolean isReal () {
18
+ Map <Character , Integer > freq = new HashMap <>();
19
+ for (char c : name .replaceAll ("-" , "" ).toCharArray ()) {
20
+ freq .merge (c , 1 , Integer ::sum );
21
+ }
22
+
23
+ String calculatedChecksum = freq .entrySet ().stream ()
24
+ .sorted ((a , b ) -> {
25
+ int comp = b .getValue ().compareTo (a .getValue ());
26
+ return comp != 0 ? comp : a .getKey ().compareTo (b .getKey ());
27
+ })
28
+ .limit (5 )
29
+ .map (e -> String .valueOf (e .getKey ()))
30
+ .collect (Collectors .joining ());
31
+
32
+ return calculatedChecksum .equals (checksum );
33
+ }
34
+
35
+ public String decrypt () {
36
+ StringBuilder result = new StringBuilder ();
37
+ for (char c : name .toCharArray ()) {
38
+ if (c == '-' ) {
39
+ result .append (' ' );
40
+ } else {
41
+ int shifted = ((c - 'a' + sectorId ) % 26 ) + 'a' ;
42
+ result .append ((char ) shifted );
43
+ }
44
+ }
45
+ return result .toString ();
46
+ }
47
+ }
33
48
34
- return calculatedChecksum .equals (checksum );
49
+ private Room parseRoom (String line ) {
50
+ String [] parts = line .split ("\\ [" );
51
+ String checksum = parts [1 ].substring (0 , parts [1 ].length () - 1 );
52
+ String [] nameParts = parts [0 ].split ("-(?=\\ d)" );
53
+ String name = nameParts [0 ];
54
+ int sectorId = Integer .parseInt (nameParts [1 ]);
55
+ return new Room (name , sectorId , checksum );
35
56
}
36
57
37
58
@ Override
38
59
public Object part1 () {
39
60
return dayStream ()
40
- .map (line -> {
41
- // Parse room string into components
42
- int checksumStart = line .indexOf ('[' );
43
- String checksum = line .substring (checksumStart + 1 , line .length () - 1 );
44
- String [] parts = line .substring (0 , checksumStart ).split ("-" );
45
- int sectorId = Integer .parseInt (parts [parts .length - 1 ]);
46
- String name = String .join ("-" , Arrays .copyOf (parts , parts .length - 1 ));
47
-
48
- return isRealRoom (name , checksum ) ? sectorId : 0 ;
49
- })
50
- .mapToInt (Integer ::intValue )
61
+ .map (this ::parseRoom )
62
+ .filter (Room ::isReal )
63
+ .mapToInt (Room ::sectorId )
51
64
.sum ();
52
65
}
53
66
54
67
@ Override
55
68
public Object part2 () {
56
- return "" ;
69
+ return dayStream ()
70
+ .map (this ::parseRoom )
71
+ .filter (Room ::isReal )
72
+ .filter (room -> room .decrypt ().contains ("northpole" ))
73
+ .findFirst ()
74
+ .map (Room ::sectorId )
75
+ .orElse (0 );
57
76
}
58
77
}
0 commit comments