Kaprekar的例程 - Haskell实现

时间:2015-03-30 05:17:07

标签: list haskell recursion subroutine

我对Haskell有点麻烦。我正在实施Kaprekar的例行程序(http://en.wikipedia.org/wiki/6174_%28number%29),我已经完成了所有工作,但能够成功打印例程生成的数字列表。所以,如果我输入数字5432,我希望输出为[5432,3087,8352,6174]。

这是我的代码:

kaprekarList :: Integer -> [Integer]

kaprekarList x = n
  where p = kaprekar x
        n =
          if p == 6174
              then [p]
              else
                -- add to list of kaprekar numbers
                kaprekarList p

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:2)

虽然不是最美丽的例程(并且有一个小问题见下文),你的工作似乎有效(如果kaprekar函数有效),所以我猜你的问题确实存在。

以下是与您的功能一起使用的简单实现:

kaprekar :: Integer -> Integer
kaprekar n = big - small
  where big = read digits
        small = read (reverse digits)
        digits = take 4 $ (reverse . sort . show $ n) ++ "0000"

kaprekarList :: Integer -> [Integer]
kaprekarList x = n
  where p = kaprekar x
        n =
          if p == 6174
              then [x, p]
              else
                -- add to list of kaprekar numbers
                x : kaprekarList p

请注意小的更改,以便您可以看到完整的派生,而不仅仅是最后一个元素(始终是固定的)。

替代版本

kaprekarList :: Integer -> [Integer]
kaprekarList x = x : if x == 6174 then [] else kaprekarList (kaprekar x)

这个似乎有点习惯但不包括最后的6174

kaprekarList :: Integer -> [Integer]
kaprekarList x = takeWhile (/= 6174) $ iterate kaprekar x

这个人会(但是很难看 - 也许有人在前奏中知道takeUntil之类的东西?):

kaprekarList :: Integer -> [Integer]
kaprekarList x = (takeWhile (/= 6174) $ iterate kaprekar x) ++ [6174]

答案 1 :(得分:1)

这是一个实现:

import Data.List (sort)

-- Convert a number to a list of digits
digits :: Integral x => x -> [x]
digits 0 = []
digits x = digits (x `div` 10) ++ [x `mod` 10]

-- Convert a list of digits to a number
undigits :: Integral x => [x] -> x
undigits = foldl (\ a b -> a * 10 + b) 0

-- Compute the next Kaprekar number
nextKapNumber :: Integral x => x -> x
nextKapNumber x = b - a
  where n = sort . digits $ x
        a = undigits n
        b = undigits . reverse $ n

-- Compute the Kaprekar list for a number
kapList :: Integral x => x -> [x]
kapList x = genList [x]
  where genList as@(6174:_) = reverse as
        genList as@(a:_)    = genList $ nextKapNumber a : as

main :: IO ()
main = putStrLn . show $ kapList 5432