요정들의 암호를 복호화 어쩌고 하는 명목으로 숫자 위치 옮기기 퍼즐을 푸는 문제였다. 각 숫자를 숫자 크기만큼 위치를 바꾸되(1인 경우 오른쪽으로 한 칸, -2인 경우 왼쪽으로 두 칸), 옮기는 숫자는 원래 주어진 숫자의 순서대로(중요)여야 했다. 즉 3번째 차례에서 옮겨야 하는 숫자가 반드시 3번째 자리에 있지는 않다는 뜻이므로, 숫자를 섞으면서도 원래 이 숫자가 어디에 있었는지를 기억해야 했다. 그나마 다행인 것은 숫자 목록의 끝과 끝이 이어져 있어 순서만 맞다면 무엇이 첫 숫자로 오든 큰 상관이 없었다는 점 정도.
1번과 2번 문제의 푸는 방법이 약간 다른데, 1번은 위치 바꾸기를 숫자 목록의 각 숫자에 대해 한 번씩만 하면 되어 이진 플래그를 썼고, 2번은 열 바퀴 돌려야 했기 때문에 그냥 마음 편히 숫자의 원래 위치를 기억하는 인덱스를 썼다는 정도. 그렇게 보면 2번 문제 푸는 방법으로도 1번 문제를 충분히 풀 수 있다. 오히려 그 쪽이 확실하다.
defmodule Omicron.Day20 do
@dir "data/day20/"
def q1(file_name \\ "q.txt") do
list =
File.read!(@dir <> file_name)
|> String.split("\n")
|> Enum.map(&String.to_integer/1)
|> Enum.map(fn v -> {v, false} end)
size = length(list)
result =
list
|> Enum.reduce(list, fn {value, false}, acc ->
idx = Enum.find_index(acc, &(elem(&1, 1) == false))
new_idx = Integer.mod(idx + value, size - 1)
# IO.inspect(acc, label: "Next number: #{value} at #{idx} to #{new_idx}")
next_list =
if idx == 0 do
Enum.slice(acc, (idx + 1)..-1)
else
Enum.slice(acc, 0..(idx - 1)) ++ Enum.slice(acc, (idx + 1)..-1)
end
|> List.insert_at(new_idx, {value, true})
next_list
end)
|> IO.inspect()
zero_index = Enum.find_index(result, &(&1 == {0, true})) |> IO.inspect()
num_1000 = Enum.at(result, rem(1000 + zero_index, size)) |> elem(0)
num_2000 = Enum.at(result, rem(2000 + zero_index, size)) |> elem(0)
num_3000 = Enum.at(result, rem(3000 + zero_index, size)) |> elem(0)
num_1000 + num_2000 + num_3000
end
def q2(file_name \\ "q.txt") do
multiplier = 811_589_153
list =
File.read!(@dir <> file_name)
|> String.split("\n")
|> Enum.map(&String.to_integer/1)
|> Enum.map(fn v -> v * multiplier end)
|> Enum.with_index()
size = length(list)
result =
1..10
|> Enum.flat_map(fn _ -> list end)
|> Enum.reduce(list, fn {value, idx}, acc ->
if idx == 0 do
IO.inspect(acc, label: "Round finished")
end
real_index = Enum.find_index(acc, fn {v, i} -> i == idx end)
new_idx = Integer.mod(real_index + value, size - 1)
# IO.inspect(acc)
# IO.puts("Next number: #{value} at #{real_index} to #{new_idx}")
next_list =
if real_index == 0 do
Enum.slice(acc, (real_index + 1)..-1)
else
Enum.slice(acc, 0..(real_index - 1)) ++ Enum.slice(acc, (real_index + 1)..-1)
end
|> List.insert_at(new_idx, {value, idx})
next_list
end)
|> IO.inspect()
zero_index = Enum.find_index(result, &(elem(&1, 0) == 0))
num_1000 = Enum.at(result, rem(1000 + zero_index, size)) |> elem(0) |> IO.inspect()
num_2000 = Enum.at(result, rem(2000 + zero_index, size)) |> elem(0) |> IO.inspect()
num_3000 = Enum.at(result, rem(3000 + zero_index, size)) |> elem(0) |> IO.inspect()
(num_1000 + num_2000 + num_3000) * 1
end
end
'호두나무 공방 > Advent of Code' 카테고리의 다른 글
Advent of Code 2022 Day 22 in Elixir - Monkey Map 풀이 (0) | 2023.01.24 |
---|---|
Advent of Code 2022 Day 21 in Elixir - Monkey Math 풀이 (0) | 2023.01.23 |
Advent of Code 2022 Day 19 in Elixir - Not Enough Minerals 풀이 (0) | 2023.01.23 |
Advent of Code 2022 Day 18 in Elixir - Boiling Boulders 풀이 (0) | 2023.01.23 |
Advent of Code 2022 Day 17 in Elixir - Pyroclastic Flow 풀이 (0) | 2023.01.23 |