# AoC 2015 Puzzle 7

###### Info

I solved this puzzle. You can find the code here, but I have yet to write a good explanation of the solution here. I will do this shortly, thank you for your patience.

## Day 7: Some Assembly Required

This year, Santa brought little Bobby Tables a set of wires and bitwise logic gates! Unfortunately, little Bobby is a little under the recommended age range, and he needs help assembling the circuit.

Each wire has an identifier (some lowercase letters) and can carry a 16-bit signal (a number from 0 to 65535). A signal is provided to each wire by a gate, another wire, or some specific value. Each wire can only get a signal from one source, but can provide its signal to multiple destinations. A gate provides no signal until all of its inputs have a signal.

The included instructions booklet describes how to connect the parts together: x AND y -> z means to connect wires x and y to an AND gate, and then connect its output to wire z.

For example:

• 123 -> x means that the signal 123 is provided to wire x.
• x AND y -> z means that the bitwise AND of wire x and wire y is provided to wire z.
• p LSHIFT 2 -> q means that the value from wire p is left-shifted by 2 and then provided to wire q.
• NOT e -> f means that the bitwise complement of the value from wire e is provided to wire f.

Other possible gates include OR (bitwise OR) and RSHIFT (right-shift). If, for some reason, you'd like to emulate the circuit instead, almost all programming languages (for example, C, JavaScript, or Python) provide operators for these gates.

For example, here is a simple circuit:

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

After it is run, these are the signals on the wires:

d: 72 e: 507 f: 492 g: 114 h: 65412 i: 65079 x: 123 y: 456

In little Bobby's kit's instructions booklet (provided as your puzzle input), what signal is ultimately provided to wire a?

### Part 2

Now, take the signal you got on wire a, override wire b to that signal, and reset the other wires (including wire a). What new signal is ultimately provided to wire a?

### Complete Solution

```public enum Op {
AND((x, y) -> (x & y)), OR((x, y) -> (x | y)), NOT((x, y) -> (~x & 0xffff)), RSHIFT((x, y) -> (x >> y)),
LSHIFT((x, y) -> (x << y)), ASSIGNX((x, y) -> (x));

private final IntBinaryOperator func;

Op(IntBinaryOperator func) {
this.func = func;
}
}

@AllArgsConstructor
@RequiredArgsConstructor
@ToString
@EqualsAndHashCode
public class Gate {
@NonNull
String name;
Wire left;
Wire right;
Wire result;
Op op;

public boolean allWiresHaveValue() {
boolean valid = true;
if (left != null && left.value == -1)
valid = false;
if (right != null && right.value == -1)
valid = false;
return valid;
}

public void perform() {
if (op == null)
return;
result.value = op.func.applyAsInt(left != null ? left.value : 0, right != null ? right.value : 0);
}

public void fire() {
if (allWiresHaveValue()) {
perform();
} else {
if (left != null && !left.name.equals("")) {
Gate g = getGate(left.name);
g.fire();
}
if (right != null && !right.name.equals("")) {
Gate g = getGate(right.name);
g.fire();
}
}
}
}

@AllArgsConstructor
@RequiredArgsConstructor
@ToString
@EqualsAndHashCode
public class Wire {
@NonNull
String name;
int value = -1;
//Gate gate = null;
}

Map<String, Wire> wires = new HashMap<>();
Map<String, Gate> gates = new HashMap<>();

public Wire getWire(String name) {
Wire result = isDigit(name) ? new Wire("", Integer.parseInt(name))
: wires.getOrDefault(name, new Wire(name));
return result;
}

public Gate getGate(String resultName) {
Gate result = isDigit(resultName) ? new Gate(resultName)
: gates.getOrDefault(resultName, new Gate(resultName));
return result;
}

public boolean isDigit(String input) {
return Character.isDigit(input.charAt(0));
}

public void storeWires(Wire... wires) {
for (Wire w : wires) {
if (w != null) {
this.wires.put(w.name, w);
}
}
}

public void createCircuit(List<String> input) {

for (String i : input) {
String[] inst = i.split(" ");

Wire left = null, right = null, result = null;
Op op = null;

switch (inst.length) {
case 3: // ASSIGN
left = getWire(inst[0]);
result = getWire(inst[2]);

op = Op.ASSIGNX;
break;
case 4: // NOT
left = getWire(inst[1]);
result = getWire(inst[3]);
op = Op.NOT;
break;
case 5: // operation
left = getWire(inst[0]);
right = getWire(inst[2]);
op = Op.valueOf(inst[1]);
result = getWire(inst[4]);
break;
default:
System.out.println("Unknown case detected!");
}

// Should always return a new Gate
Gate g = getGate(result.name);

if (g.op != null) {
System.out.println("Gate returned an existing gate? " + g);
}

g.left = left;
g.right = right;
g.result = result;
g.op = op;

gates.put(g.result.name, g);
storeWires(left, right, result);
}

}

protected int fireWire(String name) {
Gate g = getGate(name);
while (g.result.value == -1) {
g.fire();
}
return g.result.value;
}

@Override
public String part1(List<String> input) {
Day07 app = new Day07();
app.wires.clear();
app.gates.clear();
app.createCircuit(input);
return String.valueOf(app.fireWire("a"));
}

@Override
public String part2(List<String> input) {
Day07 app = new Day07();
app.wires.clear();
app.gates.clear();
app.createCircuit(input);
int value = app.fireWire("a");

app.wires.clear();
app.gates.clear();
app.createCircuit(input);

Gate b = app.getGate("b");
b.result.value = value;
b.op = null;

return String.valueOf(app.fireWire("a"));
}
```