heh
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 93 |
1 files changed, 92 insertions, 1 deletions
diff --git a/src/main.rs b/src/main.rs index fabbd10..fd0049a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -140,9 +140,100 @@ pub fn p1(x: &str) -> impl Display { z } +#[no_mangle] +pub fn p2(x: &str) -> impl Display { + let mut gates = Vec::with_capacity(128); + let x = &x.as_bytes()[7 * 45 * 2 + 1..]; + fn gate(x: &[u8]) -> [u8; 3] { + x.try_into().unwrap() + } + const XOR: u8 = 0; + const AND: u8 = 1; + const OR: u8 = 2; + for connection in x.行() { + let mut i = connection.split(|x| *x == b' '); + let [i1, op, i2, _, out] = std::array::from_fn(|_| i.Δ()); + let [i1, i2, out] = [i1, i2, out].map(gate); + let op = match op { + b"XOR" => XOR, + b"AND" => AND, + b"OR" => OR, + _ => shucks!(), + }; + gates.push((i1, i2, out, op)); + } + let find = |i1, op: u8, i2| { + gates + .iter() + .find(|x| { + (x.0 == i1 && x.1 == i2 && x.3 == op) || (x.1 == i1 && x.0 == i2 && x.3 == op) + }) + .map(|x| x.2) + }; + let find_using = |op: u8, i2| { + gates.iter().find_map(|x| { + (x.1 == i2 && x.3 == op) + .then_some((x.0, x.2)) + .or((x.0 == i2 && x.3 == op).then_some((x.1, x.2))) + }) + }; + // search for full adders (this is a ripple carry adder) + // x ^ y -> t0 + // x & y -> t1 + // c0 & t0 -> t2 + // c0 ^ t0 -> z + // t1 | t2 -> c1 + let mut swaps = vec![]; + for [x, y, should_z] in const { + let input: [[[u8; 3]; 3]; 44] = car::from_fn!(|i| { + let i = i + 1; + let x = [b'x', (i as u8 / 10) + b'0', (i as u8 % 10) + b'0']; + let y = [b'y', (i as u8 / 10) + b'0', (i as u8 % 10) + b'0']; + let z = [b'z', (i as u8 / 10) + b'0', (i as u8 % 10) + b'0']; + [x, y, z] + }); + input + } { + let t0 = find(x, XOR, y).unwrap(); // x ^ y -> t0 + + // println!("{} ^ {} -> {} (t0)", x.p(), y.p(), t0.p()); + + let t1 = find(x, AND, y).unwrap(); // x & y -> t1 + + // println!("{} & {} -> {} (t1)", x.p(), y.p(), t1.p()); + + // c0 & t0 -> t2 + let Some((_c0, _t2)) = find_using(AND, t0) else { + swaps.push(t0); + swaps.push(t1); + // println!("swap {} with {}", t0.p(), t1.p()); + continue; + }; + // println!("(c0) {} & {} (t0) -> {} (t2)", c0.p(), t0.p(), t2.p()); + let (_, z) = find_using(XOR, t0).unwrap(); // c0 ^ t0 -> z + + // println!("(c0) {} ^ {} (t0) -> {} (z)", c0.p(), t0.p(), z.p()); + if z != should_z { + swaps.push(z); + swaps.push(should_z); + // println!("swap {} with {}", z.p(), format!("z{i:02}")); + continue; + } + // t1 | t2 -> c1 + // let c1 = find(t1, b"OR", t2).unwrap(); + } + swaps.sort_unstable(); + let mut out = String::with_capacity(40); + for swap in swaps { + use std::fmt::Write; + _ = write!(out, "{},", swap.p()); + } + out +} + fn main() { let s = include_str!("inp.txt"); - println!("{}", unsafe { p1(s) }); + println!("{}", unsafe { p2(s) }); // dbg!(exec(&program, regi)); } |