项目Euler#4使用Haskell

时间:2012-08-20 19:30:54

标签: haskell

我希望通过粘贴并运行“runghc euler4.hs 1000”来实现这一点。由于我很难学习Haskell,有人可以告诉我如何在这里改进吗?特别是那些“来自整体”的人都是一团糟。

module Main where
import System.Environment

main :: IO ()
main = do 
    args <- getArgs
    let 
        hBound = read (args !! 0)::Int
        squarePal = pal hBound
        lBound = floor $ fromIntegral squarePal / 
                   (fromIntegral hBound / fromIntegral squarePal)
        euler = maximum $ takeWhile (>squarePal) [ x | y <- [lBound..hBound], 
                                                       z <- [y..hBound],
                                                       let x = y * z,
                                                       let s = show x,
                                                       s == reverse s ]
    putStrLn $ show euler

pal :: Int -> Int
pal n
    | show pow == reverse (show pow) = n
    | otherwise = pal (n-1)
    where
        pow = n^2

2 个答案:

答案 0 :(得分:1)

如果您想要的是整数除法,则应使用div而不是来回转换为Integral以使用普通/

module Main where                                                              
import System.Environment                                                      

main :: IO ()                                                                  
main = do                                                                      
    (arg:_) <- getArgs                                                         
    let                                                                        
        hBound = read arg :: Int                                               
        squarePal = pal hBound                                                 
        lBound = squarePal * squarePal `div` hBound                            
        euler = maximum $ takeWhile (>squarePal) [ x | y <- [lBound..hBound],
                                                       z <- [y..hBound],       
                                                       let x = y * z,          
                                                       let s = show x,         
                                                       s == reverse s ]        
    print euler                                                                

pal :: Int -> Int                                                              
pal n                                                                          
    | show pow == reverse (show pow) = n                                       
    | otherwise = pal (n - 1)                                                  
    where                                                                      
        pow = n * n                                                            

(我重新编写了使用两个lbound的{​​{1}}表达式,修复了/突出显示的一些样式问题。)

答案 1 :(得分:0)

好的,有几件事:

首先,传递这个问题的下限和上限可能会更好,它会使它更具扩展性。

如果您只使用CL中的前两个(前一个案例中的一个)参数,我们可以轻松处理这种模式匹配并避免像(args !! 0)这样的令人讨厌的语句:

(arg0:arg1:_) <- getArgs

让我们将这些转换为Int s:

let [a, b] = map (\x -> read x :: Int) [arg0,arg1]

现在我们可以引用ab,我们的上限和下限。 接下来,让我们创建一个函数,遍历上限和下限之间的所有数字,并获取其产品列表:

products a b = [x*y | x <- [a..b], y <- [x..b]]

我们不必将每个号码重复两次,因此我们在当前x处开始y以获取所有不同的产品。

从这里开始,我们想要制作一个过滤掉某些数据集中非回文的方法:

palindromes xs = filter palindrome xs
  where palindrome x = show x == reverse $ show x

最后,在我们的主要功能中:

print . maximum . palindromes $ products a b

如果您想查看完整代码,请参阅以下内容:

import System.Environment
main = do
  (arg0:arg1:_) <- getArgs
  let [a, b] = map (\x -> read x :: Int) [arg0,arg1]
  print . maximum . palindromes $ products a b

products a b = [x*y | x <- [a..b], y <- [x..b]]

palindromes = filter palindrome
  where palindrome x = (show x) == (reverse $ show x)