-- zigzagMatrix on zigzagMatrix(n) -- diagonals :: n -> [[n]] script diagonals on |λ|(n) script mf on diags(xs, iCol, iRow) if (iCol < length of xs) then if iRow < n then set iNext to iCol + 1 else set iNext to iCol - 1 end if set {headList, tail} to splitAt(iCol, xs) {headList} & diags(tail, iNext, iRow + 1) else {xs} end if end diags end script diags(enumFromTo(0, n * n - 1), 1, 1) of mf end |λ| end script -- oddReversed :: [a] -> Int -> [a] script oddReversed on |λ|(lst, i) if i mod 2 = 0 then lst else reverse of lst end if end |λ| end script rowsFromDiagonals(n, map(oddReversed, |λ|(n) of diagonals)) end zigzagMatrix -- Rows of given length from list of diagonals -- rowsFromDiagonals :: Int -> [[a]] -> [[a]] on rowsFromDiagonals(n, lst) if length of lst > 0 then -- lengthOverOne :: [a] -> Bool script lengthOverOne on |λ|(lst) length of lst > 1 end |λ| end script set {edge, residue} to splitAt(n, lst) {map(my head, edge)} & ¬ rowsFromDiagonals(n, ¬ map(my tail, ¬ filter(lengthOverOne, edge)) & residue) else {} end if end rowsFromDiagonals -- TEST ----------------------------------------------------------------------- on run zigzagMatrix(5) end run -- GENERIC FUNCTIONS ---------------------------------------------------------- -- enumFromTo :: Int -> Int -> [Int] on enumFromTo(m, n) if n < m then set d to -1 else set d to 1 end if set lst to {} repeat with i from m to n by d set end of lst to i end repeat return lst end enumFromTo -- filter :: (a -> Bool) -> [a] -> [a] on filter(f, xs) tell mReturn(f) set lst to {} set lng to length of xs repeat with i from 1 to lng set v to item i of xs if |λ|(v, i, xs) then set end of lst to v end repeat return lst end tell end filter -- head :: [a] -> a on head(xs) if length of xs > 0 then item 1 of xs else missing value end if end head -- 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 |λ|(item i of xs, i, xs) end repeat return lst end tell end map -- 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 |λ| : f end script end if end mReturn -- splitAt:: n -> list -> {n items from start of list, rest of list} -- splitAt :: Int -> [a] -> ([a], [a]) on splitAt(n, xs) if n > 0 and n < length of xs then {items 1 thru n of xs, items (n + 1) thru -1 of xs} else if n < 1 then {{}, xs} else {xs, {}} end if end if end splitAt -- tail :: [a] -> [a] on tail(xs) if length of xs > 1 then items 2 thru -1 of xs else {} end if end tail