Skip to content

Instantly share code, notes, and snippets.

@kunna
Last active May 4, 2024 15:11
Show Gist options
  • Select an option

  • Save kunna/9dee6c96ca85f0d8a1257d0d6bb43ce3 to your computer and use it in GitHub Desktop.

Select an option

Save kunna/9dee6c96ca85f0d8a1257d0d6bb43ce3 to your computer and use it in GitHub Desktop.
SomeAssemblyRequired
defmodule SomeAssemblyRequired do
import Bitwise
def run(lines) do
lines
|> String.split("\n")
|> Enum.reject(&(&1 == ""))
|> Enum.reduce([], fn line, binding ->
[operation_or_value, var] = line |> String.split("->") |> Enum.map(&String.trim/1)
val = eval(operation_or_value, binding)
Keyword.put(binding, String.to_atom(var), val)
end)
end
def eval(operation_or_value, binding \\ []) do
case String.split(operation_or_value) do
[l, "AND", r] ->
[l, r] = get_value([l, r], binding)
l &&& r
[l, "OR", r] ->
[l, r] = get_value([l, r], binding)
l ||| r
[l, "LSHIFT", r] ->
[l, r] = get_value([l, r], binding)
l <<< r
[l, "RSHIFT", r] ->
[l, r] = get_value([l, r], binding)
l >>> r
["NOT", value] ->
value = get_value(value, binding)
~~~value &&& 0xFFFF
_ ->
String.to_integer(operation_or_value)
end
end
defp get_value(list, binding) when is_list(list) do
Enum.map(list, &get_value(&1, binding))
end
defp get_value(string, binding) do
if Regex.match?(~r/^\d+$/, string),
do: String.to_integer(string),
else: Keyword.get(binding, String.to_atom(string))
end
end
ExUnit.start()
defmodule SomeAssemblyRequiredTest do
use ExUnit.Case
test "eval works" do
assert 72 = SomeAssemblyRequired.eval("123 AND 456")
assert 72 = SomeAssemblyRequired.eval("x AND 456", x: 123)
assert 507 = SomeAssemblyRequired.eval("123 OR 456")
assert 4 = SomeAssemblyRequired.eval("1 LSHIFT 2")
assert 0 = SomeAssemblyRequired.eval("1 RSHIFT 2")
assert 65534 = SomeAssemblyRequired.eval("NOT 1")
assert 1111 = SomeAssemblyRequired.eval("1111")
end
test "it works" do
input = """
123 -> x
456 -> y
x AND y -> d
x OR y -> e
x LSHIFT 2 -> f
y RSHIFT 2 -> g
NOT x -> h
NOT y -> i
"""
assert %{d: 72, e: 507, f: 492, g: 114, h: 65412, i: 65079, x: 123, y: 456} ==
SomeAssemblyRequired.run(input) |> Enum.into(%{})
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment