My 2023 Attempts
Day 1
Nice exercise in working with strings! The overlapping strings (e.g. “eightwo”) were a nice touch.
Part 1
import pandas as pd
import re
input = pd.read_table("2023/day_01/input_day01.txt", names=["string"])
def day1(input, pt2=False):
if pt2:
input["string"] = input["string"].apply(lambda k: _translate(k))
input["first_num"] = input["string"].apply(lambda k: re.search(r"\d+", k).group())
input["first_num"] = input["first_num"].str[0]
input["last_num"] = input["string"].apply(
lambda k: re.search(r"\d+", k[::-1]).group()
)
input["last_num"] = input["last_num"].str[0]
input["value"] = input["first_num"] + input["last_num"]
return input["value"].astype(int).sum()
print(day1(input, pt2=False))55017
0.928 seconds elapsed
Part 2
import pandas as pd
import re
input = pd.read_table("2023/day_01/input_day01.txt", names=["string"])
mapping = {
"one": "1",
"two": "2",
"three": "3",
"four": "4",
"five": "5",
"six": "6",
"seven": "7",
"eight": "8",
"nine": "9",
}
def _translate(s):
for word in mapping:
s = s.replace(word, word[0] + mapping[word] + word[~0])
return s
def day1(input, pt2=False):
if pt2:
input["string"] = input["string"].apply(lambda k: _translate(k))
input["first_num"] = input["string"].apply(lambda k: re.search(r"\d+", k).group())
input["first_num"] = input["first_num"].str[0]
input["last_num"] = input["string"].apply(
lambda k: re.search(r"\d+", k[::-1]).group()
)
input["last_num"] = input["last_num"].str[0]
input["value"] = input["first_num"] + input["last_num"]
return input["value"].astype(int).sum()
print(day1(input, pt2=True))53539
0.029 seconds elapsed
Day 2
Perfect exercise for {tidyverse}, not so much for Python or pandas. The parsing was hard, but got some inspiration from David Robinson there.
Part 1
library(tidyverse)
input <- read_delim(here::here("2023", "day_02", "input_day02.txt"),
delim = ":", col_names = c("game", "result")
)
input_parsed <- input |>
mutate(
result = str_trim(result),
game = parse_number(game),
cubes = str_extract_all(result, "\\d+ [a-z]+")
) |>
unnest(cubes) |>
separate(cubes, c("number", "color"), sep = " ", convert = TRUE)
max_number <- tribble(
~color, ~max_value,
"red", 12,
"green", 13,
"blue", 14
)
input_parsed |>
inner_join(max_number, by = "color") |>
group_by(game) |>
filter(!any(number > max_value)) |>
distinct(game) |>
pull(game) |>
sum() |>
print()[1] 2331
0.357 sec elapsed
Part 2
library(tidyverse)
input <- read_delim(here::here("2023", "day_02", "input_day02.txt"),
delim = ":", col_names = c("game", "result")
)
input_parsed <- input |>
mutate(
result = str_trim(result),
game = parse_number(game),
cubes = str_extract_all(result, "\\d+ [a-z]+")
) |>
unnest(cubes) |>
separate(cubes, c("number", "color"), sep = " ", convert = TRUE)
input_parsed |>
inner_join(max_number, by = "color") |>
group_by(game, color) |>
summarise(number = max(number)) |>
summarise(power = prod(number)) |>
pull(power) |>
sum() |>
print()[1] 71585
0.093 sec elapsed
Day 3
Really not good at these grid searches, used the solution by Jared Summers in the hope I could learn
Part 1
import os
import re
input = open(os.path.join("2023", "day_03", "input_day03.txt"), "r").read().splitlines()
def part1(input):
padding = "." * len(input[0])
padded = [padding] + input
parts = []
for i in range(len(input)):
for match in re.finditer(r"\d+", input[i]):
start, end = match.span()
start, end = max(start - 1, 0), min(end + 1, len(input[i]))
region = "".join([row[start:end] for row in padded[i : i + 3]])
if re.search(r"[^.0-9]", region):
parts.append(int(match.group(0)))
return sum(parts)
print(part1(input))538046
0.014 seconds elapsed
Part 2
import os
import re
input = open(os.path.join("2023", "day_03", "input_day03.txt"), "r").read().splitlines()
def part2(input):
padding = "." * len(input[0])
padded = [padding] + input
gear_ratios = []
for i in range(len(input)):
for gear in re.finditer(r"\*", input[i]):
numbers = []
for row in padded[i : i + 3]:
for n in re.finditer(r"\d+", row):
lower, upper = n.span()
if lower - 1 <= gear.start() <= upper:
numbers.append(int(n.group(0)))
if len(numbers) == 2:
gear_ratios.append(numbers[0] * numbers[1])
return sum(gear_ratios)
print(part2(input))81709807
0.016 seconds elapsed
Day 4
Part 1
library(tidyverse)
input <- read_delim(here::here("2023", "day_04", "input_day04.txt"),
delim = ":",
col_names = c("card", "numbers")
) |>
mutate(numbers = str_trim(numbers))
input |>
separate_wider_delim(
numbers,
delim = "|", names = c("winning", "hand")
) |>
mutate(
across(everything(), str_trim),
across(everything(), ~ str_extract_all(.x, "\\d+")),
match = map2(winning, hand, intersect),
n_match = lengths(match)
) |>
filter(n_match > 0) |>
summarise(
points = sum(2^(n_match - 1))
) |>
pull(points) |>
print()[1] 27059
0.067 sec elapsed
Part 2
library(tidyverse)
input <- read_delim(here::here("2023", "day_04", "input_day04.txt"),
delim = ":",
col_names = c("card", "numbers")
) |>
mutate(numbers = str_trim(numbers))
data_games <- input |>
separate_wider_delim(
numbers,
delim = "|", names = c("winning", "hand")
) |>
mutate(
across(everything(), str_trim),
across(everything(), ~ str_extract_all(.x, "\\d+")),
card = as.numeric(unlist(card)),
match = map2(winning, hand, intersect),
n_match = lengths(match)
) |>
rowwise() |>
mutate(copies = ifelse(n_match > 0, list(card + seq(n_match)), NA)) |>
ungroup()
cards <- data_games |> pull(card)
collect_scratchcards <- list()
while (!is.null(cards)) {
collect_scratchcards <- append(collect_scratchcards, list(cards))
cards <- data_games$copies[cards] |> unlist()
}
print(unlist(collect_scratchcards) |> length())[1] 5744979
0.885 sec elapsed