Untitled notebook
Section
Mix.install([
{:kino, "~> 0.14.2"}
])
input = Kino.Input.textarea("Please paste your input file")
defmodule Griddy do
def enum_to_map(enum) do
Stream.iterate(0, &(&1 + 1)) |> Enum.zip(enum) |> Map.new()
end
def new_from_string(string) do
Griddy.enum_to_map(
string
|> String.split("\n")
|> Enum.map(&String.graphemes/1)
|> Enum.map(&Griddy.enum_to_map/1)
)
end
def reduce(grid, initial, func) do
grid
|> Enum.reduce(initial, fn {y, sub_map}, acc ->
sub_map
|> Enum.reduce(acc, fn {x, value}, acc ->
func.(value, acc, x, y)
end)
end)
end
def map(grid, func) do
grid
|> Enum.map(fn {y, sub_map} ->
new_sub_map =
sub_map
|> Enum.map(fn {x, value} ->
{x, func.(value, x, y)}
end)
|> Map.new()
{y, new_sub_map}
end)
|> Map.new()
end
def get_nearby_cells(grid, x, y) do
above_below_range = -1..1//1
above_below_range
|> Enum.map(fn dy ->
-1..1//1
|> Enum.map(fn dx ->
if dx == 0 && dy == 0 do
nil
else
grid |> Griddy.get(x + dx, y + dy)
end
end)
end)
|> Enum.flat_map(fn a -> a end)
|> Enum.filter(fn a -> a end)
end
def get(grid, x, y) do
grid[y][x]
end
def put(grid, x, y, value) do
grid |> Map.update(y, nil, fn sub_map -> sub_map |> Map.put(x, value) end)
end
def update(grid, x, y, default, func) do
grid |> Map.update(y, nil, fn sub_map -> sub_map |> Map.update(x, default, func) end)
end
def find(map, value) do
map
|> Enum.reduce({0, 0}, fn {y, sub_map}, acc ->
sub_map
|> Enum.reduce(acc, fn {x, _}, acc ->
if map[y][x] == value, do: {x, y}, else: acc
end)
end)
end
def to_string(grid) do
{string, _} =
grid
|> Griddy.reduce({"", nil}, fn value, {acc, prev_y}, _, y ->
if y != prev_y do
{acc <> "\n" <> value, y}
else
{acc <> value, y}
end
end)
string
end
def print(grid) do
grid |> Griddy.to_string() |> IO.puts()
grid
end
end
defmodule Main do
def handle_split(grid, x, y, just_split) do
value = grid |> Griddy.get(x, y)
case value do
nil ->
[0, grid]
"." ->
update_grid = grid |> Griddy.put(x, y, "|")
if just_split do
[value, final_grid] = Main.handle_split(update_grid, x, y + 1, false)
[value, final_grid]
else
Main.handle_split(update_grid, x, y + 1, false)
end
"^" ->
[first_split, update_grid] = Main.handle_split(grid, x + 1, y, true)
[second_split, final_grid] = Main.handle_split(update_grid, x - 1, y, true)
[first_split + second_split + 1, final_grid]
"|" ->
[0, grid]
end
end
end
grid =
input
|> Kino.Input.read()
|> String.split("\n", trim: true)
|> Enum.map(&String.trim/1)
|> Enum.join("\n")
|> Griddy.new_from_string()
{s_x, s_y} = grid |> Griddy.find("S")
[answer, grid] = Main.handle_split(grid, s_x, s_y + 1, false)
answer
defmodule Test do
def handle_quantum_split(grid, x, y, just_split) do
{value, _memo} = do_split(grid, x, y, just_split, %{})
value
end
defp do_split(grid, x, y, just_split, memo) do
key = {x, y, just_split}
case memo do
%{^key => count} ->
{count, memo}
_ ->
value = Griddy.get(grid, x, y)
{count, memo} =
case value do
nil ->
{1, memo}
"." ->
if just_split do
do_split(grid, x, y + 1, false, memo)
else
do_split(grid, x, y + 1, false, memo)
end
"^" ->
{v1, memo} = do_split(grid, x + 1, y, true, memo)
{v2, memo} = do_split(grid, x - 1, y, true, memo)
{v1 + v2, memo}
"|" ->
do_split(grid, x, y + 1, false, memo)
end
memo = Map.put(memo, key, count)
{count, memo}
end
end
end
grid =
input
|> Kino.Input.read()
|> String.split("\n", trim: true)
|> Enum.map(&String.trim/1)
|> Enum.join("\n")
|> Griddy.new_from_string()
{s_x, s_y} = grid |> Griddy.find("S")
Test.handle_quantum_split(grid, s_x, s_y + 1, false)