multi out
This commit is contained in:
195
src/main.rs
195
src/main.rs
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user