my solutions to advent of code
aoc advent-of-code
at main 4.7 kB view raw
1import gleam/dict.{type Dict} 2import gleam/int 3import gleam/io 4import gleam/list 5import gleam/set.{type Set} 6import gleam/string 7import simplifile.{read} 8 9pub type Relation { 10 Relation(person: String, neighbor: String) 11} 12 13pub type SingularHappinessDict = 14 Dict(Relation, Int) 15 16pub type HappinessDict = 17 Dict(Relation, Int) 18 19pub type People = 20 Set(String) 21 22pub type Sign { 23 Gain 24 Lose 25} 26 27fn do_find_happiest_table( 28 happiness_dict, 29 people, 30 first_person first_person, 31 last_person last_person, 32 table table, 33) { 34 case people |> set.is_empty { 35 True -> { 36 let assert Ok(relation) = 37 happiness_dict |> dict.get(Relation(last_person, first_person)) 38 as "There should be more than one person" 39 table + relation 40 } 41 False -> { 42 people 43 |> set.fold(0, fn(happiest_table, person) { 44 let assert Ok(relation) = 45 happiness_dict |> dict.get(Relation(last_person, person)) 46 as { 47 "Relation between " 48 <> { last_person <> " and " <> person } 49 <> " was not found" 50 } 51 // ok so i figured out why this works, it's because it's only comparing to stuff that starts at the same level 52 let table = 53 do_find_happiest_table( 54 happiness_dict, 55 people |> set.delete(person), 56 first_person, 57 last_person: person, 58 table: table + relation, 59 ) 60 case table > happiest_table { 61 True -> table 62 False -> happiest_table 63 } 64 }) 65 } 66 } 67} 68 69pub fn find_happiest_table(happiness_dict: HappinessDict, people: People) { 70 let assert Ok(person) = people |> set.to_list |> list.first 71 as "People list is empty" 72 do_find_happiest_table( 73 happiness_dict, 74 people |> set.delete(person), 75 first_person: person, 76 last_person: person, 77 table: 0, 78 ) 79} 80 81pub fn parse_sign(sign: String) { 82 case sign { 83 "gain" -> Ok(Gain) 84 "lose" -> Ok(Lose) 85 _ -> Error("Some sign input was neither gain or lose: " <> sign) 86 } 87} 88 89pub fn main() { 90 let assert Ok(input) = read(from: "../input.txt") as "Input file not found" 91 92 let singular_happiness_dict: SingularHappinessDict = 93 input 94 |> string.trim 95 |> string.split("\n") 96 |> list.map(fn(value) { 97 case value |> string.split(" ") { 98 // (person) would (gain/lose) (amount) happiness units by sitting next to (neighbor.) 99 [person, _, sign, happiness, _, _, _, _, _, _, neighbor] -> { 100 let assert Ok(happiness) = happiness |> int.base_parse(10) 101 as { "Happiness values should be integers: " <> happiness } 102 let sign = case parse_sign(sign) { 103 Ok(sign) -> sign 104 Error(message) -> panic as message 105 } 106 let happiness = case sign { 107 Gain -> happiness 108 Lose -> happiness |> int.negate 109 } 110 111 let neighbor = case neighbor |> string.last { 112 Ok(".") -> neighbor |> string.drop_end(1) 113 _ -> panic as { "Neighbor didn't end in a dot: " <> neighbor } 114 } 115 116 #(Relation(person, neighbor), happiness) 117 } 118 _ -> panic as { "Value doesn't match constrainsts" <> value } 119 } 120 }) 121 |> dict.from_list 122 123 let happiness_dict: HappinessDict = 124 singular_happiness_dict 125 |> dict.fold(dict.new(), fn(hd, relation, singular_happiness) { 126 let Relation(person1, person2) = relation 127 128 case hd |> dict.has_key(relation) { 129 False -> { 130 let other_relation = Relation(person2, person1) 131 let assert Ok(other_singular_happiness) = 132 singular_happiness_dict |> dict.get(other_relation) 133 as "Malformed singular_happiness_dict" 134 let total_happiness = singular_happiness + other_singular_happiness 135 136 hd 137 |> dict.insert(relation, total_happiness) 138 |> dict.insert(other_relation, total_happiness) 139 } 140 True -> hd 141 } 142 }) 143 144 let people: People = 145 singular_happiness_dict 146 |> dict.fold(set.new(), fn(people, relation, _) { 147 people |> set.insert(relation.person) 148 }) 149 150 "Part 1" |> io.println 151 let happiest_table = find_happiest_table(happiness_dict, people) 152 happiest_table |> int.to_string |> io.println 153 154 "Part 2" |> io.println 155 let relations_with_me: HappinessDict = 156 people 157 |> set.to_list 158 |> list.map(fn(person) { 159 [#(Relation(person, "Me"), 0), #(Relation("Me", person), 0)] 160 }) 161 |> list.flatten 162 |> dict.from_list 163 let happiness_dict = happiness_dict |> dict.merge(relations_with_me) 164 let people = people |> set.insert("Me") 165 166 let happiest_table_with_me = find_happiest_table(happiness_dict, people) 167 happiest_table_with_me |> int.to_string |> io.println 168}