Main.hs 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. module Main where
  2. import Numeric (showHex)
  3. import Data.List (isInfixOf, genericIndex)
  4. import Data.List.Split(splitOn)
  5. import Text.Read (readMaybe)
  6. import System.IO (hFlush, stdout)
  7. hexPi :: Integer -> Char
  8. hexPi n =
  9. let
  10. summation = (4 * sumPi n 1) - (2 * sumPi n 4) - (sumPi n 5) - (sumPi n 6)
  11. skimmedSum = summation - (fromIntegral (floor summation :: Integer))
  12. in
  13. showHex (floor (16 * skimmedSum) :: Integer) "" !! 0
  14. sumPi :: Integer -> Integer -> Double
  15. sumPi n x =
  16. let
  17. summation1 = [(fromIntegral ((16^(n-k) `mod` ((8*k)+x)))) / (fromIntegral ((8*k)+x)) | k <- [0..n]]
  18. -- 5000 is used in place of Infinity. This value drops off quickly, so no need to go too far.
  19. summation2 = [16^^(n-k) / (fromIntegral ((8*k)+x)) | k <- [(n+1)..5000]]
  20. in
  21. sum $ summation1 ++ summation2
  22. rangePi :: Maybe Integer -> Maybe Integer -> IO ()
  23. rangePi num1 num2 = do
  24. case (num1, num2) of
  25. (Just one, Just two) ->
  26. if one >= two then
  27. putStrLn "Please give a proper range."
  28. else
  29. putStrLn $ foldr (:) [] (drop (fromIntegral one) . take (fromIntegral two) $ hexDigits)
  30. (_,_) -> putStrLn "Error: Please give an Integer (ex: 3) or a range (ex: 3..5)."
  31. prompt :: IO ()
  32. prompt = do
  33. putStr ":: "
  34. hFlush stdout
  35. response <- getLine
  36. -- Check if response is range, or single digit.
  37. if (isInfixOf ".." response) then
  38. let
  39. range = splitOn ".." response
  40. in
  41. rangePi (readMaybe $ range !! 0 :: Maybe Integer) (readMaybe $ range !! 1 :: Maybe Integer)
  42. else do
  43. case (readMaybe response :: Maybe Integer) of
  44. Nothing -> putStrLn "Error: Please give an Integer (ex: 3) or a range (ex: 3..5)."
  45. Just x -> putStrLn $ hexDigits `genericIndex` x :[]
  46. prompt
  47. -- Establish the list of answers
  48. hexDigits :: [Char]
  49. hexDigits = [hexPi x | x <- [0..]]
  50. main :: IO ()
  51. main = do
  52. putStrLn "Enter a digit or range (Ctrl-C to exit)"
  53. prompt