this repo has no description
1<!-- livebook:{"persist_outputs":true} --> 2 3# Day 12 4 5```elixir 6Mix.install([ 7 {:kino_aoc, git: "https://github.com/ljgago/kino_aoc"}, 8 {:libgraph, ">= 0.0.0"} 9]) 10``` 11 12<!-- livebook:{"output":true} --> 13 14``` 15:ok 16``` 17 18## Section 19 20<!-- livebook:{"attrs":{"day":"12","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 21 22```elixir 23{:ok, puzzle_input} = 24 KinoAOC.download_puzzle("2022", "12", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 25``` 26 27<!-- livebook:{"output":true} --> 28 29``` 30{:ok, 31 "abccccaaacaccccaaaaacccccccaaccccccccaaaaaaccccccaaaaaccccccccccaaaaaaaaacccccccaaaaaaaaaaaaaaccaaaaaccccccccccccaccacccccccccccccccccccccccccccccccccccccccaaaaaa\nabccaacaaaaaccaaaaacccccaaaaaccccccccaaaaaaccccccaaaaaacccccccccaaaaaaaaaaaaacccaaaaaaaaaaaaaaaaaaaaaccccccccccccaaaacccccccccccccccccccccccccccccccccccccccaaaaaa\nabccaaaaaaaaccaaaaaacccccaaaaaccccccaaaaaaaacccccaaaaaaccccccccccaaaaaaaaaaaacccaaaaaacaaaaaacaaaaaaaaccccccccccaaaaacccccaccccccccccccccccccaaacccccccccccccaaaaa\nabcccaaaaaccccccaaaacccccaaaaacccccaaaaaaaaaaccccaaaaaacccccccccaaaaaaaaaaaaaacaaaaaaaaaaaaaacaaaaaaaaccccccccccaaaaaacccaaacccccccccccccccccaaaccccccccccccccaaaa\nabaaacaaaaacccccacccccccaaaaaccccccaaaaaaaaaaccccccaaaccccccccccaaaaaaaaacaaaaaaaaaaaaaaaaaaacccaaacaccaaaccccccaaaaaaaacaaacccccccccccaaccccaaacccccccccccccccaac\nabaaacaacaaaaccccccccccccccaaccccccacaaaaacccccaacccccccccccccccaaaacaaaaaaaaaacccaacccaaacaacccaaccccaaaaccccccccaacaaaaaaaaaaccccccccaaaaccaaaccccccccccccccaaac\nabaaccaaccaaacacccccccccccccccccccccccaaaacccaaaaaaccaaaccccccccccaacaaaaaaaaaacccaaccccccccccccccccccaaaaccccccccccccaaaaaaaaaccccccciiiiiaaaaacccccccccccccccccc\nabaaccccaaaaaaaacccccccccccccccccccccccaaccccaaaaaaccaaaaaccccacccaaccaaacaaaaacccccccccccccccaacccccccaaaccccccccccccccaaaaacccccccciiiiiiiiaaaaaccccccaaaccccccc\nabaaacccaaaaaaaacccccccccccccccccccccccccccccaaaaaacaaaaaccccaaaaaaaccaaccaaacccccccaaaaacacccaaccccccccccaacccccccccccaaaaaaccccccciiiiiiiiijjaaaaaccccaaacaccccc\nabaaaccccaaaaaaccccccccccccccccccccaaccccccccaaaaaccaaaaacccccaaaaaaaaccccccccccccccaaaaaaaaaaaaccccccccccaaacaaccccccaaaaaaaccccccciiinnnnoijjjjjjjjjjaaaaaaacccc\nabccccccccaaaaacccccaacccccccccccaaaacccccccccaaaacccaaaaaccccaaaaaaaaacccccccccccccaaaaaaaaaaaaaaccccccccaaaaaacccaacaaacaaacccccchhinnnnnoojjjjjjjjjkkaaaaaacccc\nabcccccccaaaaaacaaacaacccccccccccaaaaaaccccccccccccccaacccccccaaaaaaaaacaaccccccccccaaaaaaaaaaaaaaacccccaaaaaaacccaaaaccccccacaaccchhinnnnnoooojjjjjjkkkkaaaaccccc\nabaacccaccaaaccccaaaaaccccccccccccaaaaccccccccccccccccccccccccaaaaaaaacaaaaaaaccccccaaaaaaaaaaaaaaacccccaaaaaaacccaaaaccccaaacaaachhhnnntttuooooooooppkkkaaaaccccc\nabaacccaaaaaaaccccaaaaaacccccccccaaaaaccccccccccccccccccccccccaaaaaaacccaaaaacccccccccaaacaaaaaaaaccccccccaaaaacccaaaacccccaaaaacchhhnnnttttuooooooppppkkkaaaccccc\nabaacccaaaaaaccccaaaaaaacccccccccaacaaccccccccccccccccccccccaaaccaaaccaaaaaaacccccccccccccaaaaaaaccccccaacaacaaacccccccccccaaaaaahhhhnntttttuuouuuuupppkkkcccccccc\nabaaaacaaaaaaaaaaaaaaacccccccccccccccccccccccccccccccccccccaaaacccaaacaaaaaaaaccccccccccccaccaaaccccccaaacaaccccccccccccccaaaaaahhhhnnntttxxxuuuuuuupppkkkcccccccc\nabaaaacaaaaaaaaaaacaaacccaaacccccccccccccccccccccacccccccccaaaacccccccaaaaaaaaccccccccccccccccaaacccccaaacaaacccccccccccccaaaaaahhhhmnnttxxxxuuyuuuuuppkkkcccccccc\nabaaaccaaaaaaaaccccaaaccccaaaccacccccccccccaaaaaaaaccccccccaaaacccccccccaaacaacccccccccccccccccccccaaaaaaaaaacccccacccccccaacaghhhmmmmtttxxxxxxyyyuupppkkccccccccc\nabaaccaaaaaaaccccccccccccaaaaaaaacccccccccccaaaaaaccccccccccccccccccccccaaccccccaacccccccccccccccccaaaaaaaaacccccaaccccccccccagggmmmmttttxxxxxyyyyvvppkkkccccccccc\nabaacccaccaaacccccccccccaaaaaaaaccccccccccccaaaaaaccccccccccccccccccccccccccaaacaaaccccccccccccccccccaaaaaccccaaaaacaacccccccgggmmmmttttxxxxxyyyyvvpppiiiccccccccc\nSbaaaaaccccaaccccccccccaaaaaaaaacacccccccccaaaaaaaacccccccccccccccaacccccccccaaaaaccccccccccaaaacccccaaaaaacccaaaaaaaaccaaaccgggmmmsssxxxEzzzzyyvvvpppiiiccccccccc\nabaaaaaccccccccccccccccaaaaaaaaaaaaaaaaaccaaaaaaaaaacccccccccccaaaaacccccccccaaaaaaaccccccccaaaaaccccaaaaaaaccccaaaaacccaaaaagggmmmsssxxxxxyyyyyyvvqqqiiiccccccccc\nabaaaaacccccccccccccccccaaaaaaaacaaaaaacccaaaaaaaaaaccccccccccccaaaaacccccccaaaaaaaacccccccaaaaaaccccaaacaaacccaaaaacccaaaaaagggmmmssswwwwwyyyyyyyvvqqqiiicccccccc\nabaaaaccccccccccccccccccccaaaaaaaaaaaaacccacacaaacccccccccccccccaaaaacccccccaaaaaaaacccccccaaaaaaccccacccccccccaacaaaccaaaaaagggmmmsssswwwwyyyyyyyvvvqqiiicccccccc\nabaaaaacccccccccccccccccccaacccaaaaaaaaaccccccaaaccccccccccccccaaaaaccccccccaacaaacccccccccaaaaaacccccccccccccccccaaccccaaaaagggmmmmssssswwyywwvvvvvvqqiiicccccccc\nabaaaaacccccccccccccc" <> ...} 32``` 33 34```elixir 35# puzzle_input = """ 36# Sabqponm 37# abcryxxl 38# accszExk 39# acctuvwj 40# abdefghi 41# """ 42``` 43 44<!-- livebook:{"output":true} --> 45 46``` 47nil 48``` 49 50```elixir 51min = ?a - ?a 52max = ?z - ?a 53 54{map, start, stop} = 55 puzzle_input 56 |> String.split("\n", trim: true) 57 |> Enum.map(&to_charlist/1) 58 |> Enum.with_index() 59 |> Enum.flat_map(fn {line, y} -> 60 line 61 |> Enum.with_index() 62 |> Enum.map(fn {c, x} -> {{x, y}, c} end) 63 end) 64 |> Enum.reduce({%{}, nil, nil}, fn {p, v}, {map, s, e} -> 65 case v do 66 ?S -> {Map.put(map, p, min), p, e} 67 ?E -> {Map.put(map, p, max), s, p} 68 _ -> {Map.put(map, p, v - ?a), s, e} 69 end 70 end) 71 72graph = 73 map 74 |> Enum.reduce(Graph.new(), fn {p, v}, graph -> 75 {x, y} = p 76 77 graph = 78 if map[{x - 1, y}] && v + 1 >= map[{x - 1, y}], 79 do: Graph.add_edge(graph, {x, y}, {x - 1, y}, label: [v, map[{x - 1, y}]]), 80 else: graph 81 82 graph = 83 if map[{x + 1, y}] && v + 1 >= map[{x + 1, y}], 84 do: Graph.add_edge(graph, {x, y}, {x + 1, y}, label: [v, map[{x + 1, y}]]), 85 else: graph 86 87 graph = 88 if map[{x, y - 1}] && v + 1 >= map[{x, y - 1}], 89 do: Graph.add_edge(graph, {x, y}, {x, y - 1}, label: [v, map[{x, y - 1}]]), 90 else: graph 91 92 graph = 93 if map[{x, y + 1}] && v + 1 >= map[{x, y + 1}], 94 do: Graph.add_edge(graph, {x, y}, {x, y + 1}, label: [v, map[{x, y + 1}]]), 95 else: graph 96 end) 97``` 98 99<!-- livebook:{"output":true} --> 100 101``` 102warning: variable "graph" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used) 103 2022/day12.livemd#cell:7urrvoyk6ltuxa4kdqc63nncfh37x2fn:30 104 105``` 106 107<!-- livebook:{"output":true} --> 108 109``` 110#Graph<type: directed, num_vertices: 6642, num_edges: 24117> 111``` 112 113## Task 1 114 115```elixir 116length(Graph.get_shortest_path(graph, start, stop)) - 1 117``` 118 119<!-- livebook:{"output":true} --> 120 121``` 122437 123``` 124 125```elixir 126graph.vertices 127``` 128 129<!-- livebook:{"output":true} --> 130 131``` 132%{ 133 1148931603 => {118, 31}, 134 15476201 => {158, 33}, 135 3480980581 => {19, 26}, 136 513279067 => {86, 0}, 137 1642831488 => {111, 2}, 138 669567979 => {38, 18}, 139 1898334127 => {77, 28}, 140 2414760132 => {41, 27}, 141 1433989350 => {134, 33}, 142 4010762779 => {100, 37}, 143 1619384061 => {142, 27}, 144 2736818014 => {105, 29}, 145 3132807327 => {56, 13}, 146 1603662291 => {94, 23}, 147 183280155 => {35, 27}, 148 2518352043 => {127, 27}, 149 824501714 => {15, 33}, 150 1813555375 => {70, 18}, 151 733666720 => {72, 5}, 152 4293490381 => {13, 24}, 153 4037128590 => {87, 10}, 154 1287605231 => {99, 3}, 155 2697150767 => {19, 29}, 156 3345146674 => {78, 5}, 157 811252706 => {132, 14}, 158 3035418479 => {156, 5}, 159 2090318173 => {149, 1}, 160 1306366779 => {71, 39}, 161 113692275 => {158, 28}, 162 1809958846 => {4, 0}, 163 2979249361 => {95, 23}, 164 712034521 => {2, 34}, 165 838646858 => {127, 2}, 166 2636390019 => {97, 34}, 167 200998860 => {73, 23}, 168 2440897975 => {91, 7}, 169 2757930521 => {103, 38}, 170 2626031906 => {92, 21}, 171 4000959801 => {44, 20}, 172 2762901234 => {69, 16}, 173 3967362516 => {72, 9}, 174 1858208296 => {81, 16}, 175 3063825234 => {140, 14}, 176 1669140133 => {46, 21}, 177 684221776 => {146, 38}, 178 623366404 => {63, 40}, 179 3623360588 => {149, 6}, 180 2885933829 => {137, 14}, 181 3219344086 => {136, ...}, 182 3451324297 => {...}, 183 ... 184} 185``` 186 187## Task 2 188 189```elixir 190tgraph = Graph.transpose(graph) 191``` 192 193<!-- livebook:{"output":true} --> 194 195``` 196#Graph<type: directed, num_vertices: 6642, num_edges: 24117> 197``` 198 199```elixir 200lowest = 201 Enum.flat_map(map, fn 202 {p, 0} -> [p] 203 _ -> [] 204 end) 205``` 206 207<!-- livebook:{"output":true} --> 208 209``` 210[32256290, 409066827, 186924390, 1502865800, 887663648, 2543466388, 697356458, 1070575781, 211 1659702078, 4000784021, 1947564743, 2361038489, 3904452243, 3615669650, 270460033, 1281654811, 212 3153535741, 2393890474, 3946102901, 2210758189, 2982223724, 2654353783, 2656280720, 3935389969, 213 2818948768, 4279780723, 3595206681, 3496428192, 2269119594, 2583881244, 3997991000, 520325395, 214 457672928, 1453390554, 3289433936, 2574402082, 1560492086, 3242480874, 389839366, 4176230802, 215 1147783117, 2469841095, 2034019869, 438932546, 1799582666, 1100008137, 467060197, 162439868, 216 3928107970, 800548913, ...] 217``` 218 219```elixir 220# Copied BF implementation from `libgraph` to optimise it 221 222defmodule BellmanFord do 223 @moduledoc """ 224 The Bellman–Ford algorithm is an algorithm that computes shortest paths from a single 225 source vertex to all of the other vertices in a weighted digraph. 226 It is capable of handling graphs in which some of the edge weights are negative numbers 227 Time complexity: O(VLogV) 228 """ 229 230 @type distance :: %{Graph.vertex_id() => integer} 231 232 @doc """ 233 Returns nil when graph has negative cycle. 234 """ 235 @spec call(Graph.t(), Graph.vertex()) :: [Graph.vertex()] | nil 236 def call(%Graph{vertices: vs, edges: meta}, source) do 237 distances = source |> Graph.Utils.vertex_id() |> init_distances(vs) 238 239 weights = Enum.map(meta, &edge_weight/1) 240 241 distances = 242 for _ <- 1..map_size(vs), 243 {{u, v}, weight} <- weights, 244 reduce: distances do 245 distances -> 246 case distances do 247 %{^u => :infinity} -> 248 distances 249 250 %{^u => du, ^v => dv} when du + weight < dv -> 251 %{distances | v => du + weight} 252 253 _ -> 254 distances 255 end 256 end 257 258 if has_negative_cycle?(distances, weights) do 259 nil 260 else 261 Map.new(distances, fn {k, v} -> {Map.fetch!(vertices, k), v} end) 262 end 263 end 264 265 @spec init_distances(Graph.vertex(), Graph.vertices()) :: distance 266 defp init_distances(vertex_id, vertices) do 267 Map.new(vertices, fn 268 {id, _vertex} when id == vertex_id -> {id, 0} 269 {id, _} -> {id, :infinity} 270 end) 271 end 272 273 @spec edge_weight(term) :: float 274 defp edge_weight({e, edge_value}), do: {e, edge_value |> Map.values() |> List.first()} 275 276 defp has_negative_cycle?(%{} = distances, meta) do 277 Enum.any?(meta, fn {{u, v}, weight} -> 278 %{^u => du, ^v => dv} = distances 279 280 du != :infinity and du + weight < dv 281 end) 282 end 283end 284``` 285 286<!-- livebook:{"output":true} --> 287 288``` 289{:module, BellmanFord, <<70, 79, 82, 49, 0, 0, 19, ...>>, {:has_negative_cycle?, 2}} 290``` 291 292```elixir 293min_paths = 294 tgraph 295 # |> Graph.bellman_ford(stop) 296 |> BellmanFord.call(stop) 297 |> Map.take(lowest) 298 |> Map.values() 299``` 300 301<!-- livebook:{"output":true} --> 302 303``` 304[:infinity, :infinity, :infinity, 454, :infinity, :infinity, :infinity, :infinity, :infinity, 305 :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, 306 :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, 307 :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, 308 :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, :infinity, 309 :infinity, :infinity, :infinity, :infinity, :infinity, ...] 310``` 311 312```elixir 313Enum.min(min_paths) 314``` 315 316<!-- livebook:{"output":true} --> 317 318``` 319430 320```