Multiplication tables: Difference between revisions

Content added Content deleted
(→‎{{header|Python}}: Simplified the functional variant, defining a string in terms of a list comprehension.)
Line 4,130: Line 4,130:




Or, as a string defined by a list comprehension:
Or, separating model from view, and composing from generic functions:


<lang python>from itertools import (groupby)
<lang python>'''Multiplication table'''
from functools import (reduce)
from operator import (le, mul)




# table :: Int -> [(Int, [Int])]
# mulTable :: Int -> String
def table(n):
def mulTable(n):
'''A multiplication table of dimension n,
return list(
without redundant entries beneath
map(
the diagonal of squares.'''
fmapTuple(lambda x: list(map(uncurry(mul), x))),
groupby(
xs = enumFromTo(1)(n)
return unlines([
filter(
uncurry(le),
str(y).rjust(2, ' ') + ': ' + unwords([
joinFn(cartesianProduct)(
str(x * y).rjust(3, ' ') if x >= y
enumFromTo(1)(n)
else ' ' for x in xs
)
]) for y in xs
),
])
fst
)
)
)


# showTable :: [(Int, [Int])] -> String
def showTable(xs):
mx = xs[-1]
colW = 1 + len(str(mx[1][-1]))
tab = ' ' * colW
padIndex = justifyRight(1 + len(str(fst(mx))))(' ')
padCol = justifyRight(colW)(' ')

return unlines(
map(
lambda x: padIndex(str(fst(x))) + ':' +
tab * (fst(x) - 1) + concatMap(
lambda n: padCol(str(n))
)(
snd(x)
),
xs
)
)




# TEST ----------------------------------------------------
# main :: IO ()
# main :: IO ()
def main():
def main():
print (
'''Test'''
showTable(
table(12)
)
)


print(

mulTable(12)
# GENERIC FUNCTIONS -------------------------------------

# apList (<*>) :: [(a -> b)] -> [a] -> [b]
def apList(fs):
return lambda xs: reduce(
lambda a, f: a + reduce(
lambda a, x: a + [f(x)], xs, []
), fs, []
)
)




# GENERIC -------------------------------------------------
# bindFn :: (a -> b) -> (b -> c) -> a -> c
def bindFn(m):
return lambda mf: lambda x: mf(lambda y: m(x)(y))(x)




# cartesianProduct :: [a] -> [b] -> [(a, b)]
# enumFromTo :: (Int, Int) -> [Int]
def cartesianProduct(xs):
return lambda ys: apList(
map(lambda x: lambda y: (x, y), xs)
)(ys)


# concatMap :: (a -> [b]) -> [a] -> [b]
def concatMap(f):
return lambda xs: (
xs if not xs else reduce(
lambda a, b: a + b, map(f, xs), '')
)


# enumFromTo :: Int -> Int -> [Int]
def enumFromTo(m):
def enumFromTo(m):
'''Integer enumeration from m to n.'''
return lambda n: list(range(m, 1 + n))
return lambda n: list(range(m, 1 + n))


# fmapTuple (<$>) :: (a -> b) -> (a, a) -> (a, b)
def fmapTuple(f):
return lambda tpl: (fst(tpl), f(snd(tpl)))


# fst :: (a, b) -> a
def fst(tpl):
return tpl[0]


# join :: Monad m => m (m a) -> m a
def joinFn(f):
return bindFn(f)(lambda x: x)


# justifyRight :: Int -> Char -> String -> String
def justifyRight(n):
return lambda cFiller: lambda s: (
((n * cFiller) + s)[-n:]
)


# snd :: (a, b) -> b
def snd(tpl):
return tpl[1]


# uncurry :: (a -> b -> c) -> ((a, b) -> c)
def uncurry(f):
return lambda xy: f(fst(xy), snd(xy))




# unlines :: [String] -> String
# unlines :: [String] -> String
def unlines(xs):
def unlines(xs):
'''A newline-delimited string derives from a list of lines.'''
return '\n'.join(xs)
return '\n'.join(xs)




# unwords :: [String] -> String
# MAIN ---
def unwords(xs):
main()</lang>
'''A space-delimited string derived from a list of words.'''
return ' '.join(xs)


if __name__ == '__main__':
main()</lang>
{{Out}}
{{Out}}
<pre> 1: 1 2 3 4 5 6 7 8 9 10 11 12
<pre> 1: 1 2 3 4 5 6 7 8 9 10 11 12
2: 4 6 8 10 12 14 16 18 20 22 24
2: 4 6 8 10 12 14 16 18 20 22 24
3: 9 12 15 18 21 24 27 30 33 36
3: 9 12 15 18 21 24 27 30 33 36
4: 16 20 24 28 32 36 40 44 48
4: 16 20 24 28 32 36 40 44 48
5: 25 30 35 40 45 50 55 60
5: 25 30 35 40 45 50 55 60
6: 36 42 48 54 60 66 72
6: 36 42 48 54 60 66 72
7: 49 56 63 70 77 84
7: 49 56 63 70 77 84
8: 64 72 80 88 96
8: 64 72 80 88 96
9: 81 90 99 108
9: 81 90 99 108
10: 100 110 120
10: 100 110 120
11: 121 132
11: 121 132
12: 144</pre>
12: 144</pre>


=={{header|R}}==
=={{header|R}}==