פיתרון שלי באליקסיר לשני החלקים עם חישוב מלא של המטריצה בלי המתמטיקה:
defmodule Directions do
def up({x, y}), do: { x, y - 1 }
def down({x, y}), do: { x, y + 1 }
def left({x, y}), do: { x - 1, y }
def right({x, y}), do: { x + 1, y }
def next(dir) do
directions = [ &Directions.right/1, &Directions.up/1, &Directions.left/1, &Directions.down/1 ]
idx = Enum.find_index(directions, fn(x) -> x == dir end)
Enum.at(directions, rem(idx + 1, 4))
end
def available?(matrix, xy) do
!Map.has_key?(matrix, xy)
end
end
defmodule Day3 do
def go1(steps, part \\&Day3.part1/3, matrix \\ %{ {0, 0} => 1 }, xy \\ {0, 0}, val \\ 1, pd \\ &Directions.down / 1)
def go1(steps, part, matrix, xy, val, pd) when steps > 1 do
{ next_xy, next_val, next_matrix, pd } = next(matrix, xy, val, pd, part)
go1(steps - 1, part, next_matrix, next_xy, next_val, pd)
end
def go1(_, _, _, {x, y}, _, _) do
abs(x) + abs(y)
end
def go2(steps, part \\&Day3.part2/3, matrix \\ %{ {0, 0} => 1 }, xy \\ {0, 0}, val \\ 1, pd \\ &Directions.down / 1)
def go2(steps, part, matrix, xy, val, pd) when val < 277678 do
{ next_xy, next_val, next_matrix, pd } = next(matrix, xy, val, pd, part)
go2(steps - 1, part, next_matrix, next_xy, next_val, pd)
end
def go2(_, _, matrix, _, val, _) do
val
end
def part1(_, _, val) do
val + 1
end
def part2(matrix, xy, _) do
[
Map.get(matrix, Directions.up(xy), 0),
Map.get(matrix, Directions.down(xy), 0),
Map.get(matrix, Directions.left(xy), 0),
Map.get(matrix, Directions.right(xy), 0),
Map.get(matrix, Directions.up(Directions.right(xy)), 0),
Map.get(matrix, Directions.up(Directions.left(xy)), 0),
Map.get(matrix, Directions.down(Directions.left(xy)), 0),
Map.get(matrix, Directions.down(Directions.right(xy)), 0),
]
|> Enum.sum
end
def next(matrix, xy, val, pd, part) do
direction = if Directions.available?(matrix, Directions.next(pd).(xy)) do
Directions.next(pd)
else
pd
end
next_val = part.(matrix, direction.(xy), val)
{ direction.(xy), next_val , Map.put(matrix, direction.(xy), next_val), direction }
end
end
System.argv()
|> Enum.at(0)
|> String.to_integer
|> Day3.go2
|> IO.inspect