dev-resources.site
for different kinds of informations.
Advent of Code #8 (in Gleam)
Published at
12/8/2024
Categories
adventofcode
gleam
Author
sethcalebweeks
Author
14 person written this
sethcalebweeks
open
I'm not particularly proud of my code for today's solution. I could definitely refactor it to reduce a lot of the duplication, but I have a lot of other things going on, so I'm just going to leave it as is. The only other thing I'll mention is that this problem would really benefit from generator functions, list comprehensions, or lazy evaluated ranges, but without those features, I resorted to recursion. I suppose this is an example of where my brain decided that recursion was easier to wrap my head around than fold_until
. Anyway, here's the code:
import gleam/int
import gleam/io
import gleam/list
import gleam/string
import gleam/pair
import gleam/set.{type Set}
import gleam/option.{Some, None}
import gleam/dict.{type Dict}
import simplifile as file
const example = "
............
........0...
.....0......
.......0....
....0.......
......A.....
............
............
........A...
.........A..
............
............
"
pub fn main() {
let assert Ok(input) = file.read("input")
let assert 14 = part1(example)
let assert 34 = part2(example)
part1(input) |> int.to_string |> io.println
part2(input) |> int.to_string |> io.println
}
type Bounds = #(Int, Int)
type Coord = #(Int, Int)
type Map = Dict(String, List(Coord))
fn parse_input(input: String) -> #(Bounds, Map) {
input
|> string.trim
|> string.split("\n")
|> list.index_fold(#(#(0, 0), dict.new()), fn(acc, line, x) {
line
|> string.to_graphemes
|> list.index_fold(acc, fn(acc, char, y) {
let #(_, map) = acc
let map =
dict.upsert(map, char, fn(val) {
case char, val {
".", _ -> []
_, Some(positions) -> list.append(positions, [#(x, y)])
_, None -> [#(x, y)]
}
})
#(#(x, y), map)
})
})
}
fn in_bounds(bounds: Bounds, coord: Coord) -> Bool {
let #(x, y) = coord
let #(max_x, max_y) = bounds
x >= 0 && x <= max_x && y >= 0 && y <= max_y
}
fn part1(input: String) -> Int {
let #(bounds, map) = parse_input(input)
map
|> dict.fold(set.new(), fn(antinodes, _, positions) {
positions
|> list.combination_pairs
|> list.fold(antinodes, fn(antinodes, pair) {
let #(x1, y1) = pair.first(pair)
let #(x2, y2) = pair.second(pair)
let a1 = #(2 * x1 - x2, 2 * y1 - y2)
let a2 = #(2 * x2 - x1, 2 * y2 - y1)
case in_bounds(bounds, a1), in_bounds(bounds, a2) {
True, True -> antinodes |> set.insert(a1) |> set.insert(a2)
True, False -> antinodes |> set.insert(a1)
False, True -> antinodes |> set.insert(a2)
False, False -> antinodes
}
})
})
|> set.size
}
fn get_antinodes(bounds: Bounds, pair: #(Coord, Coord)) -> Set(Coord) {
set.new()
|> set.insert(pair.first(pair))
|> set.insert(pair.second(pair))
|> direction_1(bounds, pair)
|> direction_2(bounds, pair)
}
fn direction_1(set: Set(Coord), bounds: Bounds, pair: #(Coord, Coord)) -> Set(Coord) {
let #(x1, y1) = pair.first(pair)
let #(x2, y2) = pair.second(pair)
let d1 = #(2 * x1 - x2, 2 * y1 - y2)
case in_bounds(bounds, d1) {
True -> set |> set.insert(d1) |> direction_1(bounds, #(d1, #(x1, y1)))
False -> set
}
}
fn direction_2(set: Set(Coord), bounds: Bounds, pair: #(Coord, Coord)) -> Set(Coord) {
let #(x1, y1) = pair.first(pair)
let #(x2, y2) = pair.second(pair)
let d2 = #(2 * x2 - x1, 2 * y2 - y1)
case in_bounds(bounds, d2) {
True -> set |> set.insert(d2) |> direction_2(bounds, #(#(x2, y2), d2))
False -> set
}
}
fn part2(input: String) -> Int {
let #(bounds, map) = parse_input(input)
map
|> dict.fold(set.new(), fn(antinodes, _, positions) {
positions
|> list.combination_pairs
|> list.fold(antinodes, fn(antinodes, pair) {
set.union(antinodes, get_antinodes(bounds, pair))
})
})
|> set.size
}
adventofcode Article's
30 articles in total
Climbing a depth-first search hill, Advent of Code 2024, day 10
read article
Hoof It
read article
How to parse computer code, Advent of Code 2024 day 3
read article
Disk Fragmenter
read article
How to repair a bridge, Advent of Code 2024 Day 7
read article
Resonant Collinearity
read article
Advent of Code 2024 - Day 23: LAN Party
read article
How to trace steps in a map, Advent of Code 2024 day 6
read article
Advent of Code 2024 - Day 21: Keypad Conundrum
read article
Advent of Code 2024 - Day 18: Ram Run
read article
Advent of Code 2024 - Day 17: Chronospatial Computer
read article
Guard Gallivant
read article
Advent of Code 2024 Day 5 in Golang: Ordering Pages
read article
Advent of Code '24 - Day9: Disk Fragmenter (Python)
read article
Advent of Code #8 (in Gleam)
currently reading
Advent of Code #7 (in Gleam)
read article
Advent of Code #6 (in Gleam)
read article
Advent of Code #5 (in Gleam)
read article
AoC 24 - Day 4: Ceres Search
read article
Wednesday Links β Edition 2024-12-04
read article
Mull It Over
read article
Bridge Repair
read article
Advent of Code #3 (in Gleam)
read article
Day 3: Mull It Over | Advent of Code 2024 | Swift | δΈζ
read article
Red-Nosed Reports
read article
Day 1: Historian Hysteria | Advent of Code 2024 | Swift | δΈζ
read article
Advent of Code 2024 - Day 19: Linen Layout
read article
Advent of Code - It's More Than a Competition
read article
Advent of Code '24 - Day 10: Hoof It
read article
Advent of Code 2024 Retro: What could you do if you didn't care whether you failed?
read article
Featured ones: