RosettaCodeData/Task/Forward-difference/JavaScript/forward-difference.js

58 lines
1.5 KiB
JavaScript

(() => {
'use strict';
// forwardDifference :: [Int] -> [Int]
const forwardDifference = (n, xs) => {
const fd = xs => zipWith((a, b) => a - b, tail(xs), xs);
return until(
m => m.index < 1,
m => ({
index: m.index - 1,
list: fd(m.list)
}), {
index: n,
list: xs
}
)
.list;
};
// GENERIC FUNCTIONS ---------------------------------------
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = (f, xs, ys) => {
const ny = ys.length;
return (xs.length <= ny ? xs : xs.slice(0, ny))
.map((x, i) => f(x, ys[i]));
};
// until :: (a -> Bool) -> (a -> a) -> a -> a
const until = (p, f, x) => {
const go = x => p(x) ? x : go(f(x));
return go(x);
};
// tail :: [a] -> [a]
const tail = xs => xs.length ? xs.slice(1) : undefined;
// TEST ----------------------------------------------------
// range :: Int -> Int -> [Int]
const range = (m, n) =>
Array.from({
length: Math.floor(n - m) + 1
}, (_, i) => m + i);
// show :: a -> String
const show = x => JSON.stringify(x);
// Sample
const test = [90, 47, 58, 29, 22, 32, 55, 5, 55, 73];
return range(1, 9)
.map(x => `${x} ${show(forwardDifference(x, test))}`)
.join('\n');
})();