diff options
-rw-r--r-- | src/hitomezashi.rs | 51 | ||||
-rw-r--r-- | src/main.rs | 4 |
2 files changed, 29 insertions, 26 deletions
diff --git a/src/hitomezashi.rs b/src/hitomezashi.rs index 6fb785e..9ec8758 100644 --- a/src/hitomezashi.rs +++ b/src/hitomezashi.rs @@ -21,38 +21,39 @@ use rand::distributions::{Bernoulli, Distribution}; const TRANSPARENT_SQUARE: char = ' '; const OPAQUE_SQUARE: char = '█'; -fn print_square(is_transparent: bool) { +fn print_square(is_opaque: bool) { print!( "{}", - if is_transparent { - TRANSPARENT_SQUARE - } else { + 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); 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; - + // 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; @@ -61,28 +62,30 @@ pub fn hitomezashi(width: usize, height: usize, skew: Option<f64>) { alternator = !alternator; } - // each new row of the pattern depends on the bits directly above it - let mut above_bits: Vec<bool> = Vec::with_capacity(width); + /* 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; - above_bits.push(init_bit); + let mut cur_row: Vec<bool> = Vec::with_capacity(width); - 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]); + /* 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(above_bits[above_bits.capacity() - 1]); - println!(); + print_square(cur_row[cur_row.capacity() - 1]); + println!(); // End of base case - // 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 + /* 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)| { @@ -90,6 +93,6 @@ pub fn hitomezashi(width: usize, height: usize, skew: Option<f64>) { print_square(*x1); }); - println!(); + println!(); // End of recursive case } } diff --git a/src/main.rs b/src/main.rs index 3732b50..0da3b0e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,14 +33,14 @@ struct Cli { #[arg(value_parser = value_parser!(usize))] height: usize, + /// Set skew #[arg(short, long)] #[arg(default_value_t = 0.5)] #[arg(value_parser = value_parser!(f64))] - /// Set skew skew: f64, } -/* CLI for hitomezashi */ +// CLI for hitomezashi fn main() { let cli = Cli::parse(); |