如何创建非重复的回文数字?

时间:2016-10-24 12:00:05

标签: haskell numbers

所以我正在尝试做一些事情,而我几乎就在那里,但我无法解决它的最后一部分。我必须制作一个代码,其中有人给出一个数字(让它变成22)我需要找到当我将两个小于22的数字相乘时所有的回文数:

  

查找a*ba < n && b < n的所有回文数字。但他们不能重演。

我得到了这个

calc :: Int -> [Int]
calc n = [a*b|a<-[1..n-1], b<-[a..n-1], a*b>10, reverse(show(a*b))==show(a*b)]

如果我们calc 22,结果应为

[11,22,33,44,55,66,77,88,99,171,121,252,272,323] 

但我正在

[11,22,33,44,55,66,77,88,99,171,121,252,252,272,323]

因为14x18 = 12x21 = 252。

我哪里出错了?

1 个答案:

答案 0 :(得分:0)

嗯,你必须确保每个数字都是唯一的。对于具有至少三个素因子(x * y * z = (x * y) * z = x * (y * z))的所有数字存在多个表示。因此,我们可以解决这个问题的一种方法是对它们进行主要因素分析和推理。但这可能是一种过度杀伤。

相反,我们可以使用一个函数来确保排序列表中的每个数字都是唯一的:

unique :: Eq a => [a] -> [a]
unique (x:y:xs) = if x == y then unique (y:xs) else x : unique (y:xs)
unique xs       = xs

(或者,使用unique = map head . group

现在,您可以使用sort中的Data.List,最终得到实际的calUniuqe

calcUnique :: Int -> [Int]
calcUnique = unique . sort . calc

但是,如果我们将回文检查移动到自己的函数中,我们可以使calc更容易阅读:

isPalindrome :: Int -> Bool
isPalindrome n = n > 10 && reverse n' == n'
  where n' = show n

calc :: Int -> [Int]
calc n = [a * b | a <- [1..n-1], b <- [a..n-1], isPalindrome (a * b)]