Add 2024 Day 24

This commit is contained in:
Burnus 2024-12-29 16:03:30 +01:00
parent 7520d4956b
commit 1f6501498e
5 changed files with 947 additions and 0 deletions

View file

@ -0,0 +1,13 @@
[package]
name = "day24_crossed_wires"
version = "0.1.0"
edition = "2021"
[dependencies]
[dev-dependencies]
# criterion = "0.5.1"
[[bench]]
name = "test_benchmark"
harness = false

View file

@ -0,0 +1,225 @@
You and The Historians arrive at the edge of a [large grove](/2022/day/23) somewhere in the jungle. After the last incident, the Elves installed a small device that monitors the fruit. While The Historians search the grove, one of them asks if you can take a look at the monitoring device; apparently, it's been malfunctioning recently.
The device seems to be trying to produce a number through some boolean logic gates. Each gate has two inputs and one output. The gates all operate on values that are either *true* (`1`) or *false* (`0`).
* `AND` gates output `1` if *both* inputs are `1`; if either input is `0`, these gates output `0`.
* `OR` gates output `1` if *one or both* inputs is `1`; if both inputs are `0`, these gates output `0`.
* `XOR` gates output `1` if the inputs are *different*; if the inputs are the same, these gates output `0`.
Gates wait until both inputs are received before producing output; wires can carry `0`, `1` or no value at all. There are no loops; once a gate has determined its output, the output will not change until the whole system is reset. Each wire is connected to at most one gate output, but can be connected to many gate inputs.
Rather than risk getting shocked while tinkering with the live system, you write down all of the gate connections and initial wire values (your puzzle input) so you can consider them in relative safety. For example:
```
x00: 1
x01: 1
x02: 1
y00: 0
y01: 1
y02: 0
x00 AND y00 -> z00
x01 XOR y01 -> z01
x02 OR y02 -> z02
```
Because gates wait for input, some wires need to start with a value (as inputs to the entire system). The first section specifies these values. For example, `x00: 1` means that the wire named `x00` starts with the value `1` (as if a gate is already outputting that value onto that wire).
The second section lists all of the gates and the wires connected to them. For example, `x00 AND y00 -> z00` describes an instance of an `AND` gate which has wires `x00` and `y00` connected to its inputs and which will write its output to wire `z00`.
In this example, simulating these gates eventually causes `0` to appear on wire `z00`, `0` to appear on wire `z01`, and `1` to appear on wire `z02`.
Ultimately, the system is trying to produce a *number* by combining the bits on all wires starting with `z`. `z00` is the least significant bit, then `z01`, then `z02`, and so on.
In this example, the three output bits form the binary number `100` which is equal to the decimal number `*4*`.
Here's a larger example:
```
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
```
After waiting for values on all wires starting with `z`, the wires in this system have the following values:
```
bfw: 1
bqk: 1
djm: 1
ffh: 0
fgs: 1
frj: 1
fst: 1
gnj: 1
hwm: 1
kjc: 0
kpj: 1
kwq: 0
mjb: 1
nrd: 1
ntg: 0
pbm: 1
psh: 1
qhw: 1
rvg: 0
tgd: 0
tnw: 1
vdt: 1
wpb: 0
z00: 0
z01: 0
z02: 0
z03: 1
z04: 0
z05: 1
z06: 1
z07: 1
z08: 1
z09: 1
z10: 1
z11: 0
z12: 0
```
Combining the bits from all wires starting with `z` produces the binary number `0011111101000`. Converting this number to decimal produces `*2024*`.
Simulate the system of gates and wires. *What decimal number does it output on the wires starting with `z`?*
Your puzzle answer was `57270694330992`.
\--- Part Two ---
----------
After inspecting the monitoring device more closely, you determine that the system you're simulating is trying to *add two binary numbers*.
Specifically, it is treating the bits on wires starting with `x` as one binary number, treating the bits on wires starting with `y` as a second binary number, and then attempting to add those two numbers together. The output of this operation is produced as a binary number on the wires starting with `z`. (In all three cases, wire `00` is the least significant bit, then `01`, then `02`, and so on.)
The initial values for the wires in your puzzle input represent *just one instance* of a pair of numbers that sum to the wrong value. Ultimately, *any* two binary numbers provided as input should be handled correctly. That is, for any combination of bits on wires starting with `x` and wires starting with `y`, the sum of the two numbers those bits represent should be produced as a binary number on the wires starting with `z`.
For example, if you have an addition system with four `x` wires, four `y` wires, and five `z` wires, you should be able to supply any four-bit number on the `x` wires, any four-bit number on the `y` numbers, and eventually find the sum of those two numbers as a five-bit number on the `z` wires. One of the many ways you could provide numbers to such a system would be to pass `11` on the `x` wires (`1011` in binary) and `13` on the `y` wires (`1101` in binary):
```
x00: 1
x01: 1
x02: 0
x03: 1
y00: 1
y01: 0
y02: 1
y03: 1
```
If the system were working correctly, then after all gates are finished processing, you should find `24` (`11+13`) on the `z` wires as the five-bit binary number `11000`:
```
z00: 0
z01: 0
z02: 0
z03: 1
z04: 1
```
Unfortunately, your actual system needs to add numbers with many more bits and therefore has many more wires.
Based on forensic analysis of scuff marks and scratches on the device, you can tell that there are exactly *four* pairs of gates whose output wires have been *swapped*. (A gate can only be in at most one such pair; no gate's output was swapped multiple times.)
For example, the system below is supposed to find the bitwise `AND` of the six-bit number on `x00` through `x05` and the six-bit number on `y00` through `y05` and then write the result as a six-bit number on `z00` through `z05`:
```
x00: 0
x01: 1
x02: 0
x03: 1
x04: 0
x05: 1
y00: 0
y01: 0
y02: 1
y03: 1
y04: 0
y05: 1
x00 AND y00 -> z05
x01 AND y01 -> z02
x02 AND y02 -> z01
x03 AND y03 -> z03
x04 AND y04 -> z04
x05 AND y05 -> z00
```
However, in this example, two pairs of gates have had their output wires swapped, causing the system to produce wrong answers. The first pair of gates with swapped outputs is `x00 AND y00 -> z05` and `x05 AND y05 -> z00`; the second pair of gates is `x01 AND y01 -> z02` and `x02 AND y02 -> z01`. Correcting these two swaps results in this system that works as intended for any set of initial values on wires that start with `x` or `y`:
```
x00 AND y00 -> z00
x01 AND y01 -> z01
x02 AND y02 -> z02
x03 AND y03 -> z03
x04 AND y04 -> z04
x05 AND y05 -> z05
```
In this example, two pairs of gates have outputs that are involved in a swap. By sorting their output wires' names and joining them with commas, the list of wires involved in swaps is `*z00,z01,z02,z05*`.
Of course, your actual system is much more complex than this, and the gates that need their outputs swapped could be *anywhere*, not just attached to a wire starting with `z`. If you were to determine that you need to swap output wires `aaa` with `eee`, `ooo` with `z99`, `bbb` with `ccc`, and `aoc` with `z24`, your answer would be `*aaa,aoc,bbb,ccc,eee,ooo,z24,z99*`.
Your system of gates and wires has *four* pairs of gates which need their output wires swapped - *eight* wires in total. Determine which four pairs of gates need their outputs swapped so that your system correctly performs addition; *what do you get if you sort the names of the eight wires involved in a swap and then join those names with commas?*
Your puzzle answer was `gwh,jct,rcb,wbw,wgb,z09,z21,z39`.
Both parts of this puzzle are complete! They provide two gold stars: \*\*
At this point, you should [return to your Advent calendar](/2024) and try another puzzle.
If you still want to see it, you can [get your puzzle input](24/input).

View file

@ -0,0 +1,349 @@
use core::fmt::Display;
use std::{collections::{HashMap, HashSet}, num::ParseIntError};
#[derive(Debug, PartialEq, Eq)]
pub enum ParseError<'a> {
DuplicateName(&'a str),
InputMalformed,
IllegalSate(&'a str, &'a str),
ParseIntError(std::num::ParseIntError),
LineMalformed(&'a str),
}
impl From<ParseIntError> for ParseError<'_> {
fn from(value: ParseIntError) -> Self {
Self::ParseIntError(value)
}
}
impl Display for ParseError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::DuplicateName(v) => write!(f, "Input for gate {v} is defined twice"),
Self::InputMalformed => write!(f, "Input must consist of the initial states, followed by an empty line, and the rules block"),
Self::IllegalSate(name, state) => write!(f, "Unable to set gate {name} to {state}. Only '0' and '1' are allowed."),
Self::LineMalformed(v) => write!(f, "Line is malformed:\n{v}\n Must be of form: x01 XOR y01 -> z01."),
Self::ParseIntError(e) => write!(f, "Unable to parse into integer: {e}"),
}
}
}
#[derive(Clone, Copy, Debug)]
enum Gate<'a> {
Value(bool),
And(&'a str, &'a str),
Or(&'a str, &'a str),
Xor(&'a str, &'a str),
}
#[derive(Clone)]
struct Device<'a> {
gates: HashMap<&'a str, Gate<'a>>,
output_gates: usize,
x: usize,
y: usize,
}
impl<'a> TryFrom<&'a str> for Device<'a> {
type Error = ParseError<'a>;
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
if let Some((input, rules)) = value.split_once("\n\n") {
let mut gates = HashMap::new();
let mut output_gates = 0;
let mut x = 0;
let mut y = 0;
for line in input.lines() {
if let Some((name, val)) = line.split_once(": ") {
let input = name.chars().next();
let idx = name[1..].parse::<usize>()?;
match (input, val) {
(_, "0") => (),
(Some('x'), "1") => x |= 1 << idx,
(Some('y'), "1") => y |= 1 << idx,
_ => return Err(Self::Error::IllegalSate(name, val)),
}
}
}
for line in rules.lines() {
let components: Vec<_> = line.split_whitespace().collect();
if components.len() != 5 {
return Err(Self::Error::LineMalformed(line));
}
let op = components[1];
let in_0 = components[0];
let in_1 = components[2];
let this = components[4];
if let Some(idx) = this.strip_prefix('z') {
let idx = idx.parse::<usize>()?;
output_gates = output_gates.max(idx+1);
match op {
"AND" => _ = gates.insert(this, Gate::And(in_0, in_1)),
"OR" => _ = gates.insert(this, Gate::Or(in_0, in_1)),
"XOR" => _ = gates.insert(this, Gate::Xor(in_0, in_1)),
e => return Err(Self::Error::IllegalSate(components[4], e)),
}
} else {
if gates.contains_key(&this) {
return Err(Self::Error::DuplicateName(components[4]));
}
match op {
"AND" => _ = gates.insert(this, Gate::And(in_0, in_1)),
"OR" => _ = gates.insert(this, Gate::Or(in_0, in_1)),
"XOR" => _ = gates.insert(this, Gate::Xor(in_0, in_1)),
e => return Err(Self::Error::IllegalSate(components[4], e)),
}
}
}
Ok(Self {
gates,
output_gates,
x,
y,
})
} else {
Err(Self::Error::InputMalformed)
}
}
}
impl<'a> Device<'a> {
fn eval_gate(&mut self, name: &str, modifying: bool) -> bool {
if let Some(num) = name.strip_prefix('x') {
if let Ok(digit) = num.parse::<usize>() {
return self.x & (1 << digit) > 0;
}
} else if let Some(num) = name.strip_prefix('y') {
if let Ok(digit) = num.parse::<usize>() {
return self.y & (1 << digit) > 0;
}
}
// unwrap() is safe here, because we know we will only ever call this function on valid
// gates.
let this = *self.gates.get(name).unwrap();
let res = match this {
Gate::Value(a) => a,
Gate::And(a, b) => match (self.gates.get(a), self.gates.get(b)) {
(Some(Gate::Value(false)), _) | (_, Some(Gate::Value(false))) => {
false
},
_ => {
self.eval_gate(a, modifying) && self.eval_gate(b, modifying)
},
},
Gate::Or(a, b) => match (self.gates.get(a), self.gates.get(b)) {
(Some(Gate::Value(true)), _) | (_, Some(Gate::Value(true))) => {
true
},
_ => {
self.eval_gate(a, modifying) || self.eval_gate(b, modifying)
},
},
Gate::Xor(a, b) => self.eval_gate(a, modifying) ^ self.eval_gate(b, modifying),
};
if modifying {
// unwrap() is safe here because we would have failed earlier otherwise
*self.gates.get_mut(name).unwrap() = Gate::Value(res);
}
res
}
fn eval_output_gate(&mut self, idx: usize, modifying: bool) -> usize {
let name = if idx < 10 {
&format!("z0{idx}")[..]
} else {
&format!("z{idx}")[..]
};
self.eval_gate(name, modifying) as usize
}
fn eval(&mut self) -> usize {
(0..self.output_gates).map(|idx| self.eval_output_gate(idx, true) << idx).sum()
}
fn get_dependent_gates(&self, name: &'a str) -> HashSet<&'a str> {
match self.gates.get(name) {
Some(Gate::And(a, b)) | Some(Gate::Or(a, b )) | Some(Gate::Xor(a, b)) =>
HashSet::from([name]).union(&self.get_dependent_gates(a)).cloned().collect::<HashSet<_>>().union(&self.get_dependent_gates(b)).cloned().collect(),
Some(Gate::Value(_)) => HashSet::from([name]),
None => HashSet::new(),
}
}
fn is_loop_free(&self, name: &str, previous: &HashSet<&str>) -> bool {
match self.gates.get(name) {
None | Some(Gate::Value(_)) => true,
Some(Gate::And(a, b)) | Some(Gate::Or(a, b )) | Some(Gate::Xor(a, b)) => {
if previous.contains(a) || previous.contains(b) {
return false;
}
let mut previous = previous.clone();
previous.insert(a);
previous.insert(b);
self.is_loop_free(a, &previous) && self.is_loop_free(b, &previous)
}
}
}
fn output_gate(idx: usize) -> String {
if idx < 10 {
format!("z0{idx}")
} else {
format!("z{idx}")
}
}
fn output_is_loop_free(&self, idx: usize) -> bool {
self.is_loop_free(&Self::output_gate(idx)[..], &HashSet::new())
}
fn check_until(&mut self, z_idx: usize) -> Option<usize> {
let tests_0 = [(0, 0), (0, 1), (1, 0), (1, 1)];
if tests_0.iter().any(|(l, r)| {
self.x = *l;
self.y = *r;
!self.output_is_loop_free(0) ||
self.eval_output_gate(0, false) != l ^ r
}) {
return Some(0);
}
if z_idx == 0 {
return None;
}
let tests = [
(0, 0, 0, 0), (0, 1, 0, 0), (1, 0, 0, 0), (1, 1, 0, 0),
(0, 0, 0, 1), (0, 1, 0, 1), (1, 0, 0, 1), (1, 1, 0, 1),
(0, 0, 1, 0), (0, 1, 1, 0), (1, 0, 1, 0), (1, 1, 1, 0),
(0, 0, 1, 1), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 1, 1),
];
(1..=z_idx).find(|&z_idx| {
!self.output_is_loop_free(z_idx) ||
tests.iter().any(|(l, r, prev_l, prev_r)| {
self.x = ((*l << 1) + *prev_l) << (z_idx - 1);
self.y = ((*r << 1) + *prev_r) << (z_idx - 1);
self.eval_output_gate(z_idx, false) != l ^ r ^ (prev_l & prev_r)
})
})
}
fn try_swaps(&'a mut self, z_idx: usize, must_include: &[&'a str], swapped_before: &[&'a str]) -> Vec<Vec<String>> {
let mut res = Vec::new();
// We need to clone these so the borrow checker won't complain about concurrent borrows in the
// swap loops.
let all_inputs: Vec<_> = self.gates.keys().cloned().collect();
// Try only switching one pair of gates and hope we find a solution this way (works for my
// input).
for &gate_1 in must_include {
if swapped_before.contains(&gate_1) {
continue;
}
// The unwrap()s below are safe because the constructor made shure all gates exist.
let inputs_1 = *self.gates.get(gate_1).unwrap();
for &gate_2 in all_inputs.iter().filter(|&&gate_2|
gate_2 != gate_1 &&
!swapped_before.contains(&gate_2))
{
let inputs_2 = *self.gates.get(gate_2).unwrap();
*self.gates.get_mut(gate_1).unwrap() = inputs_2;
*self.gates.get_mut(gate_2).unwrap() = inputs_1;
if self.check_until(z_idx).is_none() {
res.push(Vec::from([gate_1.into(), gate_2.into()]));
}
*self.gates.get_mut(gate_1).unwrap() = inputs_1;
*self.gates.get_mut(gate_2).unwrap() = inputs_2;
}
}
res
}
fn swap_gates(&mut self, swapped_before: &[String]) -> Vec<String> {
let mut swaps_performed = swapped_before.to_vec();
loop {
if let Some(next_error) = self.check_until(self.output_gates-2) {
let output_name = Self::output_gate(next_error);
let swapped_before: Vec<_> = swaps_performed.iter().map(|s: &String| &s[..]).collect();
let must_include: Vec<&str> = self.get_dependent_gates(&output_name[..]).into_iter().collect();
let mut next = self.clone();
let new_possible_swaps = next.try_swaps(next_error, &must_include, &swapped_before);
match new_possible_swaps.len() {
// The unwrap()s below are safe because the constructor made shure all gates exist.
0 => return Vec::new(), // If we found no solution, return early
1 => {
// We found one solution. Continue with it.
for swap in new_possible_swaps[0].chunks(2) {
let (gate_1, gate_2) = (swap[0].to_string(), swap[1].to_string());
let inputs_1 = *self.gates.get(&gate_1[..]).unwrap();
*self.gates.get_mut(&gate_1[..]).unwrap() = *self.gates.get(&gate_2[..]).unwrap();
*self.gates.get_mut(&gate_2[..]).unwrap() = inputs_1;
swaps_performed.push(gate_1);
swaps_performed.push(gate_2);
}
},
_ => {
// We found more than one solution. Spawn a new Device for each and try
// them all.
for swaps in new_possible_swaps {
if swaps.len() + swaps_performed.len() > 8 {
continue;
}
let mut next = self.clone();
let mut swapped_before = swaps_performed.to_vec();
for swap in swaps.chunks(2) {
let (gate_1, gate_2) = (swap[0].to_string(), swap[1].to_string());
let inputs_1 = *self.gates.get(&gate_1[..]).unwrap();
*next.gates.get_mut(&gate_1[..]).unwrap() = *self.gates.get(&gate_2[..]).unwrap();
*next.gates.get_mut(&gate_2[..]).unwrap() = inputs_1;
swapped_before.push(gate_1);
swapped_before.push(gate_2);
}
let res = next.swap_gates(&swapped_before);
if res.len() <= 8 {
return res;
}
}
return Vec::new();
}
}
} else if swaps_performed.len() <= 8 {
swaps_performed.sort();
return swaps_performed;
} else {
return Vec::new();
}
}
}
}
pub fn run(input: &str) -> Result<(usize, String), ParseError> {
let mut device_1 = Device::try_from(input)?;
let mut device_2 = device_1.clone();
let first = device_1.eval();
let second = if device_2.output_gates > 13 {
device_2.swap_gates(&[]).join(",")
} else {
String::new()
};
Ok((first, second))
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::read_to_string;
fn read_file(name: &str) -> String {
read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string()
}
#[test]
fn test_sample() {
let sample_input = read_file("tests/sample_input");
assert_eq!(run(&sample_input), Ok((2024, "".to_string())));
}
#[test]
fn test_challenge() {
let challenge_input = read_file("tests/challenge_input");
assert_eq!(run(&challenge_input), Ok((57270694330992, "gwh,jct,rcb,wbw,wgb,z09,z21,z39".to_string())));
}
}

View file

@ -0,0 +1,313 @@
x00: 1
x01: 1
x02: 0
x03: 0
x04: 0
x05: 1
x06: 0
x07: 1
x08: 1
x09: 0
x10: 1
x11: 0
x12: 0
x13: 1
x14: 0
x15: 1
x16: 0
x17: 1
x18: 1
x19: 1
x20: 1
x21: 0
x22: 0
x23: 1
x24: 1
x25: 0
x26: 0
x27: 1
x28: 1
x29: 1
x30: 1
x31: 0
x32: 0
x33: 1
x34: 0
x35: 1
x36: 0
x37: 1
x38: 0
x39: 0
x40: 1
x41: 1
x42: 0
x43: 1
x44: 1
y00: 1
y01: 0
y02: 1
y03: 1
y04: 0
y05: 0
y06: 1
y07: 1
y08: 0
y09: 1
y10: 1
y11: 1
y12: 1
y13: 1
y14: 0
y15: 1
y16: 1
y17: 0
y18: 1
y19: 0
y20: 0
y21: 1
y22: 1
y23: 1
y24: 1
y25: 0
y26: 1
y27: 0
y28: 0
y29: 1
y30: 1
y31: 1
y32: 1
y33: 1
y34: 0
y35: 1
y36: 0
y37: 1
y38: 1
y39: 0
y40: 0
y41: 0
y42: 0
y43: 1
y44: 1
mrg XOR wrd -> z32
x36 AND y36 -> pfc
sqk AND jcq -> bmc
tfh AND nkd -> jrd
x19 XOR y19 -> mcv
x39 XOR y39 -> ksf
rtb AND whc -> jsf
x00 XOR y00 -> z00
vjg XOR jgc -> z37
y02 XOR x02 -> qpd
mrg AND wrd -> vcm
x34 XOR y34 -> bgg
nbb OR vjc -> bwm
y25 AND x25 -> dbt
vmj AND wtw -> nbw
vcd OR vch -> nhh
pmg AND rnc -> dmp
y21 XOR x21 -> sbs
wbw AND qwr -> dqm
gdt XOR nsb -> z43
nsb AND gdt -> dnc
x09 XOR y09 -> mnm
x28 AND y28 -> shp
x10 XOR y10 -> cvv
kdn AND pbv -> mhd
sgk XOR krk -> z41
gwh AND cvv -> pgn
x06 XOR y06 -> hsn
dfq OR dbt -> kgs
x25 XOR y25 -> nfm
mcv XOR ppf -> z19
x36 XOR y36 -> dkj
dtn OR nnq -> svk
dkj XOR dmj -> z36
y41 AND x41 -> kfp
y40 AND x40 -> qhf
hnj OR bmc -> kpf
dmj AND dkj -> vnw
y04 AND x04 -> dtn
x38 XOR y38 -> spg
spg XOR bwb -> z38
fjr OR jgh -> whc
pjg OR cvk -> z45
y30 AND x30 -> rvc
qwt XOR nhk -> z40
nth OR rvc -> mwg
rtb XOR whc -> z28
sgk AND krk -> qvv
x38 AND y38 -> crp
svk XOR sfn -> z05
jrd OR ktg -> bgh
x23 XOR y23 -> gcj
y07 AND x07 -> vjc
jct OR hvf -> nhk
nfm AND vsw -> dfq
y44 AND x44 -> cvk
pfc OR vnw -> jgc
mjf AND qrw -> jgh
gcj AND grk -> cdw
gvt OR hhb -> tjc
nfm XOR vsw -> z25
spg AND bwb -> wjg
bgh AND pvj -> vcd
jcq XOR sqk -> z01
y31 XOR x31 -> tkw
pmg XOR rnc -> z33
x11 AND y11 -> cbm
x43 AND y43 -> bmf
kgk AND sbs -> z21
kvw AND bgg -> gwm
x17 XOR y17 -> tdb
kfp OR qvv -> pwt
y37 AND x37 -> nbc
y42 AND x42 -> qjp
x29 AND y29 -> bqn
hbn OR dmp -> kvw
y10 AND x10 -> bcw
x21 AND y21 -> knb
x16 XOR y16 -> vgb
y20 AND x20 -> vwh
cjh XOR hsn -> z06
grk XOR gcj -> z23
sbn AND pwt -> qwg
mnm XOR gqb -> gwh
tdh XOR jrb -> z44
y04 XOR x04 -> ptv
vwh OR vvc -> kgk
wtw XOR vmj -> z29
jrb AND tdh -> pjg
jbp AND wtc -> pfh
y27 XOR x27 -> qrw
tkw AND mwg -> vmq
x29 XOR y29 -> wtw
x44 XOR y44 -> jrb
qwg OR qjp -> gdt
x28 XOR y28 -> rtb
y16 AND x16 -> fhn
pfh OR gpq -> ppf
kgs AND jkt -> wtd
nhh XOR vgb -> z16
x26 AND y26 -> jck
nhk AND qwt -> qwh
gjv AND wcs -> nbb
ksf AND wjf -> hvf
y27 AND x27 -> fjr
qgc AND bqb -> nth
bwm XOR jhr -> z08
jgf AND htr -> dmc
nrw OR cdw -> pbv
kpf XOR qpd -> z02
htr XOR jgf -> z12
y13 AND x13 -> wbw
x43 XOR y43 -> nsb
hrr OR rtt -> bdk
bcw OR pgn -> jbk
bgg XOR kvw -> z34
y18 AND x18 -> gpq
vjg AND jgc -> mqh
y23 AND x23 -> nrw
fpk OR ffh -> wtc
ctv XOR tdb -> z17
y33 XOR x33 -> pmg
x24 AND y24 -> frv
ppf AND mcv -> gvt
kdn XOR pbv -> z24
y03 AND x03 -> rtt
btr OR fhn -> ctv
bwm AND jhr -> tvw
wcs XOR gjv -> z07
vcm OR ttt -> rnc
jck OR wtd -> mjf
gqb AND mnm -> dsk
wtc XOR jbp -> z18
nbc OR mqh -> bwb
y05 XOR x05 -> sfn
fkt OR wnq -> cjh
y14 XOR x14 -> tfh
x40 XOR y40 -> qwt
y02 AND x02 -> tng
y24 XOR x24 -> kdn
knd OR hds -> wcs
x39 AND y39 -> z39
y15 AND x15 -> vch
crp OR wjg -> wjf
y26 XOR x26 -> jkt
y35 XOR x35 -> prn
x12 XOR y12 -> htr
pwt XOR sbn -> z42
gpp OR vmq -> mrg
dsk OR ptc -> z09
cbm OR hgb -> jgf
frv OR mhd -> vsw
x09 AND y09 -> ptc
y34 AND x34 -> rkq
dqm OR wgb -> nkd
x00 AND y00 -> jcq
drv OR qph -> dmj
bgh XOR pvj -> z15
vdc AND tjc -> vvc
x41 XOR y41 -> krk
dmc OR njd -> qwr
wjf XOR ksf -> jct
ptv XOR bdk -> z04
x42 XOR y42 -> sbn
tpv AND npk -> hrr
x14 AND y14 -> ktg
x22 XOR y22 -> qgd
bqb XOR qgc -> z30
kpf AND qpd -> pwk
vdc XOR tjc -> z20
y18 XOR x18 -> jbp
x19 AND y19 -> hhb
x22 AND y22 -> dpg
jsf OR shp -> vmj
y15 XOR x15 -> pvj
dpg OR vsb -> grk
prn AND bhd -> drv
bhd XOR prn -> z35
qgd AND tvj -> vsb
y32 XOR x32 -> wrd
tvw OR qpg -> gqb
nkd XOR tfh -> z14
ksb XOR jbk -> z11
vgb AND nhh -> btr
y06 AND x06 -> knd
cjh AND hsn -> hds
dnc OR bmf -> tdh
nbw OR bqn -> bqb
tpv XOR npk -> z03
x20 XOR y20 -> vdc
x32 AND y32 -> ttt
y13 XOR x13 -> wgb
x12 AND y12 -> njd
y35 AND x35 -> qph
tdb AND ctv -> ffh
x03 XOR y03 -> npk
qrw XOR mjf -> z27
y30 XOR x30 -> qgc
y08 AND x08 -> qpg
x08 XOR y08 -> jhr
tng OR pwk -> tpv
cvv XOR gwh -> z10
mwg XOR tkw -> z31
kgk XOR sbs -> rcb
x17 AND y17 -> fpk
qwr XOR wbw -> z13
y07 XOR x07 -> gjv
x33 AND y33 -> hbn
ksb AND jbk -> hgb
x01 XOR y01 -> sqk
x11 XOR y11 -> ksb
rcb OR knb -> tvj
jkt XOR kgs -> z26
qhf OR qwh -> sgk
y31 AND x31 -> gpp
sfn AND svk -> wnq
ptv AND bdk -> nnq
x01 AND y01 -> hnj
x05 AND y05 -> fkt
qgd XOR tvj -> z22
rkq OR gwm -> bhd
x37 XOR y37 -> vjg

View file

@ -0,0 +1,47 @@
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