1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
/*
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_transparent: bool) {
print!(
"{}",
if is_transparent {
TRANSPARENT_SQUARE
} else {
OPAQUE_SQUARE
}
);
}
pub fn hitomezashi(width: usize, height: usize, skew: Option<f64>) {
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<bool> = Vec::with_capacity(height - 1);
for _ in 0..row_bits.capacity() {
row_bits.push(brn.sample(&mut rng));
}
let mut col_bits: Vec<bool> = Vec::with_capacity(width - 1);
for _ in 0..col_bits.capacity() {
col_bits.push(brn.sample(&mut rng));
}
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;
}
// each new row of the pattern depends on the bits directly above it
let mut above_bits: Vec<bool> = 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!();
}
}
|