8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ElixirAdvent Calendar 2024

Day 17

Advent of code 2015 Day 7 Part 2 を Livebook で楽しむ

Last updated at Posted at 2024-11-22

はじめに

Advent of code 2024 の準備として、過去回の Advent of code 2015 を Livebook で楽しみます

本記事では Day 7 の Part 2 を解きます

問題文はこちら

実装したノートブックはこちら

Part 1 はこちら

セットアップ

Kino AOC をインストールします

Mix.install([
  {:kino_aoc, "~> 0.1"}
])

Kino AOC の使い方はこちらを参照

入力の取得

"Advent of Code Helper" スマートセルを追加し、 Day 7 の入力を取得します

スクリーンショット 2024-11-21 16.55.19.png

私の答え

私の答えです。
折りたたんでおきます。
▶を押して開いてください。

回答

Part 1 でかなり苦戦しましたが、 Part 2 は単純でした

まずビット演算のために Bitwise を import しておき、 Part 1 と同じモジュールを定義します

import Bitwise
defmodule Solver do
  import Bitwise

  defp bit_not(input) do
    <<output::integer-size(2)-unit(8)>> = <<(~~~input)::size(16)>>
    output
  end

  defp parse_variable(nil, _), do: nil
  defp parse_variable("", _), do: nil
  defp parse_variable(variable, _) when is_integer(variable), do: variable
  defp parse_variable(variable, dict) do
    case Integer.parse(variable) do
      {number, ""} -> number
      _ -> Map.get(dict, variable, variable)
    end
  end

  defp calc("", input_a, _) when is_integer(input_a), do: input_a
  defp calc("NOT", _, input_b) when is_integer(input_b), do: bit_not(input_b)
  defp calc("AND", input_a, input_b) when (is_integer(input_a) and is_integer(input_b)) do
    input_a &&& input_b
  end
  defp calc("OR", input_a, input_b) when (is_integer(input_a) and is_integer(input_b)) do
    input_a ||| input_b
  end
  defp calc("LSHIFT", input_a, input_b) when (is_integer(input_a) and is_integer(input_b)) do
    input_a <<< input_b
  end
  defp calc("RSHIFT", input_a, input_b) when (is_integer(input_a) and is_integer(input_b)) do
    input_a >>> input_b
  end
  defp calc(_, _, _), do: nil

  defp solve(instruction, dict) do
    %{
      "input_a" => input_a,
      "input_b" => input_b,
      "op" => op,
      "output" => output
    } = instruction

    input_a = parse_variable(input_a, dict)
    input_b = parse_variable(input_b, dict)

    result = calc(op, input_a, input_b)
    solved = !is_nil(result)

    instruction = Map.put(instruction, :solved, solved)
    dict = if solved, do: Map.put(dict, output, result), else: dict

    {instruction, dict}
  end

  def parse_instraction(row) do
    Regex.named_captures(
      ~r/(?<input_a>[a-z0-9]*) *(?<op>[A-Z]*) *(?<input_b>[a-z0-9]*) -> (?<output>.+)/,
      row
    )
  end

  def cyclic_solve(%{solved: true}, instructions, dict), do: {instructions, dict}
  def cyclic_solve(new_instruction, instructions, dict) do
    {new_instruction, dict} = solve(new_instruction, dict)

    if new_instruction.solved do
      {instructions, dict} =
        instructions
        |> Enum.reduce({[], dict}, fn sub_instruction, {acc_instructions, acc_dict} ->
          cyclic_solve(sub_instruction, acc_instructions, acc_dict)
        end)

      {[new_instruction | instructions], dict}
    else
      {[new_instruction | instructions], dict}
    end
  end
end

2 回、全ワイヤーの値を計算しないといけないので、関数化しておきます

get_a = fn rows ->
  rows
  |> Enum.reduce({[], %{}}, fn row, {instructions, dict} ->
    new_instruction = Solver.parse_instraction(row)
    Solver.cyclic_solve(new_instruction, instructions, dict)
  end)
  |> elem(1)
  |> Map.get("a")
end

1回目の計算で取得した a ワイヤーの値で b ワイヤーの入力を上書き、再度 a ワイヤーの値を取得します

rows = String.split(puzzle_input, "\n")

override_value = get_a.(rows)

rows
|> Enum.map(fn row ->
  if String.ends_with?(row, "-> b") do
    "#{override_value} -> b"
  else
    row
  end
end)
|> get_a.()

まとめ

問題文から ChatGPT に画像を生成してもらいました

wire.jpeg

Part 1 でモジュール化しておいたので、 Part 2 は何も躓くことなく解けました

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?