Skip to content

Instantly share code, notes, and snippets.

@tfwright

tfwright/1.exs Secret

Created December 19, 2022 17:41
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/15371e9082c7a9789058e0e1d60dddb5 to your computer and use it in GitHub Desktop.
Save tfwright/15371e9082c7a9789058e0e1d60dddb5 to your computer and use it in GitHub Desktop.
AOC 2022 12
grid =
System.argv()
|> List.first()
|> File.read!()
|> String.split("\n")
|> Enum.map(&String.graphemes/1)
|> IO.inspect
find_node_by_code = fn code ->
grid
|> Enum.with_index()
|> Enum.find_value([], fn {row, row_idx} ->
if col_idx = Enum.find_index(row, fn node_code -> node_code == code end) do
{row_idx, col_idx}
end
end)
end
start_node = find_node_by_code.("S")
heuristic = fn {current_row, current_col}, {goal_row, goal_col} ->
abs(current_row - goal_row) + abs(current_col - goal_col)
end
end_node = find_node_by_code.("E")
get_code = fn node_row, node_col ->
grid
|> Enum.with_index()
|> Enum.find_value(fn {row, row_idx} ->
row_idx == node_row && Enum.find_value(Enum.with_index(row), fn {code, col_idx} -> if col_idx == node_col, do: code end)
end)
end
get_dirs = fn {node_row, node_col} ->
node_code = get_code.(node_row, node_col)
[
{node_row - 1, node_col},
{node_row, node_col - 1},
{node_row, node_col + 1},
{node_row + 1, node_col}
]
|> Enum.filter(fn {dir_row, dir_col} ->
get_code.(dir_row, dir_col)
|> case do
nil ->
false
"E" -> node_code == "z"
"a" ->
true
dir_code ->
[node_point] = String.to_charlist(node_code)
[dir_point] = String.to_charlist(dir_code)
dir_point <= node_point + 1
end
end)
end
djikstra = fn d, frontier, path, steps ->
{current, frontier} = List.pop_at(frontier, 0)
if current == end_node do
Map.fetch!(steps, current)
else
{frontier, path, steps} =
current
|> get_dirs.()
|> Enum.reduce({frontier, path, steps}, fn node, acc = {frontier, path, steps} ->
node_steps = Map.fetch!(steps, current) + 1
existing_steps = Map.get(steps, node, :infinity)
if node_steps < existing_steps do
steps = Map.put(steps, node, node_steps)
path = Map.put(path, node, current)
frontier =
frontier
|> Enum.concat([node])
|> Enum.sort_by(& steps[&1] + heuristic.(&1, end_node))
{frontier, path, steps}
else
acc
end
end)
d.(d, frontier, path, steps)
end
end
djikstra.(djikstra, [start_node], %{start_node => nil}, %{start_node => 0})
|> IO.inspect
grid =
System.argv()
|> List.first()
|> File.read!()
|> String.split("\n")
|> Enum.map(&String.graphemes/1)
|> IO.inspect
find_node_by_code = fn code ->
grid
|> Enum.with_index()
|> Enum.find_value([], fn {row, row_idx} ->
if col_idx = Enum.find_index(row, fn node_code -> node_code == code end) do
{row_idx, col_idx}
end
end)
end
heuristic = fn {current_row, current_col}, {goal_row, goal_col} ->
abs(current_row - goal_row) + abs(current_col - goal_col)
end
end_node = find_node_by_code.("E")
get_code = fn node_row, node_col ->
grid
|> Enum.with_index()
|> Enum.find_value(fn {row, row_idx} ->
row_idx == node_row && Enum.find_value(Enum.with_index(row), fn {code, col_idx} -> if col_idx == node_col, do: code end)
end)
end
get_dirs = fn {node_row, node_col} ->
node_code = get_code.(node_row, node_col)
[
{node_row - 1, node_col},
{node_row, node_col - 1},
{node_row, node_col + 1},
{node_row + 1, node_col}
]
|> Enum.filter(fn {dir_row, dir_col} ->
get_code.(dir_row, dir_col)
|> case do
nil ->
false
"E" -> node_code == "z"
"a" ->
true
dir_code ->
[node_point] = String.to_charlist(node_code)
[dir_point] = String.to_charlist(dir_code)
dir_point <= node_point + 1
end
end)
end
djikstra = fn
_, [], _, _ -> :infinity
d, frontier, path, steps ->
{current, frontier} = List.pop_at(frontier, 0)
if current == end_node do
Map.fetch!(steps, current)
else
{frontier, path, steps} =
current
|> get_dirs.()
|> Enum.reduce({frontier, path, steps}, fn node, acc = {frontier, path, steps} ->
node_steps = Map.fetch!(steps, current) + 1
existing_steps = Map.get(steps, node, :infinity)
if node_steps < existing_steps do
steps = Map.put(steps, node, node_steps)
path = Map.put(path, node, current)
frontier =
frontier
|> Enum.concat([node])
|> Enum.sort_by(& steps[&1] + heuristic.(&1, end_node))
{frontier, path, steps}
else
acc
end
end)
d.(d, frontier, path, steps)
end
end
grid
|> Enum.with_index()
|> Enum.flat_map(fn {row, row_idx} ->
row
|> Enum.with_index()
|> Enum.flat_map(fn {node, col_idx} ->
if node == "a" do
[{row_idx, col_idx}]
else
[]
end
end)
end)
|> Enum.map(fn start ->
IO.inspect(start)
djikstra.(djikstra, [start], %{start => nil}, %{start => 0})
end)
|> Enum.min()
|> IO.inspect()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment