80 lines
2.1 KiB
JavaScript
80 lines
2.1 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
// NUMBERING CONSTRAINTS --------------------------------------------------
|
|
|
|
// options :: Int -> Int -> Int -> [(Int, Int, Int)]
|
|
function options(lo, hi, total) {
|
|
var bind = flip(concatMap),
|
|
ds = enumFromTo(lo, hi);
|
|
|
|
return bind(filter(even, ds),
|
|
function (x) { // X is even,
|
|
return bind(filter(function (d) { return d !== x; }, ds),
|
|
function (y) { // Y is distinct from X,
|
|
return bind([total - (x + y)],
|
|
function (z) { // Z sums with x and y to total, and is in ds.
|
|
return z !== y && lo <= z && z <= hi ? [
|
|
[x, y, z]
|
|
] : [];
|
|
})})})};
|
|
|
|
// GENERIC FUNCTIONS ------------------------------------------------------
|
|
|
|
// concatMap :: (a -> [b]) -> [a] -> [b]
|
|
function concatMap(f, xs) {
|
|
return [].concat.apply([], xs.map(f));
|
|
};
|
|
|
|
// enumFromTo :: Int -> Int -> [Int]
|
|
function enumFromTo(m, n) {
|
|
return Array.from({
|
|
length: Math.floor(n - m) + 1
|
|
}, function (_, i) {
|
|
return m + i;
|
|
});
|
|
};
|
|
|
|
// even :: Integral a => a -> Bool
|
|
function even(n) {
|
|
return n % 2 === 0;
|
|
};
|
|
|
|
// filter :: (a -> Bool) -> [a] -> [a]
|
|
function filter(f, xs) {
|
|
return xs.filter(f);
|
|
};
|
|
|
|
// flip :: (a -> b -> c) -> b -> a -> c
|
|
function flip(f) {
|
|
return function (a, b) {
|
|
return f.apply(null, [b, a]);
|
|
};
|
|
};
|
|
|
|
// length :: [a] -> Int
|
|
function length(xs) {
|
|
return xs.length;
|
|
};
|
|
|
|
// map :: (a -> b) -> [a] -> [b]
|
|
function map(f, xs) {
|
|
return xs.map(f);
|
|
};
|
|
|
|
// show :: a -> String
|
|
function show(x) {
|
|
return JSON.stringify(x);
|
|
}; //, null, 2);
|
|
|
|
// unlines :: [String] -> String
|
|
function unlines(xs) {
|
|
return xs.join('\n');
|
|
};
|
|
|
|
// TEST -------------------------------------------------------------------
|
|
var xs = options(1, 7, 12);
|
|
return '(Police, Sanitation, Fire)\n\n' +
|
|
unlines(map(show, xs)) + '\n\nNumber of options: ' + length(xs);
|
|
})();
|