RosettaCodeData/Task/Increment-a-numerical-string/JavaScript/increment-a-numerical-strin...

60 lines
1.6 KiB
JavaScript

(() => {
'use strict';
// succString :: Bool -> String -> String
const succString = blnPruned => s => {
const go = w => {
const
v = w.includes('.') ? (
parseFloat(w)
) : parseInt(w);
return isNaN(v) ? (
blnPruned ? [] : [w]
) : [(1 + v).toString()];
};
return unwords(concatMap(go, words(s)));
};
// TEST -----------------------------------------------
const main = () =>
console.log(
unlines(
ap(
map(succString, [true, false]),
['41 pine martens in 1491.3 -1.5 mushrooms ≠ 136']
)
)
);
// GENERIC FUNCTIONS ----------------------------------
// Each member of a list of functions applied to each
// of a list of arguments, deriving a list of new values.
// ap (<*>) :: [(a -> b)] -> [a] -> [b]
const ap = (fs, xs) => //
fs.reduce((a, f) => a.concat(
xs.reduce((a, x) => a.concat([f(x)]), [])
), []);
// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = (f, xs) =>
xs.reduce((a, x) => a.concat(f(x)), []);
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
// unlines :: [String] -> String
const unlines = xs => xs.join('\n');
// unwords :: [String] -> String
const unwords = xs => xs.join(' ');
// words :: String -> [String]
const words = s => s.split(/\s+/);
// MAIN ---
return main();
})();