diff options
Diffstat (limited to 'src/hitomezashi.rs')
-rw-r--r-- | src/hitomezashi.rs | 102 |
1 files changed, 0 insertions, 102 deletions
diff --git a/src/hitomezashi.rs b/src/hitomezashi.rs deleted file mode 100644 index 8e2a773..0000000 --- a/src/hitomezashi.rs +++ /dev/null @@ -1,102 +0,0 @@ -/* - 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 <https://www.gnu.org/licenses/>. -*/ - -use rand::distributions::{Bernoulli, Distribution}; - -const TRANSPARENT_SQUARE: char = ' '; -const OPAQUE_SQUARE: char = '█'; - -fn print_square(is_opaque: bool) { - print!( - "{}", - if is_opaque { - OPAQUE_SQUARE - } else { - TRANSPARENT_SQUARE - } - ); -} - -pub fn hitomezashi(width: usize, height: usize, skew: Option<f64>) { - // skew=0.5 generates the most random-looking patterns - let skew: f64 = skew.unwrap_or(0.5); - - assert!(width >= 1, "Width must be a positive number!"); - assert!(height >= 1, "Height must be a positive number!"); - assert!(skew >= 0.0 && skew <= 1.0, "Skew must be between zero and one inclusive!"); - - let mut rng = rand::thread_rng(); - let brn = Bernoulli::new(skew).unwrap(); - - // Each value represents whether to start that row with a stitch or no stitch - let mut row_bits: Vec<bool> = Vec::with_capacity(height - 1); - - for _ in 0..row_bits.capacity() { - row_bits.push(brn.sample(&mut rng)); - } - - // Each value represents whether to start that column with a stitch or no stitch - let mut col_bits: Vec<bool> = Vec::with_capacity(width - 1); - - for _ in 0..col_bits.capacity() { - col_bits.push(brn.sample(&mut rng)); - } - - // Precomputed values to facilitate alternating between stitch presence and stitch absence - let mut alt_bits: Vec<bool> = Vec::with_capacity(width); - - let mut alternator: bool = false; - for _ in 0..alt_bits.capacity() { - alt_bits.push(alternator); - alternator = !alternator; - } - - /* The first square is always opaque to prevent invisible 1xN or Nx1 patterns. Invisible - * patterns must be prevented so that users don't mistakenly conclude that the function does - * not work. */ - let first_square: bool = true; - - let mut cur_row: Vec<bool> = Vec::with_capacity(width); - - /* Base case - * - * The first row has no preceding row, so it's computing using the column stitches */ - cur_row.push(first_square); - for col in 0..(cur_row.capacity() - 1) { - print_square(cur_row[col]); - cur_row.push(cur_row[col] ^ col_bits[col]); - } - - print_square(cur_row[cur_row.capacity() - 1]); - println!(); // End of base case - - for row_bit in row_bits.iter() { - /* Recursive case - * - * Each row after the first row is computed based on the preceding row. */ - cur_row - .iter_mut() - .zip(alt_bits.iter()) - .for_each(|(x1, &x2)| { - *x1 ^= x2 ^ row_bit; - print_square(*x1); - }); - - println!(); // End of recursive case - } -} |