library(tidyverse)
Read in the problem:
dat <- read_lines("aoc03.txt")
Line breaks aren’t special, so paste the lot together:
longmess <- paste(dat, collapse = "")
Part 1
Regex time. Try with an easy test:
easy_test <- "mul(2,4)ggsrjkgjdfmul(224,221)gielmul(1234,12)fskjd"
str_extract_all(easy_test, "mul\\([0-9]{1,3},[0-9]{1,3}\\)")
[[1]]
[1] "mul(2,4)" "mul(224,221)"
It worked. Now do it for longmess.
mults <- str_extract_all(longmess, "mul\\([0-9]{1,3},[0-9]{1,3}\\)")[[1]]
mults |> head(20)
[1] "mul(363,974)" "mul(307,210)" "mul(542,323)" "mul(238,474)"
[5] "mul(251,668)" "mul(184,693)" "mul(279,48)" "mul(96,310)"
[9] "mul(393,809)" "mul(95,723)" "mul(2,997)" "mul(114,838)"
[13] "mul(981,859)" "mul(137,289)" "mul(632,274)" "mul(963,844)"
[17] "mul(398,724)" "mul(87,650)" "mul(373,567)" "mul(683,987)"
I’m going to let R parse each string.
mul <- function(x,y) x * y
mult_one <- function(str) {
str |> parse(text = _) |> eval()
}
Here’s a test:
mult_one("mul(6,7)")
[1] 42
The answer to part 1:
map_int(mults, mult_one) |> sum()
[1] 175015740
Part 2
The logic is, hike out anything between a “don’t()” and a “do()”,
then run the code above on what remains. This also deals with
consecutive “do()”s automatically.
get_do <- function(str) {
doing_do <- TRUE
dont_exp <- "don't\\(\\)"
do_exp <- "do\\(\\)"
res <- ""
rest <- str
while (str_length(rest) != 0) {
if (doing_do) {
loc <- str_locate(rest, dont_exp)
if (!is.na(loc[1])) {
res <- paste0(res, str_sub(rest, 1, loc[1] - 1))
rest <- str_sub(rest, loc[2] + 1)
}
else {
res <- paste0(res, str_sub(rest, 1))
rest <- ""
}
doing_do <- FALSE
}
else {
loc <- str_locate(rest, do_exp)
if (!is.na(loc[1])) {
rest <- str_sub(rest, loc[2] + 1)
}
else {
rest <- ""
}
doing_do <- TRUE
}
}
res
}
Give it a go:
new_longmess <- longmess |> get_do()
A bit of copy and paste…
mults <- str_extract_all(new_longmess, "mul\\([0-9]{1,3},[0-9]{1,3}\\)")[[1]]
map_int(mults, mult_one) |> sum()
[1] 112272912
And it works!
LS0tDQp0aXRsZTogIkRheSAzOiBNdWxsIEl0IE92ZXIiDQphdXRob3I6IEFuZGlGDQpkYXRlOiAzIERlYyAyMDI0DQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOiANCiAgICBjb2RlX2ZvbGRpbmc6IG5vbmUNCi0tLQ0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpgYGANCg0KUmVhZCBpbiB0aGUgcHJvYmxlbToNCg0KYGBge3J9DQpkYXQgPC0gcmVhZF9saW5lcygiYW9jMDMudHh0IikNCmBgYA0KDQpMaW5lIGJyZWFrcyBhcmVuJ3Qgc3BlY2lhbCwgc28gcGFzdGUgdGhlIGxvdCB0b2dldGhlcjoNCg0KYGBge3J9DQpsb25nbWVzcyA8LSBwYXN0ZShkYXQsIGNvbGxhcHNlID0gIiIpDQpgYGANCg0KIyMjIFBhcnQgMQ0KDQpSZWdleCB0aW1lLiBUcnkgd2l0aCBhbiBlYXN5IHRlc3Q6DQoNCmBgYHtyfQ0KZWFzeV90ZXN0IDwtICJtdWwoMiw0KWdnc3Jqa2dqZGZtdWwoMjI0LDIyMSlnaWVsbXVsKDEyMzQsMTIpZnNramQiDQpzdHJfZXh0cmFjdF9hbGwoZWFzeV90ZXN0LCAibXVsXFwoWzAtOV17MSwzfSxbMC05XXsxLDN9XFwpIikNCmBgYA0KDQpJdCB3b3JrZWQuIE5vdyBkbyBpdCBmb3IgX2xvbmdtZXNzXy4NCg0KYGBge3J9DQptdWx0cyA8LSBzdHJfZXh0cmFjdF9hbGwobG9uZ21lc3MsICJtdWxcXChbMC05XXsxLDN9LFswLTldezEsM31cXCkiKVtbMV1dDQptdWx0cyB8PiBoZWFkKDIwKQ0KYGBgDQoNCkknbSBnb2luZyB0byBsZXQgUiBwYXJzZSBlYWNoIHN0cmluZy4NCg0KYGBge3J9DQptdWwgPC0gZnVuY3Rpb24oeCx5KSB4ICogeQ0KDQptdWx0X29uZSA8LSBmdW5jdGlvbihzdHIpIHsNCiAgc3RyIHw+IHBhcnNlKHRleHQgPSBfKSB8PiBldmFsKCkNCn0NCmBgYA0KDQpIZXJlJ3MgYSB0ZXN0Og0KDQpgYGB7cn0NCm11bHRfb25lKCJtdWwoNiw3KSIpDQpgYGANCg0KVGhlIGFuc3dlciB0byBwYXJ0IDE6DQoNCmBgYHtyfQ0KbWFwX2ludChtdWx0cywgbXVsdF9vbmUpIHw+IHN1bSgpDQpgYGANCg0KIyMjIFBhcnQgMg0KDQpUaGUgbG9naWMgaXMsIGhpa2Ugb3V0IGFueXRoaW5nIGJldHdlZW4gYSAiZG9uJ3QoKSIgYW5kIGEgImRvKCkiLCB0aGVuIHJ1biB0aGUgY29kZSBhYm92ZSBvbiB3aGF0IHJlbWFpbnMuIFRoaXMgYWxzbyBkZWFscyB3aXRoIGNvbnNlY3V0aXZlICJkbygpInMgYXV0b21hdGljYWxseS4NCg0KYGBge3J9DQpnZXRfZG8gPC0gZnVuY3Rpb24oc3RyKSB7DQogIGRvaW5nX2RvIDwtIFRSVUUNCiAgZG9udF9leHAgPC0gImRvbid0XFwoXFwpIg0KICBkb19leHAgICA8LSAiZG9cXChcXCkiDQoNCiAgcmVzICA8LSAiIg0KICByZXN0IDwtIHN0cg0KDQogIHdoaWxlIChzdHJfbGVuZ3RoKHJlc3QpICE9IDApIHsNCiAgICBpZiAoZG9pbmdfZG8pIHsNCiAgICAgIGxvYyA8LSBzdHJfbG9jYXRlKHJlc3QsIGRvbnRfZXhwKQ0KICAgICAgDQogICAgICBpZiAoIWlzLm5hKGxvY1sxXSkpIHsNCiAgICAgICAgcmVzICA8LSBwYXN0ZTAocmVzLCBzdHJfc3ViKHJlc3QsIDEsIGxvY1sxXSAtIDEpKQ0KICAgICAgICByZXN0IDwtIHN0cl9zdWIocmVzdCwgbG9jWzJdICsgMSkNCiAgICAgIH0NCiAgICAgIGVsc2Ugew0KICAgICAgICByZXMgIDwtIHBhc3RlMChyZXMsIHN0cl9zdWIocmVzdCwgMSkpDQogICAgICAgIHJlc3QgPC0gIiINCiAgICAgIH0NCiAgICAgIA0KICAgICAgZG9pbmdfZG8gPC0gRkFMU0UNCiAgICB9DQogICAgZWxzZSB7DQogICAgICBsb2MgPC0gc3RyX2xvY2F0ZShyZXN0LCBkb19leHApDQogICAgICANCiAgICAgIGlmICghaXMubmEobG9jWzFdKSkgew0KICAgICAgICByZXN0IDwtIHN0cl9zdWIocmVzdCwgbG9jWzJdICsgMSkNCiAgICAgIH0NCiAgICAgIGVsc2Ugew0KICAgICAgICByZXN0IDwtICIiDQogICAgICB9DQogICAgICANCiAgICAgIGRvaW5nX2RvIDwtIFRSVUUNCiAgICB9DQogIH0NCiAgDQogIHJlcw0KfQ0KYGBgDQoNCkdpdmUgaXQgYSBnbzoNCg0KYGBge3J9DQpuZXdfbG9uZ21lc3MgPC0gbG9uZ21lc3MgfD4gZ2V0X2RvKCkNCmBgYA0KDQpBIGJpdCBvZiBjb3B5IGFuZCBwYXN0ZS4uLg0KDQpgYGB7cn0NCm11bHRzIDwtIHN0cl9leHRyYWN0X2FsbChuZXdfbG9uZ21lc3MsICJtdWxcXChbMC05XXsxLDN9LFswLTldezEsM31cXCkiKVtbMV1dDQptYXBfaW50KG11bHRzLCBtdWx0X29uZSkgfD4gc3VtKCkNCmBgYA0KDQpBbmQgaXQgd29ya3MhDQo=