my aoc solutions
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

mend

nnuuvv dcccb52e 47d524b3

+199
+93
src/aoc_2025/day_2.gleam
··· 1 + import gleam/int 2 + import gleam/list 3 + import gleam/result 4 + import gleam/string 5 + 6 + pub fn parse(input: String) -> List(Int) { 7 + let assert Ok(values) = { 8 + use values <- result.try( 9 + string.split(input, ",") 10 + |> list.map(string.split_once(_, "-")) 11 + |> result.all, 12 + ) 13 + 14 + use values <- result.try( 15 + values 16 + |> list.map(fn(val) { 17 + use first <- result.try(int.parse(val.0)) 18 + use second <- result.try(int.parse(val.1)) 19 + 20 + Ok(#(first, second)) 21 + }) 22 + |> result.all, 23 + ) 24 + 25 + let values = list.flat_map(values, fn(val) { list.range(val.0, val.1) }) 26 + 27 + Ok(values) 28 + } 29 + as "Invalid input" 30 + 31 + values 32 + } 33 + 34 + pub fn pt_1(input: List(Int)) { 35 + input 36 + |> list.filter(filter_pt_1) 37 + |> list.fold(0, int.add) 38 + } 39 + 40 + fn filter_pt_1(value: Int) -> Bool { 41 + let value = int.to_string(value) 42 + let length = string.length(value) 43 + 44 + case int.is_odd(length) { 45 + True -> False 46 + False -> { 47 + let half = 48 + value 49 + |> string.drop_start(length / 2) 50 + string.starts_with(value, half) 51 + } 52 + } 53 + } 54 + 55 + pub fn pt_2(input: List(Int)) { 56 + input 57 + |> list.filter(pt_2_filter) 58 + |> list.fold(0, int.add) 59 + } 60 + 61 + fn pt_2_filter(value: Int) -> Bool { 62 + let value = int.to_string(value) 63 + let length = string.length(value) 64 + 65 + divisors(of: length, starting_at: length / 2, acc: []) 66 + |> list.any(fn(divisor) { 67 + let after_split_reassemble = 68 + value 69 + |> string.to_graphemes 70 + |> list.sized_chunk(length / divisor) 71 + |> list.map(list.fold(_, "", fn(a, b) { a <> b })) 72 + |> list.unique 73 + 74 + case after_split_reassemble { 75 + // there is one item left 76 + // and it isnt just the initial string split and reassembled 77 + [remaining] if remaining != value -> True 78 + _ -> False 79 + } 80 + }) 81 + } 82 + 83 + fn divisors( 84 + of n: Int, 85 + starting_at potential_divisor: Int, 86 + acc acc: List(Int), 87 + ) -> List(Int) { 88 + case n % potential_divisor { 89 + _ if potential_divisor == 0 -> [n, ..acc] 90 + 0 -> divisors(n, potential_divisor - 1, [potential_divisor, ..acc]) 91 + _ -> divisors(n, potential_divisor - 1, acc) 92 + } 93 + }
+106
src/aoc_2025/day_3.gleam
··· 1 + import gleam/int 2 + import gleam/list 3 + import gleam/pair 4 + import gleam/result 5 + import gleam/string 6 + 7 + pub fn parse(input: String) { 8 + string.split(input, "\n") 9 + |> list.map(string.to_graphemes) 10 + |> list.map(list.map(_, int.parse)) 11 + |> list.map(parsed_to_batterybank) 12 + } 13 + 14 + fn parsed_to_batterybank(parsed: List(Result(Int, Nil))) { 15 + let assert Ok(value) = result.all(parsed) 16 + BatteryBank(value) 17 + } 18 + 19 + pub type BatteryBank { 20 + BatteryBank(batteries: List(Int)) 21 + } 22 + 23 + pub fn pt_1(input: List(BatteryBank)) { 24 + input 25 + |> list.map(fn(battery_bank) { 26 + list.fold_right(battery_bank.batteries, #(0, 0), fn(largest, current) { 27 + case largest { 28 + // first loop 29 + #(0, 0) -> #(0, current) 30 + // second loop 31 + #(0, last) -> #(current, last) 32 + #(ten_spot, one_spot) if current >= ten_spot && ten_spot > one_spot -> #( 33 + current, 34 + ten_spot, 35 + ) 36 + #(ten_spot, one_spot) if current >= ten_spot && ten_spot <= one_spot -> #( 37 + current, 38 + one_spot, 39 + ) 40 + _ -> largest 41 + } 42 + }) 43 + }) 44 + |> list.map(fn(pair) { pair.0 * 10 + pair.1 }) 45 + |> list.fold(0, int.add) 46 + } 47 + 48 + pub fn pt_2(input: List(BatteryBank)) { 49 + input 50 + |> list.map(fn(bank) { 51 + let length = list.length(bank.batteries) 52 + 53 + let #(left_to_check, initial_selection) = 54 + bank.batteries 55 + |> list.split(length - 12) 56 + 57 + loop(left_to_check:, initial_selection:, acc: []) 58 + |> list.fold(#(1, 0), fn(acc, current_value) { 59 + let #(multiplier, accumulated_value) = acc 60 + 61 + #(multiplier * 10, accumulated_value + current_value * multiplier) 62 + }) 63 + |> pair.second 64 + }) 65 + |> list.fold(0, int.add) 66 + } 67 + 68 + fn loop( 69 + left_to_check left_to_check, 70 + initial_selection initial_selection, 71 + acc result_selected, 72 + ) { 73 + case initial_selection { 74 + [] -> result_selected 75 + [current, ..rest] -> { 76 + let left_to_check = list.reverse(left_to_check) 77 + 78 + let #(result, left_to_check) = inner_loop(current, left_to_check, [], []) 79 + 80 + // echo result as "selected" 81 + 82 + loop(left_to_check, rest, [result, ..result_selected]) 83 + } 84 + } 85 + } 86 + 87 + fn inner_loop(current, left_to_check, discard, passed_cause_smaller) { 88 + // echo left_to_check as "left" 89 + case left_to_check { 90 + // nothing left to check, return selection and discard 91 + [] -> #(current, discard) 92 + // head >= current -> discard current, head is new current 93 + [head, ..tail] if head >= current -> 94 + inner_loop( 95 + head, 96 + tail, 97 + list.append(passed_cause_smaller, [current, ..discard]), 98 + [], 99 + ) 100 + // head < current -> temp_discard head, keep current 101 + [head, ..tail] if head < current -> 102 + inner_loop(current, tail, discard, [head, ..passed_cause_smaller]) 103 + 104 + [_, ..] -> panic as "what" 105 + } 106 + }