71 lines
1.6 KiB
Python
71 lines
1.6 KiB
Python
'''Department numbers'''
|
|
|
|
from itertools import (chain)
|
|
from operator import (ne)
|
|
|
|
|
|
# options :: Int -> Int -> Int -> [(Int, Int, Int)]
|
|
def options(lo, hi, total):
|
|
'''Eligible integer triples.'''
|
|
ds = enumFromTo(lo)(hi)
|
|
return bind(filter(even, ds))(
|
|
lambda x: bind(filter(curry(ne)(x), ds))(
|
|
lambda y: bind([total - (x + y)])(
|
|
lambda z: [(x, y, z)] if (
|
|
z != y and lo <= z <= hi
|
|
) else []
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
# TEST ----------------------------------------------------
|
|
# main :: IO ()
|
|
def main():
|
|
'''Test'''
|
|
|
|
xs = options(1, 7, 12)
|
|
print(('Police', 'Sanitation', 'Fire'))
|
|
for tpl in xs:
|
|
print(tpl)
|
|
print('\nNo. of options: ' + str(len(xs)))
|
|
|
|
|
|
# GENERIC ABSTRACTIONS ------------------------------------
|
|
|
|
# bind (>>=) :: [a] -> (a -> [b]) -> [b]
|
|
def bind(xs):
|
|
'''List monad injection operator.
|
|
Two computations sequentially composed,
|
|
with any value produced by the first
|
|
passed as an argument to the second.'''
|
|
return lambda f: list(
|
|
chain.from_iterable(
|
|
map(f, xs)
|
|
)
|
|
)
|
|
|
|
|
|
# curry :: ((a, b) -> c) -> a -> b -> c
|
|
def curry(f):
|
|
'''A curried function derived
|
|
from an uncurried function.'''
|
|
return lambda a: lambda b: f(a, b)
|
|
|
|
|
|
# enumFromTo :: (Int, Int) -> [Int]
|
|
def enumFromTo(m):
|
|
'''Integer enumeration from m to n.'''
|
|
return lambda n: list(range(m, 1 + n))
|
|
|
|
|
|
# even :: Int -> Bool
|
|
def even(x):
|
|
'''True if x is an integer
|
|
multiple of two.'''
|
|
return 0 == x % 2
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|