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