summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hitomezashi.rs51
-rw-r--r--src/main.rs4
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();