This commit is contained in:
Hamcha 2024-12-08 12:09:44 +01:00
parent 31fe648c94
commit e6d4f3bf21
Signed by: hamcha
GPG key ID: 1669C533B8CF6D89
4 changed files with 226 additions and 0 deletions

12
sample/day8-sample.txt Normal file
View file

@ -0,0 +1,12 @@
............
........0...
.....0......
.......0....
....0.......
......A.....
............
............
........A...
.........A..
............
............

10
sample/day8-sample2.txt Normal file
View file

@ -0,0 +1,10 @@
T.........
...T......
.T........
..........
..........
..........
..........
..........
..........
..........

96
src/day8_p1.gleam Normal file
View file

@ -0,0 +1,96 @@
import gleam/dict.{type Dict}
import gleam/io
import gleam/iterator
import gleam/list.{filter, fold, map}
import gleam/pair
import gleam/result
import gleam/string
import stdin.{stdin}
pub fn main() {
stdin()
|> read_input
|> calculate_resonance
|> io.debug
}
fn calculate_resonance(chart: Map) -> Int {
let Map(w, h, antennas) = chart
antennas
|> dict.fold([], fn(acc, _, coords) {
let antinodes =
coords
|> ordered_combinations
|> map(resolve_antinode)
[antinodes, ..acc]
})
|> list.flatten
|> list.unique
|> filter(fn(coord) {
let #(x, y) = coord
x >= 0 && x < w && y >= 0 && y < h
})
|> list.length
}
fn resolve_antinode(coords: #(#(Int, Int), #(Int, Int))) -> #(Int, Int) {
let #(#(ax, ay), #(bx, by)) = coords
#(ax - { bx - ax }, ay - { by - ay })
}
fn ordered_combinations(items: List(a)) -> List(#(a, a)) {
items
|> list.combination_pairs
|> map(fn(x) { [x, pair.swap(x)] })
|> list.flatten
}
pub type Map {
Map(width: Int, height: Int, antennas: Dict(String, List(#(Int, Int))))
}
fn read_input(it: iterator.Iterator(String)) -> Map {
let maptxt =
it
|> iterator.to_list
|> map(string.trim)
|> filter(not(string.is_empty))
let assert Ok(width) = list.first(maptxt) |> result.map(string.length)
let height = list.length(maptxt)
let antennas =
maptxt
|> list.index_fold([], find_antennas)
|> fold(dict.new(), fn(acc, v) {
let #(group, coord) = v
let current =
acc
|> dict.get(group)
|> result.unwrap([])
dict.insert(acc, group, [coord, ..current])
})
Map(width, height, antennas)
}
fn find_antennas(
acc: List(#(String, #(Int, Int))),
line: String,
y: Int,
) -> List(#(String, #(Int, Int))) {
line
|> string.to_graphemes
|> list.index_fold(acc, fn(cur, chr, x) {
case chr {
"." -> cur
c -> [#(c, #(x, y)), ..cur]
}
})
}
fn not(a: fn(a) -> Bool) {
fn(param: a) -> Bool { !a(param) }
}

108
src/day8_p2.gleam Normal file
View file

@ -0,0 +1,108 @@
import gleam/dict.{type Dict}
import gleam/io
import gleam/iterator.{Done, Next}
import gleam/list.{filter, fold, map}
import gleam/pair
import gleam/result
import gleam/string
import stdin.{stdin}
pub fn main() {
stdin()
|> read_input
|> calculate_resonance
|> io.debug
}
fn calculate_resonance(chart: Map) -> Int {
let Map(w, h, antennas) = chart
antennas
|> dict.fold([], fn(acc, _, coords) {
let antinodes =
coords
|> ordered_combinations
|> map(fn(coord) {
let #(dx, dy) = resolve_antinode_frequency(coord)
// Spawn antinodes until out ot bounds
coord
|> pair.first
|> iterator.unfold(fn(pos) {
let #(x, y) = pos
let newpos = #(x + dx, y + dy)
case newpos {
#(tx, ty) if tx < 0 || tx >= w || ty < 0 || ty >= h -> Done
_ -> Next(newpos, newpos)
}
})
|> iterator.to_list
})
|> list.flatten
[coords, antinodes, acc] |> list.flatten
})
|> list.unique
|> list.length
}
fn resolve_antinode_frequency(
coords: #(#(Int, Int), #(Int, Int)),
) -> #(Int, Int) {
let #(#(ax, ay), #(bx, by)) = coords
#(ax - bx, ay - by)
}
fn ordered_combinations(items: List(a)) -> List(#(a, a)) {
items
|> list.combination_pairs
|> map(fn(x) { [x, pair.swap(x)] })
|> list.flatten
}
pub type Map {
Map(width: Int, height: Int, antennas: Dict(String, List(#(Int, Int))))
}
fn read_input(it: iterator.Iterator(String)) -> Map {
let maptxt =
it
|> iterator.to_list
|> map(string.trim)
|> filter(not(string.is_empty))
let assert Ok(width) = list.first(maptxt) |> result.map(string.length)
let height = list.length(maptxt)
let antennas =
maptxt
|> list.index_fold([], find_antennas)
|> fold(dict.new(), fn(acc, v) {
let #(group, coord) = v
let current =
acc
|> dict.get(group)
|> result.unwrap([])
dict.insert(acc, group, [coord, ..current])
})
Map(width, height, antennas)
}
fn find_antennas(
acc: List(#(String, #(Int, Int))),
line: String,
y: Int,
) -> List(#(String, #(Int, Int))) {
line
|> string.to_graphemes
|> list.index_fold(acc, fn(cur, chr, x) {
case chr {
"." -> cur
c -> [#(c, #(x, y)), ..cur]
}
})
}
fn not(a: fn(a) -> Bool) {
fn(param: a) -> Bool { !a(param) }
}