my solutions to advent of code
aoc advent-of-code
at main 1.5 kB view raw
1import gleam/dict.{type Dict} 2import gleam/dynamic/decode 3import gleam/int.{to_string} 4import gleam/io.{println} 5import gleam/json 6import gleam/list 7import gleam/result.{unwrap} 8import simplifile.{read} 9 10type Nested { 11 NestedList(List(Nested)) 12 NestedDict(Dict(String, Nested)) 13 IntValue(Int) 14 StringValue(String) 15} 16 17fn nested_decoder() -> decode.Decoder(Nested) { 18 use <- decode.recursive 19 decode.one_of(decode.int |> decode.map(IntValue), or: [ 20 decode.list(nested_decoder()) |> decode.map(NestedList), 21 decode.dict(decode.string, nested_decoder()) |> decode.map(NestedDict), 22 decode.string |> decode.map(StringValue), 23 ]) 24} 25 26// unfortunately this isn't tail call optimised. making it so would make it ugly :( 27fn get_total_number(data: Nested, no_red no_red) { 28 case data { 29 NestedList(items) -> 30 items 31 |> list.fold(0, fn(acc, data) { acc + get_total_number(data, no_red) }) 32 NestedDict(items) -> { 33 items 34 |> dict.values 35 |> list.fold_until(0, fn(acc, data) { 36 case no_red, data { 37 True, StringValue("red") -> list.Stop(0) 38 _, _ -> list.Continue(acc + get_total_number(data, no_red)) 39 } 40 }) 41 } 42 IntValue(v) -> v 43 _ -> 0 44 } 45} 46 47pub fn main() { 48 let assert Ok(input) = 49 read(from: "../input.json") 50 |> unwrap("") 51 |> json.parse(nested_decoder()) 52 53 println( 54 get_total_number(input, no_red: False) 55 |> to_string, 56 ) 57 println( 58 get_total_number(input, no_red: True) 59 |> to_string, 60 ) 61}