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.. 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)