Compare commits
No commits in common. "f10b2fdf9957e952e2ca0d9f0d7d110805c125fd" and "d2af80fa2632ac938f7fb45815bf10a406edc82f" have entirely different histories.
f10b2fdf99
...
d2af80fa26
|
@ -1,5 +1,4 @@
|
||||||
# Used by "mix format"
|
# Used by "mix format"
|
||||||
[
|
[
|
||||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"],
|
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||||
locals_without_parens: [assemble_macro: 2]
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
defmodule Day8 do
|
|
||||||
def part1 do
|
|
||||||
File.read!("lib/day8/input.txt")
|
|
||||||
|> parse_input()
|
|
||||||
|> split_into_layers(25, 6)
|
|
||||||
|> min_zeros()
|
|
||||||
|> ones_times_twos()
|
|
||||||
|
|
||||||
# "123456789012"
|
|
||||||
# |> parse_input()
|
|
||||||
# |> split_into_layers(3, 2)
|
|
||||||
# |> min_zeros()
|
|
||||||
# |> ones_times_twos()
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2 do
|
|
||||||
File.read!("lib/day8/input.txt")
|
|
||||||
|> parse_input()
|
|
||||||
|> split_into_layers(25, 6)
|
|
||||||
|> combine_layers()
|
|
||||||
|> Enum.map(fn
|
|
||||||
0 -> ?\s
|
|
||||||
1 -> ?X
|
|
||||||
end)
|
|
||||||
|> Enum.chunk_every(25)
|
|
||||||
|> Enum.each(&IO.puts/1)
|
|
||||||
|
|
||||||
# "0222112222120000"
|
|
||||||
# |> parse_input()
|
|
||||||
# |> split_into_layers(2, 2)
|
|
||||||
# |> combine_layers()
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse_input(str) do
|
|
||||||
str
|
|
||||||
|> String.trim()
|
|
||||||
|> String.to_charlist()
|
|
||||||
|> Enum.map(fn digit -> digit - ?0 end)
|
|
||||||
end
|
|
||||||
|
|
||||||
def split_into_layers(input, layer_width, layer_height) do
|
|
||||||
Enum.chunk_every(input, layer_width * layer_height)
|
|
||||||
end
|
|
||||||
|
|
||||||
def min_zeros(layers) do
|
|
||||||
layers
|
|
||||||
|> Enum.min_by(fn layer ->
|
|
||||||
Enum.count(layer, &(&1 == 0))
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
def ones_times_twos(layer) do
|
|
||||||
ones = Enum.count(layer, &(&1 == 1))
|
|
||||||
twos = Enum.count(layer, &(&1 == 2))
|
|
||||||
ones * twos
|
|
||||||
end
|
|
||||||
|
|
||||||
def combine_layers(layers) do
|
|
||||||
Enum.zip(layers)
|
|
||||||
|> Enum.map(&combine_pixel/1)
|
|
||||||
end
|
|
||||||
|
|
||||||
def combine_pixel(pixel) do
|
|
||||||
0..(tuple_size(pixel) - 1)
|
|
||||||
|> Enum.map(fn index -> elem(pixel, index) end)
|
|
||||||
|> Enum.reduce(2, fn
|
|
||||||
val, 2 -> val
|
|
||||||
_, it -> it
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
File diff suppressed because one or more lines are too long
|
@ -1,17 +1,5 @@
|
||||||
defmodule Assembler.Helpers do
|
|
||||||
defmacro assemble_macro(match, asm) do
|
|
||||||
quote do
|
|
||||||
def assemble_insn(unquote(match), memory) do
|
|
||||||
{macro_mem, _} = do_assemble(unquote(asm), length(memory))
|
|
||||||
macro_mem ++ memory
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defmodule Assembler do
|
defmodule Assembler do
|
||||||
import NimbleParsec
|
import NimbleParsec
|
||||||
import Assembler.Helpers
|
|
||||||
|
|
||||||
label =
|
label =
|
||||||
ascii_string([?a..?z, ?A..?Z, ?_], min: 1)
|
ascii_string([?a..?z, ?A..?Z, ?_], min: 1)
|
||||||
|
@ -33,7 +21,7 @@ defmodule Assembler do
|
||||||
|> ascii_string([{:not, ?,}], min: 1)
|
|> ascii_string([{:not, ?,}], min: 1)
|
||||||
|
|
||||||
instruction =
|
instruction =
|
||||||
ignore(ascii_string([?\s, ?\t], min: 0))
|
ignore(ascii_string([?\s], 2))
|
||||||
|> ascii_string([?a..?z], min: 1)
|
|> ascii_string([?a..?z], min: 1)
|
||||||
|> repeat(param |> ignore(ascii_char([?,])))
|
|> repeat(param |> ignore(ascii_char([?,])))
|
||||||
|> optional(param)
|
|> optional(param)
|
||||||
|
@ -49,14 +37,45 @@ defmodule Assembler do
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@asm """
|
||||||
|
in res
|
||||||
|
clt $res, _self + 1, cmpRes
|
||||||
|
jnz $cmpRes, lessThan
|
||||||
|
ceq $res, 8, cmpRes
|
||||||
|
jnz $cmpRes, equal
|
||||||
|
out 1001
|
||||||
|
hlt
|
||||||
|
|
||||||
|
lessThan:
|
||||||
|
out 999
|
||||||
|
hlt
|
||||||
|
|
||||||
|
equal:
|
||||||
|
out 1000
|
||||||
|
hlt
|
||||||
|
|
||||||
|
res: 0
|
||||||
|
cmpRes: 0
|
||||||
|
"""
|
||||||
def test do
|
def test do
|
||||||
File.read!("test/intcode/cmp8.asm")
|
assemble(@asm)
|
||||||
|> assemble()
|
|
||||||
|> Day5.run_cli()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def assemble(asm, offset \\ 0) do
|
def assemble(asm) do
|
||||||
{memory, labels} = do_assemble(asm, offset)
|
{memory, labels} =
|
||||||
|
asm
|
||||||
|
|> String.trim_trailing("\n")
|
||||||
|
|> String.split("\n")
|
||||||
|
|> Enum.map(fn line ->
|
||||||
|
case parse_line(line) do
|
||||||
|
{:ok, res, _, _, _, _} ->
|
||||||
|
res
|
||||||
|
|
||||||
|
err ->
|
||||||
|
raise "Unable to parse line: '#{line}':\n#{inspect(err)}"
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|> Enum.reduce({[], %{}}, &assemble_line/2)
|
||||||
|
|
||||||
memory
|
memory
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|
@ -73,47 +92,23 @@ defmodule Assembler do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def do_assemble(asm, offset) do
|
def assemble_line([], acc), do: acc
|
||||||
asm
|
|
||||||
|> String.trim_trailing("\n")
|
|
||||||
|> String.split("\n")
|
|
||||||
|> Enum.map(fn line ->
|
|
||||||
case parse_line(line) do
|
|
||||||
{:ok, res, _, _, _, _} ->
|
|
||||||
res
|
|
||||||
|
|
||||||
err ->
|
def assemble_line([label: [name]], {memory, labels}) do
|
||||||
raise "Unable to parse line: '#{line}':\n#{inspect(err)}"
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|> Enum.reduce({[], %{}}, fn line, acc ->
|
|
||||||
assemble_line(line, acc, offset)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
def assemble_line([], acc, _), do: acc
|
|
||||||
|
|
||||||
def assemble_line([label: [name]], {memory, labels}, offset) do
|
|
||||||
{
|
{
|
||||||
memory,
|
memory,
|
||||||
Map.put(labels, name, length(memory) + offset)
|
Map.put(labels, name, length(memory))
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def assemble_line([data_label: [name, value]], {memory, labels}, _) do
|
def assemble_line([data_label: [name, value]], {memory, labels}) do
|
||||||
value =
|
|
||||||
case value do
|
|
||||||
{:neg, [val]} -> -val
|
|
||||||
val when is_integer(val) -> val
|
|
||||||
end
|
|
||||||
|
|
||||||
{
|
{
|
||||||
[value | memory],
|
[value | memory],
|
||||||
Map.put(labels, name, length(memory))
|
Map.put(labels, name, length(memory))
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def assemble_line([insn: insn], {memory, labels}, _) do
|
def assemble_line([insn: insn], {memory, labels}) do
|
||||||
{
|
{
|
||||||
assemble_insn(insn, memory),
|
assemble_insn(insn, memory),
|
||||||
labels
|
labels
|
||||||
|
@ -164,46 +159,6 @@ defmodule Assembler do
|
||||||
[99 | memory]
|
[99 | memory]
|
||||||
end
|
end
|
||||||
|
|
||||||
# macros
|
|
||||||
assemble_macro ["mov", src, dest],
|
|
||||||
"""
|
|
||||||
add 0, #{src}, #{dest}
|
|
||||||
"""
|
|
||||||
|
|
||||||
assemble_macro ["jmp", dest],
|
|
||||||
"""
|
|
||||||
jnz _self, #{dest}
|
|
||||||
"""
|
|
||||||
|
|
||||||
assemble_macro ["sub", a, b, dest],
|
|
||||||
"""
|
|
||||||
mul #{b}, -1, #{dest}
|
|
||||||
add #{a}, $#{dest}, #{dest}
|
|
||||||
"""
|
|
||||||
|
|
||||||
assemble_macro ["cle", a, b, dest],
|
|
||||||
"""
|
|
||||||
clt #{a}, #{b}, #{dest}
|
|
||||||
jnz $#{dest}, end
|
|
||||||
ceq #{a}, #{b}, #{dest}
|
|
||||||
|
|
||||||
end:
|
|
||||||
"""
|
|
||||||
|
|
||||||
assemble_macro ["cgt", a, b, dest],
|
|
||||||
"""
|
|
||||||
clt #{a}, #{b}, #{dest}
|
|
||||||
jnz $#{dest}, false
|
|
||||||
ceq #{a}, #{b}, #{dest}
|
|
||||||
jnz $#{dest}, false
|
|
||||||
mov 1, #{dest}
|
|
||||||
jmp end
|
|
||||||
|
|
||||||
false:
|
|
||||||
mov 0, #{dest}
|
|
||||||
end:
|
|
||||||
"""
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Raises the base to to the given power.
|
Raises the base to to the given power.
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,6 @@ defmodule AssemblerTest do
|
||||||
assert assemble(" hlt") == [99]
|
assert assemble(" hlt") == [99]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "assembles macros" do
|
|
||||||
assert assemble("mov 1, 2") == [1101, 0, 1, 2]
|
|
||||||
assert assemble("jmp 2") == [1105, 1, 2]
|
|
||||||
assert assemble("sub 5, 3, res\nres: 0") == [1102, 3, -1, 8, 101, 5, 8, 8, 0]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "assembles simple program" do
|
test "assembles simple program" do
|
||||||
program = """
|
program = """
|
||||||
add 1, 2, 10
|
add 1, 2, 10
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
in res
|
|
||||||
clt $res, 8, cmpRes
|
|
||||||
jnz $(res + 1), lessThan
|
|
||||||
ceq $res, 8, cmpRes
|
|
||||||
jnz $cmpRes, equal
|
|
||||||
out 1001
|
|
||||||
hlt
|
|
||||||
|
|
||||||
lessThan:
|
|
||||||
out 999
|
|
||||||
hlt
|
|
||||||
|
|
||||||
equal:
|
|
||||||
out 1000
|
|
||||||
hlt
|
|
||||||
|
|
||||||
res: 0
|
|
||||||
cmpRes: 0
|
|
||||||
|
|
Loading…
Reference in New Issue