53 lines
1.4 KiB
Elixir
53 lines
1.4 KiB
Elixir
defmodule BreadthFirstSearch do
|
|
def search(graph, initial_vertex, search_fn) do
|
|
initial_search_queue = list_to_queue(graph[initial_vertex])
|
|
do_search(initial_search_queue, search_fn, [], graph)
|
|
end
|
|
|
|
defp do_search(_empty_queue = {[], []}, _, _, _), do: nil
|
|
|
|
defp do_search(search_queue, search_fn, searched_list, graph) do
|
|
{{:value, value}, rest_queue} = :queue.out(search_queue)
|
|
|
|
cond do
|
|
value in searched_list ->
|
|
do_search(rest_queue, search_fn, searched_list, graph)
|
|
|
|
search_fn.(value) ->
|
|
value
|
|
|
|
true ->
|
|
continue_search(rest_queue, value, search_fn, searched_list, graph)
|
|
end
|
|
end
|
|
|
|
defp continue_search(search_queue, value, search_fn, searched_list, graph) do
|
|
join_with_search_queue = &:queue.join(search_queue, &1)
|
|
|
|
updated_search_queue =
|
|
graph[value]
|
|
|> list_to_queue()
|
|
|> join_with_search_queue.()
|
|
|
|
do_search(updated_search_queue, search_fn, [value | searched_list], graph)
|
|
end
|
|
|
|
defp list_to_queue(list), do: :queue.from_list(list)
|
|
end
|
|
|
|
graph = %{
|
|
"you" => ["alice", "bob", "claire"],
|
|
"bob" => ["anuj", "peggy"],
|
|
"alice" => ["peggy"],
|
|
"claire" => ["thom", "jonny"],
|
|
"anuj" => [],
|
|
"peggy" => [],
|
|
"thom" => [],
|
|
"jonny" => []
|
|
}
|
|
|
|
person_is_seller? = &String.ends_with?(&1, "m")
|
|
|
|
name = BreadthFirstSearch.search(graph, "you", person_is_seller?)
|
|
IO.puts("#{name} is a mango seller!")
|