add more grid helper functions to prelude
This commit is contained in:
parent
d3d86a5b50
commit
0a5d25abb6
3 changed files with 76 additions and 14 deletions
|
@ -64,13 +64,6 @@ aoc 2024, 10 do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
## shared
|
|
||||||
|
|
||||||
defp n({x, y}), do: {x, y + 1}
|
|
||||||
defp s({x, y}), do: {x, y - 1}
|
|
||||||
defp e({x, y}), do: {x + 1, y}
|
|
||||||
defp w({x, y}), do: {x - 1, y}
|
|
||||||
|
|
||||||
## input
|
## input
|
||||||
|
|
||||||
def read_map(input) do
|
def read_map(input) do
|
||||||
|
|
|
@ -64,11 +64,6 @@ aoc 2024, 12 do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def n({x, y}), do: {x, y + 1}
|
|
||||||
def s({x, y}), do: {x, y - 1}
|
|
||||||
def e({x, y}), do: {x + 1, y}
|
|
||||||
def w({x, y}), do: {x - 1, y}
|
|
||||||
|
|
||||||
defp count_sides(plot) do
|
defp count_sides(plot) do
|
||||||
# find exterior faces
|
# find exterior faces
|
||||||
exterior_faces =
|
exterior_faces =
|
||||||
|
|
|
@ -28,7 +28,9 @@ defmodule AOC.Prelude do
|
||||||
|> Enum.map(&String.to_integer/1)
|
|> Enum.map(&String.to_integer/1)
|
||||||
end
|
end
|
||||||
|
|
||||||
@type map_grid(a) :: %{{x :: non_neg_integer(), y :: non_neg_integer()} => a}
|
@type coord() :: {x :: integer(), y :: integer()}
|
||||||
|
@type coord(t) :: {x :: t, y :: t}
|
||||||
|
@type map_grid(a) :: %{coord(non_neg_integer()) => a}
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Reads an Advent of Code-style grid of characters into a map of x, y positions
|
Reads an Advent of Code-style grid of characters into a map of x, y positions
|
||||||
|
@ -45,6 +47,78 @@ defmodule AOC.Prelude do
|
||||||
Returns `true` if the given position tuple is within the bounds of the
|
Returns `true` if the given position tuple is within the bounds of the
|
||||||
map_grid.
|
map_grid.
|
||||||
"""
|
"""
|
||||||
@spec in_bounds?(map_grid(any()), {x :: integer(), y :: integer()}) :: boolean()
|
@spec in_bounds?(map_grid(any()), coord()) :: boolean()
|
||||||
def in_bounds?(grid, pos), do: Map.has_key?(grid, pos)
|
def in_bounds?(grid, pos), do: Map.has_key?(grid, pos)
|
||||||
|
|
||||||
|
@type direction() :: :up | :down | :left | :right | :n | :ne | :e | :se | :s | :sw | :w | :nw
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Applies a single movement to a coordindate pair
|
||||||
|
|
||||||
|
There are also single function shorthands:
|
||||||
|
"""
|
||||||
|
@spec move_coord(coord(), direction()) :: coord()
|
||||||
|
def move_coord({x, y}, dir) when dir in [:up, :n], do: {x, y - 1}
|
||||||
|
def move_coord({x, y}, dir) when dir in [:down, :s], do: {x, y + 1}
|
||||||
|
def move_coord({x, y}, dir) when dir in [:left, :w], do: {x - 1, y}
|
||||||
|
def move_coord({x, y}, dir) when dir in [:right, :e], do: {x + 1, y}
|
||||||
|
def move_coord(pos, :ne), do: Enum.reduce([:n, :e], pos, &move_coord/2)
|
||||||
|
def move_coord(pos, :se), do: Enum.reduce([:s, :e], pos, &move_coord/2)
|
||||||
|
def move_coord(pos, :sw), do: Enum.reduce([:s, :w], pos, &move_coord/2)
|
||||||
|
def move_coord(pos, :nw), do: Enum.reduce([:n, :w], pos, &move_coord/2)
|
||||||
|
|
||||||
|
directions = ~w[up down left right n ne e se s sw w nw]a
|
||||||
|
|
||||||
|
for dir <- directions do
|
||||||
|
@doc """
|
||||||
|
A shorthand for `move_coord(pos, #{inspect(dir)})`
|
||||||
|
"""
|
||||||
|
@spec unquote(dir)(coord()) :: coord()
|
||||||
|
def unquote(dir)(coord), do: move_coord(coord, unquote(dir))
|
||||||
|
end
|
||||||
|
|
||||||
|
@type neighborhood_opt() :: {:include_center, boolean()}
|
||||||
|
@type neighborhood_opts() :: list(neighborhood_opt())
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
For a given coordinate position, returns the [Von Neumann neighborhood][1].
|
||||||
|
|
||||||
|
The Von Neumann neighborhood consists of the cells to the north, south, east,
|
||||||
|
and west of the center cell.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
- `:include_center`, whether or not to include the passed position. Defaults
|
||||||
|
to `false`
|
||||||
|
|
||||||
|
[1]: https://en.wikipedia.org/wiki/Von_Neumann_neighborhood
|
||||||
|
"""
|
||||||
|
@spec von_neumann_neighborhood(coord()) :: nonempty_list(coord())
|
||||||
|
@spec von_neumann_neighborhood(coord(), opts :: neighborhood_opts()) :: nonempty_list(coord())
|
||||||
|
def von_neumann_neighborhood(pos, opts \\ []) do
|
||||||
|
include_center = Keyword.get(opts, :include_center, false)
|
||||||
|
cells = Enum.map(~w[n e s w]a, &move_coord(pos, &1))
|
||||||
|
maybe_center = if include_center, do: [pos], else: []
|
||||||
|
maybe_center ++ cells
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
For a given coordinate position, returns the [Moore neighborhood][1].
|
||||||
|
|
||||||
|
The Moore neighborhood consists of the cells to the north, northeast, east,
|
||||||
|
southeast, south, southwest, west, and northwest of the center cell.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
- `:include_center`, whether or not to include the passed position. Defaults
|
||||||
|
to `false`
|
||||||
|
|
||||||
|
[1]: https://en.wikipedia.org/wiki/Moore_neighborhood
|
||||||
|
"""
|
||||||
|
def moore_neighborhood(pos, opts \\ []) do
|
||||||
|
include_center = Keyword.get(opts, :include_center, false)
|
||||||
|
cells = Enum.map(~w[n ne e se s sw w nw]a, &move_coord(pos, &1))
|
||||||
|
maybe_center = if include_center, do: [pos], else: []
|
||||||
|
maybe_center ++ cells
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue