Sum of first n cubes: Difference between revisions
→{{header|AppleScript}}: Replaced a map-accumulation with a scanning accumulation.
(→{{header|AppleScript}}: Replaced a map-accumulation with a scanning accumulation.) |
(→{{header|AppleScript}}: Replaced a map-accumulation with a scanning accumulation.) |
||
Line 57:
1071225 1168561 1272384 1382976 1500625</pre>
=={{header|AppleScript}}==
<lang applescript>
"use strict";
// -------------- SUM OF FIRST N CUBES ---------------
// sumsOfFirstNCubes :: Int -> [Int]
const sumsOfFirstNCubes = n =>
// Cumulative sums of first n cubes.
scanl(
a => x => a + (x ** 3)
)(0)(
enumFromTo(1)(n - 1)
);
// ---------------------- TEST -----------------------
// main :: IO ()
const main = () =>
table(" ")(justifyRight)(
chunksOf(5)(
sumsOfFirstNCubes(50)
.map(x => `${x}`)
)
);
// --------------------- GENERIC ---------------------
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = m =>
n => Array.from({
length: 1 + n - m
}, (_, i) => m + i);
// scanl :: (b -> a -> b) -> b -> [a] -> [b]
const scanl = f => startValue => xs =>
// The series of interim values arising
// from a catamorphism. Parallel to foldl.
xs.reduce((a, x) => {
const v = f(a[0])(x);
return [v, a[1].concat(v)];
}, [startValue, [startValue]])[1];
const chunksOf = n => {
// xs split into sublists of length n.
// The last sublist will be short if n
// does not evenly divide the length of xs .
const chunk = xs.slice(0, n);
return 0 < chunk.length ? (
[chunk].concat(
go(xs.slice(n))
)
) : [];
};
return go;
};
const compose = (...fs) =>
// A function defined by the right-to-left
// composition of all the functions in fs.
(f, g) => x
const flip = op =>
// The binary function op with
1 < op.length ? (
// intercalate :: String -> [String] -> String
const intercalate = s =>
// The concatenation of xs
// interspersed with copies of s.
xs => xs.join(s);
const justifyRight = n =>
c => s =>
const maximum = xs => (
// The largest value in a non-empty list.
ys => 0 < ys.length ? (
ys.slice(1).reduce(
(a, y) => y > a ? (
y
) : a, ys[0]
)
) : undefined
)(xs);
// (Int -> Char -> String -> String) ->
// [[String]] -> String
const table = gap =>
// A tabulation of rows of string values,
// and choice of cell alignment function
// (justifyLeft | center | justifyRight)
alignment => rows => {
const
colWidths = transpose(rows).map(
row => maximum(row.map(x => x.length))
);
return rows.map(
compose(
intercalate(gap),
zipWith(
flip(alignment)(" ")
)(colWidths)
)
).join("\n");
};
// transpose :: [[a]] -> [[a]]
const transpose = rows => {
// If any rows are shorter than those that follow,
// their elements are skipped:
// > transpose [[10,11],[20],[],[30,31,32]]
// == [[10,20,30],[11,31],[32]]
const go = xss =>
0 < xss.length ? (() => {
const
h = xss[0],
t = xss.slice(1);
return 0 < h.length ? [
[h[0]].concat(t.reduce(
(a, xs) => a.concat(
0 < xs.length ? (
[xs[0]]
) : []
),
[]
))
].concat(go([h.slice(1)].concat(
t.map(xs => xs.slice(1))
))) : go(t);
})() : [];
return go(rows);
};
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = f =>
// A list constructed by zipping with a
// custom function, rather than with the
// default tuple constructor.
xs => ys => xs.map(
(x, i) => f(x)(ys[i])
).slice(
0, Math.min(xs.length, ys.length)
);
// MAIN ---
return main();
})();</lang>
{{Out}}
<pre> 0 1 9 36 100
|