library(tidyverse)
library(stringr)
library(tictoc)
library(gmp)
dat <- read_lines("aoc09.txt") |>
strsplit("") |>
first() |>
as.numeric()
spec <- data.frame(n = dat) |>
mutate(type = c(rep(c("data", "free"), floor(n()/2)), "data"),
i = 1:n(),
id = floor((i + 1)/2) - 1)
head(spec)
build_disk <- function(id, type, n) {
data.frame(dat = rep(ifelse(type == "data", id, NA), n))
}
the_disk <- pmap(list(spec$id, spec$type, spec$n), build_disk) |>
bind_rows()
head(the_disk)
Part 1
Move the blocks:
tic()
start <- 1
end <- nrow(the_disk)
while (start < end) {
if (!is.na(the_disk[start, "dat"])) {
# Find the next free space
start <- start + 1
}
else {
while (start < end && is.na(the_disk[end, "dat"])) {
# Find the next data
end <- end - 1
}
if (start < end) {
# Finally move the data!
the_disk[start, "dat"] <- the_disk[end, "dat"]
the_disk[end, "dat"] <- NA
end <- end - 1
start <- start + 1
}
}
}
toc()
10.42 sec elapsed
Calculate the checksums:
pos <- 0
the_disk$pos <- rep(NA, nrow(the_disk))
for (i in 1:nrow(the_disk)) {
if (!is.na(the_disk[i, "dat"])) {
the_disk[i, "pos"] <- pos
pos <- pos + 1
}
}
the_disk <- the_disk |>
mutate(check = pos * dat)
summary(the_disk$check)
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
0 41929318 123670738 125973979 208262546 261908897 44944
sum(the_disk$check |> as.bigz(), na.rm = TRUE)
Big Integer ('bigz') :
[1] 6242766523059
LS0tDQp0aXRsZTogIkRheSA5OiBEaXNrIEZyYWdtZW50ZXIiDQphdXRob3I6IEFuZGlGDQpkYXRlOiA5IERlYyAyMDI0DQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOiANCiAgICBjb2RlX2ZvbGRpbmc6IG5vbmUNCi0tLQ0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KHRpY3RvYykNCmxpYnJhcnkoZ21wKQ0KYGBgDQoNCmBgYHtyfQ0KZGF0IDwtIHJlYWRfbGluZXMoImFvYzA5LnR4dCIpIHw+DQogIHN0cnNwbGl0KCIiKSB8Pg0KICBmaXJzdCgpIHw+DQogIGFzLm51bWVyaWMoKQ0KDQpzcGVjIDwtIGRhdGEuZnJhbWUobiA9IGRhdCkgfD4NCiAgbXV0YXRlKHR5cGUgPSBjKHJlcChjKCJkYXRhIiwgImZyZWUiKSwgZmxvb3IobigpLzIpKSwgImRhdGEiKSwNCiAgICAgICAgIGkgPSAxOm4oKSwNCiAgICAgICAgIGlkID0gZmxvb3IoKGkgKyAxKS8yKSAtIDEpDQoNCmhlYWQoc3BlYykNCmBgYA0KDQoNCmBgYHtyfQ0KYnVpbGRfZGlzayA8LSBmdW5jdGlvbihpZCwgdHlwZSwgbikgew0KICBkYXRhLmZyYW1lKGRhdCA9IHJlcChpZmVsc2UodHlwZSA9PSAiZGF0YSIsIGlkLCBOQSksIG4pKQ0KfQ0KYGBgDQoNCg0KYGBge3J9DQp0aGVfZGlzayA8LSBwbWFwKGxpc3Qoc3BlYyRpZCwgc3BlYyR0eXBlLCBzcGVjJG4pLCBidWlsZF9kaXNrKSB8Pg0KICBiaW5kX3Jvd3MoKQ0KYGBgDQoNCg0KYGBge3J9DQpoZWFkKHRoZV9kaXNrKQ0KYGBgDQoNCg0KIyMjIFBhcnQgMQ0KDQpNb3ZlIHRoZSBibG9ja3M6DQoNCmBgYHtyfQ0KdGljKCkNCnN0YXJ0IDwtIDENCmVuZCAgIDwtIG5yb3codGhlX2Rpc2spDQoNCndoaWxlIChzdGFydCA8IGVuZCkgew0KICBpZiAoIWlzLm5hKHRoZV9kaXNrW3N0YXJ0LCAiZGF0Il0pKSB7DQogICAgIyBGaW5kIHRoZSBuZXh0IGZyZWUgc3BhY2UNCiAgICBzdGFydCA8LSBzdGFydCArIDENCiAgfQ0KICBlbHNlIHsNCiAgICB3aGlsZSAoc3RhcnQgPCBlbmQgJiYgaXMubmEodGhlX2Rpc2tbZW5kLCAiZGF0Il0pKSB7DQogICAgICAjIEZpbmQgdGhlIG5leHQgZGF0YQ0KICAgICAgZW5kIDwtIGVuZCAtIDENCiAgICB9DQogICAgaWYgKHN0YXJ0IDwgZW5kKSB7DQogICAgICAjIEZpbmFsbHkgbW92ZSB0aGUgZGF0YSENCiAgICAgIHRoZV9kaXNrW3N0YXJ0LCAiZGF0Il0gPC0gdGhlX2Rpc2tbZW5kLCAiZGF0Il0NCiAgICAgIHRoZV9kaXNrW2VuZCwgImRhdCJdIDwtIE5BDQogICAgICBlbmQgPC0gZW5kIC0gMQ0KICAgICAgc3RhcnQgPC0gc3RhcnQgKyAxDQogICAgfQ0KICB9DQp9DQp0b2MoKQ0KYGBgDQoNCkNhbGN1bGF0ZSB0aGUgY2hlY2tzdW1zOg0KDQpgYGB7cn0NCnBvcyA8LSAwDQp0aGVfZGlzayRwb3MgPC0gcmVwKE5BLCBucm93KHRoZV9kaXNrKSkNCg0KZm9yIChpIGluIDE6bnJvdyh0aGVfZGlzaykpIHsNCiAgaWYgKCFpcy5uYSh0aGVfZGlza1tpLCAiZGF0Il0pKSB7DQogICAgdGhlX2Rpc2tbaSwgInBvcyJdIDwtIHBvcw0KICAgIHBvcyA8LSBwb3MgKyAxDQogIH0NCn0NCg0KdGhlX2Rpc2sgPC0gdGhlX2Rpc2sgfD4NCiAgbXV0YXRlKGNoZWNrID0gcG9zICogZGF0KQ0KYGBgDQoNCg0KYGBge3J9DQpzdW1tYXJ5KHRoZV9kaXNrJGNoZWNrKQ0KYGBgDQoNCmBgYHtyfQ0Kc3VtKHRoZV9kaXNrJGNoZWNrIHw+IGFzLmJpZ3ooKSwgbmEucm0gPSBUUlVFKQ0KYGBgDQoNCiMjIyBQYXJ0IDINCg0KVEJDLi4u