McNuggets problem: Difference between revisions

→‎Python - List monad in parallel to comprehension: Pylinted, tidied, updated output, added {Works with} tag
No edit summary
(→‎Python - List monad in parallel to comprehension: Pylinted, tidied, updated output, added {Works with} tag)
Line 855:
 
Note that the innermost function wraps its results in a (potentially empty) list. The resulting list of lists, some empty, is then flattened by the concatenation component of '''bind'''.
 
{{Works with|Python|3.7}}
<lang python>'''mcNuggets list monad'''
 
Line 860 ⟶ 862:
 
 
# mcNuggetsByListMonad :: Int -> Set Int
def main():
def mcNuggetsByListMonad(limit):
'''List monad equivalent of the list comprehension.'''
'''McNugget numbers up to limit.'''
 
defbox = size(nlimit):
return enumFromThenToset(0)bind(nbox(6))(100)
lambda x:
 
# List monad version bind(box(9))(
lambda y:
mcNuggets1 = (
bind(size(6))(
lambda x:
bind(size(9))(
lambda y:
bind(size(20))(
lambda z: (
lambda v=sum([x, y, z]): (
[v] if v <= 100 else []
)
)())))
)
 
bind(box(20))(
# List comprehension version
mcNuggets2 = [v for v in lambda z: (
sum([x, y, z])
for x in size(6)
for y in size(9)
for z in size(20)
) if v <= 100]
 
lambda v=sum([x, y, z]): (
def test(xs):
[] if v > limit else [v]
ys = list(dropwhile(
lambda x: x in xs, )
enumFromThenTo(100 )(99)(1))))
))
return ys[0] if ys else (
'No unreachable quantities found in this range.'
)
 
for xs in [mcNuggets1, mcNuggets2]:
print(
test(xs)
)
 
# Which, for comparison, is equivalent to:
 
# mcNuggetsByComprehension :: Int -> Set Int
# GENERIC ABSTRACTIONS ------------------------------------
def mcNuggetsByComprehension(limit):
'''McNuggets numbers up to limit'''
box = size(limit)
return {
v for v in (
sum([x, y, z])
for x in box(6)
for y in box(9)
for z in box(20)
) if v <= limit
}
 
 
# size :: Int -> Int -> [Int]
def size(limit):
'''Multiples of n up to limit.'''
return lambda n: enumFromThenTo(0)(n)(limit)
 
 
# TEST -----------------------------------------------------------
def main():
'''List monad and set comprehension - parallel routes'''
 
def test(limit):
def go(nuggets):
ys = list(dropwhile(
lambda x: x in nuggets,
enumFromThenTo(limit)(limit - 1)(1)
))
return str(ys[0]) if ys else (
'No unreachable targets in this range.'
)
return lambda nuggets: go(nuggets)
 
def fName(f):
return f.__name__
 
limit = 100
print(
fTable(main.__doc__ + ':\n')(fName)(test(limit))(
lambda f: f(limit)
)([mcNuggetsByListMonad, mcNuggetsByComprehension])
)
 
 
# GENERIC ABSTRACTIONS ------------------------------------
 
# bind (>>=) :: [a] -> (a -> [b]) -> [b]
Line 911 ⟶ 937:
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(
Line 921 ⟶ 948:
# enumFromThenTo :: Int -> Int -> Int -> [Int]
def enumFromThenTo(m):
'''List of integerInteger values enumerated from m to n
with a step defined by nxt - m.'''
'''
return lambda next: lambda n: (
def listgo(range(mnxt, 1 + n, next - m)):
d = nxt - m
return range(m, n - 1 if d < 0 else 1 + n, d)
return lambda nxt: lambda n: list(go(nxt, n))
 
 
# FORMATTING ----------------------------------------------
 
# fTable :: String -> (a -> String) ->
# (b -> String) -> (a -> b) -> [a] -> String
def fTable(s):
'''Heading -> x display function -> fx display function ->
f -> xs -> tabular string.
'''
def go(xShow, fxShow, f, xs):
ys = [xShow(x) for x in xs]
w = max(map(len, ys))
return s + '\n' + '\n'.join(map(
lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),
xs, ys
))
return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
xShow, fxShow, f, xs
)
 
 
# MAIN ---
if __name__ == '__main__':
main()</lang>
{{Out}}
<pre>43
List monad and set comprehension - parallel routes:
43</pre>
 
mcNuggetsByListMonad -> 43
mcNuggetsByComprehension -> 43</pre>
 
=={{header|REXX}}==
9,659

edits