/* 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 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 . */ use rand::distributions::{Bernoulli, Distribution}; const TRANSPARENT_SQUARE: char = ' '; const OPAQUE_SQUARE: char = '█'; fn print_square(is_transparent: bool) { print!( "{}", if is_transparent { TRANSPARENT_SQUARE } else { OPAQUE_SQUARE } ); } pub fn hitomezashi(width: usize, height: usize, skew: Option) { let skew: f64 = skew.unwrap_or(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 = Vec::with_capacity(height - 1); for _ in 0..(height - 1) { row_bits.push(brn.sample(&mut rng)); } let mut col_bits: Vec = Vec::with_capacity(width - 1); for _ in 0..(width - 1) { col_bits.push(brn.sample(&mut rng)); } let mut alt_bits: Vec = Vec::with_capacity(width); 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 = Vec::with_capacity(width); above_bits.push(init_bit); for col in 0..(width - 1) { /* 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. */ print_square(above_bits[col]); above_bits.push(above_bits[col] ^ col_bits[col]); } print_square(above_bits[width - 1]); println!(); // height-1 because the first row has already been printed for row_bit in row_bits.iter() { /* 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_bit; print_square(*x1); }); println!(); } }