2
2
3
3
import com .sbaars .adventofcode .year24 .Day2024 ;
4
4
5
+ import static com .sbaars .adventofcode .util .AoCUtils .zipWithIndex ;
6
+ import static java .lang .Integer .parseInt ;
7
+ import static java .util .Collections .reverseOrder ;
8
+ import static java .util .stream .IntStream .range ;
9
+ import static java .util .stream .IntStream .rangeClosed ;
10
+
11
+ import java .util .*;
12
+ import java .util .concurrent .atomic .AtomicBoolean ;
13
+ import java .util .concurrent .atomic .AtomicInteger ;
14
+ import java .util .stream .Collectors ;
15
+ import java .util .stream .Stream ;
16
+
17
+
5
18
public class Day9 extends Day2024 {
6
19
public Day9 () {
7
20
super (9 );
@@ -11,13 +24,97 @@ public static void main(String[] args) {
11
24
new Day9 ().printParts ();
12
25
}
13
26
27
+ record Data (int start , int end , int length ) {
28
+ Data (int start ) {
29
+ this (start , start , 1 );
30
+ }
31
+
32
+ Data updateEnd (int end ) {
33
+ return new Data (this .start , end , end - this .start + 1 );
34
+ }
35
+ }
36
+
14
37
@ Override
15
38
public Object part1 () {
16
- return "" ;
39
+ var disk = disk ();
40
+ compactDisk (disk );
41
+ return checksum (disk );
17
42
}
18
43
19
44
@ Override
20
45
public Object part2 () {
21
- return "" ;
46
+ var disk = disk ();
47
+ var files = parseData (disk );
48
+ moveFiles (disk , files );
49
+ return checksum (disk );
50
+ }
51
+
52
+ private List <Integer > disk () {
53
+ AtomicInteger id = new AtomicInteger (0 );
54
+ AtomicBoolean b = new AtomicBoolean (true );
55
+ return dayStream ("" ).filter (s -> !s .isBlank ()).map (c -> parseInt (c )).flatMap (length -> {
56
+ int value = b .getAndSet (!b .get ()) ? id .getAndIncrement () : -1 ;
57
+ return Stream .generate (() -> value ).limit (length );
58
+ }).collect (Collectors .toCollection (ArrayList ::new ));
59
+ }
60
+
61
+ private void compactDisk (List <Integer > disk ) {
62
+ while (disk .indexOf (-1 ) != -1 ) {
63
+ int rightBlock ;
64
+ do {
65
+ rightBlock = disk .remove (disk .size () - 1 );
66
+ } while (rightBlock == -1 );
67
+ disk .set (disk .indexOf (-1 ), rightBlock );
68
+ }
69
+ }
70
+
71
+ private Map <Integer , Data > parseData (List <Integer > disk ) {
72
+ return zipWithIndex (disk .stream ()).filter (b -> b .e () != -1 ).reduce (new HashMap <Integer , Data >(), (map , b ) -> {
73
+ map .merge (b .e (), new Data (b .i ()), (d1 , d2 ) -> d1 .updateEnd (b .i ()));
74
+ return map ;
75
+ }, (a , b ) -> {
76
+ a .putAll (b );
77
+ return a ;
78
+ });
79
+ }
80
+
81
+ private void moveFiles (List <Integer > disk , Map <Integer , Data > files ) {
82
+ files .keySet ().stream ().sorted (reverseOrder ()).forEach (id -> {
83
+ Data d = files .get (id );
84
+ int l = d .length ();
85
+ int file = findFile (disk , l , d .start ());
86
+
87
+ if (file != -1 ) {
88
+ clearOldPositions (disk , d );
89
+ setNewPositions (disk , id , file , l );
90
+ files .put (id , new Data (file , file + l - 1 , l ));
91
+ }
92
+ });
93
+ }
94
+
95
+ private int findFile (List <Integer > disk , int length , int start ) {
96
+ int count = 0 , segmentStart = -1 ;
97
+ for (int i = 0 ; i < start ; i ++) {
98
+ if (disk .get (i ) == -1 ) {
99
+ if (segmentStart == -1 ) segmentStart = i ;
100
+ if (++count == length ) return segmentStart ;
101
+ } else {
102
+ count = 0 ;
103
+ segmentStart = -1 ;
104
+ }
105
+ }
106
+ return -1 ;
107
+ }
108
+
109
+ private void clearOldPositions (List <Integer > disk , Data data ) {
110
+ rangeClosed (data .start (), data .end ()).forEach (pos -> disk .set (pos , -1 ));
111
+ }
112
+
113
+ private void setNewPositions (List <Integer > disk , int id , int start , int length ) {
114
+ range (start , start + length ).forEach (pos -> disk .set (pos , id ));
115
+ }
116
+
117
+ private long checksum (List <Integer > disk ) {
118
+ return zipWithIndex (disk .stream ()).filter (b -> b .e () != -1 ).mapToLong (b -> (long ) b .i () * b .e ()).sum ();
22
119
}
23
120
}
0 commit comments