diff options
author | H.J <thechairman@thechairman.info> | 2024-10-09 11:36:55 -0400 |
---|---|---|
committer | H.J <thechairman@thechairman.info> | 2024-10-09 11:36:55 -0400 |
commit | 8777ff071f7bb37631baa7b6717ad29961e50911 (patch) | |
tree | 6d59c4ed58e454b960339c3d1151f0a879e8d7cb /aoc2017-gleam/src/aoc_2017 | |
parent | 6156a9ef7be4012063a042aafb4e9b0d7eadde8e (diff) | |
download | gleam_aoc-8777ff071f7bb37631baa7b6717ad29961e50911.tar.gz gleam_aoc-8777ff071f7bb37631baa7b6717ad29961e50911.zip |
sorting by language
Diffstat (limited to 'aoc2017-gleam/src/aoc_2017')
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_1.gleam | 32 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_10.gleam | 77 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_11.gleam | 75 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_12.gleam | 44 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_13.gleam | 58 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_14.gleam | 82 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_15.gleam | 93 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_16.gleam | 104 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_17.gleam | 55 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_2.gleam | 47 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_3.gleam | 87 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_4.gleam | 31 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_5.gleam | 48 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_6.gleam | 65 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_7.gleam | 108 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_8.gleam | 131 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_9.gleam | 48 |
17 files changed, 0 insertions, 1185 deletions
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 - } -} |