Skip to content

Advent of Code. Year 2015. Day 7

Published: (3 min read)

--- Day 7: Some Assembly Required ---

In this challenge, we need to help little Bobby Tables to assemble the circuit. In order to do this, we have a booklet that describes how to connect parts together: x AND y -> z means to connect x and y to an AND gate, and then connect its output to wire z.

Table of Contents

Open Table of Contents

Part 1

We need to find out, which signal is ultimately provided to wire a. Our solution is based on recursive function which can calculate value of a given wire. For example, imagine that we have such instructions:

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

And here’s what happens if we call Process("d"):

private Dictionary<string, string[]>
            _instructions = new Dictionary<string, string[]>();

private int Process(string input)
{
  var ins = _instructions[input];
  var value = GetValue(ins);
  _instructions[input] = new[] { value.ToString(), "->", input };
  return value;
}

private int GetValue(IReadOnlyList<string> instruction)
{
  int ComputeValue(string x) => char.IsLetter(x[0]) ? Process(x) : int.Parse(x);
  int Assign(IReadOnlyList<string> x) => ComputeValue(x[0]);
  int And(IReadOnlyList<string> x) => ComputeValue(x[0]) & ComputeValue(x[2]);
  int Or(IReadOnlyList<string> x) => ComputeValue(x[0]) | ComputeValue(x[2]);
  int LShift(IReadOnlyList<string> x) => ComputeValue(x[0]) << ComputeValue(x[2]);
  int RShift(IReadOnlyList<string> x) => ComputeValue(x[0]) >> ComputeValue(x[2]);
  int Not(IReadOnlyList<string> x) => ~ComputeValue(x[1]);

  switch (instruction[1])
  {
    case "->":
      return Assign(instruction);
    case "AND":
      return And(instruction);
    case "OR":
      return Or(instruction);
    case "LSHIFT":
      return LShift(instruction);
    case "RSHIFT":
      return RShift(instruction);
    default:
      return instruction[0] == "NOT" ? Not(instruction) : 0;
  }
}

When we got all this code, we needed only populate _instructions and then to compute the value of wire a by only calling Process("a").

public string Part1(IEnumerable<string> input)
{
  _instructions = input.Select(r => r.Split()).ToDictionary(r => r.Last());
  var value = Process("a");
  return value.ToString();
}

Part 2

In the second part, after we computed the value of wire a we needed to override wire b to that signal, and reset the other wires (including wire a). After that, we needed again to find the value of wire a.

public string Part2(IEnumerable<string> input)
{
  var enumerable = input as string[] ?? input.ToArray();
  _instructions = enumerable.Select(r => r.Split()).ToDictionary(r => r.Last());
  var value = Process("a");
  _instructions = enumerable.Select(r => r.Split()).ToDictionary(r => r.Last());
  _instructions["b"] = new []{value.ToString(), "->", "b"};
  return Process("a").ToString();
}

Links:

Other posts