2

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

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
4

2 回答 2

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了使用两个 的表达式,/并修复了一些由 . 突出显示的样式问题hlint。)

于 2012-08-21T12:17:11.143 回答
0

好的,有几件事:

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

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

(arg0:arg1:_) <- getArgs

让我们将它们转换为Ints:

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

最后,在我们的 main 函数中:

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)
于 2012-08-21T19:39:11.710 回答