multi out

This commit is contained in:
2025-10-22 16:17:07 -06:00
parent d1176cff5f
commit faa0608575

View File

@@ -3,11 +3,11 @@
use std::collections::HashMap;
struct BakedGate {
table: Vec<bool>
table: Vec<Vec<bool>>
}
impl BakedGate {
fn test(&self, input: Vec<bool>) -> bool {
fn test(&self, input: &[bool]) -> &[bool] {
let mut total = 0;
@@ -17,7 +17,7 @@ impl BakedGate {
}
}
self.table[total]
&self.table[total]
}
}
@@ -28,14 +28,14 @@ struct Gate<T> {
}
trait Logic = Fn(Vec<bool>) -> bool;
trait Logic = Fn(&[bool]) -> Vec<bool>;
impl<T: Logic> Gate<T> {
fn new(expected_inputs: usize, f: T) -> Self {
fn new(expected_inputs: usize, expected_outputs: usize, f: T) -> Self {
Self {
function: f,
qty_inputs: expected_inputs,
qty_outputs: 1,
qty_outputs: expected_outputs,
}
}
@@ -55,7 +55,7 @@ impl<T: Logic> Gate<T> {
}
inputs.reverse();
let output = self.tick(inputs);
let output = self.tick(&inputs);
// The index is the question, and the item at the index is the answer
options.push(output);
@@ -66,55 +66,74 @@ impl<T: Logic> Gate<T> {
}
}
fn tick(&self, inputs: Vec<bool>) -> bool {
fn tick(&self, inputs: &[bool]) -> Vec<bool> {
assert!(self.qty_inputs == inputs.len());
(self.function)(inputs)
let out = (self.function)(&inputs);
assert!(out.len() == self.qty_outputs);
out
}
}
#[test]
fn mimo() {
let gate = Gate::new(2, 2, |f| {
vec![true, f[0] | f[1]]
});
assert_eq!(gate.tick(&[true, false]), &[true, true]);
assert_eq!(gate.tick(&[false, false]), &[true, false]);
let baked = gate.bake();
assert_eq!(baked.test(&[true, false]), &[true, true]);
assert_eq!(baked.test(&[false, false]), &[true, false]);
}
#[test]
fn baked_gate() {
let and = Gate::new(2, |f| {
let and = Gate::new(2, 1, |f| {
let a = f[0];
let b = f[1];
a && b
vec![a && b]
});
let baked = and.bake();
assert_eq!(baked.test(vec![true, true]), true);
assert_eq!(baked.test(vec![true, false]), false);
assert_eq!(baked.test(vec![false, true]), false);
assert_eq!(baked.test(vec![false, false]), false);
assert_eq!(baked.test(&[true, true])[0], true);
assert_eq!(baked.test(&[true, false])[0], false);
assert_eq!(baked.test(&[false, true])[0], false);
assert_eq!(baked.test(&[false, false])[0], false);
let or = Gate::new(2, |f| {
let or = Gate::new(2, 1, |f| {
let a = f[0];
let b = f[1];
a || b
vec![a || b]
});
let baked = or.bake();
assert_eq!(baked.test(vec![true, true]), true);
assert_eq!(baked.test(vec![true, false]), true);
assert_eq!(baked.test(vec![false, true]), true);
assert_eq!(baked.test(vec![false, false]), false);
assert_eq!(baked.test(&[true, true])[0], true);
assert_eq!(baked.test(&[true, false])[0], true);
assert_eq!(baked.test(&[false, true])[0], true);
assert_eq!(baked.test(&[false, false])[0], false);
let not = Gate::new(1, |f| {
!f[0]
let not = Gate::new(1, 1, |f| {
vec![!f[0]]
});
let baked = not.bake();
assert_eq!(baked.test(vec![true]), false);
assert_eq!(baked.test(vec![false]), true);
assert_eq!(baked.test(&[true])[0], false);
assert_eq!(baked.test(&[false])[0], true);
}
#[test]
fn baked_registry() {
let mut registry: HashMap<&str, BakedGate> = HashMap::new();
let and = Gate::new(2, |f| f[0] && f[1]);
let or = Gate::new(2, |f| f[0] | f[1]);
let not = Gate::new(1, |f| !f[0]);
let and = Gate::new(2, 1, |f| vec![f[0] && f[1]]);
let or = Gate::new(2, 1, |f| vec![f[0] | f[1]]);
let not = Gate::new(1, 1, |f| vec![!f[0]]);
registry.insert("AND", and.bake());
registry.insert("OR", or.bake());
@@ -122,18 +141,19 @@ fn baked_registry() {
if let (Some(and), Some(not)) = (registry.get("AND"), registry.get("NOT")) {
let nand = Gate::new(2, |f| {
not.test(vec![and.test(f)])
let nand = Gate::new(2, 1, |f| {
let and_r = and.test(&f);
not.test(and_r).to_vec()
});
registry.insert("NAND", nand.bake());
}
if let Some(nand) = registry.get("NAND") {
assert_eq!(nand.test(vec![true, true]), false);
assert_eq!(nand.test(vec![false, true]), true);
assert_eq!(nand.test(vec![true, false]), true);
assert_eq!(nand.test(vec![false, false]), true);
assert_eq!(nand.test(&[true, true])[0], false);
assert_eq!(nand.test(&[false, true])[0], true);
assert_eq!(nand.test(&[true, false])[0], true);
assert_eq!(nand.test(&[false, false])[0], true);
} else {
unreachable!()
}
@@ -148,110 +168,81 @@ fn unbaked_registry() {
let and: Gate<Box<dyn Logic>> = Gate::new(
2,
Box::new(|f| f[0] && f[1]),
1,
Box::new(|f| vec![f[0] && f[1]]),
);
registry.insert("AND", and);
let not: Gate<Box<dyn Logic>> = Gate::new(1, Box::new(|f| !f[0]));
let not: Gate<Box<dyn Logic>> = Gate::new(1, 1, Box::new(|f| vec![!f[0]]));
registry.insert("NOT", not);
if let (Some(not), Some(and)) = (registry.get("NOT"), registry.get("AND")) {
let nand: Gate<Box<dyn Logic>> = Gate::new(
2,
1,
Box::new(|f| {
let a = f[0];
let b = f[1];
let n = and.tick(vec![a, b]);
not.tick(vec![n])
let n = and.tick(&[a, b]);
not.tick(&n)
}),
);
assert_eq!(not.tick(vec![true]), false);
assert_eq!(not.tick(vec![false]), true);
assert_eq!(not.tick(&[true])[0], false);
assert_eq!(not.tick(&[false])[0], true);
assert_eq!(and.tick(vec![true, true]), true);
assert_eq!(and.tick(vec![true, false]), false);
assert_eq!(and.tick(vec![false, true]), false);
assert_eq!(and.tick(vec![false, false]), false);
assert_eq!(and.tick(&[true, true])[0], true);
assert_eq!(and.tick(&[true, false])[0], false);
assert_eq!(and.tick(&[false, true])[0], false);
assert_eq!(and.tick(&[false, false])[0], false);
assert_eq!(nand.tick(vec![true, true]), false);
assert_eq!(nand.tick(vec![true, false]), true);
assert_eq!(nand.tick(vec![false, true]), true);
assert_eq!(nand.tick(vec![false, false]), true);
assert_eq!(nand.tick(&[true, true])[0], false);
assert_eq!(nand.tick(&[true, false])[0], true);
assert_eq!(nand.tick(&[false, true])[0], true);
assert_eq!(nand.tick(&[false, false])[0], true);
};
}
#[test]
fn nand_gate() {
let and = Gate::new(2, |f| {
let a = f[0];
let b = f[1];
a && b
});
let not = Gate::new(1, |f| !f[0]);
let nand = Gate::new(2, |f| not.tick(vec![and.tick(f)]));
assert_eq!(nand.tick(vec![true, true]), false);
assert_eq!(nand.tick(vec![true, false]), true);
assert_eq!(nand.tick(vec![false, true]), true);
assert_eq!(nand.tick(vec![false, false]), true);
}
#[test]
fn generic_gates() {
let and = Gate::new(2, |f| {
let and = Gate::new(2, 1,|f| {
let a = f[0];
let b = f[1];
a && b
vec![a && b]
});
assert_eq!(and.tick(vec![true, true]), true);
assert_eq!(and.tick(vec![true, false]), false);
assert_eq!(and.tick(vec![false, true]), false);
assert_eq!(and.tick(vec![false, false]), false);
assert_eq!(and.tick(&[true, true])[0], true);
assert_eq!(and.tick(&[true, false])[0], false);
assert_eq!(and.tick(&[false, true])[0], false);
assert_eq!(and.tick(&[false, false])[0], false);
let not = Gate::new(1, |f| !f[0]);
let not = Gate::new(1, 1, |f| vec![!f[0]]);
assert_eq!(not.tick(vec![true]), false);
assert_eq!(not.tick(vec![false]), true);
assert_eq!(not.tick(&[true])[0], false);
assert_eq!(not.tick(&[false])[0], true);
let or = Gate::new(2, |f| {
let or = Gate::new(2, 1, |f| {
let a = f[0];
let b = f[1];
a | b
vec![a | b]
});
assert_eq!(or.tick(vec![true, true]), true);
assert_eq!(or.tick(vec![true, false]), true);
assert_eq!(or.tick(vec![false, true]), true);
assert_eq!(or.tick(vec![false, false]), false);
assert_eq!(or.tick(&[true, true])[0], true);
assert_eq!(or.tick(&[true, false])[0], true);
assert_eq!(or.tick(&[false, true])[0], true);
assert_eq!(or.tick(&[false, false])[0], false);
let nand = Gate::new(2, 1, |f| not.tick(&and.tick(f)));
assert_eq!(nand.tick(&[true, true])[0], false);
assert_eq!(nand.tick(&[true, false])[0], true);
assert_eq!(nand.tick(&[false, true])[0], true);
assert_eq!(nand.tick(&[false, false])[0], true);
}
fn main() {
let g = Gate::new(2, |f| {true});
let mut registry: HashMap<&str, BakedGate> = HashMap::new();
let and = Gate::new(2, |f| f[0] && f[1]);
let or = Gate::new(2, |f| f[0] | f[1]);
let not = Gate::new(1, |f| !f[0]);
registry.insert("AND", and.bake());
registry.insert("OR", or.bake());
registry.insert("NOT", not.bake());
if let (Some(and), Some(not)) = (registry.get("AND"), registry.get("NOT")) {
let nand = Gate::new(2, |f| {
not.test(vec![and.test(f)])
});
registry.insert("NAND", nand.bake());
}
g.bake();
println!("hello world");
}