import gleam/dict.{type Dict} import gleam/int import gleam/io import gleam/iterator import gleam/list.{filter, fold, index_map, map} import gleam/string import stdin.{stdin} const word_size = 4 const directions = [#(1, 0), #(1, -1), #(1, 1), #(0, 1)] pub fn main() { stdin() |> read_input |> find_xmas |> io.debug } fn find_xmas(xmas_map: Dict(#(Int, Int), String)) -> Int { xmas_map |> dict.filter(fn(_, char) { char == "X" || char == "S" }) |> dict.keys |> map(fn(coord) { directions |> list.count(fn(dir) { case xmas_map |> dict.take(traverse(coord, dir)) |> dict.values { ["X", "M", "A", "S"] -> True ["S", "A", "M", "X"] -> True _ -> False } }) }) |> fold(0, int.add) } fn traverse(start: #(Int, Int), direction: #(Int, Int)) { let #(s_x, s_y) = start direction |> list.repeat(word_size) |> list.index_map(fn(dir, idx) { let #(x, y) = dir #(s_x + x * idx, s_y + y * idx) }) } fn read_input(it: iterator.Iterator(String)) -> Dict(#(Int, Int), String) { it |> iterator.to_list |> map(string.trim) |> filter(not(string.is_empty)) |> index_map(fn(str, col) { str |> string.to_graphemes |> index_map(fn(char, row) { #(#(row, col), char) }) }) |> list.flatten |> dict.from_list } fn not(a: fn(a) -> Bool) { fn(param: a) -> Bool { !a(param) } }