@@ -39,6 +39,7 @@ func printDiskBlocks(diskBlocks []int) {
3939 fmt .Printf ("%d" , b )
4040 }
4141 }
42+ fmt .Println ()
4243}
4344
4445func compact (in []int ) []int {
@@ -60,7 +61,7 @@ func compact(in []int) []int {
6061 return out
6162}
6263
63- func checksum (diskBlocks []int ) int {
64+ func calculateChecksum (diskBlocks []int ) int {
6465 var checksum = 0
6566 for i , b := range diskBlocks {
6667 if b != FREE {
@@ -70,21 +71,90 @@ func checksum(diskBlocks []int) int {
7071 return checksum
7172}
7273
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+
73135func main () {
74136 scanner := bufio .NewScanner (os .Stdin )
75137 scanner .Split (bufio .ScanLines )
76138
139+ var diskMap string
77140 scanner .Scan ()
78- var diskMap = scanner .Text ()
141+ diskMap = scanner .Text ()
79142
80- var diskBlocks = calculateDiskBlocks (diskMap )
143+ var diskBlocks []int
144+ diskBlocks = calculateDiskBlocks (diskMap )
81145 printDiskBlocks (diskBlocks )
82- fmt .Println ()
83146
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 )
87153
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 )
90160}
0 commit comments