0

So, I have an object with two ints representing years, like this:

const targetRange = { from: 2015, to: 2020 };

Then I have an array with other ranges, like this:

const currentRanges = [
    { from: 2003, to: 2006 },
    { from: 2006, to: 2010 },
    { from: 2010, to: 2014 },
    { from: 2014, to: 2019 },
]

I want to make a function rangesCollide that checks if the target range collides with any of the current ranges.

Examples:

rangesCollide({ from: 2010, to: 2015 }, { from: 2007, to: 2010 }); // false
rangesCollide({ from: 2010, to: 2015 }, { from: 2007, to: 2011 }); // true
rangesCollide({ from: 2010, to: 2015 }, { from: 2010, to: 2010 }); // false
rangesCollide({ from: 2010, to: 2015 }, { from: 2010, to: 2013 }); // true
rangesCollide({ from: 2010, to: 2015 }, { from: 2011, to: 2014 }); // true
rangesCollide({ from: 2010, to: 2015 }, { from: 2015, to: 2015 }); // false
rangesCollide({ from: 2010, to: 2015 }, { from: 2014, to: 2018 }); // true
rangesCollide({ from: 2010, to: 2015 }, { from: 2015, to: 2020 }); // false
rangesCollide({ from: 2010, to: 2015 }, { from: 2018, to: 2022 }); // false

I can't wrap my head about how I could make it work.

Ok, I found this:

Find out if two line segments intersect

Which is basically the same problem, this is the solution:

function overlap(A1,A2,B1,B2) {
    return A1<=B1?A2>=B1:B2>=A1;
}

But I had to change the <= and >= to < and > respectively.

nick
  • 2,819
  • 5
  • 33
  • 69

3 Answers3

0

I think you can use the some method on the array of ranges.

const targetRange = { from: 2015, to: 2020 };

const currentRanges = [
    { from: 2003, to: 2006 },
    { from: 2006, to: 2010 },
    { from: 2010, to: 2014 },
    { from: 2014, to: 2019 },
];

const rangeConflicts = (f1, t1) => {
  return currentRanges.some(({from: f, to: t}) => {
    return (f1 >= f && f1 <= t) || (t1 >= f && t1 <= t);
  });
};

console.log(rangeConflicts(targetRange.from, targetRange.to));
Bibberty
  • 4,670
  • 2
  • 8
  • 23
0

const rangesCollide = (target,other) => 
  (target.to <= other.to) 
  ? !(target.to <= other.from)
  : !(other.to <= target.from)
  
console.log(rangesCollide({ from: 2010, to: 2015 }, { from: 2011, to: 2014 }))

console.log(rangesCollide({ from: 2010, to: 2015 }, { from: 2015, to: 2015 }))

console.log(rangesCollide({ from: 2010, to: 2015 }, { from: 2014, to: 2018 }))
Alan Omar
  • 4,023
  • 1
  • 9
  • 20
0

There are two things here, first you want to check if a value is present in an array. The [array.prototype.some method][1] is perfect for this. The second is whether the ranges collide.

The some method takes a function as an argument and passes to that function the value of each array index, ending as soon as true is returned of until it has checked every value in the array.

With that said we can't write the collision checking function to accept two arguments as it won't work with some, instead we use a curried function, a function that returns a function. We call the first part with the target value, some then calls the second part until it finds a match, or checks every value in the array.

I've added a few more target ranges to the code in order to test the collision logic is working as you would expect.

const targetRange1 = { from: 2015, to: 2020 }
const targetRange2 = { from: 2000, to: 2022 }
const targetRange3 = { from: 2000, to: 2001 }
const targetRange4 = { from: 2020, to: 2021 }
const targetRange5 = { from: 2000, to: 2004 }
const targetRange6 = { from: 2015, to: 2016 }

const currentRanges = [
    { from: 2003, to: 2006 },
    { from: 2006, to: 2010 },
    { from: 2010, to: 2014 },
    { from: 2014, to: 2019 },
]

const rangesCollide = (r1) => (r2) => {
  if ((r1.from > r2.from && r1.from < r2.to) || (r1.from <= r2.from && r1.to > r2.from)) {
    return true
  }
  return false
}

const check1 = currentRanges.some(rangesCollide(targetRange1))
const check2 = currentRanges.some(rangesCollide(targetRange2))
const check3 = currentRanges.some(rangesCollide(targetRange3))
const check4 = currentRanges.some(rangesCollide(targetRange4))
const check5 = currentRanges.some(rangesCollide(targetRange5))
const check6 = currentRanges.some(rangesCollide(targetRange6))

document.querySelector('.p1').innerHTML = `check1 = ${check1}`
document.querySelector('.p2').innerHTML = `check2 = ${check2}`
document.querySelector('.p3').innerHTML = `check3 = ${check3}`
document.querySelector('.p4').innerHTML = `check4 = ${check4}`
document.querySelector('.p5').innerHTML = `check5 = ${check5}`
document.querySelector('.p6').innerHTML = `check6 = ${check6}`
<p class="p1"></p>
<p class="p2"></p>
<p class="p3"></p>
<p class="p4"></p>
<p class="p5"></p>
<p class="p6"></p>


  [1]: https://developer.cdn.mozilla.net/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some
spirift
  • 2,994
  • 1
  • 13
  • 18