From 900541c05f83f84b5370a423730995c9c2b641fe Mon Sep 17 00:00:00 2001 From: Arne Keller Date: Mon, 15 Mar 2021 16:42:00 +0100 Subject: [PATCH] Basic SVG output --- Cargo.lock | 5 ++++ Cargo.toml | 1 + src/bin/svg.rs | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 21 ++++++++++++--- src/main.rs | 1 - src/ui.rs | 28 +++++++++++++++++++ 6 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 src/bin/svg.rs create mode 100644 src/ui.rs diff --git a/Cargo.lock b/Cargo.lock index 08bc4ea..e1e220c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,4 +20,9 @@ name = "kv" version = "0.0.1" dependencies = [ "itertools", + "svg_fmt", ] + +[[package]] +name = "svg_fmt" +version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 29e311c..d05514c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,4 @@ edition = "2018" [dependencies] itertools = "0.10.0" +svg_fmt = { path = "../rust_debug/svg_fmt" } diff --git a/src/bin/svg.rs b/src/bin/svg.rs new file mode 100644 index 0000000..b9a390c --- /dev/null +++ b/src/bin/svg.rs @@ -0,0 +1,73 @@ +use svg_fmt::*; + +use kv::*; + +const SIZE_FACTOR: usize = 64; +const SIZE_FONT: f32 = 20.0; +const SIZE4: usize = SIZE_FACTOR / 4; + +const COLORS: &'static [Color] = &[ + rgb(0, 0, 255), + rgb(255, 0, 0), + rgb(0, 255, 0), + rgb(255, 255, 0), +]; + +fn main() { + let function = vec![0, 0, 1, 1, 1, 1, 1, 0].into_iter().map(Into::into).collect(); + let groups = find_groups(&function, &[A, B, C], One); + eprintln!("all:"); + for x in &groups { + eprintln!("{}", print_implicant(x)); + } + eprintln!("prime:"); + let prime = find_prime(&function, &[A, B, C], One, &groups); + for x in &prime { + eprintln!("{}", print_implicant(x)); + } + eprintln!("solutions:"); + let solutions = all_solutions(function.clone(), &[A, B, C], One, &prime, &groups); + for sol in solutions { + for x in &prime { + eprint!("{} | ", print_implicant(x)); + } + for x in &sol { + eprint!("{} | ", print_implicant(x)); + } + eprintln!(); + } + + let block_masks = groups.iter() + .map(block_to_mask) + .collect::>(); + + let (grid, w, h) = grid(3); + println!("{}", BeginSvg { w: w * SIZE_FACTOR + 3, h: h * SIZE_FACTOR + 3 }); + for (i, (x, y)) in grid.iter().enumerate() { + println!("{}", + rectangle(1 + x * SIZE_FACTOR, 1 + y * SIZE_FACTOR, SIZE_FACTOR, SIZE_FACTOR) + .fill(white()) + .stroke(Stroke::Color(black(), 2.0)) + ); + let mut rect = rectangle(1 + x * SIZE_FACTOR, 1 + y * SIZE_FACTOR, SIZE_FACTOR, SIZE_FACTOR) + .fill(white()) + .stroke_opacity(0.7); + for (idx, &(mask, inv_mask)) in block_masks.iter().enumerate() { + rect = rect.inflate(-2, -2); + if check_mask(i, mask, inv_mask) { + println!("{}", rect.stroke(Stroke::Color(COLORS[idx], 2.0))); + } + } + println!("{}", + text((x+1) * SIZE_FACTOR - SIZE4, (y+1) * SIZE_FACTOR - SIZE4 / 3, i.to_string()) + .size(SIZE_FONT) + .color(black()) + ); + println!("{}", + text(x * SIZE_FACTOR + SIZE4, (y+1) * SIZE_FACTOR - SIZE4, function[i].to_string()) + .size(SIZE_FONT * 2.0) + .color(black()) + ); + } + println!("{}", EndSvg); +} diff --git a/src/lib.rs b/src/lib.rs index dd0c670..d0712ec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,10 @@ +use std::fmt::{self, Display}; + use itertools::Itertools; +mod ui; +pub use ui::*; + pub type Variable = usize; pub type Block = Vec<(Variable, Output)>; pub type BlockRef<'a> = &'a [(Variable, Output)]; @@ -15,7 +20,7 @@ pub enum Output { Any } -use Output::*; +pub use Output::*; impl Output { fn to_num(self) -> usize { @@ -45,6 +50,16 @@ impl From for Output { } } +impl fmt::Display for Output { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Zero => write!(f, "0"), + One => write!(f, "1"), + Any => write!(f, "-") + } + } +} + pub type FunctionSpec = Vec; pub fn find_groups(func: &FunctionSpec, vars: &[Variable], typ: Output) -> Vec> { @@ -175,7 +190,7 @@ fn subset_of(a: &[T], b: &[T]) -> bool { a.iter().all(|x| b.contains(x)) } -fn block_to_mask>(block: T) -> (Variable, Variable) { +pub fn block_to_mask>(block: T) -> (Variable, Variable) { let mut mask = 0; let mut inv_mask = !0; for &(var, out) in block.as_ref() { @@ -186,7 +201,7 @@ fn block_to_mask>(block: T) -> (Variable, Variabl } #[inline(always)] -fn check_mask(input: usize, mask: usize, inv_mask: usize) -> bool { +pub fn check_mask(input: usize, mask: usize, inv_mask: usize) -> bool { input | mask == input && input & inv_mask == input } diff --git a/src/main.rs b/src/main.rs index c2d6f17..24555f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ use kv::*; -use kv::Output::*; fn main() { let function = vec![0, 0, 1, 1, 1, 1, 1, 0].into_iter().map(Into::into).collect(); diff --git a/src/ui.rs b/src/ui.rs new file mode 100644 index 0000000..a88fdc7 --- /dev/null +++ b/src/ui.rs @@ -0,0 +1,28 @@ +/// Returns grid coordinates, width, height +pub fn grid(var_count: usize) -> (Vec<(usize, usize)>, usize, usize) { + let mut grid = vec![(0, 0), (1, 0)]; + let mut h = 1; + let mut w = 2; + + for _ in 1..var_count { + if w > h { + h *= 2; + let prev_grid_size = grid.len(); + for i in 0..prev_grid_size { + let mut cell = grid[i]; + cell.1 = h - 1 - cell.1; + grid.push(cell); + } + } else { + w *= 2; + let prev_grid_size = grid.len(); + for i in 0..prev_grid_size { + let mut cell = grid[i]; + cell.0 = w - 1 - cell.0; + grid.push(cell); + } + } + } + + (grid, w, h) +}