Magic squares of doubly even order: Difference between revisions
Content added Content deleted
(→JS ES6) |
|||
Line 35: | Line 35: | ||
* [http://www.1728.org/magicsq2.htm Doubly Even Magic Squares (1728.org)] |
* [http://www.1728.org/magicsq2.htm Doubly Even Magic Squares (1728.org)] |
||
<br><br> |
<br><br> |
||
=={{header|AppleScript}}== |
|||
<lang AppleScript>-- magicSquare :: Int -> [[Int]] |
|||
on magicSquare(n) |
|||
if n mod 4 > 0 then |
|||
{} |
|||
else |
|||
script scale |
|||
on lambda(x) |
|||
replicate(n / 4, x) |
|||
end lambda |
|||
end script |
|||
set sqr to n * n |
|||
set maybePowerOfTwo to asPowerOfTwo(sqr) |
|||
if maybePowerOfTwo is not missing value then |
|||
-- For powers of 2, the (append not) 'magic' series directly |
|||
-- yields the truth table that we need |
|||
set truthSeries to magicSeries(maybePowerOfTwo) |
|||
else |
|||
-- where n is not a power of 2, we can replicate a |
|||
-- minimum truth table, horizontally and vertically |
|||
set truthSeries to ¬ |
|||
flatten(scale's lambda(map(scale, splitEvery(4, magicSeries(4))))) |
|||
end if |
|||
set limit to sqr + 1 |
|||
script inOrderOrReversed |
|||
on lambda(x, i) |
|||
cond(x, i, limit - i) |
|||
end lambda |
|||
end script |
|||
-- Taken directly from an integer series [1..sqr] where True |
|||
-- and from the reverse of that series where False |
|||
splitEvery(n, map(inOrderOrReversed, truthSeries)) |
|||
end if |
|||
end magicSquare |
|||
-- magicSeries :: Int -> [Bool] |
|||
on magicSeries(n) |
|||
script boolToggle |
|||
on lambda(x) |
|||
not x |
|||
end lambda |
|||
end script |
|||
if n ≤ 0 then |
|||
{true} |
|||
else |
|||
set xs to magicSeries(n - 1) |
|||
xs & map(boolToggle, xs) |
|||
end if |
|||
end magicSeries |
|||
-- TEST --------------------------------------------------------------------------- |
|||
on run |
|||
formattedTable(magicSquare(8)) |
|||
end run |
|||
-- formattedTable :: [[Int]] -> String |
|||
on formattedTable(lstTable) |
|||
set n to length of lstTable |
|||
set w to 2.5 * n |
|||
"magic(" & n & ")" & linefeed & wikiTable(lstTable, ¬ |
|||
false, "text-align:center;width:" & ¬ |
|||
w & "em;height:" & w & "em;table-layout:fixed;") |
|||
end formattedTable |
|||
-- wikiTable :: [Text] -> Bool -> Text -> Text |
|||
on wikiTable(lstRows, blnHdr, strStyle) |
|||
script fWikiRows |
|||
on lambda(lstRow, iRow) |
|||
set strDelim to cond(blnHdr and (iRow = 0), "!", "|") |
|||
set strDbl to strDelim & strDelim |
|||
linefeed & "|-" & linefeed & strDelim & space & ¬ |
|||
intercalate(space & strDbl & space, lstRow) |
|||
end lambda |
|||
end script |
|||
linefeed & "{| class=\"wikitable\" " & ¬ |
|||
cond(strStyle ≠ "", "style=\"" & strStyle & "\"", "") & ¬ |
|||
intercalate("", ¬ |
|||
map(fWikiRows, lstRows)) & linefeed & "|}" & linefeed |
|||
end wikiTable |
|||
-- GENERIC FUNCTIONS ------------------------------------------------------------- |
|||
-- splitEvery :: Int -> [a] -> [[a]] |
|||
on splitEvery(n, xs) |
|||
if length of xs ≤ n then |
|||
{xs} |
|||
else |
|||
set {gp, t} to splitAt(n, xs) |
|||
{gp} & splitEvery(n, t) |
|||
end if |
|||
end splitEvery |
|||
-- isPowerOf :: Int -> Int -> Bool |
|||
on isPowerOf(k, n) |
|||
set v to k |
|||
script remLeft |
|||
property divisor : k |
|||
on lambda(x) |
|||
x mod (remLeft's divisor) is not 0 |
|||
end lambda |
|||
end script |
|||
script integerDiv |
|||
property divisor : k |
|||
on lambda(x) |
|||
x div (integerDiv's divisor) |
|||
end lambda |
|||
end script |
|||
|until|(remLeft, integerDiv, n) = 1 |
|||
end isPowerOf |
|||
-- asPowerOfTwo :: Int -> maybe Int |
|||
on asPowerOfTwo(n) |
|||
if not isPowerOf(2, n) then |
|||
missing value |
|||
else |
|||
set strCMD to ("echo 'l(" & n as string) & ")/l(2)' | bc -l" |
|||
(do shell script strCMD) as integer |
|||
end if |
|||
end asPowerOfTwo |
|||
-- map :: (a -> b) -> [a] -> [b] |
|||
on map(f, xs) |
|||
tell mReturn(f) |
|||
set lng to length of xs |
|||
set lst to {} |
|||
repeat with i from 1 to lng |
|||
set end of lst to lambda(item i of xs, i, xs) |
|||
end repeat |
|||
return lst |
|||
end tell |
|||
end map |
|||
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] |
|||
on zipWith(f, xs, ys) |
|||
set nx to length of xs |
|||
set ny to length of ys |
|||
if nx < 1 or ny < 1 then |
|||
{} |
|||
else |
|||
set lng to cond(nx < ny, nx, ny) |
|||
set lst to {} |
|||
tell mReturn(f) |
|||
repeat with i from 1 to lng |
|||
set end of lst to lambda(item i of xs, item i of ys) |
|||
end repeat |
|||
return lst |
|||
end tell |
|||
end if |
|||
end zipWith |
|||
-- cond :: Bool -> a -> a -> a |
|||
on cond(bool, f, g) |
|||
if bool then |
|||
f |
|||
else |
|||
g |
|||
end if |
|||
end cond |
|||
-- flatten :: Tree a -> [a] |
|||
on flatten(t) |
|||
if class of t is list then |
|||
concatMap(my flatten, t) |
|||
else |
|||
t |
|||
end if |
|||
end flatten |
|||
-- concatMap :: (a -> [b]) -> [a] -> [b] |
|||
on concatMap(f, xs) |
|||
script append |
|||
on lambda(a, b) |
|||
a & b |
|||
end lambda |
|||
end script |
|||
foldl(append, {}, map(f, xs)) |
|||
end concatMap |
|||
-- foldl :: (a -> b -> a) -> a -> [b] -> a |
|||
on foldl(f, startValue, xs) |
|||
tell mReturn(f) |
|||
set v to startValue |
|||
set lng to length of xs |
|||
repeat with i from 1 to lng |
|||
set v to lambda(v, item i of xs, i, xs) |
|||
end repeat |
|||
return v |
|||
end tell |
|||
end foldl |
|||
-- until :: (a -> Bool) -> (a -> a) -> a -> a |
|||
on |until|(p, f, x) |
|||
set mp to mReturn(p) |
|||
set mf to mReturn(f) |
|||
script iterate |
|||
property p : mp's lambda |
|||
property f : mf's lambda |
|||
on lambda(v) |
|||
repeat until p(v) |
|||
set v to f(v) |
|||
end repeat |
|||
return v |
|||
end lambda |
|||
end script |
|||
iterate's lambda(x) |
|||
end |until| |
|||
-- Lift 2nd class handler function into 1st class script wrapper |
|||
-- mReturn :: Handler -> Script |
|||
on mReturn(f) |
|||
if class of f is script then |
|||
f |
|||
else |
|||
script |
|||
property lambda : f |
|||
end script |
|||
end if |
|||
end mReturn |
|||
-- Egyptian multiplication - progressively doubling a list, appending |
|||
-- stages of doubling to an accumulator where needed for binary |
|||
-- assembly of a target length |
|||
-- replicate :: Int -> a -> [a] |
|||
on replicate(n, a) |
|||
set out to {} |
|||
if n < 1 then return out |
|||
set dbl to {a} |
|||
repeat while (n > 1) |
|||
if (n mod 2) > 0 then set out to out & dbl |
|||
set n to (n div 2) |
|||
set dbl to (dbl & dbl) |
|||
end repeat |
|||
return out & dbl |
|||
end replicate |
|||
-- splitAt :: Int -> [a] -> ([a],[a]) |
|||
on splitAt(n, xs) |
|||
if n > 0 and n < length of xs then |
|||
if class of xs is text then |
|||
{items 1 thru n of xs as text, items (n + 1) thru -1 of xs as text} |
|||
else |
|||
{items 1 thru n of xs, items (n + 1) thru -1 of xs} |
|||
end if |
|||
else |
|||
if n < 1 then |
|||
{{}, xs} |
|||
else |
|||
{xs, {}} |
|||
end if |
|||
end if |
|||
end splitAt |
|||
-- intercalate :: Text -> [Text] -> Text |
|||
on intercalate(strText, lstText) |
|||
set {dlm, my text item delimiters} to {my text item delimiters, strText} |
|||
set strJoined to lstText as text |
|||
set my text item delimiters to dlm |
|||
return strJoined |
|||
end intercalate</lang> |
|||
{{Out}} |
|||
magic(8) |
|||
{| class="wikitable" style="text-align:center;width:20.0em;height:20.0em;table-layout:fixed;" |
|||
|- |
|||
| 1 || 63 || 62 || 4 || 60 || 6 || 7 || 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|C++}}== |
=={{header|C++}}== |