this repo has no description
at master 2.8 kB view raw
1<!-- vim:set ft=markdown: --> 2 3<!-- livebook:{"persist_outputs":true} --> 4 5# Day 4 6 7## Input 8 9This time it is a little bit more convoluted, as there are 2 parts of the input. 10Fortunately we can easily disect the parts via pattern matching. 11 12Technically the conversion to the numbers is not needed, but it does no harm 13and provides additional layer of safety against some whitespace characters left there 14and here. 15 16The `Day4.win/2` function is manually unrolled, as it is easier to write than some 17random jumping in the list. 18 19<!-- livebook:{"disable_formatting":true} --> 20 21```elixir 22[numbers | bingos] = 23 File.read!("day4.txt") 24 |> String.split("\n\n", trim: true) 25 26numbers = 27 numbers 28 |> String.trim() 29 |> String.split(",") 30 |> Enum.map(&String.to_integer/1) 31 32bingos = 33 bingos 34 |> Enum.map(fn bingo -> 35 bingo 36 |> String.split(~r/\s+/, trim: true) 37 |> Enum.map(&String.to_integer/1) 38 end) 39 40defmodule Day4 do 41 def win( 42 [ 43 a1, a2, a3, a4, a5, 44 b1, b2, b3, b4, b5, 45 c1, c2, c3, c4, c5, 46 d1, d2, d3, d4, d5, 47 e1, e2, e3, e4, e5 48 ], 49 nums 50 ) do 51 # Rows 52 all_in([a1, a2, a3, a4, a5], nums) or 53 all_in([b1, b3, b3, b4, b5], nums) or 54 all_in([c1, c2, c3, c4, c5], nums) or 55 all_in([d1, d2, d3, d4, d5], nums) or 56 all_in([e1, e2, e3, e4, e5], nums) or 57 # Columns 58 all_in([a1, b1, c1, d1, e1], nums) or 59 all_in([a2, b2, c2, d2, e2], nums) or 60 all_in([a3, b3, c3, d3, e3], nums) or 61 all_in([a4, b4, c4, d4, e4], nums) or 62 all_in([a5, b5, c5, d5, e5], nums) 63 end 64 65 def not_matched(bingo, nums) do 66 Enum.reject(bingo, &(&1 in nums)) 67 end 68 69 defp all_in(list, nums) do 70 Enum.all?(list, &(&1 in nums)) 71 end 72end 73``` 74 75```output 76{:module, Day4, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:all_in, 2}} 77``` 78 79## Task 1 80 81We simply traverse the `numbers` list aggregating the numbers (order doesn't really matter, 82here we aggregate them in reverse order to speedup the code). When we have enough numbers 83that any of the `bingos` is winning one, then we halt the reduction and return computed 84result. 85 86```elixir 87numbers 88|> Enum.reduce_while([], fn elem, acc -> 89 matches = [elem | acc] 90 91 case Enum.find(bingos, &Day4.win(&1, matches)) do 92 nil -> {:cont, matches} 93 bingo -> {:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem} 94 end 95end) 96``` 97 98```output 9934506 100``` 101 102## Task 2 103 104```elixir 105numbers 106|> Enum.reduce_while({bingos, []}, fn elem, {bingos, acc} -> 107 matches = [elem | acc] 108 109 case bingos do 110 [bingo] -> 111 if Day4.win(bingo, matches) do 112 {:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem} 113 else 114 {:cont, {bingos, matches}} 115 end 116 117 _ -> 118 {:cont, {Enum.reject(bingos, &Day4.win(&1, matches)), matches}} 119 end 120end) 121``` 122 123```output 1247686 125```