aboutsummaryrefslogtreecommitdiff
path: root/aoc2023
diff options
context:
space:
mode:
Diffstat (limited to 'aoc2023')
-rw-r--r--aoc2023/.DS_Storebin6148 -> 0 bytes
-rw-r--r--aoc2023/.github/workflows/test.yml23
-rw-r--r--aoc2023/.gitignore6
-rw-r--r--aoc2023/README.md28
-rw-r--r--aoc2023/gleam.toml22
-rw-r--r--aoc2023/manifest.toml29
-rw-r--r--aoc2023/src/.gitignore1
-rw-r--r--aoc2023/src/aoc2023.gleam12
-rw-r--r--aoc2023/src/day1/.gitignore1
-rw-r--r--aoc2023/src/day1/solve.gleam57
-rw-r--r--aoc2023/src/day10/.gitignore1
-rw-r--r--aoc2023/src/day10/solve.gleam177
-rw-r--r--aoc2023/src/day11/.gitignore1
-rw-r--r--aoc2023/src/day11/solve.gleam84
-rw-r--r--aoc2023/src/day12/.gitignore1
-rw-r--r--aoc2023/src/day12/solve.gleam90
-rw-r--r--aoc2023/src/day13/.gitignore1
-rw-r--r--aoc2023/src/day13/solve.gleam87
-rw-r--r--aoc2023/src/day14/.gitignore1
-rw-r--r--aoc2023/src/day14/solve.gleam94
-rw-r--r--aoc2023/src/day15/.gitignore1
-rw-r--r--aoc2023/src/day15/solve.gleam104
-rw-r--r--aoc2023/src/day16/.gitignore1
-rw-r--r--aoc2023/src/day16/solve.gleam119
-rw-r--r--aoc2023/src/day17/.gitignore1
-rw-r--r--aoc2023/src/day17/solve.gleam143
-rw-r--r--aoc2023/src/day18/.gitignore1
-rw-r--r--aoc2023/src/day18/solve.gleam113
-rw-r--r--aoc2023/src/day19/.gitignore1
-rw-r--r--aoc2023/src/day19/solve.gleam255
-rw-r--r--aoc2023/src/day2/.gitignore1
-rw-r--r--aoc2023/src/day2/solve.gleam66
-rw-r--r--aoc2023/src/day20/.gitignore1
-rw-r--r--aoc2023/src/day20/solve.gleam251
-rw-r--r--aoc2023/src/day22/.gitignore1
-rw-r--r--aoc2023/src/day22/solve.gleam199
-rw-r--r--aoc2023/src/day23/.gitignore1
-rw-r--r--aoc2023/src/day23/solve.gleam194
-rw-r--r--aoc2023/src/day3/.gitignore1
-rw-r--r--aoc2023/src/day3/solve.gleam180
-rw-r--r--aoc2023/src/day4/.gitignore1
-rw-r--r--aoc2023/src/day4/solve.gleam98
-rw-r--r--aoc2023/src/day5/.gitignore1
-rw-r--r--aoc2023/src/day5/solve.gleam162
-rw-r--r--aoc2023/src/day6/.gitignore1
-rw-r--r--aoc2023/src/day6/solve.gleam85
-rw-r--r--aoc2023/src/day7/.gitignore1
-rw-r--r--aoc2023/src/day7/solve.gleam140
-rw-r--r--aoc2023/src/day8/.gitignore1
-rw-r--r--aoc2023/src/day8/solve.gleam91
-rw-r--r--aoc2023/src/day9/.gitignore1
-rw-r--r--aoc2023/src/day9/solve.gleam70
-rw-r--r--aoc2023/src/utilities/array2d.gleam74
-rw-r--r--aoc2023/src/utilities/memo.gleam57
-rw-r--r--aoc2023/src/utilities/prioqueue.gleam64
-rw-r--r--aoc2023/test/aoc2023_test.gleam5
-rw-r--r--aoc2023/test/day1/day1_test.gleam57
-rw-r--r--aoc2023/test/day10/day10_test.gleam60
-rw-r--r--aoc2023/test/day11/day11_test.gleam66
-rw-r--r--aoc2023/test/day12/day12_test.gleam48
-rw-r--r--aoc2023/test/day13/day13_test.gleam76
-rw-r--r--aoc2023/test/day14/day14_test.gleam66
-rw-r--r--aoc2023/test/day15/day15_test.gleam42
-rw-r--r--aoc2023/test/day16/day16_test.gleam66
-rw-r--r--aoc2023/test/day17/day17_test.gleam54
-rw-r--r--aoc2023/test/day18/day18_test.gleam74
-rw-r--r--aoc2023/test/day19/day19_test.gleam80
-rw-r--r--aoc2023/test/day2/day2_test.gleam57
-rw-r--r--aoc2023/test/day20/day20_test.gleam55
-rw-r--r--aoc2023/test/day22/day22_test.gleam60
-rw-r--r--aoc2023/test/day23/day23_test.gleam92
-rw-r--r--aoc2023/test/day3/day3_test.gleam66
-rw-r--r--aoc2023/test/day4/day4_test.gleam58
-rw-r--r--aoc2023/test/day5/day5_test.gleam112
-rw-r--r--aoc2023/test/day6/day6_test.gleam50
-rw-r--r--aoc2023/test/day7/day7_test.gleam56
-rw-r--r--aoc2023/test/day8/day8_test.gleam61
-rw-r--r--aoc2023/test/day9/day9_test.gleam52
78 files changed, 0 insertions, 4610 deletions
diff --git a/aoc2023/.DS_Store b/aoc2023/.DS_Store
deleted file mode 100644
index 5172429..0000000
--- a/aoc2023/.DS_Store
+++ /dev/null
Binary files differ
diff --git a/aoc2023/.github/workflows/test.yml b/aoc2023/.github/workflows/test.yml
deleted file mode 100644
index cf2096e..0000000
--- a/aoc2023/.github/workflows/test.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: test
-
-on:
- push:
- branches:
- - master
- - main
- pull_request:
-
-jobs:
- test:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: erlef/setup-beam@v1
- with:
- otp-version: "26.0.2"
- gleam-version: "0.32.4"
- rebar3-version: "3"
- # elixir-version: "1.15.4"
- - run: gleam deps download
- - run: gleam test
- - run: gleam format --check src test
diff --git a/aoc2023/.gitignore b/aoc2023/.gitignore
deleted file mode 100644
index 8248306..0000000
--- a/aoc2023/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-*.beam
-*.ez
-build
-erl_crash.dump
-
-aoc.toml \ No newline at end of file
diff --git a/aoc2023/README.md b/aoc2023/README.md
deleted file mode 100644
index 3f534e8..0000000
--- a/aoc2023/README.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# aoc2023
-
-[![Package Version](https://img.shields.io/hexpm/v/aoc2023)](https://hex.pm/packages/aoc2023)
-[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/aoc2023/)
-
-## Quick start
-
-```sh
-gleam run # Run the project
-gleam test # Run the tests
-gleam shell # Run an Erlang shell
-```
-
-## Installation
-
-If available on Hex this package can be added to your Gleam project:
-
-```sh
-gleam add aoc2023
-```
-
-and its documentation can be found at <https://hexdocs.pm/aoc2023>.
-
-## Use
-
-* Set up a solution: `gleam run -m adglent/day <n>`
-* Check against examples: `gleam test -- --modules=day<n>/day<n>_test`
-* Get final answer: `gleam run -m day<n>/solve <p>` \ No newline at end of file
diff --git a/aoc2023/gleam.toml b/aoc2023/gleam.toml
deleted file mode 100644
index 8190aef..0000000
--- a/aoc2023/gleam.toml
+++ /dev/null
@@ -1,22 +0,0 @@
-name = "aoc2023"
-version = "0.1.0"
-gleam = ">= 0.33.0"
-
-# Fill out these fields if you intend to generate HTML documentation or publish
-# your project to the Hex package manager.
-#
-# description = ""
-# licences = ["Apache-2.0"]
-# repository = { type = "github", user = "username", repo = "project" }
-# links = [{ title = "Website", href = "https://gleam.run" }]
-
-[dependencies]
-gleam_stdlib = "~> 0.33"
-simplifile = "~> 1.0"
-gleam_erlang = "~> 0.23"
-gleam_community_maths = "~> 1.0"
-gleam_otp = "~> 0.8"
-pqueue = "~> 2.0"
-
-[dev-dependencies]
-adglent = "~> 1.2"
diff --git a/aoc2023/manifest.toml b/aoc2023/manifest.toml
deleted file mode 100644
index 900b5c0..0000000
--- a/aoc2023/manifest.toml
+++ /dev/null
@@ -1,29 +0,0 @@
-# This file was generated by Gleam
-# You typically do not need to edit this file
-
-packages = [
- { name = "adglent", version = "1.2.0", build_tools = ["gleam"], requirements = ["glint", "gleam_http", "gleam_stdlib", "simplifile", "gleam_erlang", "gap", "gleam_httpc", "snag", "gleam_community_ansi", "tom", "gleam_otp"], otp_app = "adglent", source = "hex", outer_checksum = "A20D35001061F8AD602E3B92FB3AC0E1E4EEC642AD2AAE0ACEAD3A85F37DA7F0" },
- { name = "gap", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_stdlib"], otp_app = "gap", source = "hex", outer_checksum = "5E369751DB547BFBDA7735878DC04DA31FCA3112193D61D5D7566010C7C8BA98" },
- { name = "gleam_community_ansi", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "8B5A9677BC5A2738712BBAF2BA289B1D8195FDF962BBC769569976AD5E9794E1" },
- { name = "gleam_community_colour", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "036C206886AFB9F153C552700A7A0B4D2864E3BC96A20C77E5F34A013C051BE3" },
- { name = "gleam_community_maths", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_community_maths", source = "hex", outer_checksum = "1B9DB313E94A0E4674CA84C5D29F45ECFE211BFB38ABBD8B23737395F47D08B3" },
- { name = "gleam_erlang", version = "0.23.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "C21CFB816C114784E669FFF4BBF433535EEA9960FA2F216209B8691E87156B96" },
- { name = "gleam_http", version = "3.5.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "AECDA43AFD523D07A8F09068598A6E271C505278A0CB6F9C7A2E4365EAE8D11E" },
- { name = "gleam_httpc", version = "2.1.1", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "06AC1CA52C9BAA66C9D5C0303B2BF34E39AA1546BB96AEE496E4B06D513AB8C7" },
- { name = "gleam_otp", version = "0.8.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_erlang"], otp_app = "gleam_otp", source = "hex", outer_checksum = "18EF8242A5E54BA92F717C7222F03B3228AEE00D1F286D4C56C3E8C18AA2588E" },
- { name = "gleam_stdlib", version = "0.33.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "539E37A2AA5EBE8E75F4B74755E4CC604BD957C3000AC8D705A2024886A2738B" },
- { name = "glint", version = "0.13.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_community_ansi", "gleam_community_colour", "snag"], otp_app = "glint", source = "hex", outer_checksum = "46E56049CD370D61F720D319D0AB970408C9336EEB918F08B5DCB1DCE9845FA3" },
- { name = "pqueue", version = "2.0.7", build_tools = ["rebar3"], requirements = [], otp_app = "pqueue", source = "hex", outer_checksum = "8B0204BB202335890E4E7F9B99A8EC0B84DDB8513EE298EB180EE9B3BCB4C859" },
- { name = "simplifile", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0BD6F0E7DA1A7E11D18B8AD48453225CAFCA4C8CFB4513D217B372D2866C501C" },
- { name = "snag", version = "0.2.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "8FD70D8FB3728E08AC425283BB509BB0F012BE1AE218424A597CDE001B0EE589" },
- { name = "tom", version = "0.2.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "tom", source = "hex", outer_checksum = "5C5A9B8586C547F1F39542B1A3BBD9FEE17AFEAB51CE53B32B13D0D46B421249" },
-]
-
-[requirements]
-adglent = { version = "~> 1.2" }
-gleam_community_maths = { version = "~> 1.0" }
-gleam_erlang = { version = "~> 0.23" }
-gleam_otp = { version = "~> 0.8" }
-gleam_stdlib = { version = "~> 0.33" }
-pqueue = { version = "~> 2.0" }
-simplifile = { version = "~> 1.0" }
diff --git a/aoc2023/src/.gitignore b/aoc2023/src/.gitignore
deleted file mode 100644
index bc13a69..0000000
--- a/aoc2023/src/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-aoc2023.gleam \ No newline at end of file
diff --git a/aoc2023/src/aoc2023.gleam b/aoc2023/src/aoc2023.gleam
deleted file mode 100644
index aab904d..0000000
--- a/aoc2023/src/aoc2023.gleam
+++ /dev/null
@@ -1,12 +0,0 @@
-import gleam/io
-import gleam/bit_array
-
-const str = "abcdefgh
-abcdefgh"
-
-pub fn main() {
- let trim = 8
- let assert <<_:bytes-size(trim), "\n":utf8, rest:bytes>> =
- bit_array.from_string(str)
- io.debug(rest)
-}
diff --git a/aoc2023/src/day1/.gitignore b/aoc2023/src/day1/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day1/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day1/solve.gleam b/aoc2023/src/day1/solve.gleam
deleted file mode 100644
index 37a19d2..0000000
--- a/aoc2023/src/day1/solve.gleam
+++ /dev/null
@@ -1,57 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/list
-import gleam/string
-import gleam/regex.{type Match, Match}
-import gleam/int
-
-pub fn part1(input: String) {
- let assert Ok(re) = regex.from_string("[1-9]")
-
- input
- |> string.split("\n")
- |> list.fold(0, fn(acc, s) {
- let matches = regex.scan(s, with: re)
-
- let assert Ok(Match(content: first, ..)) = list.first(matches)
- let assert Ok(Match(content: last, ..)) = list.last(matches)
- let assert Ok(i) = int.parse(first <> last)
- acc + i
- })
- |> string.inspect
-}
-
-const substitutions = [
- #("one", "o1e"),
- #("two", "t2o"),
- #("three", "t3e"),
- #("four", "4"),
- #("five", "5e"),
- #("six", "6"),
- #("seven", "7n"),
- #("eight", "e8t"),
- #("nine", "n9e"),
-]
-
-pub fn part2(input: String) {
- list.fold(over: substitutions, from: input, with: fn(acc, sub) {
- let #(from, to) = sub
- string.replace(in: acc, each: from, with: to)
- })
- |> part1
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("1")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day10/.gitignore b/aoc2023/src/day10/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day10/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day10/solve.gleam b/aoc2023/src/day10/solve.gleam
deleted file mode 100644
index c33634d..0000000
--- a/aoc2023/src/day10/solve.gleam
+++ /dev/null
@@ -1,177 +0,0 @@
-import adglent.{First, Second}
-import gleam/bool
-import gleam/dict.{type Dict}
-import gleam/list
-import gleam/int
-import gleam/io
-import gleam/set.{type Set}
-import gleam/string
-
-type Posn {
- Posn(row: Int, col: Int)
-}
-
-fn add_posns(p1: Posn, p2: Posn) -> Posn {
- Posn(p1.row + p2.row, p1.col + p2.col)
-}
-
-type PipeGrid =
- Dict(Posn, String)
-
-const north = Posn(-1, 0)
-
-const south = Posn(1, 0)
-
-const east = Posn(0, 1)
-
-const west = Posn(0, -1)
-
-const initial_directions = [
- #(north, ["|", "7", "F"]),
- #(south, ["|", "J", "L"]),
- #(east, ["-", "J", "7"]),
- #(west, ["-", "F", "L"]),
-]
-
-fn pipe_neighbors(pipe: String) -> List(Posn) {
- case pipe {
- "|" -> [north, south]
- "-" -> [east, west]
- "L" -> [north, east]
- "F" -> [south, east]
- "7" -> [south, west]
- "J" -> [north, west]
- _ -> panic as "bad pipe"
- }
-}
-
-fn make_grid(input: String) -> PipeGrid {
- {
- use r, row <- list.index_map(string.split(input, "\n"))
- use c, col <- list.index_map(string.to_graphemes(row))
- #(Posn(r, c), col)
- }
- |> list.flatten
- |> dict.from_list
-}
-
-fn valid_start_direction(grid: PipeGrid, s: Posn) {
- let assert [dir, ..] = {
- use d <- list.filter_map(initial_directions)
- let #(delta, valids) = d
- let neighbor = add_posns(s, delta)
- case dict.get(grid, neighbor) {
- Ok(pipe) ->
- case list.contains(valids, pipe) {
- True -> Ok(neighbor)
- False -> Error(Nil)
- }
- Error(_) -> Error(Nil)
- }
- }
- dir
-}
-
-fn to_next_pipe(current: Posn, grid: PipeGrid, acc: List(Posn)) {
- let assert [prev, ..] = acc
- let assert Ok(pipe) = dict.get(grid, current)
- use <- bool.guard(pipe == "S", [current, ..acc])
- let assert [next] = {
- pipe
- |> pipe_neighbors
- |> list.filter_map(fn(p) {
- case add_posns(p, current) {
- neighbor if neighbor == prev -> Error(Nil)
- neighbor -> Ok(neighbor)
- }
- })
- }
- to_next_pipe(next, grid, [current, ..acc])
-}
-
-pub fn part1(input: String) {
- let grid =
- input
- |> make_grid
-
- let assert Ok(s) =
- grid
- |> dict.filter(fn(_, v) { v == "S" })
- |> dict.keys
- |> list.first
-
- grid
- |> valid_start_direction(s)
- |> to_next_pipe(grid, [s])
- |> list.length
- |> fn(i) { { { i - 1 } / 2 } }
- |> string.inspect
-}
-
-fn trace_ray(p: Posn, loop: Set(Posn), grid: PipeGrid) -> Bool {
- use <- bool.guard(set.contains(loop, p), False)
- int.is_odd(count_crossings(p, loop, grid, 0, ""))
-}
-
-fn count_crossings(
- p: Posn,
- loop: Set(Posn),
- grid: PipeGrid,
- acc: Int,
- corner: String,
-) {
- let maybe_cell = dict.get(grid, p)
- use <- bool.guard(maybe_cell == Error(Nil), acc)
- let assert Ok(cell) = maybe_cell
- let next = add_posns(p, east)
- case set.contains(loop, p) {
- False -> count_crossings(next, loop, grid, acc, corner)
- True ->
- case corner, cell {
- _, "|" -> count_crossings(next, loop, grid, acc + 1, corner)
- _, "F" | _, "L" -> count_crossings(next, loop, grid, acc, cell)
- "F", "J" | "L", "7" -> count_crossings(next, loop, grid, acc + 1, "")
- "F", "7" | "L", "J" -> count_crossings(next, loop, grid, acc, "")
- _, _ -> count_crossings(next, loop, grid, acc, corner)
- }
- }
-}
-
-pub fn part2(input: String) {
- let grid =
- input
- |> make_grid
-
- let assert Ok(s) =
- grid
- |> dict.filter(fn(_, v) { v == "S" })
- |> dict.keys
- |> list.first
-
- let loop_pipes =
- grid
- |> valid_start_direction(s)
- |> to_next_pipe(grid, [s])
- |> set.from_list
-
- grid
- |> dict.keys
- |> list.filter(trace_ray(_, loop_pipes, grid))
- |> list.length()
- |> string.inspect
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("10")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day11/.gitignore b/aoc2023/src/day11/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day11/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day11/solve.gleam b/aoc2023/src/day11/solve.gleam
deleted file mode 100644
index 35464a1..0000000
--- a/aoc2023/src/day11/solve.gleam
+++ /dev/null
@@ -1,84 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/int
-import gleam/string
-import gleam/list
-
-type Posn {
- Posn(x: Int, y: Int)
-}
-
-fn find_empty(grid: List(List(String))) {
- use acc, row, r <- list.index_fold(grid, [])
- case list.unique(row) {
- ["."] -> [r, ..acc]
- _ -> acc
- }
-}
-
-fn count_prior_empty_ranks(rank: Int, empty_ranks: List(Int)) -> Int {
- empty_ranks
- |> list.drop_while(fn(r_empty) { r_empty > rank })
- |> list.length
-}
-
-fn parse_with_expansion(input: String, expansion: Int) -> List(Posn) {
- let add = expansion - 1
- let grid =
- input
- |> string.split("\n")
- |> list.map(string.to_graphemes)
-
- let empty_row_list = find_empty(grid)
- let empty_col_list = find_empty(list.transpose(grid))
-
- {
- use r, row <- list.index_map(grid)
- use acc, cell, c <- list.index_fold(over: row, from: [])
-
- let p = Posn(r, c)
- let empty_r = count_prior_empty_ranks(r, empty_row_list)
- let empty_c = count_prior_empty_ranks(c, empty_col_list)
- case cell {
- "#" -> [Posn(p.x + empty_r * add, p.y + empty_c * add), ..acc]
- _empty -> acc
- }
- }
- |> list.flatten()
-}
-
-fn all_distances(stars: List(Posn)) -> Int {
- use acc, pair <- list.fold(list.combination_pairs(stars), 0)
- let #(s1, s2) = pair
- acc + int.absolute_value(s1.x - s2.x) + int.absolute_value(s1.y - s2.y)
-}
-
-fn find_distances(input: String, expand_by: Int) -> String {
- input
- |> parse_with_expansion(expand_by)
- |> all_distances
- |> string.inspect
-}
-
-pub fn part1(input: String) {
- find_distances(input, 2)
-}
-
-pub fn part2(input: String) {
- find_distances(input, 1_000_000)
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("11")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day12/.gitignore b/aoc2023/src/day12/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day12/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day12/solve.gleam b/aoc2023/src/day12/solve.gleam
deleted file mode 100644
index 893b83c..0000000
--- a/aoc2023/src/day12/solve.gleam
+++ /dev/null
@@ -1,90 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/string
-import gleam/list
-import gleam/int
-import gleam/result
-import utilities/memo.{type Cache}
-
-type ParserState =
- #(String, List(Int), Int, Bool)
-
-fn parse_folds(input: String, folds: Int) {
- let records = string.split(input, "\n")
- use record <- list.map(records)
- let assert Ok(#(template, sets_str)) = string.split_once(record, " ")
-
- let template =
- template
- |> list.repeat(folds)
- |> list.intersperse("?")
- |> string.concat
- let sets =
- sets_str
- |> string.split(",")
- |> list.map(int.parse)
- |> result.values
- |> list.repeat(folds)
- |> list.flatten()
-
- #(template, sets)
-}
-
-fn do_count(
- template: String,
- groups: List(Int),
- left: Int,
- gap: Bool,
- cache: Cache(ParserState, Int),
-) -> Int {
- use <- memo.memoize(cache, #(template, groups, left, gap))
- case template, groups, left, gap {
- "", [], 0, _ -> 1
- "?" <> t_rest, [g, ..g_rest], 0, False ->
- do_count(t_rest, g_rest, g - 1, g == 1, cache)
- + do_count(t_rest, groups, 0, False, cache)
- "?" <> t_rest, [], 0, False
- | "?" <> t_rest, _, 0, True
- | "." <> t_rest, _, 0, _ -> do_count(t_rest, groups, 0, False, cache)
- "#" <> t_rest, [g, ..g_rest], 0, False ->
- do_count(t_rest, g_rest, g - 1, g == 1, cache)
- "?" <> t_rest, gs, l, False | "#" <> t_rest, gs, l, False ->
- do_count(t_rest, gs, l - 1, l == 1, cache)
- _, _, _, _ -> 0
- }
-}
-
-fn count_solutions(acc: Int, condition: #(String, List(Int))) -> Int {
- use cache: Cache(ParserState, Int) <- memo.create()
- let #(template, groups) = condition
- acc + do_count(template, groups, 0, False, cache)
-}
-
-pub fn part1(input: String) {
- input
- |> parse_folds(1)
- |> list.fold(0, count_solutions)
- |> string.inspect
-}
-
-pub fn part2(input: String) {
- input
- |> parse_folds(5)
- |> list.fold(0, count_solutions)
- |> string.inspect
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("12")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day13/.gitignore b/aoc2023/src/day13/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day13/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day13/solve.gleam b/aoc2023/src/day13/solve.gleam
deleted file mode 100644
index 6f9b9a0..0000000
--- a/aoc2023/src/day13/solve.gleam
+++ /dev/null
@@ -1,87 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/list
-import gleam/string
-import gleam/bool
-
-type SymmetryType {
- Horizontal(Int)
- Vertical(Int)
-}
-
-fn is_symmetric(xss: List(List(a)), errs: Int) {
- let assert [left, ..right] = xss
- do_is_symmetric([left], right, errs)
-}
-
-fn do_is_symmetric(
- left: List(List(a)),
- right: List(List(a)),
- errors: Int,
-) -> Result(Int, Nil) {
- use <- bool.guard(list.is_empty(right), Error(Nil))
- let assert [h, ..t] = right
- let found_errors =
- list.zip(list.flatten(left), list.flatten(right))
- |> list.filter(fn(tup) { tup.1 != tup.0 })
- |> list.length
- case found_errors == errors {
- True -> Ok(list.length(left))
- False -> do_is_symmetric([h, ..left], t, errors)
- }
-}
-
-fn get_symmetry_type(xss: List(List(String)), errors: Int) {
- case is_symmetric(xss, errors) {
- Ok(n) -> Horizontal(n)
- _ -> {
- let assert Ok(n) = is_symmetric(list.transpose(xss), errors)
- Vertical(n)
- }
- }
-}
-
-fn summarize_notes(symmetries: List(SymmetryType)) {
- use acc, note <- list.fold(symmetries, 0)
- acc
- + case note {
- Horizontal(n) -> 100 * n
- Vertical(n) -> n
- }
-}
-
-fn solve(input: String, errors: Int) {
- input
- |> string.split("\n\n")
- |> list.map(fn(strs) {
- strs
- |> string.split("\n")
- |> list.map(string.to_graphemes)
- |> get_symmetry_type(errors)
- })
- |> summarize_notes
- |> string.inspect
-}
-
-pub fn part1(input: String) {
- solve(input, 0)
-}
-
-pub fn part2(input: String) {
- solve(input, 1)
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("13")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day14/.gitignore b/aoc2023/src/day14/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day14/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day14/solve.gleam b/aoc2023/src/day14/solve.gleam
deleted file mode 100644
index ecc5361..0000000
--- a/aoc2023/src/day14/solve.gleam
+++ /dev/null
@@ -1,94 +0,0 @@
-import adglent.{First, Second}
-import gleam/dict
-import gleam/int
-import gleam/io
-import gleam/list
-import gleam/order
-import gleam/string
-
-fn parse(input) {
- input
- |> string.split("\n")
- |> list.map(string.to_graphemes)
- |> list.transpose()
-}
-
-fn roll_boulders(strs: List(String)) {
- {
- use chunks <- list.map(list.chunk(strs, fn(c) { c == "O" || c == "." }))
- list.sort(chunks, order.reverse(string.compare))
- }
- |> list.flatten
-}
-
-fn score(matrix) {
- use acc, col <- list.fold(matrix, 0)
- acc
- + {
- use col_acc, char, n <- list.index_fold(list.reverse(col), 0)
- case char {
- "O" -> col_acc + n + 1
- _ -> col_acc
- }
- }
-}
-
-pub fn part1(input: String) {
- input
- |> parse
- |> list.map(roll_boulders)
- |> score()
- |> string.inspect
-}
-
-fn rotate(matrix) {
- matrix
- |> list.map(list.reverse)
- |> list.transpose
-}
-
-fn spin(matrix) {
- use acc, _ <- list.fold(list.range(1, 4), matrix)
- acc
- |> list.map(roll_boulders)
- |> rotate
-}
-
-fn spin_cycle(matrix) {
- let cache = dict.new()
- check_if_seen(matrix, cache, 1_000_000_000)
-}
-
-fn check_if_seen(matrix, cache, count) {
- case dict.get(cache, matrix) {
- Error(Nil) ->
- check_if_seen(spin(matrix), dict.insert(cache, matrix, count), count - 1)
- Ok(n) -> {
- let assert Ok(extra) = int.modulo(count, n - count)
- list.fold(list.range(1, extra), matrix, fn(acc, _) { spin(acc) })
- |> score
- }
- }
-}
-
-pub fn part2(input: String) {
- input
- |> parse
- |> spin_cycle
- |> string.inspect
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("14")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day15/.gitignore b/aoc2023/src/day15/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day15/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day15/solve.gleam b/aoc2023/src/day15/solve.gleam
deleted file mode 100644
index a7d250c..0000000
--- a/aoc2023/src/day15/solve.gleam
+++ /dev/null
@@ -1,104 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/string
-import gleam/list
-import gleam/int
-import gleam/dict.{type Dict}
-import gleam/option.{None, Some}
-
-fn split(input: String) -> List(String) {
- input
- |> string.split(",")
-}
-
-fn hash_algorithm(str: String) -> Int {
- let codepoints =
- str
- |> string.to_utf_codepoints()
- |> list.map(string.utf_codepoint_to_int)
- use acc, c <- list.fold(codepoints, 0)
- let assert Ok(acc) = int.modulo({ acc + c } * 17, 256)
- acc
-}
-
-pub fn part1(input: String) -> String {
- input
- |> split
- |> list.fold(0, fn(acc, str) { acc + hash_algorithm(str) })
- |> string.inspect
-}
-
-type Instruction {
- Remove(label: String)
- Insert(label: String, focal: Int)
-}
-
-fn read_instruction(str: String) -> Instruction {
- case string.split(str, "=") {
- [label, focal_str] -> {
- let assert Ok(focal) = int.parse(focal_str)
- Insert(label, focal)
- }
- _ -> Remove(string.drop_right(str, 1))
- }
-}
-
-fn parse_instructions(insts: List(String)) -> Dict(Int, List(#(String, Int))) {
- use acc, inst <- list.fold(insts, dict.new())
- case read_instruction(inst) {
- Remove(label) -> remove_lens(acc, label)
- Insert(label, focal) -> insert_lens(acc, label, focal)
- }
-}
-
-fn remove_lens(boxes, label) {
- use v <- dict.update(boxes, hash_algorithm(label))
- case v {
- Some(lenses) ->
- case list.key_pop(lenses, label) {
- Ok(#(_, updated)) -> updated
- Error(Nil) -> lenses
- }
- None -> []
- }
-}
-
-fn insert_lens(boxes, label, focal) {
- use v <- dict.update(boxes, hash_algorithm(label))
- case v {
- Some(lenses) -> list.key_set(lenses, label, focal)
- None -> [#(label, focal)]
- }
-}
-
-fn focusing_power(boxes: Dict(Int, List(#(String, Int)))) -> Int {
- use acc, k, v <- dict.fold(boxes, 0)
- let box_acc = {
- use acc, lens, i <- list.index_fold(v, 0)
- acc + lens.1 * { i + 1 }
- }
- acc + { k + 1 } * box_acc
-}
-
-pub fn part2(input: String) -> String {
- input
- |> split
- |> parse_instructions
- |> focusing_power
- |> string.inspect
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("15")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day16/.gitignore b/aoc2023/src/day16/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day16/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day16/solve.gleam b/aoc2023/src/day16/solve.gleam
deleted file mode 100644
index 65ce36b..0000000
--- a/aoc2023/src/day16/solve.gleam
+++ /dev/null
@@ -1,119 +0,0 @@
-import adglent.{First, Second}
-import gleam/bool
-import gleam/dict.{type Dict}
-import gleam/io
-import gleam/list
-import gleam/result
-import gleam/set.{type Set}
-import utilities/array2d.{type Posn, Posn}
-
-type Direction {
- Up
- Right
- Down
- Left
-}
-
-type Light {
- Light(posn: Posn, dir: Direction)
-}
-
-fn move(l: Light) -> Light {
- let Light(p, dir) = l
- case dir {
- Up -> Light(..l, posn: Posn(..p, r: p.r - 1))
- Down -> Light(..l, posn: Posn(..p, r: p.r + 1))
- Left -> Light(..l, posn: Posn(..p, c: p.c - 1))
- Right -> Light(..l, posn: Posn(..p, c: p.c + 1))
- }
-}
-
-fn transform(l: Light, cell: Result(String, Nil)) -> List(Light) {
- use <- bool.guard(result.is_error(cell), [])
- let assert Ok(c) = cell
- let Light(p, dir) = l
- case dir, c {
- // no change
- _, "." | Up, "|" | Down, "|" | Left, "-" | Right, "-" -> [l]
- // diagonal mirrors
- Left, "/" -> [Light(p, Down)]
- Down, "/" -> [Light(p, Left)]
- Right, "/" -> [Light(p, Up)]
- Up, "/" -> [Light(p, Right)]
- Left, "\\" -> [Light(p, Up)]
- Up, "\\" -> [Light(p, Left)]
- Right, "\\" -> [Light(p, Down)]
- Down, "\\" -> [Light(p, Right)]
- // splitters
- Left, "|" | Right, "|" -> [Light(p, Up), Light(p, Down)]
- Up, "-" | Down, "-" -> [Light(p, Left), Light(p, Right)]
- _, _ -> panic as "unrecognized cell type"
- }
-}
-
-fn energize(lights: List(Light), visited: Set(Light), grid: Dict(Posn, String)) {
- let next_positions =
- lights
- |> list.flat_map(fn(l) {
- let next = move(l)
- transform(next, dict.get(grid, next.posn))
- })
- |> list.filter(fn(l) { !set.contains(visited, l) })
- let all_visited = set.union(set.from_list(next_positions), visited)
- case visited == all_visited {
- True ->
- set.fold(visited, set.new(), fn(acc, l) { set.insert(acc, l.posn) })
- |> set.to_list
- |> list.length
- False -> energize(next_positions, all_visited, grid)
- }
-}
-
-pub fn part1(input: String) {
- let grid = array2d.parse_grid(input)
-
- [Light(Posn(0, -1), Right)]
- |> energize(set.new(), grid)
-}
-
-pub fn part2(input: String) {
- let grid = array2d.parse_grid(input)
-
- let Posn(rows, cols) = {
- use acc, p <- list.fold(dict.keys(grid), Posn(0, 0))
- case acc.r + acc.c > p.r + p.c {
- True -> acc
- False -> p
- }
- }
-
- let all_starts =
- list.concat([
- list.map(list.range(0, rows), fn(r) { Light(Posn(r, -1), Right) }),
- list.map(list.range(0, rows), fn(r) { Light(Posn(r, cols + 1), Left) }),
- list.map(list.range(0, cols), fn(c) { Light(Posn(-1, c), Down) }),
- list.map(list.range(0, cols), fn(c) { Light(Posn(rows + 1, c), Up) }),
- ])
-
- use acc, p <- list.fold(all_starts, 0)
- let energized = energize([p], set.new(), grid)
- case acc > energized {
- True -> acc
- False -> energized
- }
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("16")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day17/.gitignore b/aoc2023/src/day17/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day17/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day17/solve.gleam b/aoc2023/src/day17/solve.gleam
deleted file mode 100644
index 7a01c4d..0000000
--- a/aoc2023/src/day17/solve.gleam
+++ /dev/null
@@ -1,143 +0,0 @@
-import adglent.{First, Second}
-import gleam/bool
-import gleam/dict.{type Dict}
-import gleam/io
-import gleam/list
-import gleam/result
-import gleam/string
-import gleam/set.{type Set}
-import utilities/array2d.{type Posn, Posn}
-import utilities/prioqueue.{type PriorityQueue}
-
-type State {
- State(posn: Posn, heatloss: Int, previous: Posn, history: List(Posn))
-}
-
-const deltas = [Posn(-1, 0), Posn(1, 0), Posn(0, -1), Posn(0, 1)]
-
-fn make_key(s: State) {
- #(s.posn, same_dir(s))
-}
-
-fn same_dir(s: State) {
- case s.history {
- [] -> []
- [first, ..] as deltas ->
- list.take_while(deltas, fn(d) { d == first })
- |> list.take(10)
- }
-}
-
-fn is_goal(s: State, min_run: Int, goal: Posn) {
- goal == s.posn && list.length(same_dir(s)) >= min_run
-}
-
-fn find_good_neighbors(max: Int, min: Int, s: State, grid) {
- deltas
- |> list.filter(eliminate_bad_neighbors(_, s, max, min, grid))
- |> list.map(make_state(_, s, grid))
-}
-
-fn eliminate_bad_neighbors(d: Posn, s: State, max, min, grid) {
- let neighbor = array2d.add_posns(d, s.posn)
-
- use <- bool.guard(
- neighbor == s.previous || !dict.has_key(grid, neighbor),
- False,
- )
- case same_dir(s), list.length(same_dir(s)) {
- [prev, ..], l if l == max -> d != prev
- _, 0 -> True
- [prev, ..], l if l < min -> d == prev
- _, _ -> True
- }
-}
-
-fn make_state(d: Posn, s: State, grid) {
- let neighbor = array2d.add_posns(d, s.posn)
- let assert Ok(heat_lost) = dict.get(grid, neighbor)
- State(
- posn: neighbor,
- heatloss: s.heatloss + heat_lost,
- previous: s.posn,
- history: [d, ..s.history],
- )
-}
-
-fn find_path(
- grid: Dict(Posn, Int),
- queue: PriorityQueue(State),
- seen: Set(#(Posn, List(Posn))),
- get_neighbors: fn(State) -> List(State),
- is_goal: fn(State) -> Bool,
-) {
- let assert Ok(#(state, rest)) = prioqueue.pop(queue)
- let key =
- make_key(
- state
- |> io.debug,
- )
- case set.contains(seen, key) {
- True -> find_path(grid, rest, seen, get_neighbors, is_goal)
- False -> {
- let now_seen = set.insert(seen, key)
- let neighbors = get_neighbors(state)
- case list.find(neighbors, is_goal) {
- Ok(final) -> final.heatloss
- _err -> {
- let now_queue =
- list.fold(neighbors, rest, fn(acc, n) {
- prioqueue.insert(acc, n, n.heatloss)
- })
- find_path(grid, now_queue, now_seen, get_neighbors, is_goal)
- }
- }
- }
- }
-}
-
-pub fn part1(input: String) {
- let raw_grid =
- input
- |> array2d.to_list_of_lists
-
- let grid = array2d.to_2d_intarray(raw_grid)
-
- let rmax = list.length(raw_grid)
- let assert Ok(cmax) =
- raw_grid
- |> list.first
- |> result.map(list.length)
-
- let start = State(Posn(0, 0), 0, Posn(0, 0), [])
- let goal = Posn(rmax, cmax)
-
- find_path(
- grid,
- prioqueue.insert(prioqueue.new(), start, 0),
- set.new(),
- find_good_neighbors(0, 3, _, grid),
- is_goal(_, 1, goal),
- )
- |> string.inspect
-}
-
-pub fn part2(input: String) {
- input
- |> string.inspect
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("17")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day18/.gitignore b/aoc2023/src/day18/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day18/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day18/solve.gleam b/aoc2023/src/day18/solve.gleam
deleted file mode 100644
index 2c000f9..0000000
--- a/aoc2023/src/day18/solve.gleam
+++ /dev/null
@@ -1,113 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/int
-import gleam/list
-import gleam/option.{Some}
-import gleam/regex.{type Match, Match}
-import gleam/string
-
-type Coord {
- Coord(x: Int, y: Int)
-}
-
-type Direction {
- Up
- Right
- Down
- Left
-}
-
-type Dig {
- Dig(dir: Direction, dist: Int)
-}
-
-fn to_direction(c: String) {
- case c {
- "R" | "0" -> Right
- "D" | "1" -> Down
- "L" | "2" -> Left
- "U" | "3" -> Up
- _ -> panic
- }
-}
-
-fn parse_front(line: String) {
- let assert Ok(re) = regex.from_string("(.) (.*) \\(.*\\)")
- let assert [Match(submatches: [Some(dir), Some(dist)], ..)] =
- regex.scan(with: re, content: line)
- let assert Ok(n) = int.parse(dist)
- Dig(to_direction(dir), n)
-}
-
-fn parse_hex(line: String) {
- let assert Ok(re) = regex.from_string("\\(#(.....)(.)\\)")
- let assert [Match(submatches: [Some(dist), Some(dir)], ..)] =
- regex.scan(with: re, content: line)
- let assert Ok(n) = int.base_parse(dist, 16)
- Dig(to_direction(dir), n)
-}
-
-fn go(current: Coord, dig: Dig) {
- case dig {
- Dig(Up, n) -> Coord(current.x, current.y + n)
- Dig(Right, n) -> Coord(current.x + n, current.y)
- Dig(Down, n) -> Coord(current.x, current.y - n)
- Dig(Left, n) -> Coord(current.x - n, current.y)
- }
-}
-
-fn double_triangle(c1: Coord, c2: Coord) {
- { c1.x * c2.y } - { c2.x * c1.y }
-}
-
-fn start_dig(digs: List(Dig)) {
- do_next_dig(digs, Coord(0, 0), 0, 0)
-}
-
-fn do_next_dig(
- digs: List(Dig),
- current: Coord,
- area: Int,
- perimeter: Int,
-) -> Int {
- case digs {
- [] -> int.absolute_value(area) / 2 + { perimeter / 2 } + 1
- [dig, ..rest] -> {
- let next = go(current, dig)
- let area = area + double_triangle(current, next)
- let perimeter = perimeter + dig.dist
- do_next_dig(rest, next, area, perimeter)
- }
- }
-}
-
-fn solve_with(input, f) {
- input
- |> string.split("\n")
- |> list.map(f)
- |> start_dig
- |> string.inspect
-}
-
-pub fn part1(input: String) {
- solve_with(input, parse_front)
-}
-
-pub fn part2(input: String) {
- solve_with(input, parse_hex)
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("18")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day19/.gitignore b/aoc2023/src/day19/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day19/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day19/solve.gleam b/aoc2023/src/day19/solve.gleam
deleted file mode 100644
index 186e783..0000000
--- a/aoc2023/src/day19/solve.gleam
+++ /dev/null
@@ -1,255 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/string
-import gleam/dict.{type Dict}
-import gleam/order.{type Order, Gt, Lt}
-import gleam/regex.{type Match, Match}
-import gleam/list
-import gleam/option.{Some}
-import gleam/int
-
-type Rating {
- XtremelyCool
- Musical
- Aerodynamic
- Shiny
-}
-
-type Part {
- Part(x: Int, m: Int, a: Int, s: Int)
-}
-
-type Action {
- Accept
- Reject
- SendTo(String)
-}
-
-type Rule {
- If(rating: Rating, comparison: Order, threshold: Int, do: Action)
- Just(do: Action)
-}
-
-type Workflow =
- Dict(String, List(Rule))
-
-type Interval {
- Interval(min: Int, max: Int)
-}
-
-type PartRange {
- PartRange(x: Interval, m: Interval, a: Interval, s: Interval)
-}
-
-fn parse_workflow(input: String) -> Workflow {
- let assert Ok(re) = regex.from_string("(.*){(.*)}")
-
- use acc, line <- list.fold(string.split(input, "\n"), dict.new())
- let assert [Match(submatches: [Some(name), Some(all_rules)], ..)] =
- regex.scan(re, line)
- let rules =
- string.split(all_rules, ",")
- |> parse_rules
- dict.insert(acc, name, rules)
-}
-
-fn parse_rules(rules: List(String)) -> List(Rule) {
- let assert Ok(re_rule) = regex.from_string("(.*)(>|<)(.*):(.*)")
- use rule <- list.map(rules)
- case regex.scan(re_rule, rule) {
- [Match(submatches: [Some(r), Some(c), Some(t), Some(i)], ..)] ->
- If(to_rating(r), to_comp(c), to_val(t), to_instruction(i))
- _nomatch -> Just(to_instruction(rule))
- }
-}
-
-fn to_instruction(rule: String) {
- case rule {
- "A" -> Accept
- "R" -> Reject
- name -> SendTo(name)
- }
-}
-
-fn to_rating(rating: String) {
- case rating {
- "x" -> XtremelyCool
- "m" -> Musical
- "a" -> Aerodynamic
- _s -> Shiny
- }
-}
-
-fn get_rating(part: Part, rating: Rating) -> Int {
- case rating {
- XtremelyCool -> part.x
- Musical -> part.m
- Aerodynamic -> part.a
- Shiny -> part.s
- }
-}
-
-fn to_comp(comp: String) {
- case comp {
- "<" -> Lt
- _gt -> Gt
- }
-}
-
-fn to_val(val: String) {
- let assert Ok(n) = int.parse(val)
- n
-}
-
-fn parse_parts(input: String) -> List(Part) {
- let assert Ok(re) = regex.from_string("{x=(.*),m=(.*),a=(.*),s=(.*)}")
-
- use part <- list.map(string.split(input, "\n"))
- let assert [Match(submatches: [Some(x), Some(m), Some(a), Some(s)], ..)] =
- regex.scan(re, part)
- Part(to_val(x), to_val(m), to_val(a), to_val(s))
-}
-
-fn start_evaluating_workflow(part: Part, workflow: Workflow) -> Int {
- evaluate_workflow(part, "in", workflow)
-}
-
-fn evaluate_workflow(part: Part, name: String, workflow: Workflow) -> Int {
- let assert Ok(rules) = dict.get(workflow, name)
- case evaluate_rules(part, rules) {
- Accept -> part.x + part.m + part.a + part.s
- Reject -> 0
- SendTo(name) -> evaluate_workflow(part, name, workflow)
- }
-}
-
-fn evaluate_rules(part: Part, rules: List(Rule)) -> Action {
- case rules {
- [] -> panic
- [Just(do), ..] -> do
- [If(rating, comparison, threshold, do), ..rest] ->
- case int.compare(get_rating(part, rating), threshold) == comparison {
- True -> do
- False -> evaluate_rules(part, rest)
- }
- }
-}
-
-pub fn part1(input: String) {
- let assert Ok(#(workflows_str, parts_str)) = string.split_once(input, "\n\n")
-
- let workflows = parse_workflow(workflows_str)
- let parts = parse_parts(parts_str)
-
- list.map(parts, start_evaluating_workflow(_, workflows))
- |> int.sum
- |> string.inspect
-}
-
-fn size(interval: Interval) {
- interval.max - interval.min + 1
-}
-
-fn all_in_range(pr: PartRange) {
- size(pr.x) * size(pr.m) * size(pr.a) * size(pr.s)
-}
-
-fn get_partrange(pr: PartRange, rating: Rating) -> Interval {
- case rating {
- XtremelyCool -> pr.x
- Musical -> pr.m
- Aerodynamic -> pr.a
- Shiny -> pr.s
- }
-}
-
-fn update_partrange(pr: PartRange, rating: Rating, i: Interval) -> PartRange {
- case rating {
- XtremelyCool -> PartRange(..pr, x: i)
- Musical -> PartRange(..pr, m: i)
- Aerodynamic -> PartRange(..pr, a: i)
- Shiny -> PartRange(..pr, s: i)
- }
-}
-
-pub fn part2(input: String) {
- let assert Ok(#(workflows_str, _)) = string.split_once(input, "\n\n")
-
- let workflow = parse_workflow(workflows_str)
- let start = Interval(1, 4000)
-
- PartRange(start, start, start, start)
- |> evaluate_workflow_on_range("in", workflow)
- |> string.inspect
-}
-
-fn evaluate_workflow_on_range(
- pr: PartRange,
- name: String,
- workflow: Workflow,
-) -> Int {
- let assert Ok(rules) = dict.get(workflow, name)
- evaluate_rules_on_range(pr, rules, workflow)
-}
-
-fn evaluate_rules_on_range(
- pr: PartRange,
- rules: List(Rule),
- workflow: Workflow,
-) -> Int {
- case rules {
- [Just(Accept), ..] -> all_in_range(pr)
- [Just(Reject), ..] -> 0
- [Just(SendTo(name)), ..] -> evaluate_workflow_on_range(pr, name, workflow)
- [If(rating, comparison, t, action), ..rest] -> {
- let mod_i = get_partrange(pr, rating)
- case comparison {
- Lt ->
- split_range(
- keep: update_partrange(pr, rating, Interval(mod_i.min, t - 1)),
- and_do: action,
- pass: update_partrange(pr, rating, Interval(t, mod_i.max)),
- and_eval: rest,
- with: workflow,
- )
- _gt ->
- split_range(
- keep: update_partrange(pr, rating, Interval(t + 1, mod_i.max)),
- and_do: action,
- pass: update_partrange(pr, rating, Interval(mod_i.min, t)),
- and_eval: rest,
- with: workflow,
- )
- }
- }
- [] -> panic
- }
-}
-
-fn split_range(
- keep keep: PartRange,
- and_do action: Action,
- pass pass: PartRange,
- and_eval rest: List(Rule),
- with workflow: Workflow,
-) -> Int {
- int.add(
- evaluate_rules_on_range(keep, [Just(action)], workflow),
- evaluate_rules_on_range(pass, rest, workflow),
- )
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("19")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day2/.gitignore b/aoc2023/src/day2/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day2/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day2/solve.gleam b/aoc2023/src/day2/solve.gleam
deleted file mode 100644
index 608955f..0000000
--- a/aoc2023/src/day2/solve.gleam
+++ /dev/null
@@ -1,66 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/int
-import gleam/string
-import gleam/list
-
-pub type Game {
- Game(red: Int, blue: Int, green: Int)
-}
-
-fn parse(input: String) -> List(List(Game)) {
- use line <- list.map(string.split(input, "\n"))
- let assert [_, rounds] = string.split(line, on: ": ")
- use match <- list.map(string.split(rounds, on: "; "))
- use acc, draw <- list.fold(
- over: string.split(match, on: ", "),
- from: Game(0, 0, 0),
- )
- let assert Ok(#(n_str, color)) = string.split_once(draw, " ")
- let assert Ok(n) = int.parse(n_str)
- case color {
- "red" -> Game(..acc, red: n)
- "blue" -> Game(..acc, blue: n)
- "green" -> Game(..acc, green: n)
- _ -> panic as "unrecognized color"
- }
-}
-
-pub fn part1(input: String) {
- use acc, game, i <- list.index_fold(parse(input), 0)
- case list.any(game, fn(m) { m.red > 12 || m.green > 13 || m.blue > 14 }) {
- False -> acc + i + 1
- True -> acc
- }
-}
-
-pub fn part2(input: String) {
- {
- use game <- list.map(parse(input))
- use acc, match <- list.fold(game, Game(0, 0, 0))
- let Game(red: red, green: green, blue: blue) = match
- Game(
- red: int.max(red, acc.red),
- blue: int.max(blue, acc.blue),
- green: int.max(green, acc.green),
- )
- }
- |> list.fold(from: 0, with: fn(acc, g: Game) {
- acc + g.red * g.blue * g.green
- })
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("2")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day20/.gitignore b/aoc2023/src/day20/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day20/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day20/solve.gleam b/aoc2023/src/day20/solve.gleam
deleted file mode 100644
index 9192dac..0000000
--- a/aoc2023/src/day20/solve.gleam
+++ /dev/null
@@ -1,251 +0,0 @@
-import adglent.{First, Second}
-import gleam/bool
-import gleam/dict.{type Dict}
-import gleam/io
-import gleam/iterator.{type Iterator, type Step, Next}
-import gleam/list
-import gleam/queue.{type Queue}
-import gleam/set
-import gleam/string
-
-type Node {
- Broadcaster(children: List(String))
- Flipflop(children: List(String), state: Power)
- Conjunction(children: List(String), state: Dict(String, TonePitch))
- Ground
-}
-
-type Tone {
- Tone(from: String, to: String, pitch: TonePitch)
-}
-
-type Power {
- On
- Off
-}
-
-type TonePitch {
- Low
- High
-}
-
-type State {
- State(
- nodes: Dict(String, Node),
- low: Int,
- high: Int,
- cycle: Int,
- sentry_nodes: Dict(String, Int),
- )
-}
-
-fn flip_power(p: Power) -> Power {
- case p {
- On -> Off
- Off -> On
- }
-}
-
-fn flip_flop_pitch(p: Power) -> TonePitch {
- case p {
- Off -> High
- On -> Low
- }
-}
-
-fn combinator_pitch(state) {
- case list.unique(dict.values(state)) {
- [High] -> Low
- _ -> High
- }
-}
-
-fn get_children(node) {
- case node {
- Flipflop(children: cs, ..) -> cs
- Conjunction(children: cs, ..) -> cs
- Broadcaster(children: cs) -> cs
- Ground -> []
- }
-}
-
-fn parse_node(input: String) -> #(String, Node) {
- let assert [full_name, children_str] = string.split(input, on: " -> ")
- let children = string.split(children_str, on: ", ")
-
- case full_name {
- "%" <> name -> #(name, Flipflop(children: children, state: Off))
- "&" <> name -> #(name, Conjunction(children: children, state: dict.new()))
- "broadcaster" -> #("broadcaster", Broadcaster(children: children))
- name -> #(name, Ground)
- }
-}
-
-fn to_initial_state(nodes: List(#(String, Node))) -> Dict(String, Node) {
- let node_dict = dict.from_list(nodes)
- let node_names = dict.keys(node_dict)
-
- let node_dict =
- node_dict
- |> dict.values
- |> list.map(get_children)
- |> list.concat
- |> set.from_list
- |> set.drop(dict.keys(node_dict))
- |> set.to_list
- |> list.fold(node_dict, fn(acc, n) { dict.insert(acc, n, Ground) })
-
- use name, node <- dict.map_values(node_dict)
- case node {
- Conjunction(state: _, children: chs) ->
- node_names
- |> list.filter(fn(n) {
- let assert Ok(node) = dict.get(node_dict, n)
- list.contains(get_children(node), any: name)
- })
- |> list.map(fn(n) { #(n, Low) })
- |> dict.from_list()
- |> fn(dict) { Conjunction(state: dict, children: chs) }
- other -> other
- }
-}
-
-fn add_to_queue(from, children, pitch, queue) {
- use acc, c <- list.fold(children, queue)
- queue.push_back(acc, Tone(from: from, to: c, pitch: pitch))
-}
-
-fn add_tones(state: State, nodes, pitch, n) {
- case pitch {
- Low ->
- State(..state, nodes: nodes, low: state.low + n, cycle: state.cycle + 1)
- High ->
- State(..state, nodes: nodes, high: state.high + n, cycle: state.cycle + 1)
- }
-}
-
-fn press_button_once(initial: State, queue: Queue(Tone)) {
- let State(nodes: nodes, ..) = initial
-
- use <- bool.guard(queue.is_empty(queue), initial)
- let assert Ok(#(Tone(from_name, to_name, pitch), rest)) =
- queue.pop_front(queue)
-
- let assert Ok(to_node) = dict.get(nodes, to_name)
- case to_node {
- Broadcaster(children) -> {
- let new_state =
- add_tones(initial, nodes, pitch, list.length(children) + 1)
-
- let new_queue = add_to_queue(to_name, children, pitch, rest)
- press_button_once(new_state, new_queue)
- }
-
- Conjunction(state: state, children: children) -> {
- let new_state =
- state
- |> dict.insert(from_name, pitch)
-
- let updated_nodes =
- Conjunction(state: new_state, children: children)
- |> dict.insert(nodes, to_name, _)
-
- let pitch_out = combinator_pitch(new_state)
-
- let new_state =
- add_tones(initial, updated_nodes, pitch_out, list.length(children))
- |> check_for_interesting_node(from_name, pitch_out)
-
- add_to_queue(to_name, children, pitch_out, rest)
- |> press_button_once(new_state, _)
- }
-
- Flipflop(..) if pitch == High ->
- press_button_once(State(..initial, cycle: initial.cycle + 1), rest)
-
- Flipflop(state: state, children: children) -> {
- let updated_nodes =
- Flipflop(state: flip_power(state), children: children)
- |> dict.insert(nodes, to_name, _)
-
- let pitch_out = flip_flop_pitch(state)
- let new_state =
- add_tones(initial, updated_nodes, pitch_out, list.length(children))
-
- add_to_queue(to_name, children, flip_flop_pitch(state), rest)
- |> press_button_once(new_state, _)
- }
-
- Ground(..) ->
- press_button_once(State(..initial, cycle: initial.cycle + 1), rest)
- }
-}
-
-pub fn part1(input: String) {
- let initial_state =
- input
- |> string.split(on: "\n")
- |> list.map(parse_node)
- |> to_initial_state()
-
- iterator.iterate(
- from: State(initial_state, 0, 0, 1, dict.new()),
- with: press_button_once(_, queue.from_list([
- Tone("button", "broadcaster", Low),
- ])),
- )
- |> iterator.at(1000)
- |> fn(s) {
- let assert Ok(State(high: high, low: low, ..)) = s
- high * low
- }
- |> string.inspect
-}
-
-fn check_for_interesting_node(state, name, pitch_out) {
- case name, pitch_out {
- "rk", High | "cd", High | "zf", High | "qx", High ->
- State(
- ..state,
- sentry_nodes: dict.insert(state.sentry_nodes, name, state.cycle),
- )
- _, _ -> state
- }
-}
-
-pub fn part2(input: String) {
- let initial_state =
- input
- |> string.split(on: "\n")
- |> list.map(parse_node)
- |> to_initial_state()
-
- iterator.iterate(
- from: State(initial_state, 0, 0, 1, dict.new()),
- with: press_button_once(_, queue.from_list([
- Tone("button", "broadcaster", Low),
- ])),
- )
- |> iterator.drop_while(fn(s) { dict.size(s.sentry_nodes) < 4 })
- |> iterator.step
- |> fn(s: Step(State, Iterator(State))) {
- let assert Next(goal, _rest) = s
- goal.sentry_nodes
- }
- |> string.inspect
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("20")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day22/.gitignore b/aoc2023/src/day22/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day22/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day22/solve.gleam b/aoc2023/src/day22/solve.gleam
deleted file mode 100644
index 7bf2fb4..0000000
--- a/aoc2023/src/day22/solve.gleam
+++ /dev/null
@@ -1,199 +0,0 @@
-import adglent.{First, Second}
-import gleam/bool
-import gleam/dict.{type Dict}
-import gleam/int
-import gleam/io
-import gleam/list
-import gleam/option.{None, Some}
-import gleam/regex
-import gleam/result
-import gleam/set.{type Set}
-import gleam/string
-
-type Point {
- Point(x: Int, y: Int, z: Int)
-}
-
-fn down_one(p: Point) -> Point {
- Point(..p, z: p.z - 1)
-}
-
-type Block {
- Block(index: Int, from: Point, to: Point)
-}
-
-fn compare_blocks(b1: Block, b2: Block) {
- int.compare(b1.to.z, b2.to.z)
-}
-
-type Space =
- Dict(Point, Block)
-
-type AllBlocks =
- Dict(Block, List(Point))
-
-type BlockTree =
- Dict(Int, Set(Int))
-
-fn parse_block(index: Int, input: String) -> Block {
- let assert Ok(re) = regex.from_string("(.*),(.*),(.*)~(.*),(.*),(.*)")
-
- let assert [scan] = regex.scan(with: re, content: input)
-
- let assert [x1, y1, z1, x2, y2, z2] =
- scan.submatches
- |> option.all
- |> option.unwrap([])
- |> list.map(int.parse)
- |> result.values
- Block(index: index, from: Point(x1, y1, z1), to: Point(x2, y2, z2))
-}
-
-fn cross_section_at_level(b: Block, z: Int) -> List(Point) {
- use x <- list.flat_map(list.range(b.from.x, b.to.x))
- use y <- list.map(list.range(b.from.y, b.to.y))
- Point(x, y, z)
-}
-
-fn place_block(space: Space, b: Block, z: Int) -> Space {
- let now_occupied = {
- use x <- list.flat_map(list.range(b.from.x, b.to.x))
- use y <- list.flat_map(list.range(b.from.y, b.to.y))
- use z <- list.map(list.range(z, z + b.to.z - b.from.z))
- #(Point(x, y, z), b)
- }
-
- dict.merge(space, dict.from_list(now_occupied))
-}
-
-fn find_lowest_level(space: Space, b: Block) -> Space {
- do_find_lowest(space, b, b.from.z)
-}
-
-fn do_find_lowest(space: Space, b: Block, z: Int) -> Space {
- let is_intersecting =
- list.any(cross_section_at_level(b, z), dict.has_key(space, _))
-
- case z, is_intersecting {
- 0, _ -> place_block(space, b, 1)
- _, True -> place_block(space, b, z + 1)
- _, False -> do_find_lowest(space, b, z - 1)
- }
-}
-
-fn to_block_positions(space: Space) -> AllBlocks {
- use acc, point, index <- dict.fold(space, dict.new())
- use points <- dict.update(acc, index)
- case points {
- Some(ps) -> [point, ..ps]
- None -> [point]
- }
-}
-
-fn above_blocks(blocks: AllBlocks) -> BlockTree {
- use acc, block, points <- dict.fold(blocks, dict.new())
- use _ <- dict.update(acc, block.index)
- {
- use above_block, above_points <- dict.filter(blocks)
- above_block.index != block.index
- && list.any(above_points, fn(p) { list.contains(points, down_one(p)) })
- }
- |> dict.keys
- |> list.map(fn(b) { b.index })
- |> set.from_list
-}
-
-fn below_blocks(blocktree: BlockTree) -> BlockTree {
- use acc, block, _ <- dict.fold(blocktree, dict.new())
- use _ <- dict.update(acc, block)
- {
- use _, aboves <- dict.filter(blocktree)
- set.contains(aboves, block)
- }
- |> dict.keys
- |> set.from_list
-}
-
-fn vulnerable_blocks(below_tree: BlockTree) -> List(Int) {
- use block <- list.filter(dict.keys(below_tree))
- use bs <- list.any(dict.values(below_tree))
- !{ set.size(bs) == 0 } && { set.size(set.delete(bs, block)) == 0 }
-}
-
-pub fn part1(input: String) {
- let settled_blocks =
- input
- |> string.split("\n")
- |> list.index_map(parse_block)
- |> list.sort(compare_blocks)
- |> list.fold(dict.new(), find_lowest_level)
-
- let block_positions = to_block_positions(settled_blocks)
- let above_blocks = above_blocks(block_positions)
- let below_blocks = below_blocks(above_blocks)
-
- let vulnerable_blocks = vulnerable_blocks(below_blocks)
-
- list.length(dict.keys(block_positions)) - list.length(vulnerable_blocks)
-}
-
-fn all_falling_blocks(n: Int, above: BlockTree, below: BlockTree) {
- let starting_set = set.insert(set.new(), n)
- do_falling_blocks(starting_set, starting_set, above, below)
-}
-
-fn do_falling_blocks(
- fallen: Set(Int),
- blocks: Set(Int),
- above: BlockTree,
- below: BlockTree,
-) -> Int {
- use <- bool.guard(set.size(blocks) == 0, set.size(fallen) - 1)
-
- let blocks_above =
- {
- use block <- list.flat_map(set.to_list(blocks))
- let assert Ok(supports) = dict.get(above, block)
- use support <- list.filter(set.to_list(supports))
- let assert Ok(supportings) = dict.get(below, support)
- use supporting <- list.all(set.to_list(supportings))
- set.contains(fallen, supporting)
- }
- |> set.from_list()
-
- set.union(fallen, blocks_above)
- |> do_falling_blocks(blocks_above, above, below)
-}
-
-pub fn part2(input: String) {
- let settled_blocks =
- input
- |> string.split("\n")
- |> list.index_map(parse_block)
- |> list.sort(compare_blocks)
- |> list.fold(dict.new(), find_lowest_level)
-
- let block_positions = to_block_positions(settled_blocks)
- let above_blocks = above_blocks(block_positions)
- let below_blocks = below_blocks(above_blocks)
-
- let vulnerable_blocks = vulnerable_blocks(below_blocks)
-
- use acc, b <- list.fold(vulnerable_blocks, 0)
- acc + all_falling_blocks(b, above_blocks, below_blocks)
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("22")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day23/.gitignore b/aoc2023/src/day23/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day23/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day23/solve.gleam b/aoc2023/src/day23/solve.gleam
deleted file mode 100644
index e1fe638..0000000
--- a/aoc2023/src/day23/solve.gleam
+++ /dev/null
@@ -1,194 +0,0 @@
-import adglent.{First, Second}
-import gleam/int
-import gleam/io
-import gleam/dict.{type Dict}
-import gleam/list
-import gleam/option.{type Option, None, Some}
-import gleam/string
-import gleam/set.{type Set}
-import gleam/bool
-import utilities/array2d.{type Array2D, type Posn, Posn}
-
-type Path {
- Unknown
- Straight
- Junction
-}
-
-type Route {
- Route(to: Posn, distance: Int)
-}
-
-fn append_to_key(v: Option(List(a)), new: a) -> List(a) {
- case v {
- None -> [new]
- Some(xs) -> [new, ..xs]
- }
-}
-
-fn first_parse_path(c: String) -> Result(Path, Nil) {
- case c {
- "#" -> Error(Nil)
- _ -> Ok(Unknown)
- }
-}
-
-fn junction_neighbors(p: Posn) -> List(Posn) {
- [Posn(..p, r: p.r + 1), Posn(..p, c: p.c + 1)]
-}
-
-fn mark_junctions(trails: Array2D(Path)) -> Array2D(Path) {
- use trail, _ <- dict.map_values(trails)
-
- let valid_neighbors =
- trail
- |> array2d.ortho_neighbors
- |> list.filter(dict.has_key(trails, _))
-
- case list.length(valid_neighbors) {
- 2 -> Straight
- _ -> Junction
- }
-}
-
-fn start_walking_to_next_junction(
- start: Posn,
- next: Posn,
- trails: Array2D(Path),
-) {
- let seen =
- set.new()
- |> set.insert(start)
- |> set.insert(next)
- walk_to_next_junction(start, next, 1, seen, trails)
-}
-
-fn walk_to_next_junction(
- start: Posn,
- current: Posn,
- length: Int,
- seen: Set(Posn),
- trails: Array2D(Path),
-) -> #(Posn, Route) {
- let assert [next] =
- current
- |> array2d.ortho_neighbors
- |> list.filter(fn(n) { dict.has_key(trails, n) && !set.contains(seen, n) })
-
- case dict.get(trails, next) {
- Ok(Junction) -> #(start, Route(to: next, distance: length + 1))
- _ -> {
- let seen = set.insert(seen, current)
- walk_to_next_junction(start, next, { length + 1 }, seen, trails)
- }
- }
-}
-
-fn find_routes(junctions, trails) {
- use junction <- list.flat_map(junctions)
- use neighbor <- list.filter_map(junction_neighbors(junction))
- case dict.has_key(trails, neighbor) {
- True -> Ok(start_walking_to_next_junction(junction, neighbor, trails))
- False -> Error(Nil)
- }
-}
-
-fn generate_routes(
- junctions: List(Posn),
- trails: Array2D(Path),
-) -> Dict(Posn, List(Route)) {
- use acc, #(from, route) <- list.fold(
- find_routes(junctions, trails),
- dict.new(),
- )
- dict.update(acc, from, append_to_key(_, route))
-}
-
-fn generate_2way_routes(
- junctions: List(Posn),
- trails: Array2D(Path),
-) -> Dict(Posn, List(Route)) {
- use acc, #(from, route) <- list.fold(
- find_routes(junctions, trails),
- dict.new(),
- )
- acc
- |> dict.update(from, append_to_key(_, route))
- |> dict.update(route.to, append_to_key(_, Route(from, route.distance)))
-}
-
-fn dfs(routes, from, to) {
- let seen = set.insert(set.new(), from)
- do_dfs(routes, from, to, 0, seen)
-}
-
-fn do_dfs(
- routes: Dict(Posn, List(Route)),
- from: Posn,
- to: Posn,
- acc: Int,
- seen: Set(Posn),
-) -> Int {
- use <- bool.guard(to == from, acc)
-
- let assert Ok(all_routes) = dict.get(routes, from)
- let neighbors = list.filter(all_routes, fn(r) { !set.contains(seen, r.to) })
-
- case neighbors {
- [] -> 0
- neighbors ->
- list.fold(neighbors, acc, fn(inner_acc, n) {
- let score =
- do_dfs(routes, n.to, to, acc + n.distance, set.insert(seen, n.to))
- int.max(score, inner_acc)
- })
- }
-}
-
-fn solve_using(
- input: String,
- using: fn(List(Posn), Dict(Posn, Path)) -> Dict(Posn, List(Route)),
-) -> Int {
- let min_row = 0
- let max_row = list.length(string.split(input, "\n")) - 1
-
- let trails =
- input
- |> array2d.parse_grid_using(first_parse_path)
- |> mark_junctions
-
- let junctions =
- trails
- |> dict.filter(fn(_, v) { v == Junction })
- |> dict.keys
-
- let assert Ok(start) = list.find(junctions, fn(j) { j.r == min_row })
- let assert Ok(end) = list.find(junctions, fn(j) { j.r == max_row })
-
- let routes = using(junctions, trails)
-
- dfs(routes, start, end)
-}
-
-pub fn part1(input: String) {
- solve_using(input, generate_routes)
-}
-
-pub fn part2(input: String) {
- solve_using(input, generate_2way_routes)
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("23")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
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
- }
-}
diff --git a/aoc2023/src/day4/.gitignore b/aoc2023/src/day4/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day4/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day4/solve.gleam b/aoc2023/src/day4/solve.gleam
deleted file mode 100644
index 34d6098..0000000
--- a/aoc2023/src/day4/solve.gleam
+++ /dev/null
@@ -1,98 +0,0 @@
-import adglent.{First, Second}
-import gleam/bool
-import gleam/dict.{type Dict}
-import gleam/int
-import gleam/io
-import gleam/list
-import gleam/option.{None, Some}
-import gleam/result
-import gleam/set.{type Set}
-import gleam/string
-
-type Card {
- Card(number: Int, winners: Int)
-}
-
-fn numbers_to_set(str: String) -> Set(Int) {
- str
- |> string.split(" ")
- |> list.map(int.parse)
- |> result.values()
- |> set.from_list()
-}
-
-fn parse_card(card: String) -> Card {
- let assert Ok(#("Card" <> n_str, rest)) = string.split_once(card, ": ")
- let assert Ok(#(winning_str, has_str)) = string.split_once(rest, " | ")
- let assert Ok(n) = int.parse(string.trim(n_str))
-
- let winning = numbers_to_set(winning_str)
- let has = numbers_to_set(has_str)
- let winners = set.size(set.intersection(winning, has))
-
- Card(number: n, winners: winners)
-}
-
-fn win_points(n: Int) {
- bool.guard(n < 2, n, fn() { 2 * win_points(n - 1) })
-}
-
-pub fn part1(input: String) {
- use acc, c <- list.fold(string.split(input, "\n"), 0)
- c
- |> parse_card
- |> fn(c: Card) { win_points(c.winners) }
- |> int.add(acc)
-}
-
-fn win_more_cards(cards: List(String), count: Dict(Int, Int)) {
- case cards {
- [] ->
- count
- |> dict.values
- |> int.sum
- [raw_card, ..rest] -> {
- let card = parse_card(raw_card)
- case card.winners {
- 0 -> win_more_cards(rest, count)
- n -> win_more_cards(rest, update_counts(n, card, count))
- }
- }
- }
-}
-
-fn update_counts(n: Int, card: Card, count: Dict(Int, Int)) -> Dict(Int, Int) {
- let assert Ok(bonus) = dict.get(count, card.number)
- use acc, n <- list.fold(list.range(card.number + 1, card.number + n), count)
- use c <- dict.update(acc, n)
- case c {
- Some(i) -> i + bonus
- None -> panic as "won a card that doesn't exist in the card pile"
- }
-}
-
-pub fn part2(input: String) {
- let cards = string.split(input, "\n")
-
- let count =
- list.range(1, list.length(cards))
- |> list.map(fn(n) { #(n, 1) })
- |> dict.from_list()
-
- win_more_cards(cards, count)
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("4")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day5/.gitignore b/aoc2023/src/day5/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day5/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day5/solve.gleam b/aoc2023/src/day5/solve.gleam
deleted file mode 100644
index 7c05310..0000000
--- a/aoc2023/src/day5/solve.gleam
+++ /dev/null
@@ -1,162 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/string
-import gleam/result
-import gleam/list.{Continue, Stop}
-import gleam/int
-import gleam/function
-
-// Types -------------------------------------------------------------------------------------------
-
-pub type Almanac {
- Almanac(seeds: List(Int), mappers: List(Mapper))
-}
-
-pub type MappingRange {
- MRange(start: Int, end: Int, offset: Int)
-}
-
-pub type SeedRange {
- SRange(start: Int, end: Int)
-}
-
-type Mapper =
- List(MappingRange)
-
-// Parsing -----------------------------------------------------------------------------------------
-
-fn parse_input(input: String) {
- let assert ["seeds: " <> raw_seeds, ..raw_mappers] =
- string.split(input, on: "\n\n")
-
- let seeds = string_to_int_list(raw_seeds)
- let mappers =
- list.map(
- raw_mappers,
- function.compose(string.split(_, on: "\n"), parse_mapper),
- )
- Almanac(seeds, mappers)
-}
-
-fn string_to_int_list(str: String) {
- str
- |> string.split(on: " ")
- |> list.map(int.parse)
- |> result.values
-}
-
-fn parse_mapper(strs: List(String)) -> Mapper {
- let assert [_, ..raw_ranges] = strs
- list.map(raw_ranges, parse_mrange)
- |> list.sort(fn(a, b) { int.compare(a.start, b.start) })
-}
-
-fn parse_mrange(str: String) -> MappingRange {
- let assert [destination, source, range_width] = string_to_int_list(str)
- MRange(source, source + range_width - 1, destination - source)
-}
-
-// Part 1 ------------------------------------------------------------------------------------------
-
-pub fn part1(input: String) {
- let Almanac(seeds, mappers) = parse_input(input)
-
- list.map(seeds, list.fold(over: mappers, from: _, with: correspond))
- |> list.reduce(int.min)
- |> result.unwrap(0)
- |> string.inspect
-}
-
-fn correspond(n: Int, mapper: Mapper) {
- use acc, mrange <- list.fold_until(over: mapper, from: n)
- case mrange.start <= acc && acc <= mrange.end {
- True -> Stop(acc + mrange.offset)
- False -> Continue(acc)
- }
-}
-
-// Part 2 ------------------------------------------------------------------------------------------
-
-pub fn part2(input: String) {
- let Almanac(seeds, mappers) = parse_input(input)
-
- let assert [SRange(answer, _), ..] =
- seeds
- |> list.sized_chunk(into: 2)
- |> list.map(fn(chunk) {
- let assert [start, length] = chunk
- [SRange(start, start + length - 1)]
- |> remap_all_seed_ranges(mappers)
- })
- |> list.flatten()
- |> list.sort(fn(a, b) { int.compare(a.start, b.start) })
-
- string.inspect(answer)
-}
-
-fn remap_all_seed_ranges(srs: List(SeedRange), mappers: List(Mapper)) {
- case mappers {
- [] -> srs
- [mapper, ..rest] ->
- list.flat_map(srs, remap_range(_, mapper))
- |> remap_all_seed_ranges(rest)
- }
-}
-
-fn remap_range(r: SeedRange, mapper: Mapper) -> List(SeedRange) {
- do_remap_range(r, mapper, [])
-}
-
-fn transform_range(r: SeedRange, mapper: MappingRange) -> SeedRange {
- SRange(r.start + mapper.offset, r.end + mapper.offset)
-}
-
-fn do_remap_range(r: SeedRange, mapper: Mapper, acc: List(SeedRange)) {
- case mapper {
- // no more mappings -> no mapping covers this range
- [] -> [r, ..acc]
- // range is to the left of current mapping -> no mapping covers this range
- [m, ..] if r.end < m.start -> [r, ..acc]
- // range is to the right of current mapping -> move to next mapping
- [m, ..ms] if r.start > m.end -> do_remap_range(r, ms, acc)
- // range is fully inside mapping -> range is transformed
- [m, ..] if r.start >= m.start && r.end <= m.end -> [
- transform_range(r, m),
- ..acc
- ]
- // range overlaps start but not end -> left side not transformed, right side transformed
- [m, ..] if r.start < m.start && r.end <= m.end -> [
- SRange(r.start, m.start - 1),
- transform_range(SRange(m.start, r.end), m),
- ..acc
- ]
- // range overlaps end but not start -> left side transformed, right side moves to next mapping
- [m, ..ms] if r.start >= m.start && r.end > m.end ->
- do_remap_range(SRange(m.end + 1, r.end), ms, [
- transform_range(SRange(r.start, m.end), m),
- ..acc
- ])
- // mapping is fully inside range -> left not transformed, middle transformed, right to next
- [m, ..ms] ->
- do_remap_range(SRange(m.end + 1, r.end), ms, [
- SRange(r.start, m.start - 1),
- transform_range(SRange(m.start, m.end), m),
- ..acc
- ])
- }
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("5")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day6/.gitignore b/aoc2023/src/day6/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day6/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day6/solve.gleam b/aoc2023/src/day6/solve.gleam
deleted file mode 100644
index 88044c4..0000000
--- a/aoc2023/src/day6/solve.gleam
+++ /dev/null
@@ -1,85 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/string
-import gleam/int
-import gleam/list
-import gleam/result
-
-type Race {
- Race(time: Int, distance: Int)
-}
-
-fn parse_with_bad_kerning(input: String) {
- input
- |> string.split("\n")
- |> list.map(fn(str) {
- str
- |> string.split(" ")
- |> list.map(int.parse)
- |> result.values
- })
- |> list.transpose
- |> list.map(fn(ns) {
- let assert [t, d] = ns
- Race(t, d)
- })
-}
-
-fn find_bound(race: Race, button_time: Int, step: Int) {
- let travel_time = race.time - button_time
- case button_time * travel_time > race.distance {
- True -> button_time
- False -> find_bound(race, button_time + step, step)
- }
-}
-
-fn lower_bound(race: Race) {
- find_bound(race, 1, 1)
-}
-
-fn upper_bound(race: Race) {
- find_bound(race, race.time, -1)
-}
-
-pub fn part1(input: String) {
- {
- use acc, race <- list.fold(parse_with_bad_kerning(input), 1)
- acc * { upper_bound(race) - lower_bound(race) + 1 }
- }
- |> string.inspect
-}
-
-fn parse_properly(input: String) {
- input
- |> string.replace(" ", "")
- |> string.split("\n")
- |> list.flat_map(string.split(_, ":"))
- |> list.map(int.parse)
- |> result.values
-}
-
-pub fn part2(input: String) {
- let assert [time, distance] =
- input
- |> parse_properly
-
- let race = Race(time, distance)
-
- upper_bound(race) - lower_bound(race) + 1
- |> string.inspect
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("6")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day7/.gitignore b/aoc2023/src/day7/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day7/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day7/solve.gleam b/aoc2023/src/day7/solve.gleam
deleted file mode 100644
index 4454883..0000000
--- a/aoc2023/src/day7/solve.gleam
+++ /dev/null
@@ -1,140 +0,0 @@
-import adglent.{First, Second}
-import gleam/bool
-import gleam/function
-import gleam/int
-import gleam/io
-import gleam/list
-import gleam/order.{type Order, Eq, Lt}
-import gleam/string
-
-// Types -------------------------------------------------------------------------------------------
-
-type Hand {
- Hand(cards: List(Int), wager: Int)
-}
-
-// Common functions --------------------------------------------------------------------------------
-
-fn parse_hand(str: String) -> Hand {
- let assert [cards, wager] = string.split(str, " ")
- let cards =
- string.to_graphemes(cards)
- |> list.map(card_rank)
- let assert Ok(wager) = int.parse(wager)
-
- Hand(cards, wager)
-}
-
-fn classify_hand(hand: Hand) -> Int {
- case list.length(list.unique(hand.cards)), card_counts(hand) {
- 1, _ -> 8
- 2, [1, 4] -> 7
- 2, [2, 3] -> 6
- 3, [1, 1, 3] -> 5
- 3, [1, 2, 2] -> 4
- 4, _ -> 3
- 5, _ -> 2
- _, _ -> 1
- }
-}
-
-fn card_counts(hand: Hand) {
- hand.cards
- |> list.sort(int.compare)
- |> list.chunk(function.identity)
- |> list.map(list.length)
- |> list.sort(int.compare)
-}
-
-fn card_rank(card: String) -> Int {
- case int.parse(card), card {
- Ok(n), _ -> n
- _, "A" -> 14
- _, "K" -> 13
- _, "Q" -> 12
- _, "J" -> 11
- _, "T" -> 10
- _, _ -> 1
- }
-}
-
-fn compare_hands(hand1: Hand, hand2: Hand, using: fn(Hand) -> Int) -> Order {
- case int.compare(using(hand1), using(hand2)) {
- Eq -> compare_top_card(hand1.cards, hand2.cards)
- other -> other
- }
-}
-
-fn compare_top_card(cards1: List(Int), cards2: List(Int)) -> Order {
- use <- bool.guard(cards1 == [] || cards2 == [], Eq)
- let assert [c1, ..rest1] = cards1
- let assert [c2, ..rest2] = cards2
- case int.compare(c1, c2) {
- Eq -> compare_top_card(rest1, rest2)
- other -> other
- }
-}
-
-fn part(input: String, comparator: fn(Hand, Hand) -> Order) {
- input
- |> string.split("\n")
- |> list.map(parse_hand)
- |> list.sort(comparator)
- |> list.index_map(fn(i, h) { { i + 1 } * h.wager })
- |> int.sum
- |> string.inspect
-}
-
-// Part 1 ------------------------------------------------------------------------------------------
-
-pub fn part1(input: String) {
- part(input, compare_without_wilds)
-}
-
-fn compare_without_wilds(hand1: Hand, hand2: Hand) {
- compare_hands(hand1, hand2, classify_hand)
-}
-
-// Part 2 ------------------------------------------------------------------------------------------
-
-pub fn part2(input: String) {
- part(string.replace(input, "J", "*"), compare_hands_considering_jokers)
-}
-
-fn find_best_joker_substitution(hand: Hand) {
- use acc, card <- list.fold(list.range(2, 14), Hand([], 0))
- let subbed_cards = {
- use c <- list.map(hand.cards)
- case c {
- 1 -> card
- other -> other
- }
- }
- let subbed_hand = Hand(..hand, cards: subbed_cards)
- case compare_hands(acc, subbed_hand, classify_hand) {
- Lt -> subbed_hand
- _ -> acc
- }
-}
-
-fn compare_hands_considering_jokers(hand1: Hand, hand2: Hand) -> Order {
- use hand <- compare_hands(hand1, hand2)
- hand
- |> find_best_joker_substitution
- |> classify_hand
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("7")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day8/.gitignore b/aoc2023/src/day8/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day8/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day8/solve.gleam b/aoc2023/src/day8/solve.gleam
deleted file mode 100644
index 6b36e2d..0000000
--- a/aoc2023/src/day8/solve.gleam
+++ /dev/null
@@ -1,91 +0,0 @@
-import adglent.{First, Second}
-import gleam/bool
-import gleam/dict.{type Dict}
-import gleam/io
-import gleam/iterator.{type Iterator, Next}
-import gleam/list
-import gleam/option.{Some}
-import gleam/string
-import gleam/regex.{type Match, Match}
-import gleam_community/maths/arithmetics
-
-type Paths {
- Paths(to_left: String, to_right: String)
-}
-
-type Maze =
- Dict(String, Paths)
-
-fn parse(input: String) -> #(Iterator(String), Dict(String, Paths)) {
- let assert [directions_str, maze_str] = string.split(input, "\n\n")
-
- let directions =
- directions_str
- |> string.to_graphemes()
- |> iterator.from_list
- |> iterator.cycle
-
- let assert Ok(re) = regex.from_string("(...) = \\((...), (...)\\)")
- let maze =
- maze_str
- |> string.split("\n")
- |> list.map(fn(str) {
- let assert [Match(submatches: [Some(name), Some(left), Some(right)], ..)] =
- regex.scan(re, str)
- #(name, Paths(left, right))
- })
- |> dict.from_list
-
- #(directions, maze)
-}
-
-fn to_next_step(
- current: String,
- stop_at: String,
- count: Int,
- directions: Iterator(String),
- maze: Maze,
-) -> Int {
- use <- bool.guard(string.ends_with(current, stop_at), count)
- let assert Next(next_direction, rest_directions) = iterator.step(directions)
- let assert Ok(paths) = dict.get(maze, current)
- case next_direction {
- "L" -> paths.to_left
- "R" -> paths.to_right
- _ -> panic as "bad direction"
- }
- |> to_next_step(stop_at, count + 1, rest_directions, maze)
-}
-
-pub fn part1(input: String) -> Int {
- let #(directions, maze) = parse(input)
-
- to_next_step("AAA", "ZZZ", 0, directions, maze)
-}
-
-pub fn part2(input: String) -> Int {
- let #(directions, maze) = parse(input)
-
- use acc, name <- list.fold(dict.keys(maze), 1)
- case string.ends_with(name, "A") {
- False -> acc
- True ->
- to_next_step(name, "Z", 0, directions, maze)
- |> arithmetics.lcm(acc)
- }
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("8")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/day9/.gitignore b/aoc2023/src/day9/.gitignore
deleted file mode 100644
index ae40cea..0000000
--- a/aoc2023/src/day9/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-input.txt \ No newline at end of file
diff --git a/aoc2023/src/day9/solve.gleam b/aoc2023/src/day9/solve.gleam
deleted file mode 100644
index a2cc7ae..0000000
--- a/aoc2023/src/day9/solve.gleam
+++ /dev/null
@@ -1,70 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/list
-import gleam/string
-import gleam/int
-
-fn parse(input: String, backwards backwards: Bool) -> List(List(Int)) {
- use line <- list.map(string.split(input, "\n"))
- use n_str <- list.map(maybe_backwards(string.split(line, " "), backwards))
- let assert Ok(n) = int.parse(n_str)
- n
-}
-
-fn maybe_backwards(xs: List(a), backwards: Bool) -> List(a) {
- case backwards {
- False -> list.reverse(xs)
- True -> xs
- }
-}
-
-fn is_constant(ns: List(Int)) -> Bool {
- case list.unique(ns) {
- [_] -> True
- _ -> False
- }
-}
-
-fn take_derivative(ns: List(Int)) -> List(Int) {
- ns
- |> list.window_by_2
- |> list.map(fn(tup) { tup.0 - tup.1 })
-}
-
-fn extrapolate(ns: List(Int)) {
- case is_constant(ns), ns {
- True, [n, ..] -> n
- False, [n, ..] -> n + extrapolate(take_derivative(ns))
- _, _ -> panic as "list empty when it shouldn't be"
- }
-}
-
-fn part(input: String, backwards backwards: Bool) {
- input
- |> parse(backwards: backwards)
- |> list.fold(0, fn(acc, ns) { extrapolate(ns) + acc })
- |> string.inspect
-}
-
-pub fn part1(input: String) {
- part(input, backwards: False)
-}
-
-pub fn part2(input: String) {
- part(input, backwards: True)
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("9")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}
diff --git a/aoc2023/src/utilities/array2d.gleam b/aoc2023/src/utilities/array2d.gleam
deleted file mode 100644
index 8538129..0000000
--- a/aoc2023/src/utilities/array2d.gleam
+++ /dev/null
@@ -1,74 +0,0 @@
-import gleam/list
-import gleam/dict.{type Dict}
-import gleam/string
-import gleam/int
-import gleam/result
-
-pub type Posn {
- Posn(r: Int, c: Int)
-}
-
-pub type Array2D(a) =
- Dict(Posn, a)
-
-pub fn add_posns(p1: Posn, p2: Posn) -> Posn {
- case p1, p2 {
- Posn(r1, c1), Posn(r2, c2) -> Posn(r1 + r2, c1 + c2)
- }
-}
-
-pub fn ortho_neighbors(p: Posn) -> List(Posn) {
- let Posn(r, c) = p
- [Posn(r + 1, c), Posn(r - 1, c), Posn(r, c + 1), Posn(r, c - 1)]
-}
-
-pub fn to_2d_array(xss: List(List(a))) -> Array2D(a) {
- to_2d_array_using(xss, fn(x) { Ok(x) })
-}
-
-pub fn to_2d_array_using(
- xss: List(List(a)),
- f: fn(a) -> Result(b, Nil),
-) -> Array2D(b) {
- {
- use r, row <- list.index_map(xss)
- use c, cell <- list.index_map(row)
- case f(cell) {
- Ok(contents) -> Ok(#(Posn(r, c), contents))
- Error(Nil) -> Error(Nil)
- }
- }
- |> list.flatten
- |> result.values
- |> dict.from_list
-}
-
-pub fn to_2d_intarray(xss: List(List(String))) -> Array2D(Int) {
- {
- use r, row <- list.index_map(xss)
- use c, cell <- list.index_map(row)
- let assert Ok(n) = int.parse(cell)
- #(Posn(r, c), n)
- }
- |> list.flatten
- |> dict.from_list
-}
-
-pub fn to_list_of_lists(str: String) -> List(List(String)) {
- str
- |> string.split("\n")
- |> list.map(string.to_graphemes)
-}
-
-pub fn parse_grid(str: String) -> Array2D(String) {
- parse_grid_using(str, fn(x) { Ok(x) })
-}
-
-pub fn parse_grid_using(
- str: String,
- f: fn(String) -> Result(a, Nil),
-) -> Array2D(a) {
- str
- |> to_list_of_lists
- |> to_2d_array_using(f)
-}
diff --git a/aoc2023/src/utilities/memo.gleam b/aoc2023/src/utilities/memo.gleam
deleted file mode 100644
index b06d8fd..0000000
--- a/aoc2023/src/utilities/memo.gleam
+++ /dev/null
@@ -1,57 +0,0 @@
-import gleam/dict.{type Dict}
-import gleam/otp/actor.{type Next, Continue, Stop}
-import gleam/erlang/process.{type Subject, Normal}
-import gleam/option.{None}
-
-const timeout = 1000
-
-type Message(k, v) {
- Shutdown
- Get(key: k, client: Subject(Result(v, Nil)))
- Set(key: k, value: v)
-}
-
-type Server(k, v) =
- Subject(Message(k, v))
-
-pub opaque type Cache(k, v) {
- Cache(server: Server(k, v))
-}
-
-fn handle_message(
- message: Message(k, v),
- dict: Dict(k, v),
-) -> Next(Message(k, v), Dict(k, v)) {
- case message {
- Shutdown -> Stop(Normal)
- Get(key, client) -> {
- process.send(client, dict.get(dict, key))
- Continue(dict, None)
- }
- Set(key, value) -> Continue(dict.insert(dict, key, value), None)
- }
-}
-
-pub fn create(apply fun: fn(Cache(k, v)) -> t) -> t {
- let assert Ok(server) = actor.start(dict.new(), handle_message)
- let result = fun(Cache(server))
- process.send(server, Shutdown)
- result
-}
-
-pub fn set(in cache: Cache(k, v), for key: k, insert value: v) -> Nil {
- process.send(cache.server, Set(key, value))
-}
-
-pub fn get(from cache: Cache(k, v), fetch key: k) -> Result(v, Nil) {
- process.call(cache.server, fn(c) { Get(key, c) }, timeout)
-}
-
-pub fn memoize(with cache: Cache(k, v), this key: k, apply fun: fn() -> v) -> v {
- let result = case get(from: cache, fetch: key) {
- Ok(value) -> value
- Error(Nil) -> fun()
- }
- set(in: cache, for: key, insert: result)
- result
-}
diff --git a/aoc2023/src/utilities/prioqueue.gleam b/aoc2023/src/utilities/prioqueue.gleam
deleted file mode 100644
index abf21b9..0000000
--- a/aoc2023/src/utilities/prioqueue.gleam
+++ /dev/null
@@ -1,64 +0,0 @@
-//adapted from https://github.com/byronanderson/adventofcode2021/blob/main/gleam_advent/src/priority_queue.gleam
-
-import gleam/dict.{type Dict}
-
-type Ref
-
-@external(erlang, "erlang", "make_ref")
-fn make_ref() -> Ref
-
-type PQueue(a)
-
-pub opaque type PriorityQueue(a) {
- PriorityQueue(queue: PQueue(#(a, Ref)), refs: Dict(a, Ref))
-}
-
-type OutResult(a) {
- Empty
- Value(a, Int)
-}
-
-@external(erlang, "pqueue2", "new")
-fn new_() -> PQueue(a)
-
-@external(erlang, "pqueue2", "in")
-fn insert_(item: a, prio: Int, queue: PQueue(a)) -> PQueue(a)
-
-@external(erlang, "pqueue2", "pout")
-fn pop_(queue: PQueue(a)) -> #(OutResult(a), PQueue(a))
-
-pub fn new() -> PriorityQueue(a) {
- PriorityQueue(queue: new_(), refs: dict.new())
-}
-
-pub fn insert(
- queue: PriorityQueue(a),
- value: a,
- priority: Int,
-) -> PriorityQueue(a) {
- let ref = make_ref()
-
- let refs =
- queue.refs
- |> dict.insert(value, ref)
-
- PriorityQueue(
- refs: refs,
- queue: insert_(#(value, ref), priority, queue.queue),
- )
-}
-
-pub fn pop(queue: PriorityQueue(a)) -> Result(#(a, PriorityQueue(a)), Nil) {
- case pop_(queue.queue) {
- #(Value(#(value, ref), _priority), pqueue) -> {
- let assert Ok(recently_enqueued_ref) = dict.get(queue.refs, value)
- case recently_enqueued_ref == ref {
- True -> Ok(#(value, PriorityQueue(refs: queue.refs, queue: pqueue)))
- False -> pop(PriorityQueue(refs: queue.refs, queue: pqueue))
- }
- }
- #(Empty, _pqueue) -> {
- Error(Nil)
- }
- }
-}
diff --git a/aoc2023/test/aoc2023_test.gleam b/aoc2023/test/aoc2023_test.gleam
deleted file mode 100644
index 2b696a4..0000000
--- a/aoc2023/test/aoc2023_test.gleam
+++ /dev/null
@@ -1,5 +0,0 @@
-import showtime
-
-pub fn main() {
- showtime.main()
-}
diff --git a/aoc2023/test/day1/day1_test.gleam b/aoc2023/test/day1/day1_test.gleam
deleted file mode 100644
index 374653c..0000000
--- a/aoc2023/test/day1/day1_test.gleam
+++ /dev/null
@@ -1,57 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day1/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "1abc2
-pqr3stu8vwx
-a1b2c3d4e5f
-treb7uchet",
- "142",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "two1nine
-eightwothree
-abcone2threexyz
-xtwone3four
-4nineeightseven2
-zoneight234
-7pqrstsixteen",
- "281",
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day10/day10_test.gleam b/aoc2023/test/day10/day10_test.gleam
deleted file mode 100644
index be9d82e..0000000
--- a/aoc2023/test/day10/day10_test.gleam
+++ /dev/null
@@ -1,60 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day10/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "7-F7-
-.FJ|7
-SJLL7
-|F--J
-LJ.LJ",
- "8",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "...........
-.S-------7.
-.|F-----7|.
-.||OOOOO||.
-.||OOOOO||.
-.|L-7OF-J|.
-.|II|O|II|.
-.L--JOL--J.
-.....O.....",
- "4",
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day11/day11_test.gleam b/aoc2023/test/day11/day11_test.gleam
deleted file mode 100644
index 8bb8c06..0000000
--- a/aoc2023/test/day11/day11_test.gleam
+++ /dev/null
@@ -1,66 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day11/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "...#......
-.......#..
-#.........
-..........
-......#...
-.#........
-.........#
-..........
-.......#..
-#...#.....",
- "374",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "...#......
-.......#..
-#.........
-..........
-......#...
-.#........
-.........#
-..........
-.......#..
-#...#.....",
- "8410",
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day12/day12_test.gleam b/aoc2023/test/day12/day12_test.gleam
deleted file mode 100644
index 3daf0e9..0000000
--- a/aoc2023/test/day12/day12_test.gleam
+++ /dev/null
@@ -1,48 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day12/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "???.### 1,1,3
-.??..??...?##. 1,1,3
-?#?#?#?#?#?#?#? 1,3,1,6
-????.#...#... 4,1,1
-????.######..#####. 1,6,5
-?###???????? 3,2,1",
- "21",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = []
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day13/day13_test.gleam b/aoc2023/test/day13/day13_test.gleam
deleted file mode 100644
index 7c65bed..0000000
--- a/aoc2023/test/day13/day13_test.gleam
+++ /dev/null
@@ -1,76 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day13/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "#.##..##.
-..#.##.#.
-##......#
-##......#
-..#.##.#.
-..##..##.
-#.#.##.#.
-
-#...##..#
-#....#..#
-..##..###
-#####.##.
-#####.##.
-..##..###
-#....#..#",
- "405",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "#.##..##.
-..#.##.#.
-##......#
-##......#
-..#.##.#.
-..##..##.
-#.#.##.#.
-
-#...##..#
-#....#..#
-..##..###
-#####.##.
-#####.##.
-..##..###
-#....#..#",
- "400",
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day14/day14_test.gleam b/aoc2023/test/day14/day14_test.gleam
deleted file mode 100644
index 8efa74e..0000000
--- a/aoc2023/test/day14/day14_test.gleam
+++ /dev/null
@@ -1,66 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day14/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "O....#....
-O.OO#....#
-.....##...
-OO.#O....O
-.O.....O#.
-O.#..O.#.#
-..O..#O..O
-.......O..
-#....###..
-#OO..#....",
- "136",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "O....#....
-O.OO#....#
-.....##...
-OO.#O....O
-.O.....O#.
-O.#..O.#.#
-..O..#O..O
-.......O..
-#....###..
-#OO..#....",
- "64",
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day15/day15_test.gleam b/aoc2023/test/day15/day15_test.gleam
deleted file mode 100644
index 0ecaecc..0000000
--- a/aoc2023/test/day15/day15_test.gleam
+++ /dev/null
@@ -1,42 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day15/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7", "1320"),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7", "145"),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day16/day16_test.gleam b/aoc2023/test/day16/day16_test.gleam
deleted file mode 100644
index 036504e..0000000
--- a/aoc2023/test/day16/day16_test.gleam
+++ /dev/null
@@ -1,66 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day16/solve
-
-type Problem1AnswerType =
- Int
-
-type Problem2AnswerType =
- Int
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- ".|...\\....
-|.-.\\.....
-.....|-...
-........|.
-..........
-.........\\
-..../.\\\\..
-.-.-/..|..
-.|....-|.\\
-..//.|....",
- 46,
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- ".|...\\....
-|.-.\\.....
-.....|-...
-........|.
-..........
-.........\\
-..../.\\\\..
-.-.-/..|..
-.|....-|.\\
-..//.|....",
- 51,
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day17/day17_test.gleam b/aoc2023/test/day17/day17_test.gleam
deleted file mode 100644
index 2ce48e2..0000000
--- a/aoc2023/test/day17/day17_test.gleam
+++ /dev/null
@@ -1,54 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day17/solve
-
-type Problem1AnswerType =
- String
-
-// type Problem2AnswerType =
-// String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "2413432311323
-3215453535623
-3255245654254
-3446585845452
-4546657867536
-1438598798454
-4457876987766
-3637877979653
-4654967986887
-4564679986453
-1224686865563
-2546548887735
-4322674655533",
- "102",
- ),
-]
-
-// /// ```
-// const part2_examples: List(Example(Problem2AnswerType)) = []
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-// pub fn part2_test() {
-// part2_examples
-// |> should.not_equal([])
-// use example <- list.map(part2_examples)
-// solve.part2(example.input)
-// |> should.equal(example.answer)
-// }
diff --git a/aoc2023/test/day18/day18_test.gleam b/aoc2023/test/day18/day18_test.gleam
deleted file mode 100644
index 7b510c8..0000000
--- a/aoc2023/test/day18/day18_test.gleam
+++ /dev/null
@@ -1,74 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day18/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "R 6 (#70c710)
-D 5 (#0dc571)
-L 2 (#5713f0)
-D 2 (#d2c081)
-R 2 (#59c680)
-D 2 (#411b91)
-L 5 (#8ceee2)
-U 2 (#caa173)
-L 1 (#1b58a2)
-U 2 (#caa171)
-R 2 (#7807d2)
-U 3 (#a77fa3)
-L 2 (#015232)
-U 2 (#7a21e3)",
- "62",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "R 6 (#70c710)
-D 5 (#0dc571)
-L 2 (#5713f0)
-D 2 (#d2c081)
-R 2 (#59c680)
-D 2 (#411b91)
-L 5 (#8ceee2)
-U 2 (#caa173)
-L 1 (#1b58a2)
-U 2 (#caa171)
-R 2 (#7807d2)
-U 3 (#a77fa3)
-L 2 (#015232)
-U 2 (#7a21e3)",
- "952408144115",
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day19/day19_test.gleam b/aoc2023/test/day19/day19_test.gleam
deleted file mode 100644
index c911de5..0000000
--- a/aoc2023/test/day19/day19_test.gleam
+++ /dev/null
@@ -1,80 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day19/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "px{a<2006:qkq,m>2090:A,rfg}
-pv{a>1716:R,A}
-lnx{m>1548:A,A}
-rfg{s<537:gd,x>2440:R,A}
-qs{s>3448:A,lnx}
-qkq{x<1416:A,crn}
-crn{x>2662:A,R}
-in{s<1351:px,qqz}
-qqz{s>2770:qs,m<1801:hdj,R}
-gd{a>3333:R,R}
-hdj{m>838:A,pv}
-
-{x=787,m=2655,a=1222,s=2876}
-{x=1679,m=44,a=2067,s=496}
-{x=2036,m=264,a=79,s=2244}
-{x=2461,m=1339,a=466,s=291}
-{x=2127,m=1623,a=2188,s=1013}",
- "19114",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "px{a<2006:qkq,m>2090:A,rfg}
-pv{a>1716:R,A}
-lnx{m>1548:A,A}
-rfg{s<537:gd,x>2440:R,A}
-qs{s>3448:A,lnx}
-qkq{x<1416:A,crn}
-crn{x>2662:A,R}
-in{s<1351:px,qqz}
-qqz{s>2770:qs,m<1801:hdj,R}
-gd{a>3333:R,R}
-hdj{m>838:A,pv}
-
-{x=787,m=2655,a=1222,s=2876}
-{x=1679,m=44,a=2067,s=496}
-{x=2036,m=264,a=79,s=2244}
-{x=2461,m=1339,a=466,s=291}
-{x=2127,m=1623,a=2188,s=1013}",
- "167409079868000",
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day2/day2_test.gleam b/aoc2023/test/day2/day2_test.gleam
deleted file mode 100644
index 28a65da..0000000
--- a/aoc2023/test/day2/day2_test.gleam
+++ /dev/null
@@ -1,57 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day2/solve
-
-type Problem1AnswerType =
- Int
-
-type Problem2AnswerType =
- Int
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
-Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
-Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
-Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
-Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green",
- 8,
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
-Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
-Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
-Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
-Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green",
- 2286,
- ),
- Example("Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green", 48),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day20/day20_test.gleam b/aoc2023/test/day20/day20_test.gleam
deleted file mode 100644
index 9b79b05..0000000
--- a/aoc2023/test/day20/day20_test.gleam
+++ /dev/null
@@ -1,55 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day20/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "broadcaster -> a, b, c
-%a -> b
-%b -> c
-%c -> inv
-&inv -> a",
- "32000000",
- ),
- Example(
- "broadcaster -> a
-%a -> inv, con
-&inv -> b
-%b -> con
-&con -> output
-output -> ",
- "11687500",
- ),
-]
-
-// const part2_examples: List(Example(Problem2AnswerType)) = []
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-// pub fn part2_test() {
-// part2_examples
-// |> should.not_equal([])
-// use example <- list.map(part2_examples)
-// solve.part2(example.input)
-// |> should.equal(example.answer)
-// }
diff --git a/aoc2023/test/day22/day22_test.gleam b/aoc2023/test/day22/day22_test.gleam
deleted file mode 100644
index 3f8c0ca..0000000
--- a/aoc2023/test/day22/day22_test.gleam
+++ /dev/null
@@ -1,60 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day22/solve
-
-type Problem1AnswerType =
- Int
-
-type Problem2AnswerType =
- Int
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "1,0,1~1,2,1
-0,0,2~2,0,2
-0,2,3~2,2,3
-0,0,4~0,2,4
-2,0,5~2,2,5
-0,1,6~2,1,6
-1,1,8~1,1,9",
- 5,
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "1,0,1~1,2,1
-0,0,2~2,0,2
-0,2,3~2,2,3
-0,0,4~0,2,4
-2,0,5~2,2,5
-0,1,6~2,1,6
-1,1,8~1,1,9",
- 7,
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day23/day23_test.gleam b/aoc2023/test/day23/day23_test.gleam
deleted file mode 100644
index 206571c..0000000
--- a/aoc2023/test/day23/day23_test.gleam
+++ /dev/null
@@ -1,92 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day23/solve
-
-type Problem1AnswerType =
- Int
-
-type Problem2AnswerType =
- Int
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "#.#####################
-#.......#########...###
-#######.#########.#.###
-###.....#.>.>.###.#.###
-###v#####.#v#.###.#.###
-###.>...#.#.#.....#...#
-###v###.#.#.#########.#
-###...#.#.#.......#...#
-#####.#.#.#######.#.###
-#.....#.#.#.......#...#
-#.#####.#.#.#########v#
-#.#...#...#...###...>.#
-#.#.#v#######v###.###v#
-#...#.>.#...>.>.#.###.#
-#####v#.#.###v#.#.###.#
-#.....#...#...#.#.#...#
-#.#########.###.#.#.###
-#...###...#...#...#.###
-###.###.#.###v#####v###
-#...#...#.#.>.>.#.>.###
-#.###.###.#.###.#.#v###
-#.....###...###...#...#
-#####################.#",
- 94,
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "#.#####################
-#.......#########...###
-#######.#########.#.###
-###.....#.>.>.###.#.###
-###v#####.#v#.###.#.###
-###.>...#.#.#.....#...#
-###v###.#.#.#########.#
-###...#.#.#.......#...#
-#####.#.#.#######.#.###
-#.....#.#.#.......#...#
-#.#####.#.#.#########v#
-#.#...#...#...###...>.#
-#.#.#v#######v###.###v#
-#...#.>.#...>.>.#.###.#
-#####v#.#.###v#.#.###.#
-#.....#...#...#.#.#...#
-#.#########.###.#.#.###
-#...###...#...#...#.###
-###.###.#.###v#####v###
-#...#...#.#.>.>.#.>.###
-#.###.###.#.###.#.#v###
-#.....###...###...#...#
-#####################.#",
- 154,
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day3/day3_test.gleam b/aoc2023/test/day3/day3_test.gleam
deleted file mode 100644
index 30e17a9..0000000
--- a/aoc2023/test/day3/day3_test.gleam
+++ /dev/null
@@ -1,66 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day3/solve
-
-type Problem1AnswerType =
- Int
-
-type Problem2AnswerType =
- Int
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "467..114..
-...*......
-..35..633.
-......#...
-617*......
-.....+.58.
-..592.....
-......755.
-...$.*....
-.664.598..",
- 4361,
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "467..114..
-...*......
-..35..633.
-......#...
-617*......
-.....+.58.
-..592.....
-......755.
-...$.*....
-.664.598..",
- 467_835,
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day4/day4_test.gleam b/aoc2023/test/day4/day4_test.gleam
deleted file mode 100644
index 324fe36..0000000
--- a/aoc2023/test/day4/day4_test.gleam
+++ /dev/null
@@ -1,58 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day4/solve
-
-type Problem1AnswerType =
- Int
-
-type Problem2AnswerType =
- Int
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
-Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
-Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
-Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
-Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
-Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11",
- 13,
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
-Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
-Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
-Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
-Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
-Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11",
- 30,
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day5/day5_test.gleam b/aoc2023/test/day5/day5_test.gleam
deleted file mode 100644
index 86a8692..0000000
--- a/aoc2023/test/day5/day5_test.gleam
+++ /dev/null
@@ -1,112 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day5/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "seeds: 79 14 55 13
-
-seed-to-soil map:
-50 98 2
-52 50 48
-
-soil-to-fertilizer map:
-0 15 37
-37 52 2
-39 0 15
-
-fertilizer-to-water map:
-49 53 8
-0 11 42
-42 0 7
-57 7 4
-
-water-to-light map:
-88 18 7
-18 25 70
-
-light-to-temperature map:
-45 77 23
-81 45 19
-68 64 13
-
-temperature-to-humidity map:
-0 69 1
-1 0 69
-
-humidity-to-location map:
-60 56 37
-56 93 4",
- "35",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "seeds: 79 14 55 13
-
-seed-to-soil map:
-50 98 2
-52 50 48
-
-soil-to-fertilizer map:
-0 15 37
-37 52 2
-39 0 15
-
-fertilizer-to-water map:
-49 53 8
-0 11 42
-42 0 7
-57 7 4
-
-water-to-light map:
-88 18 7
-18 25 70
-
-light-to-temperature map:
-45 77 23
-81 45 19
-68 64 13
-
-temperature-to-humidity map:
-0 69 1
-1 0 69
-
-humidity-to-location map:
-60 56 37
-56 93 4",
- "46",
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day6/day6_test.gleam b/aoc2023/test/day6/day6_test.gleam
deleted file mode 100644
index c551993..0000000
--- a/aoc2023/test/day6/day6_test.gleam
+++ /dev/null
@@ -1,50 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day6/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "Time: 7 15 30
-Distance: 9 40 200",
- "288",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "Time: 7 15 30
-Distance: 9 40 200",
- "71503",
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day7/day7_test.gleam b/aoc2023/test/day7/day7_test.gleam
deleted file mode 100644
index f7f8454..0000000
--- a/aoc2023/test/day7/day7_test.gleam
+++ /dev/null
@@ -1,56 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day7/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "32T3K 765
-T55J5 684
-KK677 28
-KTJJT 220
-QQQJA 483",
- "6440",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "32T3K 765
-T55J5 684
-KK677 28
-KTJJT 220
-QQQJA 483",
- "5905",
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day8/day8_test.gleam b/aoc2023/test/day8/day8_test.gleam
deleted file mode 100644
index 2cd499a..0000000
--- a/aoc2023/test/day8/day8_test.gleam
+++ /dev/null
@@ -1,61 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day8/solve
-
-type Problem1AnswerType =
- Int
-
-type Problem2AnswerType =
- Int
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "LLR
-
-AAA = (BBB, BBB)
-BBB = (AAA, ZZZ)
-ZZZ = (ZZZ, ZZZ)",
- 6,
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "LR
-
-11A = (11B, XXX)
-11B = (XXX, 11Z)
-11Z = (11B, XXX)
-22A = (22B, XXX)
-22B = (22C, 22C)
-22C = (22Z, 22Z)
-22Z = (22B, 22B)
-XXX = (XXX, XXX)",
- 6,
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}
diff --git a/aoc2023/test/day9/day9_test.gleam b/aoc2023/test/day9/day9_test.gleam
deleted file mode 100644
index 84fd3ba..0000000
--- a/aoc2023/test/day9/day9_test.gleam
+++ /dev/null
@@ -1,52 +0,0 @@
-import gleam/list
-import showtime/tests/should
-import adglent.{type Example, Example}
-import day9/solve
-
-type Problem1AnswerType =
- String
-
-type Problem2AnswerType =
- String
-
-/// Add examples for part 1 here:
-/// ```gleam
-///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")]
-/// ```
-const part1_examples: List(Example(Problem1AnswerType)) = [
- Example(
- "0 3 6 9 12 15
-1 3 6 10 15 21
-10 13 16 21 30 45",
- "114",
- ),
-]
-
-/// Add examples for part 2 here:
-/// ```gleam
-///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")]
-/// ```
-const part2_examples: List(Example(Problem2AnswerType)) = [
- Example(
- "0 3 6 9 12 15
-1 3 6 10 15 21
-10 13 16 21 30 45",
- "2",
- ),
-]
-
-pub fn part1_test() {
- part1_examples
- |> should.not_equal([])
- use example <- list.map(part1_examples)
- solve.part1(example.input)
- |> should.equal(example.answer)
-}
-
-pub fn part2_test() {
- part2_examples
- |> should.not_equal([])
- use example <- list.map(part2_examples)
- solve.part2(example.input)
- |> should.equal(example.answer)
-}