library(tidyverse)
library(stringr)
library(tictoc)
library(gmp)
dat <- read_lines("aoc07.txt")
head(dat)
[1] "5784641: 453 6 9 3 8 25 14 356 1"
[2] "282716070: 373 831 714 455 2"
[3] "38474572: 1 3 8 4 45 1 248 1 466 2"
[4] "32688: 90 356 3 640 5"
[5] "2462846: 245 64 23 41 48"
[6] "10791: 2 4 4 896 39"
splitcolon <- strsplit(dat, ": ")
out <- splitcolon |> map(\(x) x[1] |> as.bigz())
inp <- splitcolon |> map(\(x) x[2] |>
strsplit(, split = " ") |>
pluck(1) |>
as.bigz()
)
The inputs:
head(inp, 2)
[[1]]
Big Integer ('bigz') object of length 9:
[1] 453 6 9 3 8 25 14 356 1
[[2]]
Big Integer ('bigz') object of length 5:
[1] 373 831 714 455 2
The target values:
head(out, 2)
[[1]]
Big Integer ('bigz') :
[1] 5784641
[[2]]
Big Integer ('bigz') :
[1] 282716070
Part 1
Get all combos of operators:
combs_ops <- function(num_n) {
replicate(num_n - 1, c("plus", "mult"), simplify = FALSE) |>
expand.grid(stringsAsFactors = FALSE,
KEEP.OUT.ATTRS = FALSE)
}
Do one sum:
calc <- function(nums, ops, target) {
res <- nums[1]
for (i in 2:length(nums)) {
the_op <- ops[i - 1] |> as.vector()
stopifnot(the_op %in% c("plus", "mult"))
if (the_op == "plus") {
res <- res + nums[i]
}
else {
res <- res * nums[i]
}
}
res == target
}
Check them all for one list of inputs and a target:
check_all <- function(nums, target) {
all_ops <- combs_ops(length(nums))
found_it <- FALSE
for (r in 1:nrow(all_ops)) {
this_ops <- all_ops[r,] |> as.vector()
found_it <- calc(nums, this_ops, target)
if (found_it)
break
}
found_it
}
Now do it for everything. I wonder will map work okay with {gmp}…
tic()
res <- map2_lgl(inp, out, check_all)
toc()
51.7 sec elapsed
It did. Not taking any chances with the final sum…
to_sum <- out[res]
the_sum <- to_sum[[1]]
for (i in 2:length(to_sum))
the_sum <- the_sum + to_sum[[i]]
the_sum
Big Integer ('bigz') :
[1] 2437272016585
Part 2
concat <- function(x, y) {
paste0(as.character(x), as.character(y)) |> as.bigz()
}
combs_ops_v2 <- function(num_n) {
replicate(num_n - 1, c("plus", "mult", "concat"), simplify = FALSE) |>
expand.grid(stringsAsFactors = FALSE,
KEEP.OUT.ATTRS = FALSE)
}
Well, this is going to blow up spectacularly…
calc_v2<- function(nums, ops, target) {
res <- nums[1]
for (i in 2:length(nums)) {
the_op <- ops[i - 1] |> as.vector()
stopifnot(the_op %in% c("plus", "mult", "concat"))
if (the_op == "plus") {
res <- res + nums[i]
}
else if (the_op == "mult") {
res <- res * nums[i]
}
else {
res <- concat(res, nums[i])
}
}
res == target
}
check_all_v2 <- function(nums, target) {
all_ops <- combs_ops_v2(length(nums))
found_it <- FALSE
for (r in 1:nrow(all_ops)) {
this_ops <- all_ops[r,] |> as.vector()
found_it <- calc_v2(nums, this_ops, target)
if (found_it)
break
}
found_it
}
tic()
res_v2 <- map2_lgl(inp, out, check_all_v2)
toc()
4400.59 sec elapsed
to_sum <- out[res_v2]
the_sum <- to_sum[[1]]
for (i in 2:length(to_sum))
the_sum <- the_sum + to_sum[[i]]
the_sum
Big Integer ('bigz') :
[1] 162987117690649
LS0tDQp0aXRsZTogIkRheSA3OiBCcmlkZ2UgUmVwYWlyIg0KYXV0aG9yOiBBbmRpRg0KZGF0ZTogNyBEZWMgMjAyNA0Kb3V0cHV0OiANCiAgaHRtbF9ub3RlYm9vazogDQogICAgY29kZV9mb2xkaW5nOiBub25lDQotLS0NCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeSh0aWN0b2MpDQpsaWJyYXJ5KGdtcCkNCmBgYA0KDQpgYGB7cn0NCmRhdCA8LSByZWFkX2xpbmVzKCJhb2MwNy50eHQiKQ0KYGBgDQoNCg0KYGBge3J9DQpoZWFkKGRhdCkNCmBgYA0KDQpgYGB7cn0NCnNwbGl0Y29sb24gPC0gc3Ryc3BsaXQoZGF0LCAiOiAiKQ0Kb3V0IDwtIHNwbGl0Y29sb24gfD4gbWFwKFwoeCkgeFsxXSB8PiBhcy5iaWd6KCkpDQppbnAgPC0gc3BsaXRjb2xvbiB8PiBtYXAoXCh4KSB4WzJdIHw+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnNwbGl0KCwgc3BsaXQgPSAiICIpIHw+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsdWNrKDEpIHw+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmJpZ3ooKQ0KICAgICAgICAgICAgICAgICAgICAgICAgKQ0KYGBgDQoNClRoZSBpbnB1dHM6DQoNCmBgYHtyfQ0KaGVhZChpbnAsIDIpDQpgYGANCg0KVGhlIHRhcmdldCB2YWx1ZXM6DQoNCmBgYHtyfQ0KaGVhZChvdXQsIDIpDQpgYGANCg0KIyMjIFBhcnQgMQ0KDQpHZXQgYWxsIGNvbWJvcyBvZiBvcGVyYXRvcnM6DQoNCmBgYHtyfQ0KY29tYnNfb3BzIDwtIGZ1bmN0aW9uKG51bV9uKSB7DQogIHJlcGxpY2F0ZShudW1fbiAtIDEsIGMoInBsdXMiLCAibXVsdCIpLCBzaW1wbGlmeSA9IEZBTFNFKSB8Pg0KICAgIGV4cGFuZC5ncmlkKHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICBLRUVQLk9VVC5BVFRSUyA9IEZBTFNFKQ0KfQ0KYGBgDQoNCg0KRG8gb25lIHN1bToNCg0KYGBge3J9DQpjYWxjIDwtIGZ1bmN0aW9uKG51bXMsIG9wcywgdGFyZ2V0KSB7DQogIHJlcyA8LSBudW1zWzFdDQogIA0KICBmb3IgKGkgaW4gMjpsZW5ndGgobnVtcykpIHsNCiAgICB0aGVfb3AgPC0gb3BzW2kgLSAxXSB8PiBhcy52ZWN0b3IoKQ0KICAgIHN0b3BpZm5vdCh0aGVfb3AgJWluJSBjKCJwbHVzIiwgIm11bHQiKSkNCiAgICBpZiAodGhlX29wID09ICJwbHVzIikgew0KICAgICAgcmVzIDwtIHJlcyArIG51bXNbaV0NCiAgICB9DQogICAgZWxzZSB7DQogICAgICByZXMgPC0gcmVzICogbnVtc1tpXQ0KICAgIH0NCiAgfQ0KICANCiAgcmVzID09IHRhcmdldA0KfQ0KYGBgDQoNCg0KQ2hlY2sgdGhlbSBhbGwgZm9yIG9uZSBsaXN0IG9mIGlucHV0cyBhbmQgYSB0YXJnZXQ6DQoNCmBgYHtyfQ0KY2hlY2tfYWxsIDwtIGZ1bmN0aW9uKG51bXMsIHRhcmdldCkgew0KICBhbGxfb3BzIDwtIGNvbWJzX29wcyhsZW5ndGgobnVtcykpDQogIGZvdW5kX2l0IDwtIEZBTFNFDQogIA0KICBmb3IgKHIgaW4gMTpucm93KGFsbF9vcHMpKSB7DQogICAgdGhpc19vcHMgPC0gYWxsX29wc1tyLF0gfD4gYXMudmVjdG9yKCkNCiAgICBmb3VuZF9pdCA8LSBjYWxjKG51bXMsIHRoaXNfb3BzLCB0YXJnZXQpDQogICAgaWYgKGZvdW5kX2l0KQ0KICAgICAgYnJlYWsNCiAgfQ0KICANCiAgZm91bmRfaXQNCn0NCmBgYA0KDQpOb3cgZG8gaXQgZm9yIGV2ZXJ5dGhpbmcuIEkgd29uZGVyIHdpbGwgbWFwIHdvcmsgb2theSB3aXRoIHtnbXB9Li4uDQoNCmBgYHtyfQ0KdGljKCkNCnJlcyA8LSBtYXAyX2xnbChpbnAsIG91dCwgY2hlY2tfYWxsKQ0KdG9jKCkNCmBgYA0KDQpJdCBkaWQuIE5vdCB0YWtpbmcgYW55IGNoYW5jZXMgd2l0aCB0aGUgZmluYWwgc3VtLi4uDQoNCmBgYHtyfQ0KdG9fc3VtIDwtIG91dFtyZXNdDQp0aGVfc3VtIDwtIHRvX3N1bVtbMV1dDQpmb3IgKGkgaW4gMjpsZW5ndGgodG9fc3VtKSkNCiAgdGhlX3N1bSA8LSB0aGVfc3VtICsgdG9fc3VtW1tpXV0NCnRoZV9zdW0NCmBgYA0KDQojIyMgUGFydCAyDQoNCmBgYHtyfQ0KY29uY2F0IDwtIGZ1bmN0aW9uKHgsIHkpIHsNCiAgcGFzdGUwKGFzLmNoYXJhY3Rlcih4KSwgYXMuY2hhcmFjdGVyKHkpKSB8PiBhcy5iaWd6KCkNCn0NCmBgYA0KDQoNCmBgYHtyfQ0KY29tYnNfb3BzX3YyIDwtIGZ1bmN0aW9uKG51bV9uKSB7DQogIHJlcGxpY2F0ZShudW1fbiAtIDEsIGMoInBsdXMiLCAibXVsdCIsICJjb25jYXQiKSwgc2ltcGxpZnkgPSBGQUxTRSkgfD4NCiAgICBleHBhbmQuZ3JpZChzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsDQogICAgICAgICAgICAgICAgS0VFUC5PVVQuQVRUUlMgPSBGQUxTRSkNCn0NCmBgYA0KDQoNCldlbGwsIHRoaXMgaXMgZ29pbmcgdG8gYmxvdyB1cCBzcGVjdGFjdWxhcmx5Li4uDQoNCmBgYHtyfQ0KY2FsY192MiA8LSBmdW5jdGlvbihudW1zLCBvcHMsIHRhcmdldCkgew0KICByZXMgPC0gbnVtc1sxXQ0KICANCiAgZm9yIChpIGluIDI6bGVuZ3RoKG51bXMpKSB7DQogICAgdGhlX29wIDwtIG9wc1tpIC0gMV0gfD4gYXMudmVjdG9yKCkNCiAgICBzdG9waWZub3QodGhlX29wICVpbiUgYygicGx1cyIsICJtdWx0IiwgImNvbmNhdCIpKQ0KICAgIGlmICh0aGVfb3AgPT0gInBsdXMiKSB7DQogICAgICByZXMgPC0gcmVzICsgbnVtc1tpXQ0KICAgIH0NCiAgICBlbHNlIGlmICh0aGVfb3AgPT0gIm11bHQiKSB7DQogICAgICByZXMgPC0gcmVzICogbnVtc1tpXQ0KICAgIH0NCiAgICBlbHNlIHsNCiAgICAgIHJlcyA8LSBjb25jYXQocmVzLCBudW1zW2ldKQ0KICAgIH0NCiAgfQ0KICANCiAgcmVzID09IHRhcmdldA0KfQ0KYGBgDQoNCg0KYGBge3J9DQpjaGVja19hbGxfdjIgPC0gZnVuY3Rpb24obnVtcywgdGFyZ2V0KSB7DQogIGFsbF9vcHMgPC0gY29tYnNfb3BzX3YyKGxlbmd0aChudW1zKSkNCiAgZm91bmRfaXQgPC0gRkFMU0UNCiAgDQogIGZvciAociBpbiAxOm5yb3coYWxsX29wcykpIHsNCiAgICB0aGlzX29wcyA8LSBhbGxfb3BzW3IsXSB8PiBhcy52ZWN0b3IoKQ0KICAgIGZvdW5kX2l0IDwtIGNhbGNfdjIobnVtcywgdGhpc19vcHMsIHRhcmdldCkNCiAgICBpZiAoZm91bmRfaXQpDQogICAgICBicmVhaw0KICB9DQogIA0KICBmb3VuZF9pdA0KfQ0KYGBgDQoNCg0KYGBge3J9DQp0aWMoKQ0KcmVzX3YyIDwtIG1hcDJfbGdsKGlucCwgb3V0LCBjaGVja19hbGxfdjIpDQp0b2MoKQ0KYGBgDQoNCg0KYGBge3J9DQp0b19zdW0gPC0gb3V0W3Jlc192Ml0NCnRoZV9zdW0gPC0gdG9fc3VtW1sxXV0NCmZvciAoaSBpbiAyOmxlbmd0aCh0b19zdW0pKQ0KICB0aGVfc3VtIDwtIHRoZV9zdW0gKyB0b19zdW1bW2ldXQ0KdGhlX3N1bQ0KYGBgDQoNCg0K