/* 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..row_bits.capacity() { row_bits.push(brn.sample(&mut rng)); } let mut col_bits: Vec = Vec::with_capacity(width - 1); for _ in 0..col_bits.capacity() { col_bits.push(brn.sample(&mut rng)); } let mut alt_bits: Vec = Vec::with_capacity(width); let mut alternator: bool = false; for _ in 0..alt_bits.capacity() { alt_bits.push(alternator); alternator = !alternator; } // 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..(above_bits.capacity() - 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[above_bits.capacity() - 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!(); } }