Faulhaber's formula: Difference between revisions

Content added Content deleted
(→‎Haskell: Replaced Control.Arrow with bimap and an applicative. Tidied.)
Line 937: Line 937:
<lang Haskell>import Data.Ratio ((%), numerator, denominator)
<lang Haskell>import Data.Ratio ((%), numerator, denominator)
import Data.List (intercalate, transpose)
import Data.List (intercalate, transpose)
import Control.Arrow ((&&&), (***))
import Data.Bifunctor (bimap)
import Data.Char (isSpace)
import Data.Char (isSpace)
import Data.Monoid ((<>))
import Data.Monoid ((<>))
import Data.Bool (bool)
import Data.Bool (bool)

-- FAULHABER ----------------------------------------------
------------------------- FAULHABER ------------------------
faulhaber :: [[Rational]]
faulhaber :: [[Rational]]
faulhaber =
faulhaber =
Line 952: Line 952:
[]
[]
[0 ..]
[0 ..]
---------------------------- TEST --------------------------
main :: IO ()
main = (putStrLn . unlines . expressionTable . take 10) polynomials


-- EXPRESSION STRINGS -------------------------------------
--------------------- EXPRESSION STRINGS -------------------
polynomials :: [[(String, String)]]
polynomials = fmap ((ratioPower =<<) . reverse . flip zip [1 ..]) faulhaber


-- Rows of (Power string, Ratio string) tuples -> Printable lines
-- Rows of (Power string, Ratio string) tuples -> Printable lines
Line 967: Line 970:
zipWith
zipWith
(\(lw, rw) col ->
(\(lw, rw) col ->
(fmap (justifyLeft lw ' ' *** justifyLeft rw ' ') col))
fmap (bimap (justifyLeft lw ' ') (justifyLeft rw ' ')) col)
(colWidths cols)
(colWidths cols)
cols)
cols)

polynomials :: [[(String, String)]]
polynomials = fmap ((ratioPower =<<) . reverse . flip zip [1 ..]) faulhaber
-- Value pair -> String pair (lifted into list for use with >>=)
-- Value pair -> String pair (lifted into list for use with >>=)
ratioPower :: (Rational, Integer) -> [(String, String)]
ratioPower :: (Rational, Integer) -> [(String, String)]
ratioPower (nd, j) =
ratioPower (nd, j) =
let (num, den) = (numerator &&& denominator) nd
let (num, den) = ((,) . numerator <*> denominator) nd
sn
sn
| num == 0 = []
| num == 0 = []
Line 986: Line 992:
s = sr <> sn
s = sr <> sn
in bool [(sn, sr)] [] (null s)
in bool [(sn, sr)] [] (null s)

-- Rows of uneven length -> All rows padded to length of longest
-- Rows of uneven length -> All rows padded to length of longest
fullTable :: [[(String, String)]] -> [[(String, String)]]
fullTable :: [[(String, String)]] -> [[(String, String)]]
Line 992: Line 998:
let lng = maximum $ length <$> xs
let lng = maximum $ length <$> xs
in (<>) <*> (flip replicate ([], []) . (-) lng . length) <$> xs
in (<>) <*> (flip replicate ([], []) . (-) lng . length) <$> xs

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

-- (Row index, Expression pairs) -> String joined by conjunctions
-- (Row index, Expression pairs) -> String joined by conjunctions
expressionRow :: (Int, [(String, String)]) -> String
expressionRow :: (Int, [(String, String)]) -> String
Line 1,007: Line 1,013:
(polyTerm <$> row)
(polyTerm <$> row)
]
]

-- (Power string, Ratio String) -> Combined string with possible '*'
-- (Power string, Ratio String) -> Combined string with possible '*'
polyTerm :: (String, String) -> String
polyTerm :: (String, String) -> String
Line 1,014: Line 1,020:
| head r == '-' = concat ["- ", l, " * ", tail r]
| head r == '-' = concat ["- ", l, " * ", tail r]
| otherwise = intercalate " * " [l, r]
| otherwise = intercalate " * " [l, r]

blank :: String -> Bool
blank :: String -> Bool
blank = all isSpace
blank = all isSpace

-- Maximum widths of power and ratio elements in each column
-- Maximum widths of power and ratio elements in each column
colWidths :: [[(String, String)]] -> [(Int, Int)]
colWidths :: [[(String, String)]] -> [(Int, Int)]
Line 1,025: Line 1,031:
(\(ls, rs) (lMax, rMax) -> (max (length ls) lMax, max (length rs) rMax))
(\(ls, rs) (lMax, rMax) -> (max (length ls) lMax, max (length rs) rMax))
(0, 0))
(0, 0))

-- Length of string excluding any leading '-'
-- Length of string excluding any leading '-'
unsignedLength :: String -> Int
unsignedLength :: String -> Int
unsignedLength xs =
unsignedLength xs =
let l = length xs
let l = length xs
in bool (bool l (l - 1) ('-' == head xs)) 0 (0 == l)
in bool (bool l (l - 1) ('-' == head xs)) 0 (0 == l)</lang>

-- TEST ---------------------------------------------------
main :: IO ()
main = (putStrLn . unlines . expressionTable . take 10) polynomials</lang>
{{Out}}
{{Out}}
<pre>0 -> n
<pre>0 -> n