this repo has no description
at master 9.4 kB view raw
1<!-- livebook:{"persist_outputs":true} --> 2 3# Day 14 4 5```elixir 6Mix.install([:kino_aoc, :image]) 7``` 8 9## Section 10 11<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxNCIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 12 13```elixir 14{:ok, puzzle_input} = 15 KinoAOC.download_puzzle("2024", "14", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 16``` 17 18<!-- livebook:{"output":true} --> 19 20``` 21{:ok, 22 "p=49,14 v=-82,-41\np=27,80 v=67,31\np=76,93 v=-15,-66\np=90,62 v=-84,86\np=62,86 v=46,20\np=7,72 v=25,26\np=30,32 v=-92,60\np=91,40 v=6,1\np=50,58 v=57,-21\np=71,79 v=-3,58\np=84,44 v=36,-59\np=87,12 v=-62,-95\np=69,46 v=76,39\np=50,51 v=-26,-64\np=41,58 v=30,5\np=80,97 v=-13,9\np=52,84 v=98,-50\np=52,32 v=64,39\np=52,91 v=61,20\np=31,22 v=49,45\np=85,73 v=-43,32\np=77,15 v=20,-52\np=17,10 v=74,-3\np=88,92 v=-54,26\np=20,46 v=31,-63\np=42,49 v=-26,44\np=3,101 v=40,-95\np=78,77 v=-17,48\np=10,88 v=-88,55\np=100,68 v=74,76\np=42,11 v=-97,-25\np=88,57 v=-37,93\np=11,36 v=-33,54\np=88,61 v=-58,43\np=66,47 v=-55,82\np=11,52 v=52,-60\np=9,48 v=41,-64\np=70,57 v=61,27\np=22,80 v=11,11\np=73,11 v=65,56\np=79,84 v=-28,41\np=50,79 v=-93,-12\np=55,35 v=23,-64\np=48,26 v=45,29\np=38,23 v=-86,-54\np=71,48 v=-21,6\np=60,98 v=28,-54\np=75,70 v=59,7\np=24,71 v=-20,-46\np=55,88 v=79,-23\np=13,48 v=44,49\np=37,73 v=-86,-99\np=82,12 v=-26,80\np=13,16 v=-8,30\np=86,34 v=84,99\np=45,90 v=-31,68\np=23,93 v=44,8\np=3,52 v=-65,-54\np=64,7 v=16,-30\np=97,88 v=-67,-39\np=58,87 v=72,42\np=8,70 v=-27,5\np=25,67 v=99,22\np=48,92 v=19,31\np=23,46 v=-16,-76\np=13,101 v=70,13\np=55,4 v=-25,-39\np=44,10 v=10,-59\np=56,2 v=83,67\np=90,83 v=28,42\np=28,84 v=7,-12\np=49,87 v=-7,-50\np=11,56 v=-76,87\np=27,72 v=46,-28\np=76,43 v=-59,32\np=19,50 v=80,62\np=12,1 v=44,-84\np=53,29 v=83,61\np=57,12 v=-63,-90\np=67,39 v=38,71\np=38,78 v=86,26\np=14,19 v=-72,-85\np=75,9 v=42,-43\np=89,33 v=65,-43\np=77,21 v=-64,54\np=32,72 v=-45,-71\np=9,21 v=55,-4\np=22,49 v=70,-71\np=86,73 v=-35,-7\np=32,5 v=-41,-62\np=14,51 v=89,-92\np=71,34 v=24,-69\np=87,18 v=69,-10\np=58,67 v=4,-28\np=22,75 v=15,26\np=73,14 v=-77,24\np=2,26 v=-12,91\np=53,3 v=38,-57\np=49,35 v=-37,-59\np=25,87 v=52,-83\np=47,74 v=46,-22\np=70,22 v=-81,24\np=46,57 v=23,-76\np=59,96 v=27,-40\np=72,77 v=99,28\np=66,89 v=61,-67\np=46,43 v=70,-23\np=30,55 v=-67,48\np=8,75 v=89,-17\np=15,29 v=-86,-3\np=53,2 v=38,-56\np=6,90 v=55,-83\np=44,83 v=8,-50\np=2,56 v=-54,-43\np=30,13 v=19,-62\np=21,97 v=-78,-46\np=13,53 v=70,22\np=2,5 v=59,56\np=2,48 v=18,50\np=81,94 v=92,57\np=1,1 v=6,-59\np=99,61 v=-65,-76\np=99,95 v=-24,35\np=17,53 v=-84,19\np=33,77 v=-4,53\np=100,32 v=-3,-43\np=60,74 v=-10,97\np=23,54 v=-57,-75\np=56,69 v=27,21\np=58,100 v=-51,44\np=43,77 v=-41,-93\np=75,3 v=80,13\np=66,32 v=72,34\np=67,67 v=-32,69\np=80,80 v=-23,-3\np=62,23 v=-4,48\np=77,0 v=87,30\np=2,96 v=-35,-73\np=15,4 v=4,-38\np=92,56 v=-54,-16\np=90,46 v=26,-16\np=75,2 v=1,67\np=59,71 v=-59,-33\np=79,21 v=-62,24\np=34,99 v=45,14\np=49,18 v=-37,-76\np=63,26 v=79,-41\np=97,54 v=-80,71\np=66,18 v=69,-30\np=14,25 v=74,-90\np=9,95 v=-87,96\np=24,39 v=-8,83\np=32,98 v=-75,79\np=36,50 v=-23,-92\np=97,36 v=-73,86\np=66,36 v=23,-53\np=84,3 v=2,95\np=89,73 v=48,26\np=3,94 v=-46,68\np=61,75 v=-52,-98\np=51,36 v=8,50\np=70,48 v=80,-2\np=32,39 v=-54,4\np=73,85 v=-92,-72\np=22,70 v=-12,38\np=92,48 v=-92,93\np=100,79 v=-76,-12\np=1,52 v=-43,65\np=22,98 v=78,52\np=35,76 v=-97,48\np=52,14 v=-48,-74\np=7,55 v=29,98\np=79,40 v=-2,-38\np=90,91 v=57,-72\np=60,3 v=-14,-94\np=34,69 v=-56,32\np=63,19 v=-44,24\np=48,71 v=-18,-98\np=90,42 v=-87,9\np=73,59 v=27,-28\np=30,66 v=18,-48\np=9,54 v=-79,-43\np=57,73 v=-73,-34\np=75,93 v=-39,60\np=31,75 v=-98,86\np=93,86 v=-95,-45\np=64,33 v=33,4\np=62,27 v=12,46\np=76,93 v=91,58\np=92,23 v=-13,29\np=54,93 v=69,51\np=19,53 v=59,-16\np=78,90 v=84,-7\np=17,93 v=33,25\np=100,73 v=5,59\np=74,39 v=80,28\np=88,4 v=84,19\np=63,98 v=-65,-2\np=81,98 v=32,4\np=64,89 v=-7,9\np=88,3 v=-35,9\np=77,14 v=-62,-79\np=15,15 v=18,-41\np=40,4 v=41,-24\np=14,68 v=89,-98\np=77,71 v=-14,97\np=69,28 v=1,-9\np=16,102 v=-87,52\np=26,20 v=-62,15\np=100,25 v=28,-37\np=22,63 v=93,-5\np=9,47 v=77,-47\np=78,36 v=76,-95\np=41,84 v=52,63\np=14,6 v=30,-88\np=99,72 v=59,42\np=72,45 v=7,-21\np=99,71 v=-20,-98\np=30,40 v=-6,82\np=75,50 v=-99,97\np=91,80 v=8,44\np=7,44 v=52,-91\np=96,12 v=-50,-74\np=72,48 v=-88,-33\np=21,7 v=-29,-3\np=96,38 v=2,-48\np=33,22 v=86,-36\np=79,84 v=-36,-77\np=87,65 v=2,48\np=46,42 v=98,-11\np=60,79 v=80,-27\np=95,3 v=-2,-94\np=94,75 v=88,-29\np=16,66 v=-24,48\np=83,51 v=-24,-64\np=54,94 v=-10,-7\np=0,96 v=-8,-96\np=4,50 v=-31,71\np=21,98 v=-66,-4\np=50,85 v=-48,69\np=71,14 v=5,67\np=19,56 v=71,6\np=18,43 v=-16,-49\np=11,25 v=18,45\np=38,90 v=-52,-34\np=50,9 v=-89,73\np=15,23 v=" <> ...} 23``` 24 25```elixir 26robots = 27 puzzle_input 28 |> String.split("\n", trim: true) 29 |> Enum.map(fn row -> 30 ["p=" <> pos, "v=" <> v] = String.split(row, " ") 31 32 pos = pos |> String.split(",") |> Enum.map(&String.to_integer/1) |> List.to_tuple() 33 v = v |> String.split(",") |> Enum.map(&String.to_integer/1) |> List.to_tuple() 34 35 %{pos: pos, v: v} 36 end) 37``` 38 39<!-- livebook:{"output":true} --> 40 41``` 42[ 43 %{pos: {49, 14}, v: {-82, -41}}, 44 %{pos: {27, 80}, v: {67, 31}}, 45 %{pos: {76, 93}, v: {-15, -66}}, 46 %{pos: {90, 62}, v: {-84, 86}}, 47 %{pos: {62, 86}, v: {46, 20}}, 48 %{pos: {7, 72}, v: {25, 26}}, 49 %{pos: {30, 32}, v: {-92, 60}}, 50 %{pos: {91, 40}, v: {6, 1}}, 51 %{pos: {50, 58}, v: {57, -21}}, 52 %{pos: {71, 79}, v: {-3, 58}}, 53 %{pos: {84, 44}, v: {36, -59}}, 54 %{pos: {87, 12}, v: {-62, -95}}, 55 %{pos: {69, 46}, v: {76, 39}}, 56 %{pos: {50, 51}, v: {-26, -64}}, 57 %{pos: {41, 58}, v: {30, 5}}, 58 %{pos: {80, 97}, v: {-13, 9}}, 59 %{pos: {52, 84}, v: {98, -50}}, 60 %{pos: {52, 32}, v: {64, 39}}, 61 %{pos: {52, 91}, v: {61, 20}}, 62 %{pos: {31, 22}, v: {49, 45}}, 63 %{pos: {85, 73}, v: {-43, 32}}, 64 %{pos: {77, 15}, v: {20, -52}}, 65 %{pos: {17, 10}, v: {74, -3}}, 66 %{pos: {88, 92}, v: {-54, 26}}, 67 %{pos: {20, 46}, v: {31, -63}}, 68 %{pos: {42, 49}, v: {-26, 44}}, 69 %{pos: {3, 101}, v: {40, -95}}, 70 %{pos: {78, 77}, v: {-17, 48}}, 71 %{pos: {10, 88}, v: {-88, 55}}, 72 %{pos: {100, 68}, v: {74, 76}}, 73 %{pos: {42, 11}, v: {-97, -25}}, 74 %{pos: {88, 57}, v: {-37, 93}}, 75 %{pos: {11, 36}, v: {-33, 54}}, 76 %{pos: {88, 61}, v: {-58, 43}}, 77 %{pos: {66, 47}, v: {-55, 82}}, 78 %{pos: {11, 52}, v: {52, -60}}, 79 %{pos: {9, 48}, v: {41, -64}}, 80 %{pos: {70, 57}, v: {61, 27}}, 81 %{pos: {22, 80}, v: {11, 11}}, 82 %{pos: {73, 11}, v: {65, 56}}, 83 %{pos: {79, 84}, v: {-28, 41}}, 84 %{pos: {50, 79}, v: {-93, -12}}, 85 %{pos: {55, 35}, v: {23, -64}}, 86 %{pos: {48, 26}, v: {45, 29}}, 87 %{pos: {38, 23}, v: {-86, -54}}, 88 %{pos: {71, 48}, v: {-21, 6}}, 89 %{pos: {60, 98}, v: {28, ...}}, 90 %{pos: {75, ...}, v: {...}}, 91 %{pos: {...}, ...}, 92 %{...}, 93 ... 94] 95``` 96 97```elixir 98room = {w, h} = {101, 103} 99``` 100 101<!-- livebook:{"output":true} --> 102 103``` 104{101, 103} 105``` 106 107```elixir 108defmodule Robot do 109 def walk(robots, room, n \\ 1), do: Enum.map(robots, &move(&1, room, n)) 110 111 def move(%{pos: {x, y}, v: {vx, vy}}, {w, h}, by \\ 1) do 112 x = Integer.mod(x + vx * by, w) 113 y = Integer.mod(y + vy * by, h) 114 115 %{pos: {x, y}, v: {vx, vy}} 116 end 117 118 def quad(%{pos: {x, y}}, {w, h}) do 119 hw = div(w - 1, 2) 120 hh = div(h - 1, 2) 121 122 if x == hw or y == hh do 123 :middle 124 else 125 {sign(x - hw), sign(y - hh)} 126 end 127 end 128 129 defp sign(0), do: 0 130 defp sign(n) when n < 0, do: -1 131 defp sign(n) when n > 0, do: 1 132 133 def with_neighbours(robots) do 134 set = MapSet.new(robots, & &1.pos) 135 136 with_neighbours = 137 Enum.count(robots, fn %{pos: {x, y}} -> 138 [{x + 1, y}, {x - 1, y}, {x, y - 1}, {x, y + 1}] |> Enum.any?(&(&1 in set)) 139 end) 140 141 div(with_neighbours * 100, length(robots)) 142 end 143end 144``` 145 146<!-- livebook:{"output":true} --> 147 148``` 149{:module, Robot, <<70, 79, 82, 49, 0, 0, 18, ...>>, {:with_neighbours, 1}} 150``` 151 152## Part 1 153 154```elixir 155robots 156|> Robot.walk(room, 100) 157|> Enum.group_by(fn robot -> Robot.quad(robot, room) end) 158|> Map.new(fn {k, l} -> {k, length(l)} end) 159|> Map.drop([:middle]) 160|> Map.values() 161|> Enum.product() 162``` 163 164<!-- livebook:{"output":true} --> 165 166``` 167219150360 168``` 169 170## Part 2 171 172Hack that I have found over the internet - if more than 60% of the robots have neighbours, you have found solution. 173 174Othe hack that I have found - checking whether there are no robots that are occupying the same position - didn't work for me. 175 176```elixir 177{tree, steps} = 178 Stream.from_index() 179 |> Task.async_stream( 180 fn step -> 181 robots = Robot.walk(robots, room, step) 182 183 if Robot.with_neighbours(robots) >= 60, do: {robots, step} 184 end, 185 ordered: false 186 ) 187 |> Enum.find_value(fn {:ok, val} -> val end) 188 189steps 190``` 191 192<!-- livebook:{"output":true} --> 193 194``` 1958053 196``` 197 198```elixir 199Image.new!(w, h) 200|> Image.mutate(fn img -> 201 for %{pos: {x, y}} <- tree do 202 # Add some festivity 203 color = 204 if abs(:math.sin(x + y)) < 0.5 do 205 :red 206 else 207 :green 208 end 209 210 Image.Draw.point(img, x, y, color: color) 211 end 212 213 {:ok, img} 214end) 215|> elem(1) 216|> Image.resize!(4, interpolate: :nearest) 217``` 218 219<!-- livebook:{"offset":9213,"stamp":{"token":"XCP.bbViODF6Z4_TcNSzpaXWzuFflurdyZ5JsvKHJZr6NjgJ4MQaH2OorTxA-YR5uDBN5HxiB0uC5hX0vi-Kgdm26HMcOubYpE_c39bjuPfPH_BH4SVxLeEac5c8aaRtPdt7CJk","version":2}} -->