Faulhaber's triangle: Difference between revisions

Content added Content deleted
(→‎{{header|Haskell}}: Tidied, replaced an Arrow with an Applicative.)
Line 945: Line 945:


=={{header|Haskell}}==
=={{header|Haskell}}==
{{works with|GHC|7.10.3}}
{{works with|GHC|8.6.4}}
<lang haskell>import Data.Ratio (Ratio, numerator, denominator, (%))
<lang haskell>import Data.Ratio (Ratio, numerator, denominator, (%))
import Control.Arrow ((&&&))


-- FAULHABER -------------------------------------------------------------------
------------------------ FAULHABER -----------------------

-- Infinite list of rows of Faulhaber's triangle
-- Infinite list of rows of Faulhaber's triangle
faulhaberTriangle :: [[Rational]]
faulhaberTriangle :: [[Rational]]
Line 965: Line 965:
faulhaber p n = sum (zipWith ((*) . (n ^)) [1 ..] (faulhaberTriangle !! p))
faulhaber p n = sum (zipWith ((*) . (n ^)) [1 ..] (faulhaberTriangle !! p))


-- DISPLAY ---------------------------------------------------------------------
-- (Max numerator+denominator widths) -> Column width -> Filler -> Ratio -> String
justifyRatio :: (Int, Int) -> Int -> Char -> Rational -> String
justifyRatio (wn, wd) n c nd =
let [num, den] = [numerator, denominator] <*> [nd]
w = max n (wn + wd + 2) -- Minimum column width, or more if specified.
in if 1 == den
then center w c (show num)
else let (q, r) = quotRem (w - 1) 2
in concat
[ justifyRight q c (show num)
, "/"
, justifyLeft (q + r) c (show den)
]


--------------------------- TEST -------------------------
center, justifyLeft, justifyRight :: Int -> Char -> String -> String
center n c s =
let (q, r) = quotRem (n - length s) 2
in concat [replicate q c, s, replicate (q + r) c]

justifyLeft n c s = take n (s ++ replicate n c)

justifyRight n c s = drop (length s) (replicate n c ++ s)


-- List of Ratios -> (Max numerator width, Max denominator width)
maxWidths :: [[Rational]] -> (Int, Int)
maxWidths xss =
let widest f xs = maximum $ fmap (length . show . f) xs
in widest numerator &&& widest denominator $ concat xss

-- TEST ------------------------------------------------------------------------
main :: IO ()
main :: IO ()
main = do
main = do
Line 1,004: Line 976:
[ unlines ((justifyRatio widths 8 ' ' =<<) <$> triangle)
[ unlines ((justifyRatio widths 8 ' ' =<<) <$> triangle)
, (show . numerator) (faulhaber 17 1000)
, (show . numerator) (faulhaber 17 1000)
]</lang>
]

------------------------- DISPLAY ------------------------

-- (Max numerator+denominator widths) -> Column width -> Filler -> Ratio -> String
justifyRatio :: (Int, Int) -> Int -> Char -> Rational -> String
justifyRatio (wn, wd) n c nd = go $ [numerator, denominator] <*> [nd]
where
w = max n (wn + wd + 2) -- Minimum column width, or more if specified.
go [num, den]
| 1 == den = center w c (show num)
| otherwise =
let (q, r) = quotRem (w - 1) 2
in concat
[ justifyRight q c (show num)
, "/"
, justifyLeft (q + r) c (show den)
]

justifyLeft, justifyRight, center :: Int -> Char -> String -> String
justifyLeft n c s = take n (s <> replicate n c)

justifyRight n c = (drop . length) <*> (replicate n c <>)

center n c s =
let (q, r) = quotRem (n - length s) 2
pad = replicate q c
in concat [pad, s, pad, replicate r c]

-- List of Ratios -> (Max numerator width, Max denominator width)
maxWidths :: [[Rational]] -> (Int, Int)
maxWidths xss =
let widest f xs = maximum $ fmap (length . show . f) xs
in ((,) . widest numerator <*> widest denominator) $ concat xss</lang>
{{Out}}
{{Out}}
<pre> 1
<pre> 1