57 lines
1.6 KiB
Swift
57 lines
1.6 KiB
Swift
import Foundation
|
|
|
|
func readInput(_ filePath: String) throws -> Disk {
|
|
let content = try String(contentsOfFile: filePath, encoding: .ascii)
|
|
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
.map { Int(String([$0]))! }
|
|
var pos = 0
|
|
var data: [(Int, Int)] = []
|
|
var free: [(Int, Int)] = []
|
|
for (i, x) in content.enumerated() {
|
|
if i.isMultiple(of: 2) {
|
|
data.append((pos, x))
|
|
} else {
|
|
free.append((pos, x))
|
|
}
|
|
pos += x
|
|
}
|
|
return Disk(data: data, free: free)
|
|
}
|
|
|
|
func sumRange(start: Int, len: Int) -> Int {
|
|
return len * (start + start + len - 1) / 2
|
|
}
|
|
|
|
struct Disk {
|
|
var data: [(Int, Int)]
|
|
var free: [(Int, Int)]
|
|
var csum: Int = 0
|
|
|
|
mutating func compact() {
|
|
for fileNo in (0..<data.count).reversed() {
|
|
var moved = false
|
|
let (iData, dataBlock) = data[fileNo]
|
|
for freeNo in 0..<free.count {
|
|
let (iFree, freeBlock) = free[freeNo]
|
|
if iFree > iData {
|
|
break
|
|
}
|
|
if freeBlock >= dataBlock {
|
|
csum += fileNo * sumRange(start: iFree, len: dataBlock)
|
|
free[freeNo] = (iFree + dataBlock, freeBlock - dataBlock)
|
|
data[fileNo] = (iData, 0)
|
|
moved = true
|
|
break
|
|
}
|
|
}
|
|
if !moved {
|
|
csum += fileNo * sumRange(start: iData, len:dataBlock)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var disk = try readInput(CommandLine.arguments[1])
|
|
disk.compact()
|
|
print(disk.csum)
|