Department numbers: Difference between revisions

Content added Content deleted
(Added Algol W)
(→‎{{header|Python}}: Updated bind, pylinted for Python 3, added subheaders.)
Line 1,935: Line 1,935:


=={{header|Python}}==
=={{header|Python}}==
===Procedural===
<lang python>from itertools import permutations
<lang python>from itertools import permutations
Line 1,966: Line 1,967:
14: 6 5 1 </pre>
14: 6 5 1 </pre>


===Composition of pure functions===
Or, expressing the options directly and declaratively in terms of '''reduce''' and '''add''', without importing permutations:
Expressing the options directly and declaratively in terms of a ''bind'' operator, without importing ''permutations'':
{{Works with|Python|3}}
<lang python>'''Department numbers'''


<lang python>from functools import (reduce)
from itertools import (chain)
from operator import (add)
from operator import (ne)




# options :: Int -> Int -> Int -> [(Int, Int, Int)]
# options :: Int -> Int -> Int -> [(Int, Int, Int)]
def options(lo, hi, total):
def options(lo, hi, total):
'''Eligible integer triples.'''
ds = range(lo, 1 + hi)
ds = enumFromTo(lo)(hi)
return bind(filter(lambda x: 0 == x % 2, ds))(
lambda x: bind(filter(lambda d: d != x, ds))(
return bind(filter(even, ds))(
lambda x: bind(filter(curry(ne)(x), ds))(
lambda y: bind([total - (x + y)])(
lambda y: bind([total - (x + y)])(
lambda z: [(x, y, z)] if (
lambda z: [(x, y, z)] if (
z != y and z >= lo and z <= hi
z != y and lo <= z <= hi
) else []
) else []
)
)
Line 1,987: Line 1,992:


# TEST ----------------------------------------------------
# TEST ----------------------------------------------------


# main :: IO ()
# main :: IO ()
def main():
def main():
'''Test'''

xs = options(1, 7, 12)
xs = options(1, 7, 12)
print (('Police', 'Sanitation', 'Fire'))
print(('Police', 'Sanitation', 'Fire'))
for tpl in xs:
for tpl in xs:
print (tpl)
print(tpl)
print ('\nNo. of options: ' + str(len(xs)))
print('\nNo. of options: ' + str(len(xs)))




# GENERIC ABSTRACTION -------------------------------------
# GENERIC ABSTRACTIONS ------------------------------------


# bind (>>=) :: [a] -> (a -> [b]) -> [b]
# bind (>>=) :: [a] -> (a -> [b]) -> [b]
def bind(xs):
def bind(xs):
'''List monad injection operator.
return lambda f: reduce(add, map(f, xs), [])
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
main()</lang>
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()</lang>
{{Out}}
{{Out}}
<pre>('Police', 'Sanitation', 'Fire')
<pre>('Police', 'Sanitation', 'Fire')