Skip to content

Instantly share code, notes, and snippets.

@tfwright

tfwright/1.exs Secret

Created December 20, 2022 00:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tfwright/dc9cb2aff138c34d65bbba8bbb0420a6 to your computer and use it in GitHub Desktop.
Save tfwright/dc9cb2aff138c34d65bbba8bbb0420a6 to your computer and use it in GitHub Desktop.
AOC 2022 14
draw = fn paths, x, y, code ->
put_in(paths, [Access.key(x, %{}), y], code)
end
paths =
System.argv()
|> List.first()
|> File.stream!()
|> Enum.reduce(%{}, fn path, paths ->
path
|> String.split(" -> ", trim: true)
|> Enum.map(fn node -> node |> String.trim() |> String.split(",") |> Enum.map(& String.to_integer/1) end)
|> Enum.chunk_every(2, 1, :discard)
|> Enum.reduce(paths, fn
[[x, from_y], [x, to_y]], paths -> Enum.reduce(from_y..to_y, paths, & draw.(&2, x, &1, "#"))
[[from_x, y], [to_x, y]], paths -> Enum.reduce(from_x..to_x, paths, & draw.(&2, &1, y, "#"))
end)
end)
sand_fall = fn paths, {x, y}, self ->
down_y = y + 1
paths
|> get_in([x, down_y])
|> case do
nil -> if y + 1 > paths |> Map.get(x, %{}) |> Map.keys() |> Enum.max(&>=/2, fn -> 0 end), do: :infinity, else: self.(paths, {x, down_y}, self)
floor when floor in ["#", "o"] ->
cond do
is_nil(get_in(paths, [x - 1, down_y])) -> self.(paths, {x - 1, down_y}, self)
is_nil(get_in(paths, [x + 1, down_y])) -> self.(paths, {x + 1, down_y}, self)
true -> draw.(paths, x, y, "o")
end
end
end
Stream.iterate(1, & &1 + 1)
|> Enum.reduce_while(paths, fn unit, paths ->
paths
|> sand_fall.({500, 0}, sand_fall)
|> case do
:infinity -> {:halt, unit}
paths -> {:cont, paths}
end
end)
|> IO.inspect
draw = fn paths, x, y, code ->
put_in(paths, [Access.key(x, %{}), y], code)
end
paths =
System.argv()
|> List.first()
|> File.stream!()
|> Enum.reduce(%{}, fn path, paths ->
path
|> String.split(" -> ", trim: true)
|> Enum.map(fn node -> node |> String.trim() |> String.split(",") |> Enum.map(& String.to_integer/1) end)
|> Enum.chunk_every(2, 1, :discard)
|> Enum.reduce(paths, fn
[[x, from_y], [x, to_y]], paths -> Enum.reduce(from_y..to_y, paths, & draw.(&2, x, &1, "#"))
[[from_x, y], [to_x, y]], paths -> Enum.reduce(from_x..to_x, paths, & draw.(&2, &1, y, "#"))
end)
end)
floor_y = (paths |> Map.values() |> Enum.flat_map(& Map.keys/1) |> Enum.max()) + 2
sand_fall = fn
paths, {x, y}, _ when y + 1 == floor_y ->
draw.(paths, x, y, "o")
paths, {x, y}, self ->
down_y = y + 1
paths
|> get_in([x, down_y])
|> case do
nil -> self.(paths, {x, down_y}, self)
floor when floor in ["#", "o"] ->
cond do
is_nil(get_in(paths, [x - 1, down_y])) -> self.(paths, {x - 1, down_y}, self)
is_nil(get_in(paths, [x + 1, down_y])) -> self.(paths, {x + 1, down_y}, self)
true -> draw.(paths, x, y, "o")
end
end
end
Stream.iterate(1, & &1 + 1)
|> Enum.reduce_while(paths, fn unit, paths ->
paths
|> sand_fall.({500, 0}, sand_fall)
|> case do
%{500 => %{0 => "o"}} -> {:halt, unit}
paths -> {:cont, paths}
end
end)
|> IO.inspect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment