Skip to content

Instantly share code, notes, and snippets.

@kirisaki
Created February 20, 2018 01:49
Show Gist options
  • Save kirisaki/f9d81cf4a95d25cf5149494849bf31c1 to your computer and use it in GitHub Desktop.
Save kirisaki/f9d81cf4a95d25cf5149494849bf31c1 to your computer and use it in GitHub Desktop.
Gumimaze Solution
defmodule Gumimaze do
def read() do
lines = "maze.txt" |> File.read!() |> String.trim() |> String.split("\n")
for {line, y} <- Enum.with_index(lines), {c, x} <- Enum.with_index(String.to_charlist(line)), into: %{} do
{{x, y}, c}
end
end
def solve(maze) do
{x, y} = elem(Enum.find(maze, fn {_, v} -> v == ?S end), 0)
{:ok, agent} = Agent.start_link(fn -> [] end)
walk(maze, x, y, %{}, 0, agent)
Enum.max(Agent.get(agent, &(&1)))
end
defp walk(maze, x, y, walked, pt, agent) do
walked = Map.put(walked, {x, y}, true)
for {x2, y2} <- [{x + 1, y}, {x, y + 1}, {x - 1, y}, {x, y - 1}] do
case {walked[{x2, y2}], maze[{x2, y2}]} do
{true, _} -> :walked
{_, ?W} -> :wall
{_, ?\s} -> walk(maze, x2, y2, walked, pt, agent)
{_, ?1} -> walk(maze, x2, y2, walked, pt + 1, agent)
{_, ?G} -> Agent.update(agent, fn (state) -> state ++ [pt] end)
end
end
end
end
Gumimaze.read() |> Gumimaze.solve() |> IO.puts()
defmodule Gumimaze do
def read() do
lines = "maze.txt" |> File.read!() |> String.trim() |> String.split("\n")
for {line, y} <- Enum.with_index(lines), {c, x} <- Enum.with_index(String.to_charlist(line)), into: %{} do
{{x, y}, c}
end
end
def solve(maze) do
{x, y} = elem(Enum.find(maze, fn {_, v} -> v == ?S end), 0)
Agent.start_link(fn -> [] end, name: Answers)
spawn_monitor(Gumimaze, :walk, [maze, x, y, %{}, 0])
receive do
{:DOWN, _ref, :process, _from_pid, _reason} ->
Agent.get(Answers, &(Enum.max(&1)))
end
end
def walk(maze, x, y, walked, pt) do
walked = Map.put(walked, {x, y}, true)
results = Enum.map(
[{x + 1, y}, {x, y + 1}, {x - 1, y}, {x, y - 1}],
fn {x2, y2} ->
check_floor(maze, x2, y2, walked, pt)
end)
refs = Enum.filter(results, &is_tuple(&1)) |> Enum.map(fn {_, ref} -> ref end)
walk(refs)
end
def walk(refs) do
if Enum.empty?(refs) do
send(self(), :end)
end
receive do
{:DOWN, ref, :process, _from_pid, _reason} ->
newrefs = List.delete(refs, ref)
walk(newrefs)
_ ->
:end
end
end
defp check_floor(maze, x, y, walked, pt) do
case {walked[{x, y}], maze[{x, y}]} do
{true, _} -> :walked
{_, ?W} -> :wall
{_, ?\s} ->
spawn_monitor(Gumimaze, :walk, [maze, x, y, walked, pt])
{_, ?1} ->
spawn_monitor(Gumimaze, :walk, [maze, x, y, walked, pt+1])
{_, ?G} ->
Agent.update(Answers, &(&1 ++ [pt]))
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment