Magic squares of doubly even order: Difference between revisions
Content deleted Content added
→{{header|Python}}: Added a composition of pure functions |
|||
Line 1,644: | Line 1,644: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
===Procedural=== |
|||
<lang python> |
<lang python> |
||
def MagicSquareDoublyEven(order): |
def MagicSquareDoublyEven(order): |
||
Line 1,684: | Line 1,685: | ||
Magic constant = 260 |
Magic constant = 260 |
||
>>> |
>>> </pre> |
||
</pre> |
|||
===Composition of pure functions=== |
|||
Generating test results and a magic square in the form of a wiki table: |
|||
<lang python>'''Magic squares of doubly even order''' |
|||
from itertools import chain, repeat |
|||
from functools import reduce |
|||
from math import log |
|||
# doublyEvenMagicSquare :: Int -> [[Int]] |
|||
def doublyEvenMagicSquare(n): |
|||
'''Magic square of order n''' |
|||
# magic :: Int -> [Bool] |
|||
def magic(n): |
|||
'''Truth-table series''' |
|||
if 0 < n: |
|||
xs = magic(n - 1) |
|||
return xs + [not x for x in xs] |
|||
else: |
|||
return [True] |
|||
sqr = n * n |
|||
power = log(sqr, 2) |
|||
scale = replicate(n / 4) |
|||
return chunksOf(n)([ |
|||
succ(i) if bool else sqr - i for i, bool in |
|||
enumerate(magic(power) if isInteger(power) else ( |
|||
flatten(scale( |
|||
map(scale, chunksOf(4)(magic(4))) |
|||
)) |
|||
)) |
|||
]) |
|||
# TEST ---------------------------------------------------- |
|||
# main :: IO() |
|||
def main(): |
|||
'''Tests''' |
|||
order = 8 |
|||
magicSquare = doublyEvenMagicSquare(order) |
|||
print( |
|||
'Row sums: ', |
|||
[sum(xs) for xs in magicSquare], |
|||
'\nCol sums:', |
|||
[sum(xs) for xs in transpose(magicSquare)], |
|||
'\n1st diagonal sum:', |
|||
sum(magicSquare[i][i] for i in range(0, order)), |
|||
'\n2nd diagonal sum:', |
|||
sum(magicSquare[i][(order - 1) - i] for i in range(0, order)), |
|||
'\n' |
|||
) |
|||
print(wikiTable({ |
|||
'class': 'wikitable', |
|||
'style': cssFromDict({ |
|||
'text-align': 'center', |
|||
'color': '#605B4B', |
|||
'border': '2px solid silver' |
|||
}), |
|||
'colwidth': '3em' |
|||
})(magicSquare)) |
|||
# GENERIC ------------------------------------------------- |
|||
# chunksOf :: Int -> [a] -> [[a]] |
|||
def chunksOf(n): |
|||
'''A series of lists of length n, |
|||
subdividing the contents of xs. |
|||
Where the length of xs is not evenly divible |
|||
the final list will be shorter than n.''' |
|||
return lambda xs: reduce( |
|||
lambda a, i: a + [xs[i:n + i]], |
|||
range(0, len(xs), n), [] |
|||
) if 0 < n else [] |
|||
# concatMap :: (a -> [b]) -> [a] -> [b] |
|||
def concatMap(f): |
|||
'''Concatenated list over which a function has been mapped. |
|||
The list monad can be derived by using a function f which |
|||
wraps its output a in list |
|||
(using an empty list to represent computational failure).''' |
|||
return lambda xs: list( |
|||
chain.from_iterable( |
|||
map(f, xs) |
|||
) |
|||
) |
|||
# cssFromDict :: Dict -> String |
|||
def cssFromDict(dct): |
|||
'''CSS string serialized from key values in a Dictionary.''' |
|||
return reduce( |
|||
lambda a, k: a + k + ':' + dct[k] + '; ', dct.keys(), '' |
|||
) |
|||
# flatten :: NestedList a -> [a] |
|||
def flatten(x): |
|||
'''A list of atoms resulting from fully flattening |
|||
an arbitrarily nested list.''' |
|||
return concatMap(flatten)(x) if isinstance(x, list) else [x] |
|||
# isInteger :: Num -> Bool |
|||
def isInteger(n): |
|||
'''Divisible by one without remainder ?''' |
|||
return 0 == (n - int(n)) |
|||
# replicate :: Int -> a -> [a] |
|||
def replicate(n): |
|||
'''A list of length n in which every element |
|||
has the value x.''' |
|||
return lambda x: list(repeat(x, n)) |
|||
# succ :: Enum a => a -> a |
|||
def succ(x): |
|||
'''The successor of a value. For numeric types, (1 +).''' |
|||
return 1 + x if isinstance(x, int) else ( |
|||
chr(1 + ord(x)) |
|||
) |
|||
# transpose :: Matrix a -> Matrix a |
|||
def transpose(m): |
|||
'''The rows and columns of the argument transposed. |
|||
(The matrix containers and rows can be lists or tuples).''' |
|||
if m: |
|||
inner = type(m[0]) |
|||
z = zip(*m) |
|||
return (type(m))( |
|||
map(inner, z) if tuple != inner else z |
|||
) |
|||
else: |
|||
return m |
|||
# wikiTable :: Dict -> [[a]] -> String |
|||
def wikiTable(opts): |
|||
'''List of lists rendered as a wiki table string.''' |
|||
def colWidth(): |
|||
return 'width:' + opts['colwidth'] + '; ' if ( |
|||
'colwidth' in opts |
|||
) else '' |
|||
def cellStyle(): |
|||
return opts['cell'] if 'cell' in opts else '' |
|||
return lambda rows: '{| ' + reduce( |
|||
lambda a, k: ( |
|||
a + k + '="' + opts[k] + '" ' if k in opts else a |
|||
), |
|||
['class', 'style'], |
|||
'' |
|||
) + '\n' + '\n|-\n'.join( |
|||
'\n'.join( |
|||
('|' if (0 != i and ('cell' not in opts)) else ( |
|||
'|style="' + colWidth() + cellStyle() + '"|' |
|||
)) + ( |
|||
str(x) or ' ' |
|||
) for x in row |
|||
) for i, row in enumerate(rows) |
|||
) + '\n|}\n\n' |
|||
if __name__ == '__main__': |
|||
main()</lang> |
|||
{{Out}} |
|||
<pre>Row sums: [260, 260, 260, 260, 260, 260, 260, 260] |
|||
Col sums: [260, 260, 260, 260, 260, 260, 260, 260] |
|||
1st diagonal sum: 260 |
|||
2nd diagonal sum: 260 </pre> |
|||
{| class="wikitable" style="text-align:center; color:#605B4B; border:2px solid silver; " |
|||
|style="width:3em; "|1 |
|||
|style="width:3em; "|63 |
|||
|style="width:3em; "|62 |
|||
|style="width:3em; "|4 |
|||
|style="width:3em; "|60 |
|||
|style="width:3em; "|6 |
|||
|style="width:3em; "|7 |
|||
|style="width:3em; "|57 |
|||
|- |
|||
|56 |
|||
|10 |
|||
|11 |
|||
|53 |
|||
|13 |
|||
|51 |
|||
|50 |
|||
|16 |
|||
|- |
|||
|48 |
|||
|18 |
|||
|19 |
|||
|45 |
|||
|21 |
|||
|43 |
|||
|42 |
|||
|24 |
|||
|- |
|||
|25 |
|||
|39 |
|||
|38 |
|||
|28 |
|||
|36 |
|||
|30 |
|||
|31 |
|||
|33 |
|||
|- |
|||
|32 |
|||
|34 |
|||
|35 |
|||
|29 |
|||
|37 |
|||
|27 |
|||
|26 |
|||
|40 |
|||
|- |
|||
|41 |
|||
|23 |
|||
|22 |
|||
|44 |
|||
|20 |
|||
|46 |
|||
|47 |
|||
|17 |
|||
|- |
|||
|49 |
|||
|15 |
|||
|14 |
|||
|52 |
|||
|12 |
|||
|54 |
|||
|55 |
|||
|9 |
|||
|- |
|||
|8 |
|||
|58 |
|||
|59 |
|||
|5 |
|||
|61 |
|||
|3 |
|||
|2 |
|||
|64 |
|||
|} |
|||
=={{header|REXX}}== |
=={{header|REXX}}== |