1
+ import java.math.BigInteger
2
+
3
+ fun main () {
4
+ println (solve09a(readInputLines(" 09" )))
5
+ println (solve09b(readInputLines(" 09" )))
6
+ }
7
+
8
+ fun solve09a (lines : List <String >): BigInteger = checksum(fragmentBlocks(readInput(lines[0 ])))
9
+
10
+ fun solve09b (lines : List <String >): BigInteger = checksum(fragmentBlocks2(readInput(lines[0 ])))
11
+
12
+ private data class Block (val id : Int , val size : Int , val freeAfter : Int , val moved : Boolean = false )
13
+
14
+ private fun readInput (disk : String ): List <Block > {
15
+ val fixedDisk = if (disk.length % 2 != 0 ) disk + ' 0' else disk
16
+ val result = mutableListOf<Block >()
17
+ var id = 0
18
+
19
+ for (s in fixedDisk.windowed(2 , 2 )) {
20
+ val size = s[0 ].digitToInt()
21
+ val free = s[1 ].digitToInt()
22
+ result.add(Block (id, size, free))
23
+ id + = 1
24
+ }
25
+
26
+ return result
27
+ }
28
+
29
+ private fun fragmentBlocks (blocks : List <Block >): List <Block > {
30
+ val bs = blocks.toMutableList()
31
+ val result = mutableListOf (Block (blocks[0 ].id, blocks[0 ].size, 0 ))
32
+
33
+ var i = 0
34
+ var j = bs.lastIndex
35
+
36
+ while (i < j) {
37
+ if (bs[i].freeAfter > bs[j].size) {
38
+ result.add(bs[j].copy(freeAfter = 0 ))
39
+ bs[i] = bs[i].copy(freeAfter = bs[i].freeAfter - bs[j].size)
40
+ j - = 1
41
+ } else if (bs[i].freeAfter < bs[j].size) {
42
+ result.add(Block (bs[j].id, bs[i].freeAfter, 0 ))
43
+ bs[j] = bs[j].copy(size = bs[j].size - bs[i].freeAfter)
44
+ i + = 1
45
+ result.add(bs[i].copy(freeAfter = 0 ))
46
+ } else {
47
+ result.add(bs[j].copy(freeAfter = 0 ))
48
+ i + = 1
49
+ j - = 1
50
+ if (i != j + 1 ) {
51
+ result.add(bs[i].copy(freeAfter = 0 ))
52
+ }
53
+ }
54
+ }
55
+
56
+
57
+ return result
58
+ }
59
+
60
+ private fun fragmentBlocks2 (blocks : List <Block >): List <Block > {
61
+ val result = blocks.toMutableList()
62
+
63
+ var i = blocks.lastIndex
64
+ while (i > 0 ) {
65
+ val ib = result[i]
66
+ if (ib.moved) {
67
+ i - = 1
68
+ continue
69
+ }
70
+
71
+ var moved = false
72
+ for (j in 0 until i) {
73
+ val jb = result[j]
74
+ if (jb.freeAfter >= ib.size) {
75
+ result[i - 1 ] = result[i - 1 ].copy(freeAfter = result[i - 1 ].freeAfter + ib.freeAfter + ib.size)
76
+ result.removeAt(i)
77
+ result[j] = jb.copy(freeAfter = 0 )
78
+ result.add(j + 1 , ib.copy(freeAfter = jb.freeAfter - ib.size, moved = true ))
79
+ moved = true
80
+ break
81
+ }
82
+ }
83
+ if (! moved) {
84
+ i - = 1
85
+ }
86
+ }
87
+
88
+
89
+ return result
90
+ }
91
+
92
+ private fun checksum (blocks : List <Block >): BigInteger {
93
+ var total = BigInteger .ZERO
94
+ var i = 0
95
+
96
+ for (block in blocks) {
97
+ for (j in 0 until block.size) {
98
+ total + = block.id.toBigInteger() * i.toBigInteger()
99
+ i + = 1
100
+ }
101
+ i + = block.freeAfter
102
+ }
103
+
104
+ return total
105
+ }
0 commit comments