Magic squares of doubly even order: Difference between revisions

Content deleted Content added
Hout (talk | contribs)
→‎JS ES6: Updated primitives, tidied.
Line 1,278:
'use strict';
 
// doubleEvenMagicSquaredoublyEvenMagicSquare :: Int -> [[Int]]
const doubleEvenMagicSquaredoublyEvenMagicSquare = n => {
if0 === (n % 4 >? 0(() return=> undefined;{
const
sqr = n * n,
power = Math.log2(sqr),
scale = replicate(n / 4);
return chunksOf(n)(
map((x, i) => x ? 1 + i : sqr - i)(
isInt(power) ? truthSeries(power) : (
compose(
flatten,
scale,
map(scale),
chunksOf(4)
)(truthSeries(4))
)
)
);
})() : undefined;
 
// truthSeries :: Int -> [IntBool]
const truthSeries = n => {
0 >= n if? (n <= 0) return [true];
[true]
) : (() => {
const xs = truthSeries(n - 1);
return xs.concat(xs.map(x => !x));
})();
 
// TEST -----------------------------------------------
const sqr = n * n,
const scalemain = curry(replicate)(n / 4),=>
// Magic squares of powerorders =4, Math8 and 12.log2(sqr),
map(n => {
sequence = isInt(power) ? truthSeries(power) : (
flatten(const
lines = scaledoublyEvenMagicSquare(n),
sums = splitEvery(4, truthSerieslines.concat(4))
.maptranspose(scalelines)
.concat(diagonals(lines))
)
.map(xs => xs.reduce((a, b) => a + b, 0)),
sum = sums[0];
return [
"Order: " + n.toString(),
"Summing to: " + sum.toString(),
"Row, column and diagonal sums checked: " +
all(eq(sum))(sums)
.toString() + '\n',
lines.map(
xs => xs.map(
compose(justifyRight(3)(' '), str)
)
.join(' '))
.join('\n');
].join('\n')
})([4, 8, 12])
.join('\n\n');
 
return splitEvery(n, sequence
.map((x, i) => x ? i + 1 : sqr - i));
};
 
// GENERIC FUNCTIONS ----------------------------------
 
// all :: (a -> Bool) -> [a] -> Bool
// GENERIC FUNCTIONS ----------------------------------------------------
const all = p =>
// True if p(x) holds for every x in xs.
xs => xs.every(p);
 
// flattenchunksOf :: TreeInt -> [a] -> [[a]]
const flattenchunksOf = tn => (txs instanceof Array ? concatMap(flatten, t) : [t]);=>
enumFromThenTo(0)(n)(
xs.length - 1
).reduce(
(a, i) => a.concat([xs.slice(i, (n + i))]),
[]
);
 
// concatMapcompose (<<<) :: (b -> c) -> (a -> [b]) -> [a] -> [b]c
const concatMapcompose = (f, xs...fs) => [].concat.apply([], xs.map(f));
x => fs.reduceRight((a, f) => f(a), x);
 
// splitEverydiagonals :: Int -> [[a]] -> ([a], [a]])
const splitEverydiagonals = (n, xs) => {
const
if (xs.length <= n) return [xs];
const [h, t] nRows = [xs.slice(0length, n), xs.slice(n)];
nCols = 0 < nRows ? (
return [h].concat(splitEvery(n, t));
xs[0].length
}
) : 0;
return nRows !== nCols ? [
[],
[]
] : (() => {
const
ns = enumFromTo(0)(nCols - 1),
f = zipWith(x => y => xs[y][x])(ns);
return [f(ns), f(reverse(ns))];
})();
};
 
// curryenumFromThenTo :: ((a, b) -> c)Int -> aInt -> bInt -> c[Int]
const curryenumFromThenTo = fx1 => ax2 => by => f(a, b);{
const d = x2 - x1;
 
// replicate :: Int ->return a -> [a]Array.from({
length: Math.floor(y - x2) / d + 2
const replicate = (n, a) => {
let}, v(_, i) => [a],x1 + (d * i));
o = [];
if (n < 1) return o;
while (n > 1) {
if (n & 1) o = o.concat(v);
n >>= 1;
v = v.concat(v);
}
return o.concat(v);
};
 
// isIntenumFromTo :: Int -> BoolInt -> [Int]
const isIntenumFromTo = xm => xn === Math.floor(x);>
Array.from({
length: 1 + n - m
}, (_, i) => m + i);
 
// eq (==) :: Eq a => a -> a -> Bool
const eq = a => b => a === b;
 
// flatten :: NestedList a -> [a]
// TEST AND DISPLAY FUNCTIONS -------------------------------------------
const flatten = nest => nest.flat(Infinity);
 
// transposeisInt :: [[a]]Int -> [[a]]Bool
const transposeisInt = xsx => x === Math.floor(x);
xs[0].map((_, iCol) => xs.map((row) => row[iCol]));
 
// diagonalsjustifyRight :: [[a]]Int -> ([a],Char [a])-> String -> String
const diagonalsjustifyRight = xsn => {cFiller => s =>
constn nRows> = xss.length, ? (
nCols = s.padStart(nRows > 0 ? xs[0].length :n, 0cFiller);
const cell = (x, y) =>: xs[y][x]s;
 
// map if:: (nRowsa ===-> nColsb) {-> [a] -> [b]
const nsmap = range(0,f nCols=> -xs 1);=>
(Array.isArray(xs) ? (
return [zipWith(cell, ns, ns), zipWith(cell, ns, reverse(ns))];
} else return [ xs
) : [],xs.split('')).map(f);
[]
];
};
 
// zipWithreplicate :: (aInt -> b -> c)a -> [a] -> [b] -> [c]
const zipWithreplicate = (f,n xs,=> ys)x => {
const ny = ysArray.length;from({
return (xs.length <= ny ? xs length: xs.slice(0, ny))n
}, .map((x, i) => f(x, ys[i]));
}
 
// reverse :: [a] -> [a]
const reverse = (xs) => xs.slice(0)
.reverse'string' !== typeof xs ? ()
xs.slice(0).reverse()
 
) : xs.split('').reverse().join('');
// range :: Int -> Int -> [Int]
const range = (m, n) =>
Array.from({
length: Math.floor(n - m) + 1
}, (_, i) => m + i);
 
// all :: (a -> Bool) -> [a] -> Bool
const all = (f, xs) => xs.every(f);
 
// show :: a -> String
const show = x => JSON.stringify(x);
 
// justifyRightstr :: Inta -> Char -> Text -> TextString
const justifyRightstr = (n,x cFiller,=> strTextx.toString() =>;
n > strText.length ? (
(cFiller.repeat(n) + strText)
.slice(-n)
) : strText;
 
// transpose :: [[a]] -> [[a]]
// TEST -----------------------------------------------------------------
const transpose = xs =>
xs[0].map((_, iCol) => xs.map((row) => row[iCol]));
 
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
//return doubleEvenMagicSquare(8)
const zipWith = f => xs => ys =>
xs.slice(
0, Math.min(xs.length, ys.length)
).map((x, i) => f(x)(ys[i]));
 
// MAIN -----------------------------------------------
return [4, 8, 12]
return .mapmain(n => {);
const lines = doubleEvenMagicSquare(n);
const sums = lines.concat(
transpose(lines)
.concat(diagonals(lines))
)
.map(xs => xs.reduce((a, b) => a + b, 0));
const sum = sums[0];
return [
"Order: " + n.toString(),
"Summing to: " + sum.toString(),
"Row, column and diagonal sums checked: " +
all(x => x === sum, sums)
.toString() + '\n',
lines.map(
xs => xs.map(
x => justifyRight(3, ' ', x.toString())
)
.join(' '))
.join('\n')
].join('\n')
})
.join('\n\n');
})();</lang>
 
{{Out}}
<pre>Order: 4