aboutsummaryrefslogtreecommitdiff
path: root/aoc2023/src/day3
diff options
context:
space:
mode:
Diffstat (limited to 'aoc2023/src/day3')
-rw-r--r--aoc2023/src/day3/.gitignore1
-rw-r--r--aoc2023/src/day3/solve.gleam180
2 files changed, 0 insertions, 181 deletions
diff --git a/aoc2023/src/day3/.gitignore b/aoc2023/src/day3/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day3/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day3/solve.gleam b/aoc2023/src/day3/solve.gleam
deleted file mode 100644
index ad975aa..0000000
--- a/aoc2023/src/day3/solve.gleam
+++ /dev/null
@@ -1,180 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/dict.{type Dict}
-import gleam/string
-import gleam/list
-import gleam/int
-import gleam/order.{type Order, Eq}
-
-type Coord {
- Coord(x: Int, y: Int)
-}
-
-type SymbolKind {
- Gear
- SomethingElse
-}
-
-type Symbol {
- Number(Int)
- Symbol(SymbolKind)
- Empty
-}
-
-type Board =
- Dict(Coord, Symbol)
-
-type Cell {
- Cell(coord: Coord, symbol: Symbol)
-}
-
-type Part {
- Part(coords: List(Coord), part_number: Int)
-}
-
-fn to_symbol(c: String) -> Symbol {
- case int.parse(c), c {
- Ok(n), _ -> Number(n)
- _, "." -> Empty
- _, "*" -> Symbol(Gear)
- _, _ -> Symbol(SomethingElse)
- }
-}
-
-fn to_board(input: String) -> Board {
- {
- use y, r <- list.index_map(string.split(input, "\n"))
- use x, c <- list.index_map(string.to_graphemes(r))
- #(Coord(x, y), to_symbol(c))
- }
- |> list.flatten()
- |> dict.from_list()
-}
-
-fn cell_compare(a: Cell, b: Cell) -> Order {
- case int.compare(a.coord.y, b.coord.y) {
- Eq -> int.compare(a.coord.x, b.coord.x)
- other -> other
- }
-}
-
-fn find_all_part_digits(b: Board) -> List(Cell) {
- b
- |> dict.filter(fn(_, v) {
- case v {
- Number(_) -> True
- _ -> False
- }
- })
- |> dict.to_list()
- |> list.map(fn(tup) { Cell(tup.0, tup.1) })
- |> list.sort(cell_compare)
-}
-
-fn to_parts(cells: List(Cell)) -> List(Part) {
- do_parts(cells, [])
-}
-
-fn do_parts(cells: List(Cell), parts: List(Part)) -> List(Part) {
- case cells {
- [] -> parts
- [Cell(next, Number(n)), ..t] -> {
- case parts {
- [] -> do_parts(t, [Part([next], n), ..parts])
- [Part([prev, ..] as coords, n0), ..rest_parts] ->
- case { next.x - prev.x }, { next.y - prev.y } {
- 1, 0 ->
- do_parts(t, [Part([next, ..coords], n0 * 10 + n), ..rest_parts])
- _, _ -> do_parts(t, [Part([next], n), ..parts])
- }
- _ -> panic
- }
- }
- _ -> panic
- }
-}
-
-fn all_neighbors(c: Coord) -> List(Coord) {
- use dx <- list.flat_map([-1, 0, 1])
- use dy <- list.filter_map([-1, 0, 1])
- case dx, dy {
- 0, 0 -> Error(Nil)
- _, _ -> Ok(Coord(c.x + dx, c.y + dy))
- }
-}
-
-fn sum_valid_parts(acc: Int, part: Part, board: Board) -> Int {
- let neighbors =
- part.coords
- |> list.flat_map(all_neighbors)
- |> list.unique()
-
- let sym = [Ok(Symbol(Gear)), Ok(Symbol(SomethingElse))]
- case list.any(neighbors, fn(c) { list.contains(sym, dict.get(board, c)) }) {
- True -> acc + part.part_number
- False -> acc
- }
-}
-
-pub fn part1(input: String) -> Int {
- let board = to_board(input)
-
- board
- |> find_all_part_digits
- |> to_parts
- |> list.fold(0, fn(acc, p) { sum_valid_parts(acc, p, board) })
-}
-
-fn to_part_with_neighbors(part: Part) -> Part {
- part.coords
- |> list.flat_map(all_neighbors)
- |> list.unique
- |> Part(part.part_number)
-}
-
-fn find_part_numbers_near_gear(gear: Coord, parts: List(Part)) -> List(Int) {
- use part <- list.filter_map(parts)
- case list.contains(part.coords, gear) {
- True -> Ok(part.part_number)
- False -> Error(Nil)
- }
-}
-
-fn to_sum_of_gear_ratios(adjacent_parts: List(List(Int))) -> Int {
- use acc, ps <- list.fold(adjacent_parts, 0)
- case ps {
- [p1, p2] -> acc + p1 * p2
- _ -> acc
- }
-}
-
-pub fn part2(input: String) -> Int {
- let board = to_board(input)
-
- let parts =
- board
- |> find_all_part_digits
- |> to_parts
- |> list.map(to_part_with_neighbors)
-
- board
- |> dict.filter(fn(_, v) { v == Symbol(Gear) })
- |> dict.keys
- |> list.map(find_part_numbers_near_gear(_, parts))
- |> to_sum_of_gear_ratios
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("3")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}