Advent of Code 2024 Day 6 Part 2
Mix.install([
{:kino_aoc, "~> 0.1"}
])
Get Inputs
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2024", "6", System.fetch_env!("LB_SESSION"))
My answer
sample_input =
"""
....#.....
.........#
..........
..#.......
.......#..
..........
.#..^.....
........#.
#.........
......#...
"""
|> String.trim()
Kino.Text.new(sample_input, terminal: true)
turn = fn input ->
input
|> String.replace("^", "<")
|> String.split("\n")
|> Enum.map(&String.codepoints(&1))
|> Enum.zip()
|> Enum.map(fn col -> col |> Tuple.to_list() |> Enum.join() end)
|> Enum.reverse()
|> Enum.join("\n")
end
round = fn input ->
Enum.reduce_while(1..1000, {input, [], :up}, fn _, {acc_input, tuened_points, direction} ->
turned_input = turn.(acc_input)
direction =
case direction do
:up -> :right
:right -> :down
:down -> :left
:left -> :up
end
case Regex.scan(~r/#[^\n#]*</, turned_input) do
[[route]] ->
[[{point, _}]] = Regex.scan(~r/#[^\n#]*</, turned_input, return: :index)
turned_point = {direction, point}
turned_input =
String.replace(
turned_input,
route,
"#^" <> String.duplicate("X", String.length(route) - 2)
)
if Enum.member?(tuened_points, turned_point) do
{
:halt,
{
turned_input,
direction,
true
}
}
else
{
:cont,
{
turned_input,
[turned_point | tuened_points],
direction
}
}
end
_ ->
route =
Regex.scan(~r/\.[^\n]*</, turned_input)
|> hd()
|> hd()
{
:halt,
{
String.replace(
turned_input,
route,
String.duplicate("X", String.length(route))
),
direction,
false
}
}
end
end)
end
{rounded, _, looped} =
"""
..#...
.....#
..^...
.#....
....#.
"""
|> String.trim()
|> round.()
IO.inspect(looped, label: "looped")
Kino.Text.new(rounded, terminal: true)
{rounded, direction, looped} = round.(sample_input)
IO.inspect(looped, label: "looped")
rounded =
case direction do
:up ->
rounded
:right ->
rounded
|> turn.()
|> turn.()
|> turn.()
:down ->
rounded
|> turn.()
|> turn.()
:left ->
turn.(rounded)
end
Kino.Text.new(rounded, terminal: true)
replaced =
Regex.scan(~r/X/, rounded, return: :index)
|> hd()
|> then(fn [{index, _}] ->
String.slice(sample_input, 0..(index - 1)) <>
"#" <> String.slice(sample_input, (index + 1)..-1//1)
end)
Kino.Text.new(replaced, terminal: true)
{rounded_replaced, direction, looped} = round.(replaced)
IO.inspect(looped, label: "looped")
Kino.Text.new(rounded_replaced, terminal: true)
Regex.scan(~r/X/, rounded, return: :index)
|> Enum.reduce(0, fn [{index, _}], loop_count ->
if String.at(sample_input, index) == "^" do
loop_count
else
replaced =
String.slice(sample_input, 0..(index - 1)) <>
"#" <> String.slice(sample_input, (index + 1)..-1//1)
{_, _, looped} = round.(replaced)
loop_count + if looped, do: 1, else: 0
end
end)
{rounded, direction, _} = round.(puzzle_input)
rounded =
case direction do
:up ->
rounded
:right ->
rounded
|> turn.()
|> turn.()
|> turn.()
:down ->
rounded
|> turn.()
|> turn.()
:left ->
turn.(rounded)
end
Regex.scan(~r/X/, rounded, return: :index)
|> Enum.reduce(0, fn [{index, _}], loop_count ->
if String.at(puzzle_input, index) == "^" do
loop_count
else
replaced =
String.slice(puzzle_input, 0..(index - 1)) <>
"#" <> String.slice(puzzle_input, (index + 1)..-1//1)
{_, _, looped} = round.(replaced)
loop_count + if looped, do: 1, else: 0
end
end)