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) } }