Skip to content

Instantly share code, notes, and snippets.

@PanJarda
Created October 25, 2019 18:17
Show Gist options
  • Save PanJarda/ec6d3021fb06248ef0092d3d758ec0bb to your computer and use it in GitHub Desktop.
Save PanJarda/ec6d3021fb06248ef0092d3d758ec0bb to your computer and use it in GitHub Desktop.
detects if value belongs to set of intervals and tells you to which one.
/*
* Y-Combinator
*/
const Y = fn =>
( m => (...args) => fn(m(m))(...args))
( m => (...args) => fn(m(m))(...args));
/*
* Creates function that resolves if given value belongs
* inside any given interval
*/
const match = intervals => {
/*
* transform intervals to pairs
* input notation of intervals:
* [ [[[0,1], 2, [5,6]], 'I_1']
* , [[...], 'I_2']
* ]
* transforms to sorted pairs:
* [ [[0,1], 'I_1']
* , [[2,2], 'I_1']
* , [[5,6], 'I_1']
* , [[...], 'I_2']
* ]
*/
const pairs = intervals.map(i => [ i[0].map(i => typeof i !== 'object' && [i, i] || [...i])
, i[1]
])
.reduce((acc, pair) => acc.concat(pair[0].map(i => [i, pair[1]])), [])
.sort((a, b) => a[0][0] <= b[0][0] && -1 || 1)
/*
* Build binary interval tree from pairs
*/
const tree = Y(self => (pairs, l, r) =>
( m =>
((i, p) =>
(c => ({ value: pairs[i][0][p]
, eq: c
, lt: !(l^m) ? ( p ? { in: c } : null )
: self(pairs, l, m - 1)
, gt: !(m^r) ? ( !p ? { in: c } : null )
: self(pairs, m + 1, r)
})
)(pairs[i][1])
)(m>>>1, m&1)
)(((r - l)>>>1) + l)
)(pairs, 0, (pairs.length<<1) - 1);
/*
* walking tree to match interval
*/
const match = Y(self => (node, value) =>
!!node && (node.hasOwnProperty("in")
? node.in
: !(value ^ node.value)
? node.eq
: value < node.value
? self(node.lt, value)
: self(node.gt, value)))
return value => match(tree, value);
};
// test
// const testin = match([[0,1],[2,3], [4,5], 6,7,8], 'inside']);
// testin(0); // 'inside'
// testin(10); // false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment