diff --git a/elixir/livebook/2024/day24.livemd b/elixir/livebook/2024/day24.livemd new file mode 100644 index 0000000..4fd47b4 --- /dev/null +++ b/elixir/livebook/2024/day24.livemd @@ -0,0 +1,138 @@ +# Untitled notebook + +## Section + +```elixir +example_input = """ +x00: 1 +x01: 0 +x02: 1 +x03: 1 +x04: 0 +y00: 1 +y01: 1 +y02: 1 +y03: 1 +y04: 1 + +ntg XOR fgs -> mjb +y02 OR x01 -> tnw +kwq OR kpj -> z05 +x00 OR x03 -> fst +tgd XOR rvg -> z01 +vdt OR tnw -> bfw +bfw AND frj -> z10 +ffh OR nrd -> bqk +y00 AND y03 -> djm +y03 OR y00 -> psh +bqk OR frj -> z08 +tnw OR fst -> frj +gnj AND tgd -> z11 +bfw XOR mjb -> z00 +x03 OR x00 -> vdt +gnj AND wpb -> z02 +x04 AND y00 -> kjc +djm OR pbm -> qhw +nrd AND vdt -> hwm +kjc AND fst -> rvg +y04 OR y02 -> fgs +y01 AND x02 -> pbm +ntg OR kjc -> kwq +psh XOR fgs -> tgd +qhw XOR tgd -> z09 +pbm OR djm -> kpj +x03 XOR y03 -> ffh +x00 XOR y04 -> ntg +bfw OR bqk -> z06 +nrd XOR fgs -> wpb +frj XOR qhw -> z04 +bqk OR frj -> z07 +y03 OR x01 -> nrd +hwm AND bqk -> z03 +tgd XOR rvg -> z12 +tnw OR pbm -> gnj +""" +``` + +```elixir +defmodule CrossedWires do + import Bitwise + def gate(a, b, :or), do: bor(a, b) + def gate(a, b, :and), do: a &&& b + def gate(a, b, :xor), do: bxor(a, b) + defmacro defgate(arg1, arg2, operation, output) do + quote do + def unquote(output)() do + gate( + unquote(arg1)(), + unquote(arg2)(), + unquote(operation) + ) + end + end + end + + defmacro defwire(label, int, value) do + f_name = "#{label |> Atom.to_string()}#{int |> to_string() |> String.pad_leading(2, "0")}" + quote do + def unquote(f_name |> String.to_atom())(), do: unquote(value) + end + end + + def transpile(input) do + lines = input + |> String.split("\n", trim: true) + |> Stream.reject(&(&1 == "")) + + all_zs = lines + |> Stream.filter(&(String.contains?(&1, "-> z"))) + |> Stream.map(&Enum.at(String.split(&1, " "), 4)) + |> Enum.sort() + calls = all_zs |> Enum.map(fn z -> "\#{#{z}()}" end) |> Enum.join("") + "defmodule MyCrossedWires do\nimport CrossedWires\n" <> + (lines + |> Enum.map(fn line -> + transpile_line(line) + end) + |> Enum.join("\n") + ) + <> + "\n" <> + "def z() do\n" <> + "\"#{calls}\"\nend\n" <> + "def part1() do\n" <> + "z() |> String.reverse() |> String.to_integer(2)\n" <> + "end\n" + <> "\n end" + end + + def transpile_line(line) do + if String.ends_with?(line, ": 0") or String.ends_with?(line, ": 1") do + transpile_defwire(line) + else + transpile_defgate(line) + end + end + + def transpile_defwire(<> <> <> <> ": " <> value) do + "defwire(:#{flavor},#{i},#{value})" + end + + def transpile_defgate(line) do + [arg1, op, arg2, _, output] = line |> String.split(" ") + "defgate(:#{arg1}, :#{arg2}, :#{op |> String.downcase()}, :#{output})" + end +end +``` + +```elixir +CrossedWires.transpile(example_input) |> IO.puts() +``` + +```elixir +# paste transpiled output here +``` + +```elixir +MyCrossedWires.part1() +```