aboutsummaryrefslogtreecommitdiff
path: root/aoc2017-gleam/src
diff options
context:
space:
mode:
authorH.J <thechairman@thechairman.info>2024-10-09 11:36:55 -0400
committerH.J <thechairman@thechairman.info>2024-10-09 11:36:55 -0400
commit8777ff071f7bb37631baa7b6717ad29961e50911 (patch)
tree6d59c4ed58e454b960339c3d1151f0a879e8d7cb /aoc2017-gleam/src
parent6156a9ef7be4012063a042aafb4e9b0d7eadde8e (diff)
downloadgleam_aoc-8777ff071f7bb37631baa7b6717ad29961e50911.tar.gz
gleam_aoc-8777ff071f7bb37631baa7b6717ad29961e50911.zip
sorting by language
Diffstat (limited to 'aoc2017-gleam/src')
-rw-r--r--aoc2017-gleam/src/aoc2017_gleam.gleam5
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_1.gleam32
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_10.gleam77
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_11.gleam75
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_12.gleam44
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_13.gleam58
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_14.gleam82
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_15.gleam93
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_16.gleam104
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_17.gleam55
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_2.gleam47
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_3.gleam87
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_4.gleam31
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_5.gleam48
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_6.gleam65
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_7.gleam108
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_8.gleam131
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_9.gleam48
-rw-r--r--aoc2017-gleam/src/helpers/set_state.gleam55
19 files changed, 0 insertions, 1245 deletions
diff --git a/aoc2017-gleam/src/aoc2017_gleam.gleam b/aoc2017-gleam/src/aoc2017_gleam.gleam
deleted file mode 100644
index 8c2ba67..0000000
--- a/aoc2017-gleam/src/aoc2017_gleam.gleam
+++ /dev/null
@@ -1,5 +0,0 @@
-import gleam/io
-
-pub fn main() {
- io.println("Hello from aoc2017_gleam!")
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_1.gleam b/aoc2017-gleam/src/aoc_2017/day_1.gleam
deleted file mode 100644
index 786d0dd..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_1.gleam
+++ /dev/null
@@ -1,32 +0,0 @@
-import gleam/int
-import gleam/list
-import gleam/result
-import gleam/string
-
-pub fn parse(input: String) {
- input
- |> string.to_graphemes()
- |> list.map(int.parse)
- |> result.values()
-}
-
-pub fn pt_1(input: List(Int)) {
- pair_by(numbers: input, considering: 1)
-}
-
-pub fn pt_2(input: List(Int)) {
- pair_by(numbers: input, considering: list.length(input) / 2)
-}
-
-fn find_neighbor_matches(number_pairs: List(#(Int, Int))) {
- case number_pairs {
- [] -> 0
- [#(a, b), ..rest] if a == b -> a + find_neighbor_matches(rest)
- [_, ..rest] -> find_neighbor_matches(rest)
- }
-}
-
-fn pair_by(numbers xs: List(Int), considering by: Int) {
- list.zip(xs, list.append(list.drop(xs, by), list.take(xs, by)))
- |> find_neighbor_matches()
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_10.gleam b/aoc2017-gleam/src/aoc_2017/day_10.gleam
deleted file mode 100644
index 676e0ee..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_10.gleam
+++ /dev/null
@@ -1,77 +0,0 @@
-import gleam/int
-import gleam/list
-import gleam/result
-import gleam/string
-
-const size = 256
-
-const suffix = [17, 31, 73, 47, 23]
-
-fn parse_as_numbers(input: String) {
- input
- |> string.split(",")
- |> list.map(int.parse)
- |> result.values()
-}
-
-fn parse_as_bytes(input: String) {
- input
- |> string.to_utf_codepoints
- |> list.map(string.utf_codepoint_to_int)
- |> list.append(suffix)
-}
-
-pub fn pt_1(input: String) {
- let twisted = twist(list.range(0, size - 1), parse_as_numbers(input), 0, 0)
-
- let assert #([first, second, ..], _, _) = twisted
- first * second
-}
-
-pub fn pt_2(input: String) {
- megatwist(list.range(0, size - 1), parse_as_bytes(input), 0, 0, 64)
- |> list.sized_chunk(16)
- |> list.map(fold_xor)
- |> string.concat()
-}
-
-fn twist(loop: List(Int), lengths: List(Int), skip: Int, index: Int) {
- case lengths {
- [] -> #(loop, skip, index)
- [l, ..ls] ->
- loop
- |> roll(index)
- |> flip(l)
- |> roll({ size - index } % size)
- |> twist(ls, skip + 1, { index + l + skip } % size)
- }
-}
-
-fn megatwist(loop, lengths, skip, index, iterations) {
- case iterations {
- 0 -> loop
- n -> {
- let #(next_loop, next_skip, next_index) =
- twist(loop, lengths, skip, index)
- megatwist(next_loop, lengths, next_skip, next_index, n - 1)
- }
- }
-}
-
-fn roll(list: List(a), by: Int) {
- let #(left, right) = list.split(list, by % size)
- list.append(right, left)
-}
-
-fn flip(list: List(a), length: Int) {
- let #(left, right) = list.split(list, length)
- list.append(list.reverse(left), right)
-}
-
-fn fold_xor(xs: List(Int)) {
- let assert Ok(n) = list.reduce(xs, int.bitwise_exclusive_or)
- n
- |> int.to_base16()
- |> string.pad_left(to: 2, with: "0")
- |> string.lowercase()
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_11.gleam b/aoc2017-gleam/src/aoc_2017/day_11.gleam
deleted file mode 100644
index 7d3df0b..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_11.gleam
+++ /dev/null
@@ -1,75 +0,0 @@
-import gleam/int
-import gleam/list
-import gleam/string
-
-pub type Direction {
- North
- Northeast
- Northwest
- South
- Southeast
- Southwest
-}
-
-type HexPosition {
- HexPosition(x: Int, y: Int, z: Int)
-}
-
-const start = HexPosition(0, 0, 0)
-
-fn to_direction(str: String) -> Direction {
- case str {
- "n" -> North
- "ne" -> Northeast
- "nw" -> Northwest
- "s" -> South
- "se" -> Southeast
- "sw" -> Southwest
- _ -> panic as "unrecognized direction"
- }
-}
-
-fn distance(hp1: HexPosition, hp2: HexPosition) -> Int {
- {
- int.absolute_value(hp1.x - hp2.x)
- + int.absolute_value(hp1.y - hp2.y)
- + int.absolute_value(hp1.z - hp2.z)
- }
- / 2
-}
-
-fn move(p, direction) -> HexPosition {
- case direction {
- North -> HexPosition(..p, y: p.y + 1, z: p.z - 1)
- South -> HexPosition(..p, y: p.y - 1, z: p.z + 1)
- Northeast -> HexPosition(..p, x: p.x + 1, z: p.z - 1)
- Southwest -> HexPosition(..p, x: p.x - 1, z: p.z + 1)
- Southeast -> HexPosition(..p, x: p.x + 1, y: p.y - 1)
- Northwest -> HexPosition(..p, x: p.x - 1, y: p.y + 1)
- }
-}
-
-pub fn parse(input: String) -> List(Direction) {
- input
- |> string.split(",")
- |> list.map(to_direction)
-}
-
-pub fn pt_1(input: List(Direction)) {
- do_walk(input, start, 0).0
-}
-
-pub fn pt_2(input: List(Direction)) {
- do_walk(input, start, 0).1
-}
-
-fn do_walk(steps, position, max) {
- case steps {
- [] -> #(distance(position, HexPosition(0, 0, 0)), max)
- [next, ..rest] -> {
- let new_position = move(position, next)
- let new_max = int.max(max, distance(new_position, start))
- do_walk(rest, new_position, new_max)
- }
- }
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_12.gleam b/aoc2017-gleam/src/aoc_2017/day_12.gleam
deleted file mode 100644
index a9d73c5..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_12.gleam
+++ /dev/null
@@ -1,44 +0,0 @@
-import gleam/dict
-import gleam/list
-import gleam/set.{type Set}
-import gleam/string
-
-type Pipes =
- dict.Dict(String, List(String))
-
-pub fn parse(input: String) -> Pipes {
- use acc, row <- list.fold(string.split(input, "\n"), dict.new())
- let assert Ok(#(from, to)) = string.split_once(row, " <-> ")
- let to_nodes = string.split(to, ", ")
- dict.insert(acc, from, to_nodes)
-}
-
-pub fn pt_1(input: Pipes) {
- next_nodes("0", input, set.new()) |> set.size()
-}
-
-pub fn pt_2(input: Pipes) {
- count_groups(dict.keys(input), input, 0)
-}
-
-fn next_nodes(current: String, pipes: Pipes, found: Set(String)) {
- let assert Ok(to_nodes) = dict.get(pipes, current)
-
- use acc, node <- list.fold(to_nodes, found)
- case set.contains(found, node) {
- False -> acc |> set.insert(node) |> next_nodes(node, pipes, _)
- True -> acc
- }
-}
-
-fn count_groups(all_nodes: List(String), pipes: Pipes, count: Int) {
- case all_nodes {
- [] -> count
- [first, ..] -> {
- let next_subgraph = next_nodes(first, pipes, set.new())
- let remaining =
- list.filter(all_nodes, fn(n) { !set.contains(next_subgraph, n) })
- count_groups(remaining, pipes, count + 1)
- }
- }
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_13.gleam b/aoc2017-gleam/src/aoc_2017/day_13.gleam
deleted file mode 100644
index 6b04a77..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_13.gleam
+++ /dev/null
@@ -1,58 +0,0 @@
-import gleam/int
-import gleam/list
-import gleam/option.{Some}
-import gleam/regex.{Match}
-import gleam/string
-
-pub type Layer {
- Layer(depth: Int, cycle: Int)
-}
-
-pub type Status {
- Caught(severity: Int)
- Free
-}
-
-pub fn parse(input: String) {
- let assert Ok(re) = regex.from_string("([0-9]+): ([0-9]+)")
-
- use acc, row <- list.fold(string.split(input, "\n"), [])
- let assert [Match(submatches: [Some(depth), Some(cycle)], ..)] =
- regex.scan(row, with: re)
- let assert Ok(depth) = int.parse(depth)
- let assert Ok(cycle) = int.parse(cycle)
- [Layer(depth, cycle), ..acc]
-}
-
-fn severity(time: Int, depth: Int, cycle: Int) {
- case { time + depth } % { 2 * { cycle - 1 } } {
- 0 -> Caught(cycle * depth)
- _ -> Free
- }
-}
-
-pub fn pt_1(input: List(Layer)) {
- use acc, layer <- list.fold(input, 0)
- case severity(0, layer.depth, layer.cycle) {
- Free -> acc
- Caught(severity) -> acc + severity
- }
-}
-
-pub fn pt_2(input: List(Layer)) {
- find_delay(0, input)
-}
-
-fn find_delay(delay: Int, layers: List(Layer)) {
- let trial_run =
- list.try_fold(layers, Free, fn(_, layer) {
- case severity(delay, layer.depth, layer.cycle) {
- Free -> Ok(Free)
- Caught(_) -> Error(Nil)
- }
- })
- case trial_run {
- Ok(_) -> delay
- _err -> find_delay(delay + 1, layers)
- }
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_14.gleam b/aoc2017-gleam/src/aoc_2017/day_14.gleam
deleted file mode 100644
index 2a74912..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_14.gleam
+++ /dev/null
@@ -1,82 +0,0 @@
-import aoc_2017/day_10.{pt_2 as knot}
-import gleam/int
-import gleam/list
-import gleam/result
-import gleam/set
-import gleam/string
-import helpers/set_state
-
-pub fn pt_1(input: String) {
- use acc, row <- list.fold(make_rows(input), 0)
- let count = row |> knot() |> popcount()
- acc + count
-}
-
-fn make_rows(input: String) {
- use row <- list.map(list.range(0, 127))
- input <> "-" <> int.to_string(row)
-}
-
-fn popcount(hex_number: String) -> Int {
- let assert Ok(n) = int.base_parse(hex_number, 16)
- let assert Ok(digits) = int.digits(n, 2)
-
- use acc, digit <- list.fold(digits, 0)
- case digit {
- 1 -> acc + 1
- _ -> acc
- }
-}
-
-pub fn pt_2(input: String) {
- let grid = set_state.start_actor(make_grid(input))
-
- find_next_group(grid, 0)
-}
-
-fn make_grid(input: String) {
- let raw_grid =
- list.map(make_rows(input), fn(row) {
- row
- |> knot()
- |> int.base_parse(16)
- |> result.map(int.to_base2)
- |> result.map(string.pad_left(_, with: "0", to: 128))
- |> result.map(string.to_graphemes)
- })
- |> result.values
-
- {
- use total_acc, row, i <- list.index_fold(raw_grid, set.new())
- use acc, bit, j <- list.index_fold(row, total_acc)
- case bit {
- "1" -> set.insert(acc, #(i, j))
- _zero -> acc
- }
- }
-}
-
-fn find_next_group(actor, count) {
- case set_state.pop(actor) {
- Ok(p) -> {
- list.each(neighbors(p), remove_neighbor(actor, _))
- find_next_group(actor, count + 1)
- }
- Error(Nil) -> count
- }
-}
-
-fn neighbors(of: #(Int, Int)) {
- let #(i, j) = of
- [#(i + 1, j), #(i - 1, j), #(i, j + 1), #(i, j - 1)]
-}
-
-fn remove_neighbor(actor, point) {
- case set_state.check(actor, point) {
- True -> {
- set_state.drop(actor, point)
- list.each(neighbors(point), remove_neighbor(actor, _))
- }
- False -> Nil
- }
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_15.gleam b/aoc2017-gleam/src/aoc_2017/day_15.gleam
deleted file mode 100644
index dab5c14..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_15.gleam
+++ /dev/null
@@ -1,93 +0,0 @@
-import gleam/int
-import gleam/string
-
-const sixteen_bits = 0xFFFF
-
-const generator_a = 16_807
-
-const generator_b = 48_271
-
-const divisor = 2_147_483_647
-
-const max_reps_pt1 = 40_000_000
-
-const max_reps_pt2 = 5_000_000
-
-pub fn parse(input: String) {
- let assert Ok(#(a_str, b_str)) = string.split_once(input, ",")
- let assert Ok(a) = int.parse(a_str)
- let assert Ok(b) = int.parse(b_str)
-
- #(a, b)
-}
-
-pub fn pt_1(input: #(Int, Int)) {
- let #(a, b) = input
-
- next_comparison(
- a: a,
- b: b,
- selecting_a_using: next_value,
- selecting_b_using: next_value,
- initial_matches: 0,
- initial_cycle: 0,
- up_to: max_reps_pt1,
- )
-}
-
-pub fn pt_2(input: #(Int, Int)) {
- let #(a, b) = input
-
- next_comparison(
- a: a,
- b: b,
- selecting_a_using: next_but_divisible_by(4),
- selecting_b_using: next_but_divisible_by(8),
- initial_matches: 0,
- initial_cycle: 0,
- up_to: max_reps_pt2,
- )
-}
-
-fn next_value(current, generator) {
- { current * generator } % divisor
-}
-
-fn picky_generator(current, generator, divisible_by) {
- let trial = next_value(current, generator)
- case trial % divisible_by {
- 0 -> trial
- _ -> picky_generator(trial, generator, divisible_by)
- }
-}
-
-fn next_but_divisible_by(divisible_by) {
- fn(c, g) { picky_generator(c, g, divisible_by) }
-}
-
-fn last_16_bits(n: Int) {
- int.bitwise_and(n, sixteen_bits)
-}
-
-fn next_comparison(
- a a: Int,
- b b: Int,
- selecting_a_using for_a: fn(Int, Int) -> Int,
- selecting_b_using for_b: fn(Int, Int) -> Int,
- initial_matches same: Int,
- initial_cycle count: Int,
- up_to max: Int,
-) {
- case count == max {
- True -> same
- False -> {
- let next_a = for_a(a, generator_a)
- let next_b = for_b(b, generator_b)
- let maybe_same = case last_16_bits(next_a) == last_16_bits(next_b) {
- True -> same + 1
- False -> same
- }
- next_comparison(next_a, next_b, for_a, for_b, maybe_same, count + 1, max)
- }
- }
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_16.gleam b/aoc2017-gleam/src/aoc_2017/day_16.gleam
deleted file mode 100644
index 9a5110e..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_16.gleam
+++ /dev/null
@@ -1,104 +0,0 @@
-import gleam/dict.{type Dict}
-import gleam/int
-import gleam/list
-import gleam/string
-
-pub type DanceMove {
- Spin(moving: Int)
- Exchange(first: Int, second: Int)
- Partner(first: String, second: String)
-}
-
-const initial_lineup = "abcdefghijklmnop"
-
-const dancer_count = 16
-
-const end_state = 1_000_000_000
-
-pub fn parse(input: String) {
- string.split(input, ",")
-}
-
-fn do_spin(dancers: List(String), moving: Int) {
- let #(front, back) = list.split(dancers, dancer_count - moving)
- list.append(back, front)
-}
-
-fn do_exchange(dancers: List(String), first: Int, second: Int) {
- let indexed = list.index_map(dancers, fn(d, i) { #(i, d) })
-
- let assert Ok(first_dancer) = list.key_find(indexed, first)
- let assert Ok(second_dancer) = list.key_find(indexed, second)
-
- indexed
- |> list.key_set(first, second_dancer)
- |> list.key_set(second, first_dancer)
- |> list.map(fn(tup) { tup.1 })
-}
-
-fn do_partner(dancers: List(String), first: String, second: String) {
- use dancer <- list.map(dancers)
- case dancer {
- d if d == first -> second
- d if d == second -> first
- d -> d
- }
-}
-
-pub fn pt_1(input: List(String)) {
- initial_lineup
- |> string.to_graphemes()
- |> next_move(input)
- |> string.concat()
-}
-
-fn next_move(dancers, raw_moves) {
- case raw_moves {
- [] -> dancers
- ["s" <> size, ..rest] -> dancers |> do_spin(int(size)) |> next_move(rest)
- ["x" <> swap, ..rest] -> {
- let assert Ok(#(first, second)) = string.split_once(swap, "/")
- dancers |> do_exchange(int(first), int(second)) |> next_move(rest)
- }
- ["p" <> swap, ..rest] -> {
- let assert Ok(#(first, second)) = string.split_once(swap, "/")
- dancers |> do_partner(first, second) |> next_move(rest)
- }
- _ -> panic as "bad dance move"
- }
-}
-
-pub fn pt_2(input: List(String)) {
- initial_lineup
- |> string.to_graphemes()
- |> find_cycle(caching_in: dict.new(), cycle: 0, dancing_to: input)
-}
-
-fn find_cycle(
- moving_to dance_position: List(String),
- caching_in cache: Dict(String, Int),
- cycle cycle: Int,
- dancing_to dance_moves: List(String),
-) {
- let dance_hash = string.concat(dance_position)
- case dict.get(cache, dance_hash) {
- Ok(c) -> {
- let offset = end_state % { cycle - c } - c
- let assert [#(final, _)] =
- dict.filter(cache, fn(_, v) { v == offset }) |> dict.to_list()
- final
- }
- _err ->
- find_cycle(
- moving_to: next_move(dance_position, dance_moves),
- caching_in: dict.insert(cache, dance_hash, cycle),
- cycle: cycle + 1,
- dancing_to: dance_moves,
- )
- }
-}
-
-fn int(n) {
- let assert Ok(n) = int.parse(n)
- n
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_17.gleam b/aoc2017-gleam/src/aoc_2017/day_17.gleam
deleted file mode 100644
index 5904cab..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_17.gleam
+++ /dev/null
@@ -1,55 +0,0 @@
-import gleam/int
-import gleam/list
-import glearray
-
-pub fn parse(input: String) {
- let assert Ok(n) = int.parse(input)
- n
-}
-
-pub fn pt_1(input: Int) {
- let assert [_, result] =
- next_spin([0], 0, 1, input)
- |> list.drop_while(fn(x) { x != 2017 })
- |> list.take(2)
-
- result
-}
-
-fn next_spin(list: List(Int), position: Int, cycle: Int, step: Int) {
- case cycle {
- 2018 -> list
- _ -> {
- let next_position = { position + step } % cycle + 1
- next_spin(
- insert_at(list, next_position, cycle),
- next_position,
- cycle + 1,
- step,
- )
- }
- }
-}
-
-fn insert_at(xs: List(a), at index: Int, insert new: a) {
- let #(left, right) = list.split(xs, index)
- list.concat([left, [new], right])
-}
-
-pub fn pt_2(input: Int) {
- next_spin_tracking_zero(0, 0, 1, input)
-}
-
-fn next_spin_tracking_zero(acc: Int, position: Int, cycle: Int, step: Int) {
- case cycle {
- 50_000_001 -> acc
- _ -> {
- let next_position = { position + step } % cycle + 1
- let next_acc = case next_position {
- 1 -> cycle
- _ -> acc
- }
- next_spin_tracking_zero(next_acc, next_position, cycle + 1, step)
- }
- }
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_2.gleam b/aoc2017-gleam/src/aoc_2017/day_2.gleam
deleted file mode 100644
index 6a5e85d..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_2.gleam
+++ /dev/null
@@ -1,47 +0,0 @@
-import gleam/int
-import gleam/list
-import gleam/result
-import gleam/string
-
-pub fn parse(input: String) {
- use row <- list.map(string.split(input, "\n"))
- use val <- list.map(string.split(row, "\t"))
- let assert Ok(n) = int.parse(val)
- n
-}
-
-pub fn pt_1(input: List(List(Int))) {
- use acc, row <- list.fold(input, 0)
- acc + max(row) - min(row)
-}
-
-pub fn pt_2(input: List(List(Int))) {
- use acc, row <- list.fold(input, 0)
- let assert [val] =
- row |> list.combination_pairs() |> list.map(test_pair) |> result.values()
- acc + val
-}
-
-fn max(xs) {
- let assert Ok(result) = list.reduce(xs, int.max)
- result
-}
-
-fn min(xs) {
- let assert Ok(result) = list.reduce(xs, int.min)
- result
-}
-
-fn test_pair(tup) {
- case tup {
- #(a, b) if a > b -> check_divisibility(a, b)
- #(b, a) -> check_divisibility(a, b)
- }
-}
-
-fn check_divisibility(a, b) {
- case a % b {
- 0 -> Ok(a / b)
- _ -> Error(Nil)
- }
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_3.gleam b/aoc2017-gleam/src/aoc_2017/day_3.gleam
deleted file mode 100644
index 5672e39..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_3.gleam
+++ /dev/null
@@ -1,87 +0,0 @@
-import gleam/dict
-import gleam/int
-import gleam/list
-
-type Direction {
- Up
- Down
- Left
- Right
-}
-
-type State {
- State(
- x: Int,
- y: Int,
- direction: Direction,
- branch_length: Int,
- remaining: Int,
- )
-}
-
-fn starting_state() -> State {
- State(0, 0, Right, 1, 1)
-}
-
-fn update_state(state: State) -> State {
- case state {
- State(x, y, Right, len, 0) -> State(x, y + 1, Up, len, len - 1)
- State(x, y, Up, len, 0) -> State(x - 1, y, Left, len + 1, len)
- State(x, y, Left, len, 0) -> State(x, y - 1, Down, len, len - 1)
- State(x, y, Down, len, 0) -> State(x + 1, y, Right, len + 1, len)
- State(x, y, Right, len, rem) -> State(x + 1, y, Right, len, rem - 1)
- State(x, y, Up, len, rem) -> State(x, y + 1, Up, len, rem - 1)
- State(x, y, Left, len, rem) -> State(x - 1, y, Left, len, rem - 1)
- State(x, y, Down, len, rem) -> State(x, y - 1, Down, len, rem - 1)
- }
-}
-
-type Grid =
- dict.Dict(#(Int, Int), Int)
-
-pub fn parse(input: String) -> Int {
- let assert Ok(n) = int.parse(input)
- n
-}
-
-pub fn pt_1(input: Int) -> Int {
- next_step(1, input, starting_state())
-}
-
-fn next_step(current: Int, target: Int, state: State) -> Int {
- case current == target {
- True -> int.absolute_value(state.x) + int.absolute_value(state.y)
- False -> next_step(current + 1, target, update_state(state))
- }
-}
-
-pub fn pt_2(input: Int) -> Int {
- let grid: Grid = dict.from_list([#(#(0, 0), 1)])
-
- add_next_cell(input, starting_state(), grid)
-}
-
-fn neighbors(coord: #(Int, Int)) -> List(#(Int, Int)) {
- let #(x, y) = coord
-
- use dx <- list.flat_map(list.range(-1, 1))
- use dy <- list.map(list.range(-1, 1))
- #(x + dx, y + dy)
-}
-
-fn add_next_cell(target: Int, state: State, grid: Grid) -> Int {
- let next_cell = update_state(state)
- let coords = #(next_cell.x, next_cell.y)
- let value =
- list.fold(neighbors(coords), 0, fn(acc, coord) {
- case dict.get(grid, coord) {
- Ok(n) -> acc + n
- _err -> acc
- }
- })
-
- case value >= target {
- True -> value
- False -> add_next_cell(target, next_cell, dict.insert(grid, coords, value))
- }
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_4.gleam b/aoc2017-gleam/src/aoc_2017/day_4.gleam
deleted file mode 100644
index 9bc4f9a..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_4.gleam
+++ /dev/null
@@ -1,31 +0,0 @@
-import gleam/list
-import gleam/string
-
-pub fn parse(input: String) -> List(List(String)) {
- use row <- list.map(string.split(input, "\n"))
- string.split(row, " ")
-}
-
-pub fn pt_1(input: List(List(String))) {
- use acc, passwords <- list.fold(input, 0)
- case passwords == list.unique(passwords) {
- True -> acc + 1
- False -> acc
- }
-}
-
-pub fn pt_2(input: List(List(String))) {
- use acc, passwords <- list.fold(input, 0)
- let sorted_passwords = list.map(passwords, sort_graphemes)
- case sorted_passwords == list.unique(sorted_passwords) {
- True -> acc + 1
- False -> acc
- }
-}
-
-fn sort_graphemes(word: String) -> String {
- word
- |> string.to_graphemes
- |> list.sort(string.compare)
- |> string.concat
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_5.gleam b/aoc2017-gleam/src/aoc_2017/day_5.gleam
deleted file mode 100644
index a0b9b80..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_5.gleam
+++ /dev/null
@@ -1,48 +0,0 @@
-import gary.{type ErlangArray}
-import gary/array
-import gleam/int
-import gleam/list
-import gleam/result
-import gleam/string
-
-pub fn parse(input: String) -> ErlangArray(Int) {
- input
- |> string.split("\n")
- |> list.map(int.parse)
- |> result.values()
- |> array.from_list(default: 0)
- |> array.make_fixed()
-}
-
-pub fn pt_1(input: ErlangArray(Int)) {
- next_step(input, 0, 0, part: 1)
-}
-
-pub fn pt_2(input: ErlangArray(Int)) {
- next_step(input, 0, 0, part: 2)
-}
-
-fn next_step(
- instructions: ErlangArray(Int),
- pointer: Int,
- step: Int,
- part part: Int,
-) {
- case array.get(from: instructions, at: pointer) {
- Ok(distance) -> {
- let delta = delta(distance, part)
- let assert Ok(updated_instructions) =
- array.set(instructions, at: pointer, put: distance + delta)
- next_step(updated_instructions, pointer + distance, step + 1, part)
- }
- Error(_) -> step
- }
-}
-
-fn delta(d: Int, part: Int) {
- case part, d {
- 1, _ -> 1
- _, n if n < 3 -> 1
- _, _ -> -1
- }
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_6.gleam b/aoc2017-gleam/src/aoc_2017/day_6.gleam
deleted file mode 100644
index 84222e1..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_6.gleam
+++ /dev/null
@@ -1,65 +0,0 @@
-import gary.{type ErlangArray}
-import gary/array
-import gleam/bool
-import gleam/int
-import gleam/list
-import gleam/result
-import gleam/set.{type Set}
-import gleam/string
-
-pub fn parse(input) -> ErlangArray(Int) {
- input
- |> string.split("\t")
- |> list.map(int.parse)
- |> result.values()
- |> array.from_list(default: -1)
- |> array.make_fixed()
-}
-
-pub fn pt_1(input: ErlangArray(Int)) {
- check_cycle(input, set.from_list([input]), 1).1
-}
-
-pub fn pt_2(input: ErlangArray(Int)) {
- let #(target, cycle) = check_cycle(input, set.from_list([input]), 1)
- cycle - check_cycle(input, set.from_list([input, target]), 1).1
-}
-
-fn get_max(array: ErlangArray(Int)) -> #(Int, Int) {
- use index, value, max <- array.fold(over: array, from: #(-1, -1))
- case value > max.1 {
- True -> #(index, value)
- False -> max
- }
-}
-
-fn redistribute(
- array: ErlangArray(Int),
- pointer: Int,
- remaining: Int,
-) -> ErlangArray(Int) {
- use <- bool.guard(remaining == 0, array)
- case array.get(from: array, at: pointer) {
- Error(_) -> redistribute(array, 0, remaining)
- Ok(n) -> {
- let assert Ok(updated_array) =
- array.set(into: array, at: pointer, put: n + 1)
- redistribute(updated_array, pointer + 1, remaining - 1)
- }
- }
-}
-
-fn check_cycle(
- current: ErlangArray(Int),
- cache: Set(ErlangArray(Int)),
- cycle: Int,
-) -> #(ErlangArray(Int), Int) {
- let #(index, to_redistribute) = current |> get_max
- let assert Ok(zeroed) = array.set(into: current, at: index, put: 0)
- let next = redistribute(zeroed, index + 1, to_redistribute)
-
- case set.contains(cache, next) {
- True -> #(next, cycle)
- False -> check_cycle(next, set.insert(cache, next), cycle + 1)
- }
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_7.gleam b/aoc2017-gleam/src/aoc_2017/day_7.gleam
deleted file mode 100644
index a289fa5..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_7.gleam
+++ /dev/null
@@ -1,108 +0,0 @@
-import gleam/dict.{type Dict}
-import gleam/int
-import gleam/list
-import gleam/option.{Some}
-import gleam/regex.{type Match, Match}
-import gleam/set
-import gleam/string
-
-pub type Program {
- Program(name: String, weight: Int, supporting: List(String))
-}
-
-pub fn parse(input: String) {
- let assert Ok(re) = regex.from_string("([a-z]+) \\(([0-9]+)\\)(?> -> (.*))?")
-
- use match <- list.map(string.split(input, "\n"))
- case regex.scan(re, match) {
- [Match(submatches: [Some(name), Some(weight)], ..)] ->
- Program(name, to_int(weight), [])
- [Match(submatches: [Some(name), Some(weight), Some(supporting)], ..)] ->
- Program(name, to_int(weight), string.split(supporting, ", "))
- _ -> panic as { "couldn't parse" <> match }
- }
-}
-
-fn to_int(str: String) -> Int {
- let assert Ok(n) = int.parse(str)
- n
-}
-
-pub fn pt_1(input: List(Program)) {
- let supporters = input |> list.map(fn(p) { p.name }) |> set.from_list()
- let supporting =
- input |> list.flat_map(fn(p) { p.supporting }) |> set.from_list()
-
- let assert [base] = set.difference(supporters, supporting) |> set.to_list
- base
-}
-
-pub fn pt_2(input: List(Program)) {
- let weights =
- input |> list.map(fn(p) { #(p.name, p.weight) }) |> dict.from_list
-
- let supporters =
- input
- |> list.filter_map(fn(p) {
- case list.is_empty(p.supporting) {
- True -> Error(Nil)
- False -> Ok(#(p.name, p.supporting))
- }
- })
- |> dict.from_list
-
- supporters
- |> dict.keys()
- |> list.filter_map(fn(name) {
- let branch_weights =
- name
- |> branch_weights(weights, supporters)
- |> fn(tup: #(String, List(#(Int, String)))) { tup.1 }
-
- case
- branch_weights
- |> list.map(fn(tup: #(Int, String)) { tup.0 })
- |> list.unique
- |> list.length
- {
- 2 -> Ok(#(name, branch_weights))
- _ -> Error(Nil)
- }
- })
-
- // [
- // #("hmgrlpj", [#(2078, "drjmjug"), #(2070, "nigdlq"), #(2070, "omytneg"), ...]),
- // #("smaygo", [#(14564, "hmgrlpj"), #(14556, "fbnbt"), #(14556, "nfdvsc")])
- // #("eugwuhl", [#(48292, "smaygo"), #(48284, "pvvbn"), #(48284, "hgizeb"), ...]),
- // ]
- //
- // by inspection, eugwuhl -> smaygo -> hmgrlpj -> drjmjug; changing drjmjug will fix the tower
-
- let assert Ok(w) = dict.get(weights, "drjmjug")
- w - 8
-}
-
-fn branch_weights(
- name: String,
- weights: Dict(String, Int),
- supporting: Dict(String, List(String)),
-) -> #(String, List(#(Int, String))) {
- let supported = case dict.get(supporting, name) {
- Ok(supported) -> supported
- Error(_) -> []
- }
-
- let supported_weights =
- list.map(supported, fn(s) {
- let assert Ok(weight) = dict.get(weights, s)
- let children_weights =
- s
- |> branch_weights(weights, supporting)
- |> fn(tup: #(String, List(#(Int, String)))) { tup.1 }
- |> list.map(fn(tup: #(Int, String)) { tup.0 })
- weight + int.sum(children_weights)
- })
- |> list.zip(supported)
-
- #(name, supported_weights)
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_8.gleam b/aoc2017-gleam/src/aoc_2017/day_8.gleam
deleted file mode 100644
index 2f9d0dc..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_8.gleam
+++ /dev/null
@@ -1,131 +0,0 @@
-import gleam/dict
-import gleam/int
-import gleam/list
-import gleam/option.{None, Some}
-import gleam/string
-
-const max_register = "__MAX"
-
-pub type Instruction {
- Instruction(register: String, op: Operation, condition: Condition)
-}
-
-pub type Operation {
- Inc(by: Int)
- Dec(by: Int)
-}
-
-pub type Condition {
- Equal(register: String, value: Int)
- NotEqual(register: String, value: Int)
- LessThan(register: String, value: Int)
- GreaterThan(register: String, value: Int)
- LessThanOrEq(register: String, value: Int)
- GreaterThanOrEq(register: String, value: Int)
-}
-
-type Registers =
- dict.Dict(String, Int)
-
-pub fn parse(input: String) {
- input
- |> string.split("\n")
- |> list.map(parse_instruction)
-}
-
-fn parse_instruction(str: String) -> Instruction {
- case string.split(str, " ") {
- [name, op, by, "if", cond_name, cond_type, cond_by] ->
- Instruction(name, to_op(op, by), to_cond(cond_name, cond_type, cond_by))
- _ -> panic as { "couldn't parse: " <> str }
- }
-}
-
-pub fn pt_1(input: List(Instruction)) {
- let registers = dict.new() |> dict.insert(max_register, 0)
-
- input
- |> list.fold(registers, next_instruction)
- |> dict.delete(max_register)
- |> dict.values()
- |> list.reduce(int.max)
-}
-
-fn next_instruction(regs: Registers, inst: Instruction) {
- case to_compare_fn(inst.condition)(fetch(inst.condition.register, regs)) {
- True -> {
- let updated_regs = dict.update(regs, inst.register, to_update_fn(inst.op))
- let assert Ok(max) = updated_regs |> dict.values |> list.reduce(int.max)
- dict.insert(updated_regs, max_register, max)
- }
- False -> regs
- }
-}
-
-pub fn pt_2(input: List(Instruction)) {
- let registers = dict.new() |> dict.insert(max_register, 0)
-
- input
- |> list.fold(registers, next_instruction)
- |> dict.get(max_register)
-}
-
-fn int(str: String) -> Int {
- let assert Ok(n) = int.parse(str)
- n
-}
-
-fn to_op(raw_op: String, raw_by: String) -> Operation {
- case raw_op {
- "inc" -> Inc(int(raw_by))
- "dec" -> Dec(int(raw_by))
- _ -> panic as { "bad op: " <> raw_op }
- }
-}
-
-fn to_cond(name: String, raw_type: String, raw_by: String) -> Condition {
- case raw_type {
- "==" -> Equal(name, int(raw_by))
- "!=" -> NotEqual(name, int(raw_by))
- ">" -> GreaterThan(name, int(raw_by))
- "<" -> LessThan(name, int(raw_by))
- ">=" -> GreaterThanOrEq(name, int(raw_by))
- "<=" -> LessThanOrEq(name, int(raw_by))
- _ -> panic as { "bad condition: " <> raw_type }
- }
-}
-
-fn to_compare_fn(condition: Condition) -> fn(Int) -> Bool {
- case condition {
- Equal(value: v, ..) -> fn(a) { a == v }
- NotEqual(value: v, ..) -> fn(a) { a != v }
- GreaterThan(value: v, ..) -> fn(a) { a > v }
- LessThan(value: v, ..) -> fn(a) { a < v }
- GreaterThanOrEq(value: v, ..) -> fn(a) { a >= v }
- LessThanOrEq(value: v, ..) -> fn(a) { a <= v }
- }
-}
-
-fn to_update_fn(op: Operation) {
- case op {
- Inc(n) -> fn(x) {
- case x {
- Some(i) -> i + n
- None -> n
- }
- }
- Dec(n) -> fn(x) {
- case x {
- Some(i) -> i - n
- None -> -n
- }
- }
- }
-}
-
-fn fetch(name: String, registers: Registers) -> Int {
- case dict.get(registers, name) {
- Ok(n) -> n
- Error(_) -> 0
- }
-}
diff --git a/aoc2017-gleam/src/aoc_2017/day_9.gleam b/aoc2017-gleam/src/aoc_2017/day_9.gleam
deleted file mode 100644
index 90eb4b3..0000000
--- a/aoc2017-gleam/src/aoc_2017/day_9.gleam
+++ /dev/null
@@ -1,48 +0,0 @@
-import gleam/list
-import gleam/option.{Some}
-import gleam/regex
-import gleam/string
-
-pub fn parse(input: String) {
- let assert Ok(cancel) = regex.from_string("!.")
-
- replace(input, with: cancel)
-}
-
-pub fn pt_1(input: String) {
- input
- |> strip_to_brackets()
- |> next_bracket(0, 1)
-}
-
-fn replace(input: String, with regex: regex.Regex) -> String {
- input |> regex.split(with: regex) |> string.concat()
-}
-
-fn strip_to_brackets(input: String) -> String {
- let assert Ok(garbage) = regex.from_string("<.*?>")
- let assert Ok(not_group) = regex.from_string("[^{}]")
-
- input
- |> replace(with: garbage)
- |> replace(with: not_group)
-}
-
-fn next_bracket(brackets: String, score: Int, depth: Int) -> Int {
- case string.pop_grapheme(brackets) {
- Error(Nil) -> score
- Ok(#("{", rest)) -> next_bracket(rest, score + depth, depth + 1)
- Ok(#("}", rest)) -> next_bracket(rest, score, depth - 1)
- _ -> panic as "unrecognized character"
- }
-}
-
-pub fn pt_2(input: String) {
- let assert Ok(garbage) = regex.from_string("<(.*?)>")
-
- use acc, match <- list.fold(regex.scan(input, with: garbage), 0)
- case match.submatches {
- [Some(g)] -> string.length(g) + acc
- _ -> acc
- }
-}
diff --git a/aoc2017-gleam/src/helpers/set_state.gleam b/aoc2017-gleam/src/helpers/set_state.gleam
deleted file mode 100644
index cbbad81..0000000
--- a/aoc2017-gleam/src/helpers/set_state.gleam
+++ /dev/null
@@ -1,55 +0,0 @@
-import gleam/erlang/process.{type Subject, Normal}
-import gleam/option.{None}
-import gleam/otp/actor.{type Next, Continue, Stop}
-import gleam/set.{type Set}
-
-const timeout = 1000
-
-pub type Message(k) {
- Shutdown
- Check(key: k, client: Subject(Bool))
- Add(key: k)
- Drop(key: k)
- Pop(client: Subject(Result(k, Nil)))
-}
-
-fn handle_message(message: Message(k), set: Set(k)) -> Next(Message(k), Set(k)) {
- case message {
- Shutdown -> Stop(Normal)
- Check(key, client) -> {
- process.send(client, set.contains(set, key))
- Continue(set, None)
- }
- Add(key) -> Continue(set.insert(set, key), None)
- Drop(key) -> Continue(set.delete(set, key), None)
- Pop(client) -> {
- case set.to_list(set) {
- [next, ..] -> {
- process.send(client, Ok(next))
- Continue(set.delete(set, next), None)
- }
- [] -> {
- process.send(client, Error(Nil))
- Stop(Normal)
- }
- }
- }
- }
-}
-
-pub fn start_actor(with: Set(a)) {
- let assert Ok(actor) = actor.start(with, handle_message)
- actor
-}
-
-pub fn pop(actor) {
- process.call(actor, Pop, timeout)
-}
-
-pub fn check(actor, value) {
- process.call(actor, Check(value, _), timeout)
-}
-
-pub fn drop(actor, value) {
- process.send(actor, Drop(value))
-}