d09
This commit is contained in:
67
day09/d09p1.swift
Normal file
67
day09/d09p1.swift
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
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 if x > 0 {
|
||||||
|
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
|
||||||
|
var firstFree: Int = 0 // emulate a Deque, avoid O(n) removal from front
|
||||||
|
var compact = false
|
||||||
|
|
||||||
|
mutating func evolve() {
|
||||||
|
var (iFree, freeBlock) = free[firstFree]
|
||||||
|
var (iData, dataBlock) = data.last!
|
||||||
|
let fileNo = data.count - 1
|
||||||
|
while (dataBlock >= freeBlock) {
|
||||||
|
if iFree > iData {
|
||||||
|
if dataBlock == 0 {
|
||||||
|
data.removeLast()
|
||||||
|
}
|
||||||
|
data.enumerated().forEach { fileNo, d in
|
||||||
|
let (i, len) = d
|
||||||
|
csum += fileNo * sumRange(start: i, len: len)
|
||||||
|
}
|
||||||
|
compact = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
csum += fileNo * sumRange(start: iFree, len: freeBlock)
|
||||||
|
dataBlock -= freeBlock
|
||||||
|
data[fileNo] = (iData, dataBlock)
|
||||||
|
firstFree += 1
|
||||||
|
(iFree, freeBlock) = free[firstFree]
|
||||||
|
}
|
||||||
|
if dataBlock > 0 { // not needed; only for sanity
|
||||||
|
csum += fileNo * sumRange(start: iFree, len: dataBlock)
|
||||||
|
free[firstFree] = (iFree + dataBlock, freeBlock - dataBlock)
|
||||||
|
}
|
||||||
|
data.removeLast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var disk = try readInput(CommandLine.arguments[1])
|
||||||
|
while !disk.compact {
|
||||||
|
disk.evolve()
|
||||||
|
//print(disk)
|
||||||
|
}
|
||||||
|
print(disk.csum)
|
56
day09/d09p2.swift
Normal file
56
day09/d09p2.swift
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
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)
|
1
day09/input.txt
Normal file
1
day09/input.txt
Normal file
File diff suppressed because one or more lines are too long
1
day09/test.txt
Normal file
1
day09/test.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2333133121414131402
|
1
day09/test2.txt
Normal file
1
day09/test2.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2333133020404131402
|
Reference in New Issue
Block a user