init
This commit is contained in:
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "logic_gates"
|
||||
version = "0.1.0"
|
||||
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "logic_gates"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
257
src/main.rs
Normal file
257
src/main.rs
Normal file
@@ -0,0 +1,257 @@
|
||||
#![feature(trait_alias)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
struct BakedGate {
|
||||
table: Vec<bool>
|
||||
}
|
||||
|
||||
impl BakedGate {
|
||||
fn test(&self, input: Vec<bool>) -> bool {
|
||||
|
||||
let mut total = 0;
|
||||
|
||||
for (i, input) in input.iter().enumerate() {
|
||||
if *input {
|
||||
total += 1 << i
|
||||
}
|
||||
}
|
||||
|
||||
self.table[total]
|
||||
}
|
||||
}
|
||||
|
||||
struct Gate<T> {
|
||||
function: T,
|
||||
qty_inputs: usize,
|
||||
qty_outputs: usize,
|
||||
|
||||
}
|
||||
|
||||
trait Logic = Fn(Vec<bool>) -> bool;
|
||||
|
||||
impl<T: Logic> Gate<T> {
|
||||
fn new(expected_inputs: usize, f: T) -> Self {
|
||||
Self {
|
||||
function: f,
|
||||
qty_inputs: expected_inputs,
|
||||
qty_outputs: 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn bake(&self) -> BakedGate {
|
||||
// we will count in binary for this
|
||||
let max = (1 << (self.qty_inputs)) -1;
|
||||
|
||||
let mut options = Vec::new();
|
||||
|
||||
for args in 0..=max {
|
||||
let mut inputs = Vec::new();
|
||||
|
||||
for i in 0..self.qty_inputs {
|
||||
let b = 1 << i & args;
|
||||
let ans = b > 0 ;
|
||||
inputs.push(ans);
|
||||
}
|
||||
inputs.reverse();
|
||||
|
||||
let output = self.tick(inputs);
|
||||
// The index is the question, and the item at the index is the answer
|
||||
options.push(output);
|
||||
|
||||
println!();
|
||||
}
|
||||
BakedGate {
|
||||
table: options
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&self, inputs: Vec<bool>) -> bool {
|
||||
assert!(self.qty_inputs == inputs.len());
|
||||
|
||||
(self.function)(inputs)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn baked_gate() {
|
||||
let and = Gate::new(2, |f| {
|
||||
let a = f[0];
|
||||
let b = f[1];
|
||||
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);
|
||||
|
||||
let or = Gate::new(2, |f| {
|
||||
let a = f[0];
|
||||
let b = f[1];
|
||||
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);
|
||||
|
||||
let not = Gate::new(1, |f| {
|
||||
!f[0]
|
||||
});
|
||||
let baked = not.bake();
|
||||
|
||||
assert_eq!(baked.test(vec![true]), false);
|
||||
assert_eq!(baked.test(vec![false]), 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]);
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unbaked_registry() {
|
||||
use std::collections::HashMap;
|
||||
|
||||
let mut registry: HashMap<&str, Gate<Box<dyn Logic>>> = HashMap::new();
|
||||
|
||||
let and: Gate<Box<dyn Logic>> = Gate::new(
|
||||
2,
|
||||
Box::new(|f| f[0] && f[1]),
|
||||
);
|
||||
|
||||
registry.insert("AND", and);
|
||||
|
||||
let not: Gate<Box<dyn Logic>> = Gate::new(1, Box::new(|f| !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,
|
||||
Box::new(|f| {
|
||||
let a = f[0];
|
||||
let b = f[1];
|
||||
|
||||
let n = and.tick(vec![a, b]);
|
||||
not.tick(vec![n])
|
||||
}),
|
||||
);
|
||||
|
||||
assert_eq!(not.tick(vec![true]), false);
|
||||
assert_eq!(not.tick(vec![false]), 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!(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 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 a = f[0];
|
||||
let b = f[1];
|
||||
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);
|
||||
|
||||
let not = Gate::new(1, |f| !f[0]);
|
||||
|
||||
assert_eq!(not.tick(vec![true]), false);
|
||||
assert_eq!(not.tick(vec![false]), true);
|
||||
|
||||
let or = Gate::new(2, |f| {
|
||||
let a = f[0];
|
||||
let b = f[1];
|
||||
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);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
Reference in New Issue
Block a user