Skip to content

Instantly share code, notes, and snippets.

@Michaelgathara
Created February 20, 2024 09:43
Show Gist options
  • Save Michaelgathara/7272d8f6f279e58a7dd201415e2ec461 to your computer and use it in GitHub Desktop.
Save Michaelgathara/7272d8f6f279e58a7dd201415e2ec461 to your computer and use it in GitHub Desktop.
overlapping lines problem
pub mod overlapping_line {
#[derive(Debug, Clone)]
pub enum Linetree {
Empty,
Filled,
Node {
pivot: i64,
left: Box<Linetree>,
right: Box<Linetree>,
}
}
#[derive(Debug, Clone)]
pub struct Line {
x0: i64,
x1: i64,
}
impl Linetree {
pub fn insert(&self, line: &Line) -> Linetree {
match line {
Line { x0, x1 } => {
if x0 == x1 {
return self.clone();
}
match self {
Linetree::Filled => Linetree::Filled, // If the section is already filled then just return filled
Linetree::Empty => Linetree::Node { // If the section is empty then insert the line, pick your first pivot as x0, where to the left of that is empty and to the right you have a pivot of x1 where the left is filled and the right is empty
/*
Say you have a line from 1 to 4
---EMPTY----x0--------COVERED---------x1--EMPTY---
---EMPTY----1--------COVERED----------4---EMPTY---
------------p0------------------------p1----------*/
pivot: *x0,
left: Box::new(Linetree::Empty),
right: Box::new(Linetree::Node {
pivot: *x1,
left: Box::new(Linetree::Filled),
right: Box::new(Linetree::Empty),
}),
},
Linetree::Node { pivot, left, right } => {
/*
If you already have a Node within your Linetree, then you'd want to organize this by the pivot and insert the line down both sides
First up is left side: so pivot is p0
To the left, we either have a new pivot of x0 or the same pivot depending on which is shorter
To the right, we have a new pivot of x1 or the same pivot depending on which is longer
---EMPTY----x0--------COVERED---------x1--EMPTY---
---EMPTY----1--------COVERED----------4---EMPTY---
------------p0------------------------p1----------
now you insert a line from 1 to 2
---EMPTY----x0--------COVERED---------x1--EMPTY---
---EMPTY----1--------COVERED----------4---EMPTY---
------------p0------------------------p1----------
Notice the left pivot is the same, but the right pivot is the same, because the entirety of the line is covered within the left/right pivots
Now you insert a line from 2 to 6
---EMPTY----x0--------COVERED---------x1--EMPTY---
---EMPTY----1--------COVERED----------7---EMPTY---
------------p0------------------------p1----------
Notice the left pivot stayed the same, but the right pivot changed to 7, because the new line to the right of the pivot is longer than the previous pivot. Thus now the entirety of line from 1 to 7 is covered within the left/right pivots
*/
Linetree::Node {
pivot: *pivot,
left: Box::new(left.insert(&Line { x0: std::cmp::min(*x0, *pivot), x1: std::cmp::min(*x1, *pivot) })),
right: Box::new(right.insert(&Line { x0: std::cmp::max(*x0, *pivot), x1: std::cmp::max(*x1, *pivot) })),
}
}
}
}
}
}
pub fn cov_area(&self, x0: i64, x1: i64) -> i64 {
match self {
Linetree::Empty => 0,
Linetree::Filled => x1 - x0,
Linetree::Node {pivot, left, right} => {
left.cov_area(x0, *pivot) + right.cov_area(*pivot, x1)
}
}
}
}
impl Line {
pub fn new(x0: i64, x1: i64) -> Line {
Line { x0, x1 }
}
}
pub fn total_line_area(lines: Vec<Line>) -> i64 {
let mut tree = Linetree::Empty;
for line in lines {
tree = tree.insert(&line);
}
return tree.cov_area(i64::MIN, i64::MAX);
}
}
fn main() {
let lines = vec! [
overlapping_line::Line::new(1,4),
overlapping_line::Line::new(1,7),
];
let result = overlapping_line::total_line_area(lines);
println!("{}", result);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment