RosettaCodeData/Task/Department-numbers/AppleScript/department-numbers-2.apples...

175 lines
4.1 KiB
AppleScript

-- NUMBERING CONSTRAINTS ------------------------------------------------------
-- options :: Int -> Int -> Int -> [(Int, Int, Int)]
on options(lo, hi, total)
set ds to enumFromTo(lo, hi)
script Xeven
on |λ|(x)
script Ydistinct
on |λ|(y)
script ZinRange
on |λ|(z)
if y z and lo z and z hi then
{{x, y, z}}
else
{}
end if
end |λ|
end script
concatMap(ZinRange, {total - (x + y)}) -- Z IS IN RANGE
end |λ|
end script
script notX
on |λ|(d)
d x
end |λ|
end script
concatMap(Ydistinct, filter(notX, ds)) -- Y IS NOT X
end |λ|
end script
concatMap(Xeven, filter(my even, ds)) -- X IS EVEN
end options
-- TEST -----------------------------------------------------------------------
on run
set xs to options(1, 7, 12)
intercalate("\n\n", ¬
{"(Police, Sanitation, Fire)", ¬
unlines(map(show, xs)), ¬
"Number of options: " & |length|(xs)})
end run
-- GENERIC FUNCTIONS ----------------------------------------------------------
-- concatMap :: (a -> [b]) -> [a] -> [b]
on concatMap(f, xs)
set lst to {}
set lng to length of xs
tell mReturn(f)
repeat with i from 1 to lng
set lst to (lst & |λ|(contents of item i of xs, i, xs))
end repeat
end tell
return lst
end concatMap
-- 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
-- even :: Int -> Bool
on even(x)
x mod 2 = 0
end even
-- 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
-- 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
-- length :: [a] -> Int
on |length|(xs)
length of xs
end |length|
-- 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
-- show :: a -> String
on show(e)
set c to class of e
if c = list then
script serialized
on |λ|(v)
show(v)
end |λ|
end script
"[" & intercalate(", ", map(serialized, e)) & "]"
else if c = record then
script showField
on |λ|(kv)
set {k, ev} to kv
"\"" & k & "\":" & show(ev)
end |λ|
end script
"{" & intercalate(", ", ¬
map(showField, zip(allKeys(e), allValues(e)))) & "}"
else if c = date then
"\"" & iso8601Z(e) & "\""
else if c = text then
"\"" & e & "\""
else if (c = integer or c = real) then
e as text
else if c = class then
"null"
else
try
e as text
on error
("«" & c as text) & "»"
end try
end if
end show
-- unlines :: [String] -> String
on unlines(xs)
intercalate(linefeed, xs)
end unlines