2021 day 17
This commit is contained in:
parent
f478284da5
commit
3372c8819d
2 changed files with 76 additions and 1 deletions
|
@ -16,7 +16,7 @@
|
|||
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
|
||||
| | | | [1] | [2] | [3] | [4] |
|
||||
| [5] | [6] | [7] | [8] | [9] | [10] | [11]|
|
||||
| [12]| [13]| [14]| [15] | [16] | 17 | 18 |
|
||||
| [12]| [13]| [14]| [15] | [16] | [17] | 18 |
|
||||
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
|
||||
|
||||
<!-- links -->
|
||||
|
@ -37,3 +37,4 @@
|
|||
[14]: ./lib/2021/14.ex
|
||||
[15]: ./lib/2021/15.ex
|
||||
[16]: ./lib/2021/16.ex
|
||||
[17]: ./lib/2021/17.ex
|
||||
|
|
74
2021/lib/2021/17.ex
Normal file
74
2021/lib/2021/17.ex
Normal file
|
@ -0,0 +1,74 @@
|
|||
import AOC
|
||||
|
||||
aoc 2021, 17 do
|
||||
def p1 do
|
||||
{target, {xb, yb} = bounds} = input_target()
|
||||
|
||||
for xv <- xb..0, yv <- yb..-yb do
|
||||
launch_probe(xv, yv, target, bounds)
|
||||
end
|
||||
|> Enum.filter(&match?({true, _}, &1))
|
||||
|> Enum.map(&elem(&1, 1))
|
||||
|> Enum.map(&max_height/1)
|
||||
|> Enum.max()
|
||||
end
|
||||
|
||||
def p2 do
|
||||
{target, {xb, yb} = bounds} = input_target()
|
||||
|
||||
for xv <- xb..0, yv <- yb..-yb do
|
||||
launch_probe(xv, yv, target, bounds)
|
||||
end
|
||||
|> Enum.count(&match?({true, _}, &1))
|
||||
end
|
||||
|
||||
def max_height(path) do
|
||||
path
|
||||
|> Enum.map(&elem(&1, 1))
|
||||
|> Enum.max()
|
||||
end
|
||||
|
||||
def launch_probe(xv0, yv0, target, bounds) do
|
||||
path =
|
||||
probe_path(xv0, yv0)
|
||||
|> Enum.take_while(fn curr -> not past_target?(curr, bounds) end)
|
||||
|
||||
{Enum.any?(path, &MapSet.member?(target, &1)), path}
|
||||
end
|
||||
|
||||
def probe_path(xv0, yv0) do
|
||||
Stream.unfold({{0, 0}, {xv0, yv0}}, iterate(&next/1))
|
||||
|> Stream.map(&elem(&1, 0))
|
||||
end
|
||||
|
||||
def iterate(fun), do: fn curr -> {curr, fun.(curr)} end
|
||||
|
||||
def next({_, vel} = pos_vel), do: {next_pos(pos_vel), next_vel(vel)}
|
||||
|
||||
def next_pos({{x, y}, {xv, yv}}), do: {x + xv, y + yv}
|
||||
|
||||
def next_vel({xv, yv}), do: {next_xv(xv), next_yv(yv)}
|
||||
|
||||
def next_xv(0), do: 0
|
||||
def next_xv(xv) when xv > 0, do: xv - 1
|
||||
def next_xv(xv) when xv < 0, do: xv + 1
|
||||
|
||||
def next_yv(yv), do: yv - 1
|
||||
|
||||
def past_target?({x, y}, {xb, yb}), do: past_target?(x, xb) or past_target?(y, yb)
|
||||
def past_target?(n, bound) when bound < 0, do: n < bound
|
||||
def past_target?(n, bound), do: n > bound
|
||||
|
||||
def input_target(input_string \\ input_string()) do
|
||||
[xs, ys] =
|
||||
~r/target area: x=(-?\d+)..(-?\d+), y=(-?\d+)..(-?\d+)/
|
||||
|> Regex.run(input_string, capture: :all_but_first)
|
||||
|> Enum.map(&String.to_integer/1)
|
||||
|> Enum.chunk_every(2)
|
||||
|> Enum.map(fn args -> apply(&Range.new/2, args) end)
|
||||
|
||||
target = for x <- xs, y <- ys, into: MapSet.new(), do: {x, y}
|
||||
bounds = Enum.max_by(target, fn {x, y} -> abs(x) + abs(y) end)
|
||||
{target, bounds}
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue