pub fn overlay(under: &str, over: &str, x: i32, y: i32) -> String {
    let split_under: Vec<_> = under.split('\n').collect();
    let under_width = split_under.iter().map(|s| s.len()).max().unwrap();
    let under_height = split_under.len();

    let split_over: Vec<String> = over.split('\n').map(|s| s.to_string()).collect();
    let over_width = split_over.iter().map(|s| s.len()).max().unwrap();

    // Take `over` and pad it so that it matches `under`'s dimensions

    // Trim/add lines at beginning
    let split_over: Vec<String> = if y.is_negative() {
        split_over.iter().skip(y.abs() as usize).cloned().collect()
    } else if y.is_positive() {
        (0..y)
            .map(|_| (0..over_width).map(|_| ' ').collect())
            .chain(split_over.iter().map(|s| s.to_string()))
            .collect()
    } else {
        split_over
    };

    // Trim/add chars at beginning
    let split_over: Vec<String> = if x.is_negative() {
        split_over
            .iter()
            .map(|l| l.chars().skip(x.abs() as usize).collect())
            .collect()
    } else if x.is_positive() {
        split_over
            .iter()
            .map(|s| (0..x).map(|_| ' ').chain(s.chars()).collect())
            .collect()
    } else {
        split_over
    };

    // pad out end of vector
    let over_width = split_over.iter().map(|s| s.len()).max().unwrap();
    let over_height = split_over.len();
    let lines_deficit = under_height as i32 - over_height as i32;
    let split_over: Vec<String> = if lines_deficit.is_positive() {
        let new_lines: Vec<String> = (0..lines_deficit)
            .map(|_| (0..over_width).map(|_| ' ').collect::<String>())
            .collect();
        let mut temp = split_over;
        for new_line in new_lines {
            temp.push(new_line);
        }
        temp
    } else {
        split_over
    };

    // pad out end of each line
    let line_width_deficit = under_width as i32 - over_width as i32;
    let split_over: Vec<String> = if line_width_deficit.is_positive() {
        split_over
            .iter()
            .map(|l| {
                l.chars()
                    .chain((0..line_width_deficit).map(|_| ' '))
                    .collect()
            })
            .collect()
    } else {
        split_over
    };

    // Now that the dimensions match, overlay them
    let mut out: Vec<String> = vec![];
    for (l, ol) in split_under.iter().zip(split_over.iter()) {
        let mut new_line = "".to_string();
        for (c, oc) in l.chars().zip(ol.chars()) {
            new_line.push(if oc == ' ' { c } else { oc });
        }
        out.push(new_line);
    }

    out.join("\n")
}
/// Given two 'rectangular' strings, overlay the second on the first offset by `x` and `y`
Given two 'rectangular' strings, overlay the second on the first offset by `x` and `y`
Given two ' rectangular ' strings overlay the second on the first offset by ` x ` and ` y `
pub fn overlay(under: &str, over: &str, x: i32, y: i32) -> String {
    let split_under: Vec<_> = under.split('\n').collect();
    let under_width = split_under.iter().map(|s| s.len()).max().unwrap();
    let under_height = split_under.len();
    let split_over: Vec<String> = over.split('\n').map(|s| s.to_string()).collect();
    let over_width = split_over.iter().map(|s| s.len()).max().unwrap();
    // Take `over` and pad it so that it matches `under`'s dimensions
    // Trim/add lines at beginning
    let split_over: Vec<String> = if y.is_negative() {
        split_over.iter().skip(y.abs() as usize).cloned().collect()
    } else if y.is_positive() {
        (0..y)
            .map(|_| (0..over_width).map(|_| ' ').collect())
            .chain(split_over.iter().map(|s| s.to_string()))
            .collect()
    } else {
        split_over
    };
    // Trim/add chars at beginning
    let split_over: Vec<String> = if x.is_negative() {
        split_over
            .iter()
            .map(|l| l.chars().skip(x.abs() as usize).collect())
            .collect()
    } else if x.is_positive() {
        split_over
            .iter()
            .map(|s| (0..x).map(|_| ' ').chain(s.chars()).collect())
            .collect()
    } else {
        split_over
    };
    // pad out end of vector
    let over_width = split_over.iter().map(|s| s.len()).max().unwrap();
    let over_height = split_over.len();
    let lines_deficit = under_height as i32 - over_height as i32;
    let split_over: Vec<String> = if lines_deficit.is_positive() {
        let new_lines: Vec<String> = (0..lines_deficit)
            .map(|_| (0..over_width).map(|_| ' ').collect::<String>())
            .collect();
        let mut temp = split_over;
        for new_line in new_lines {
            temp.push(new_line);
        }
        temp
    } else {
        split_over
    };
    // pad out end of each line
    let line_width_deficit = under_width as i32 - over_width as i32;
    let split_over: Vec<String> = if line_width_deficit.is_positive() {
        split_over
            .iter()
            .map(|l| {
                l.chars()
                    .chain((0..line_width_deficit).map(|_| ' '))
                    .collect()
            })
            .collect()
    } else {
        split_over
    };
    // Now that the dimensions match, overlay them
    let mut out: Vec<String> = vec![];
    for (l, ol) in split_under.iter().zip(split_over.iter()) {
        let mut new_line = "".to_string();
        for (c, oc) in l.chars().zip(ol.chars()) {
            new_line.push(if oc == ' ' { c } else { oc });
        }
        out.push(new_line);
    }
    out.join("\n")
}
pub fn overlay ( under : & str , over : & str , x : i32 , y : i32 ) -> String { let split_under : Vec < _ > = under . split ( '\n' ) . collect ( ) ; let under_width = split_under . iter ( ) . map ( | s | s . len ( ) ) . max ( ) . unwrap ( ) ; let under_height = split_under . len ( ) ; let split_over : Vec < String > = over . split ( '\n' ) . map ( | s | s . to_string ( ) ) . collect ( ) ; let over_width = split_over . iter ( ) . map ( | s | s . len ( ) ) . max ( ) . unwrap ( ) ; // Take `over` and pad it so that it matches `under`'s dimensions // Trim/add lines at beginning let split_over : Vec < String > = if y . is_negative ( ) { split_over . iter ( ) . skip ( y . abs ( ) as usize ) . cloned ( ) . collect ( ) } else if y . is_positive ( ) { ( 0 .. y ) . map ( | _ | ( 0 .. over_width ) . map ( | _ | ' ' ) . collect ( ) ) . chain ( split_over . iter ( ) . map ( | s | s . to_string ( ) ) ) . collect ( ) } else { split_over } ; // Trim/add chars at beginning let split_over : Vec < String > = if x . is_negative ( ) { split_over . iter ( ) . map ( | l | l . chars ( ) . skip ( x . abs ( ) as usize ) . collect ( ) ) . collect ( ) } else if x . is_positive ( ) { split_over . iter ( ) . map ( | s | ( 0 .. x ) . map ( | _ | ' ' ) . chain ( s . chars ( ) ) . collect ( ) ) . collect ( ) } else { split_over } ; // pad out end of vector let over_width = split_over . iter ( ) . map ( | s | s . len ( ) ) . max ( ) . unwrap ( ) ; let over_height = split_over . len ( ) ; let lines_deficit = under_height as i32 - over_height as i32 ; let split_over : Vec < String > = if lines_deficit . is_positive ( ) { let new_lines : Vec < String > = ( 0 .. lines_deficit ) . map ( | _ | ( 0 .. over_width ) . map ( | _ | ' ' ) . collect :: < String > ( ) ) . collect ( ) ; let mut temp = split_over ; for new_line in new_lines { temp . push ( new_line ) ; } temp } else { split_over } ; // pad out end of each line let line_width_deficit = under_width as i32 - over_width as i32 ; let split_over : Vec < String > = if line_width_deficit . is_positive ( ) { split_over . iter ( ) . map ( | l | { l . chars ( ) . chain ( ( 0 .. line_width_deficit ) . map ( | _ | ' ' ) ) . collect ( ) } ) . collect ( ) } else { split_over } ; // Now that the dimensions match, overlay them let mut out : Vec < String > = vec ! [ ] ; for ( l , ol ) in split_under . iter ( ) . zip ( split_over . iter ( ) ) { let mut new_line = " " . to_string ( ) ; for ( c , oc ) in l . chars ( ) . zip ( ol . chars ( ) ) { new_line . push ( if oc == ' ' { c } else { oc } ) ; } out . push ( new_line ) ; } out . join ( " \n " ) }
Given two 'rectangular' strings, overlay the second on the first offset by `x` and `y`
Given two ' rectangular ' strings overlay the second on the first offset by ` x ` and ` y `
under
&str
over
&str
x
i32
y
i32
under
&str
over
&str
x
i32
y
i32