Initial commit

This commit is contained in:
hal8174 2024-12-10 18:21:07 +01:00
commit e6cceca88c
10 changed files with 1234 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
*.png

1007
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

7
Cargo.toml Normal file
View file

@ -0,0 +1,7 @@
[package]
name = "stamp-folding"
version = "0.1.0"
edition = "2021"
[dependencies]
image = "0.25.5"

13
src/bin/image.rs Normal file
View file

@ -0,0 +1,13 @@
use image::GrayImage;
use stamp_folding::image::{draw_image, image_dimensions};
fn main() {
let data = [0, 1, 2, 3];
let (width, height) = image_dimensions(data.len());
let mut img = GrayImage::new(width, height);
draw_image(&mut img, &data);
img.save("img.png").unwrap();
}

10
src/bin/overflow_check.rs Normal file
View file

@ -0,0 +1,10 @@
fn main() {
let mut i = 1;
let mut f = 1u128;
while let Some(nf) = f.checked_mul(i) {
f = nf;
i += 1;
}
println!("{}: {f}", i - 1);
}

10
src/bin/series.rs Normal file
View file

@ -0,0 +1,10 @@
use stamp_folding::stamp_folding;
fn main() {
for length in 2.. {
let mut count = 0;
let mut state = vec![0, 1];
stamp_folding(&mut state, 1, length - 2, &mut count, &mut |_, _| {});
println!("{length:02}: {count} {}", count * 2);
}
}

8
src/bin/single_stamp.rs Normal file
View file

@ -0,0 +1,8 @@
use stamp_folding::stamp_folding;
fn main() {
let length = 4;
let mut count = 0;
let mut state = vec![0, 1];
stamp_folding(&mut state, 1, length - 2, &mut count, &mut |_, _| {});
}

View file

@ -0,0 +1,37 @@
use image::{GenericImage, GrayImage};
use stamp_folding::{
image::{draw_image, image_dimensions},
stamp_folding,
};
fn main() {
for length in 2..12 {
let mut count = 0;
let mut state = vec![0, 1];
stamp_folding(&mut state, 1, length - 2, &mut count, &mut |_, _| {});
let (width, height) = image_dimensions(length as usize);
dbg!(width, height);
let columns = count.isqrt() as u32;
let mut image = GrayImage::new(
width * columns,
height * count.div_ceil(columns as u128) as u32,
);
let mut count = 0;
let mut state = vec![0, 1];
stamp_folding(&mut state, 1, length - 2, &mut count, &mut |i, l| {
let mut subimage = image.sub_image(
width * (i as u32 % columns),
height * (i as u32 / columns),
width,
height,
);
draw_image(&mut *subimage, l);
});
image.save(format!("img{length:02}.png")).unwrap();
}
}

66
src/image.rs Normal file
View file

@ -0,0 +1,66 @@
use image::{GenericImage, Luma};
const CENTRAL_WIDTH: u32 = 5;
pub fn draw_image(image: &mut impl GenericImage<Pixel = Luma<u8>>, layout: &[u8]) {
let side_width = layout.len() as u32 + 1;
let white = Luma::from([255]);
let grey = Luma::from([125]);
for (i, &s) in layout.iter().enumerate() {
for j in 0..CENTRAL_WIDTH {
image.put_pixel(
side_width + j,
1 + i as u32 * 3,
if s == 0 { grey } else { white },
);
}
if let Some(j) = layout.iter().position(|&c| c == s + 1) {
if s % 2 == 0 {
let lower = usize::min(i, j) as u32;
let upper = usize::max(i, j) as u32;
let diff = upper - lower;
let depth = diff;
for d in 0..depth {
image.put_pixel(side_width + CENTRAL_WIDTH + d, 1 + lower * 3 + d + 1, white);
image.put_pixel(side_width + CENTRAL_WIDTH + d, 1 + upper * 3 - d - 1, white);
}
let l = 1 + lower * 3 + depth + 1;
let u = 1 + upper * 3 - depth - 1;
for y in l..=u {
image.put_pixel(side_width + CENTRAL_WIDTH + depth, y, white);
}
} else {
let lower = usize::min(i, j) as u32;
let upper = usize::max(i, j) as u32;
let diff = upper - lower;
let depth = diff;
for d in 0..depth {
image.put_pixel(side_width - d - 1, 1 + lower * 3 + d + 1, white);
image.put_pixel(side_width - d - 1, 1 + upper * 3 - d - 1, white);
}
let l = 1 + lower * 3 + depth + 1;
let u = 1 + upper * 3 - depth - 1;
for y in l..=u {
image.put_pixel(side_width - depth - 1, y, white);
}
}
}
}
}
pub fn image_dimensions(len: usize) -> (u32, u32) {
(CENTRAL_WIDTH + 2 * len as u32 + 2, 3 * len as u32)
}

74
src/lib.rs Normal file
View file

@ -0,0 +1,74 @@
pub mod image;
pub fn stamp_folding(
current: &mut Vec<u8>,
last_inserted_index: usize,
remaining: u8,
count: &mut u128,
callback: &mut impl FnMut(u128, &[u8]),
) {
let depth = current.len() as u8;
// dbg!(&current, depth, last_inserted_index);
if remaining == 0 {
callback(*count, current);
*count = count.checked_add(1).unwrap();
return;
}
let last_inserted_value = current[last_inserted_index];
let mut last = None;
for i in (0..last_inserted_index).rev() {
// dbg!(&last, &current, i);
if let Some(l) = last {
let next = if l % 2 == last_inserted_value % 2 {
l + 1
} else {
l - 1
};
if current[i] == next {
last = None;
}
} else {
current.insert(i + 1, depth);
stamp_folding(current, i + 1, remaining - 1, count, callback);
current.remove(i + 1);
if current[i] != 0 || last_inserted_value % 2 == 0 {
last = Some(current[i]);
}
}
}
if last.is_none() {
current.insert(0, depth);
stamp_folding(current, 0, remaining - 1, count, callback);
current.remove(0);
}
let mut last = None;
for i in (last_inserted_index + 1)..current.len() {
if let Some(l) = last {
let next = if l % 2 == last_inserted_value % 2 {
l + 1
} else {
l - 1
};
if current[i] == next {
last = None;
}
} else {
current.insert(i, depth);
stamp_folding(current, i, remaining - 1, count, callback);
current.remove(i);
if current[i] != 0 || last_inserted_value % 2 == 0 {
last = Some(current[i]);
}
}
}
if last.is_none() {
current.push(depth);
stamp_folding(current, current.len() - 1, remaining - 1, count, callback);
current.pop();
}
}