Zero-prefix numbers
This commit is contained in:
parent
c51a51ab63
commit
f295bd93af
18 changed files with 0 additions and 7750 deletions
92
2020/day08/day8.ex
Normal file
92
2020/day08/day8.ex
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
defmodule Day8 do
|
||||
defp read_input do
|
||||
Path.expand('input', Path.dirname(__ENV__.file))
|
||||
|> File.read!()
|
||||
end
|
||||
|
||||
defp parse_program(text) do
|
||||
String.split(String.trim(text), "\n")
|
||||
|> Enum.map(fn line ->
|
||||
[op, val] = String.split(line)
|
||||
{op, String.to_integer(val)}
|
||||
end)
|
||||
end
|
||||
|
||||
defp tick(program, pc, acc) do
|
||||
case Enum.at(program, pc) do
|
||||
{"nop", _} -> {pc + 1, acc}
|
||||
{"acc", int} -> {pc + 1, acc + int}
|
||||
{"jmp", int} -> {pc + int, acc}
|
||||
end
|
||||
end
|
||||
|
||||
defp find_loop(program, pc, acc, history) do
|
||||
{next_pc, next_acc} = tick(program, pc, acc)
|
||||
count = Map.get(history, next_pc, 0)
|
||||
|
||||
if count > 0 do
|
||||
acc
|
||||
else
|
||||
find_loop(program, next_pc, next_acc, Map.put(history, next_pc, count + 1))
|
||||
end
|
||||
end
|
||||
|
||||
def part1 do
|
||||
program = parse_program(read_input())
|
||||
find_loop(program, 0, 0, %{})
|
||||
end
|
||||
|
||||
def run(program, pc, acc, history, term_pc) do
|
||||
{next_pc, next_acc} = tick(program, pc, acc)
|
||||
count = Map.get(history, next_pc, 0)
|
||||
|
||||
cond do
|
||||
count > 0 -> :loop
|
||||
next_pc == term_pc -> {:term, next_acc}
|
||||
next_pc > term_pc -> :wtf
|
||||
true -> run(program, next_pc, next_acc, Map.put(history, next_pc, count + 1), term_pc)
|
||||
end
|
||||
end
|
||||
|
||||
def mod(program, ridx) do
|
||||
Enum.with_index(program)
|
||||
|> Enum.map(fn {{op, val}, idx} ->
|
||||
if idx == ridx do
|
||||
case op do
|
||||
"nop" -> {"jmp", val}
|
||||
"jmp" -> {"nop", val}
|
||||
_ -> {op, val}
|
||||
end
|
||||
else
|
||||
{op, val}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def mods(program) do
|
||||
Stream.with_index(program)
|
||||
|> Stream.filter(fn {{op, _val}, _idx} ->
|
||||
case op do
|
||||
"acc" -> false
|
||||
"nop" -> true
|
||||
"jmp" -> true
|
||||
end
|
||||
end)
|
||||
|> Stream.map(fn {_, idx} -> mod(program, idx) end)
|
||||
end
|
||||
|
||||
def part2 do
|
||||
program = parse_program(read_input())
|
||||
term_pc = Enum.count(program)
|
||||
|
||||
Enum.reduce_while(mods(program), nil, fn modded_program, _ ->
|
||||
case run(modded_program, 0, 0, %{}, term_pc) do
|
||||
:loop -> {:cont, nil}
|
||||
{:term, acc} -> {:halt, acc}
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
Day8.part1() |> IO.inspect()
|
||||
Day8.part2() |> IO.inspect()
|
||||
Loading…
Reference in a new issue