~jpl8/text-to-piet

91883f13272fbe530e9a2bc044c0bb3f7751954f — jpl 1 year, 6 months ago 8f15258
Add minimum image size finder.

Still buggy due to pushes on corners adding more
blocks than expected. Should fix
9 files changed, 43 insertions(+), 4 deletions(-)

D a.png
D hello.png
R bfs_instructions.ron => instruction_cache/bfs_instructions.ron
R bfs_instructions_prev.ron => instruction_cache/bfs_instructions_prev.ron
D raven-test.png
A resources/Lusiadas/Lusíadas-bfs-min_img_size.png
M src/instructions.rs
M src/main.rs
A test.png
D a.png => a.png +0 -0
D hello.png => hello.png +0 -0
R bfs_instructions.ron => instruction_cache/bfs_instructions.ron +0 -0
R bfs_instructions_prev.ron => instruction_cache/bfs_instructions_prev.ron +0 -0
D raven-test.png => raven-test.png +0 -0
A resources/Lusiadas/Lusíadas-bfs-min_img_size.png => resources/Lusiadas/Lusíadas-bfs-min_img_size.png +0 -0
M src/instructions.rs => src/instructions.rs +41 -2
@@ 9,6 9,8 @@ use Instructions::*;

use std::fs::OpenOptions;

use crate::spiral;

#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
pub enum Instructions {
    PUSH(usize),


@@ 116,7 118,7 @@ impl PietEncoder for EncoderBFS {
    }
}

pub fn expected_size(instructions: &Vec<Instructions>) -> u32 {
pub fn expected_size(instructions: &Vec<Instructions>) -> usize {
    // Num of extra blocks for corner_turn = 2 * num_corners
    // num_corners(side) = side - 3, for side > 2, 0 otherwise
    // num_blocks(instructions, side) = instructions.len() + corner_turn.len() * num_corners(side)


@@ 132,6 134,26 @@ pub fn expected_size(instructions: &Vec<Instructions>) -> u32 {
        }
    });

    eprintln!("NUM BLOCKS {num_blocks}");

    // TODO: Make the actual corner_turn vec accessible here
    let corner_turn_len = 2;

    let num_corners = |side: &usize| if *side > 3 { side - 3 } else { 0 };

    let eq_to_minimize = |side: &usize| {
        num_blocks + corner_turn_len * num_corners(side)
            <= (spiral::Spiral2D::length(*side as u32) as usize)
    };

    let min_image_size = search_for_minimum_satisfier(eq_to_minimize, 1..usize::MAX);

    match min_image_size {
        Some(img_size) => img_size,
        // heuristic
        None => 4 + (((2 * num_blocks - 8) as f64).sqrt() as usize) + 1,
    }

    // solving for side should work out to

    //4 + (((2 * n - 8) as f64).sqrt() as u32) + 1


@@ 139,7 161,24 @@ pub fn expected_size(instructions: &Vec<Instructions>) -> u32 {
    //3 + ((2 * n - 9) as f64).sqrt() as u32
    //10 + ((2.5 * (num_blocks as f64)) as f64).sqrt() as u32
    //2 + ((2 * num_blocks - 8) as f64).sqrt() as u32
    4 + (((2 * num_blocks - 8) as f64).sqrt() as u32) + 1
    // ((2 * num_blocks + corner_turn_len * corner_turn_len - 6 * corner_turn_len + 2) as f64).sqrt()
    //     as u32
    //     + corner_turn_len as u32
}

fn search_for_minimum_satisfier<T, F, I>(predicate: F, search_space: I) -> Option<T>
where
    F: Fn(&T) -> bool,
    T: Sized + PartialEq + Clone,
    I: IntoIterator<Item = T>,
{
    for (satisfies, val) in search_space.into_iter().map(|v| (predicate(&v), v)) {
        if satisfies {
            return Some(val.clone());
        }
    }

    None
}

pub fn gen_num_bfs(n: i64, initial_stack: Vec<i64>) -> Vec<Instructions> {

M src/main.rs => src/main.rs +2 -2
@@ 35,10 35,10 @@ fn main() {

    let input = fs::read_to_string(args.input_file).expect("Failed to read input file");

    let encoder = instructions::EncoderBFS::new("bfs_instructions.ron");
    let encoder = instructions::EncoderBFS::new("instruction_cache/bfs_instructions.ron");
    let instrs = encoder.encode_text(&input);

    let img_size = args.img_size.unwrap_or(expected_size(&instrs));
    let img_size = args.img_size.unwrap_or(expected_size(&instrs) as u32);
    eprintln!("img_size: {:?}", img_size);
    eprintln!("spiral_len: {:?}", Spiral2D::length(img_size));


A test.png => test.png +0 -0