diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hitomezashi.rs | 153 | ||||
-rw-r--r-- | src/main.rs | 82 |
2 files changed, 121 insertions, 114 deletions
diff --git a/src/hitomezashi.rs b/src/hitomezashi.rs index 7b74998..d8a8c42 100644 --- a/src/hitomezashi.rs +++ b/src/hitomezashi.rs @@ -1,19 +1,19 @@ /* - hitomezashi-rs Generates classical colored Hitomezashi stitch patterns - Copyright (C) 2024 Nicholas Johnson + hitomezashi-rs Generates classical colored Hitomezashi stitch patterns + Copyright (C) 2024 Nicholas Johnson - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ use rand::distributions::{Bernoulli, Distribution}; @@ -22,68 +22,75 @@ const TRANSPARENT_SQUARE: char = ' '; const OPAQUE_SQUARE: char = '█'; fn print_square(is_transparent: bool) { - print!("{}", if is_transparent { TRANSPARENT_SQUARE } else { OPAQUE_SQUARE }); + print!( + "{}", + if is_transparent { + TRANSPARENT_SQUARE + } else { + OPAQUE_SQUARE + } + ); } pub fn hitomezashi(width: usize, height: usize, skew: Option<f64>) { - let skew: f64 = match skew { - Some(n) => { n } - None => { 0.5 } - }; - - let mut rng = rand::thread_rng(); - let brn = Bernoulli::new(skew).unwrap(); - - // the first square (upper left corner) is always opaque - let init_bit: bool = false; - - let mut row_bits: Vec<bool> = Vec::with_capacity(height - 1); - - for _ in 0..(height - 1) { - row_bits.push(brn.sample(&mut rng)); - } - - let mut col_bits: Vec<bool> = Vec::with_capacity(width - 1); - - for _ in 0..(width - 1) { - col_bits.push(brn.sample(&mut rng)); - } - - let mut alt_bits: Vec<bool> = Vec::with_capacity(width - 1); - - for col in 0..width { - alt_bits.push(col % 2 == 1); - } - - // each new row of the pattern depends on the bits directly above it - let mut above_bits: Vec<bool> = Vec::with_capacity(width); - - above_bits.push(init_bit); - print_square(above_bits[0]); - - for col in 1..width { - /* each square in the first row is derived from the square to its left. the column bits - * represent whether there's a stitch between the two squares. if there's a stitch, the squares - * are different, otherwise they are the same. */ - above_bits.push(above_bits[col - 1] ^ col_bits[col - 1]); - print_square(above_bits[col]); - } - - println!(); - - // height-1 because the first row has already been printed - for row in 0..(height - 1) { - /* each square in each successive row is derived from the square above it. the row bits - * represent whether there's a stitch between the two squares. if there's a stitch, the - * squares are different, otherwise they are the same. */ - above_bits - .iter_mut() - .zip(alt_bits.iter()) - .for_each(|(x1, &x2)| { - *x1 ^= x2 ^ row_bits[row]; - print_square(*x1); - }); - - println!(); - } + let skew: f64 = match skew { + Some(n) => n, + None => 0.5, + }; + + let mut rng = rand::thread_rng(); + let brn = Bernoulli::new(skew).unwrap(); + + // the first square (upper left corner) is always opaque + let init_bit: bool = false; + + let mut row_bits: Vec<bool> = Vec::with_capacity(height - 1); + + for _ in 0..(height - 1) { + row_bits.push(brn.sample(&mut rng)); + } + + let mut col_bits: Vec<bool> = Vec::with_capacity(width - 1); + + for _ in 0..(width - 1) { + col_bits.push(brn.sample(&mut rng)); + } + + let mut alt_bits: Vec<bool> = Vec::with_capacity(width - 1); + + for col in 0..width { + alt_bits.push(col % 2 == 1); + } + + // each new row of the pattern depends on the bits directly above it + let mut above_bits: Vec<bool> = Vec::with_capacity(width); + + above_bits.push(init_bit); + print_square(above_bits[0]); + + for col in 1..width { + /* each square in the first row is derived from the square to its left. the column bits + * represent whether there's a stitch between the two squares. if there's a stitch, the squares + * are different, otherwise they are the same. */ + above_bits.push(above_bits[col - 1] ^ col_bits[col - 1]); + print_square(above_bits[col]); + } + + println!(); + + // height-1 because the first row has already been printed + for row in 0..(height - 1) { + /* each square in each successive row is derived from the square above it. the row bits + * represent whether there's a stitch between the two squares. if there's a stitch, the + * squares are different, otherwise they are the same. */ + above_bits + .iter_mut() + .zip(alt_bits.iter()) + .for_each(|(x1, &x2)| { + *x1 ^= x2 ^ row_bits[row]; + print_square(*x1); + }); + + println!(); + } } diff --git a/src/main.rs b/src/main.rs index 87274af..3732b50 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,22 @@ /* - hitomezashi-rs Generates classical colored Hitomezashi stitch patterns - Copyright (C) 2024 Nicholas Johnson + hitomezashi-rs Generates classical colored Hitomezashi stitch patterns + Copyright (C) 2024 Nicholas Johnson - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see <https://www.gnu.org/licenses/>. + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ -use clap::{Parser, value_parser}; +use clap::{value_parser, Parser}; use colored::Colorize; use std::process::exit; @@ -25,54 +25,54 @@ mod hitomezashi; #[derive(Parser)] #[command(version, about, long_about = None)] // Read from `Cargo.toml` struct Cli { - /// Pattern width - #[arg(value_parser = value_parser!(usize))] - width: usize, + /// Pattern width + #[arg(value_parser = value_parser!(usize))] + width: usize, - /// Pattern height - #[arg(value_parser = value_parser!(usize))] - height: usize, + /// Pattern height + #[arg(value_parser = value_parser!(usize))] + height: usize, - #[arg(short, long)] - #[arg(default_value_t = 0.5)] - #[arg(value_parser = value_parser!(f64))] - /// Set skew - skew: f64, + #[arg(short, long)] + #[arg(default_value_t = 0.5)] + #[arg(value_parser = value_parser!(f64))] + /// Set skew + skew: f64, } /* CLI for hitomezashi */ fn main() { - let cli = Cli::parse(); + let cli = Cli::parse(); - // validate bounds of width [1..] - if cli.width < 1 { - println!("{} invalid value '{}' for '{}': valid values are [1..]\n\nFor more information, try '{}'.", + // validate bounds of width [1..] + if cli.width < 1 { + println!("{} invalid value '{}' for '{}': valid values are [1..]\n\nFor more information, try '{}'.", "error:".red().bold(), cli.width.to_string().yellow(), "<WIDTH>".bold(), "--help".bold()); - exit(2); - } + exit(2); + } - // validate bounds of height [1..] - if cli.height < 1 { - println!("{} invalid value '{}' for '{}': valid values are [1..]\n\nFor more information, try '{}'.", + // validate bounds of height [1..] + if cli.height < 1 { + println!("{} invalid value '{}' for '{}': valid values are [1..]\n\nFor more information, try '{}'.", "error:".red().bold(), cli.height.to_string().yellow(), "<HEIGHT>".bold(), "--help".bold()); - exit(2); - } + exit(2); + } - // validate bounds of skew [0-1] - if cli.skew < 0.0 || cli.skew > 1.0 { - println!("{} invalid value '{}' for '{}': valid values are [0-1]\n\nFor more information, try '{}'.", + // validate bounds of skew [0-1] + if cli.skew < 0.0 || cli.skew > 1.0 { + println!("{} invalid value '{}' for '{}': valid values are [0-1]\n\nFor more information, try '{}'.", "error:".red().bold(), cli.skew.to_string().yellow(), "--skew <SKEW>".bold(), "--help".bold()); - exit(2); - } + exit(2); + } - hitomezashi::hitomezashi(cli.width, cli.height, Some(cli.skew)); + hitomezashi::hitomezashi(cli.width, cli.height, Some(cli.skew)); } |