Skip to content

Instantly share code, notes, and snippets.

@Nagasaki45
Created March 28, 2017 14:14
Show Gist options
  • Save Nagasaki45/f2216bde319b8e3d0f9a31e3f3c59c24 to your computer and use it in GitHub Desktop.
Save Nagasaki45/f2216bde319b8e3d0f9a31e3f3c59c24 to your computer and use it in GitHub Desktop.
Elixir solution to the UdiMaze
defmodule UdiMaze do
@moduledoc """
A solver for UdiMaze pazzle.
Issues:
- I get 404 if omitting the last slash.
- Took me some time to understand the task. It can be documented better.
- Didn't use the `x` and `y` values at all. Without knowing the size of the
maze I can't think of an algorithm that can use them.
Run this from the terminal with:
mix run -e UdiMaze.run
"""
@base_url 'http://139.59.154.221'
defstruct(
maze_id: "",
path_heads: [], # codes
rooms: Map.new, # code to score
)
@doc """
Go to the server to create a new UdiMaze.
"""
def new do
{:ok, %{body: body}} = HTTPoison.post(@base_url, "{}")
{:ok, json} = Poison.decode(body)
%__MODULE__{
maze_id: json["maze_id"],
path_heads: [json["start"]],
}
end
@doc """
Traverse the UdiMaze.
"""
def traverse(maze) do
new_maze = step_all_paths(maze)
# Couldn't find more rooms in the last step
if new_maze.rooms == maze.rooms do
maze
else
traverse(new_maze)
end
end
defp step_all_paths(maze) do
discoveries =
maze.path_heads
|> Task.async_stream(&(discover_room(maze.maze_id, &1)))
|> Enum.map(fn {:ok, value} -> value end)
%__MODULE__{
maze |
rooms:
maze.path_heads
|> Stream.zip(for x <- discoveries, do: x["score"])
|> Enum.into(Map.new)
|> Map.merge(maze.rooms),
path_heads:
discoveries
|> Stream.flat_map(&(&1["exits"]))
|> Stream.map(&(&1["code"]))
|> Enum.filter(&(!Map.has_key?(maze.rooms, &1))),
}
end
defp discover_room(maze_id, room) do
url = "#{@base_url}/#{maze_id}/#{room}/"
{:ok, %{body: body}} = HTTPoison.get(url)
{:ok, json} = Poison.decode(body)
json
end
@doc """
Check the solution.
"""
def check_result(maze) do
score =
maze.rooms
|> Map.values()
|> Enum.sum()
url = "#{@base_url}/solve/#{maze.maze_id}/#{score}/"
{:ok, %{body: body}} = HTTPoison.post(url, "{}")
{:ok, json} = Poison.decode(body)
json
end
@doc """
A runner for the UdiMaze. It gets new maze from the server,
traverse (async), and print the results.
"""
def run do
new()
|> traverse()
|> check_result()
|> IO.inspect()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment