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> |
<lang python>'''Multiplication table''' |
||
from functools import (reduce) |
|||
from operator import (le, mul) |
|||
# |
# mulTable :: Int -> String |
||
def |
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))), |
|||
xs = enumFromTo(1)(n) |
|||
return unlines([ |
|||
filter( |
|||
str(y).rjust(2, ' ') + ': ' + unwords([ |
|||
str(x * y).rjust(3, ' ') if x >= y |
|||
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(): |
||
'''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) |
|||
# |
# 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> |
<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 |
|||
3: 9 12 15 18 21 24 27 30 33 36 |
|||
4: 16 20 24 28 32 36 40 44 48 |
|||
5: 25 30 35 40 45 50 55 60 |
|||
6: 36 42 48 54 60 66 72 |
|||
7: 49 56 63 70 77 84 |
|||
8: 64 72 80 88 96 |
|||
9: 81 90 99 108 |
|||
10: 100 110 120 |
|||
11: 121 132 |
|||
12: 144</pre> |
|||
=={{header|R}}== |
=={{header|R}}== |