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.replace(word, word[0] + mapping[word] + word[~0])
s 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)
<- read_delim(here::here("2023", "day_02", "input_day02.txt"),
input delim = ":", col_names = c("game", "result")
)
<- input |>
input_parsed 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)
<- tribble(
max_number ~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)
<- read_delim(here::here("2023", "day_02", "input_day02.txt"),
input delim = ":", col_names = c("game", "result")
)
<- input |>
input_parsed 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):
= "." * len(input[0])
padding = [padding] + input
padded = []
parts
for i in range(len(input)):
for match in re.finditer(r"\d+", input[i]):
= match.span()
start, end = max(start - 1, 0), min(end + 1, len(input[i]))
start, end = "".join([row[start:end] for row in padded[i : i + 3]])
region if re.search(r"[^.0-9]", region):
int(match.group(0)))
parts.append(
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):
= "." * len(input[0])
padding = [padding] + input
padded = []
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):
= n.span()
lower, upper if lower - 1 <= gear.start() <= upper:
int(n.group(0)))
numbers.append(if len(numbers) == 2:
0] * numbers[1])
gear_ratios.append(numbers[
return sum(gear_ratios)
print(part2(input))
81709807
0.016 seconds elapsed
Day 4
Part 1
library(tidyverse)
<- read_delim(here::here("2023", "day_04", "input_day04.txt"),
input 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)
<- read_delim(here::here("2023", "day_04", "input_day04.txt"),
input delim = ":",
col_names = c("card", "numbers")
|>
) mutate(numbers = str_trim(numbers))
<- input |>
data_games 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()
<- data_games |> pull(card)
cards <- list()
collect_scratchcards while (!is.null(cards)) {
<- append(collect_scratchcards, list(cards))
collect_scratchcards <- data_games$copies[cards] |> unlist()
cards
}
print(unlist(collect_scratchcards) |> length())
[1] 5744979
0.885 sec elapsed