@@ -39,6 +39,7 @@ func printDiskBlocks(diskBlocks []int) {
39
39
fmt .Printf ("%d" , b )
40
40
}
41
41
}
42
+ fmt .Println ()
42
43
}
43
44
44
45
func compact (in []int ) []int {
@@ -60,7 +61,7 @@ func compact(in []int) []int {
60
61
return out
61
62
}
62
63
63
- func checksum (diskBlocks []int ) int {
64
+ func calculateChecksum (diskBlocks []int ) int {
64
65
var checksum = 0
65
66
for i , b := range diskBlocks {
66
67
if b != FREE {
@@ -70,21 +71,90 @@ func checksum(diskBlocks []int) int {
70
71
return checksum
71
72
}
72
73
74
+ func findFreeSpace (blocks []int , size int ) int {
75
+ var targetBegin , foundSize int
76
+ targetBegin = - 1
77
+ for i := range blocks {
78
+ if blocks [i ] == FREE && targetBegin == - 1 {
79
+ targetBegin = i
80
+ }
81
+ if blocks [i ] != FREE && targetBegin != - 1 {
82
+ foundSize = i - targetBegin
83
+ if foundSize >= size {
84
+ return targetBegin
85
+ }
86
+ targetBegin = - 1
87
+ }
88
+ }
89
+ return - 1
90
+ }
91
+
92
+ func set (blocks []int , begin , end , fileId int ) {
93
+ for i := begin ; i <= end ; i ++ {
94
+ blocks [i ] = fileId
95
+ }
96
+ }
97
+
98
+ func defrag (in []int ) []int {
99
+ var out = make ([]int , len (in ))
100
+ copy (out [:], in [:])
101
+
102
+ var fileId , sourceBegin , sourceEnd int
103
+ fileId = - 1
104
+ for i := len (in ) - 1 ; i >= 0 ; i -- {
105
+ if fileId > 0 && fileId != in [i ] {
106
+ // case 1: we've exited the file
107
+ var size , targetBegin int
108
+
109
+ sourceBegin = i + 1
110
+ size = sourceEnd - sourceBegin + 1
111
+
112
+ targetBegin = findFreeSpace (out , size )
113
+ if targetBegin >= 0 && targetBegin < sourceBegin {
114
+ fmt .Printf (" move: %d -> %d (size %d)\n " , sourceBegin , targetBegin , size )
115
+ set (out , sourceBegin , sourceEnd , FREE )
116
+ set (out , targetBegin , targetBegin + size - 1 , fileId )
117
+ } else {
118
+ fmt .Printf (" stay: %d (size %d)\n " , sourceBegin , size )
119
+ }
120
+ fileId = - 1
121
+ }
122
+ if fileId < 0 {
123
+ if in [i ] == FREE {
124
+ // case 2: we're crossing void areas
125
+ continue
126
+ }
127
+ // case 3: we're entering the file
128
+ fileId = in [i ]
129
+ sourceEnd = i
130
+ }
131
+ }
132
+ return out
133
+ }
134
+
73
135
func main () {
74
136
scanner := bufio .NewScanner (os .Stdin )
75
137
scanner .Split (bufio .ScanLines )
76
138
139
+ var diskMap string
77
140
scanner .Scan ()
78
- var diskMap = scanner .Text ()
141
+ diskMap = scanner .Text ()
79
142
80
- var diskBlocks = calculateDiskBlocks (diskMap )
143
+ var diskBlocks []int
144
+ diskBlocks = calculateDiskBlocks (diskMap )
81
145
printDiskBlocks (diskBlocks )
82
- fmt .Println ()
83
146
84
- diskBlocks = compact (diskBlocks )
85
- printDiskBlocks (diskBlocks )
86
- fmt .Println ()
147
+ var compactDiskBlocks []int
148
+ var compactChecksum int
149
+ compactDiskBlocks = compact (diskBlocks )
150
+ printDiskBlocks (compactDiskBlocks )
151
+ compactChecksum = calculateChecksum (compactDiskBlocks )
152
+ fmt .Printf ("compact checksum: %d\n " , compactChecksum )
87
153
88
- var checksum = checksum (diskBlocks )
89
- fmt .Printf ("checksum: %d\n " , checksum )
154
+ var defragDiskBlocks []int
155
+ var defragChecksum int
156
+ defragDiskBlocks = defrag (diskBlocks )
157
+ printDiskBlocks (defragDiskBlocks )
158
+ defragChecksum = calculateChecksum (defragDiskBlocks )
159
+ fmt .Printf ("defrag checksum: %d\n " , defragChecksum )
90
160
}
0 commit comments