Haskell:使用数组参数进行递归

时间:2009-03-16 23:27:17

标签: haskell recursion

免责声明:我是Haskell的新手,我不记得很多关于大学的FP,所以我的代码可能会有一两个以上的错误。这也是我的欧拉问题3的代码。

我试图递归调用一个函数,其中两个数组作为参数,一个数组作为结果。

目标:

  • 假设此问题的n为10
  • 创建一个从1到n的所有自然数的列表(变量是'allNumbers'是代码)
  • 创建从1到n的所有自然数的另一个列表(变量是'allFactors'是代码)
  • 取'allFactors'中的第一个元素,并将'allFactors'的其余数字乘以此数字。 (这会生成一组数字)
  • 从'allNumbers'
  • 中删除所有这些数字
  • 从1继续到n,直到'allFactors'为空。

这是我的代码:

mkList :: Int -> [Int]
mkList n = [1..n-1]

modArray :: Int -> Int -> [Int]
modArray a b =  [ x*b | x <- [1..a], x `mod` b == 0] 

modArrayAll :: [Int] -> [Int] -> [Int]
modArrayAll [] [] = [] 
modArrayAll (x:xs) (y:ys) = (e) 
    where
        m = head( ys)
        n = length( xs)
        e = (modArrayAll xs ys ) \\ modArray n m

(主要)

let allNumbers =  mkList (first + 1)
let allFactors = mkList (first + 1)
let mainList2 =  modArrayAll allNumbers allFactors

这会产生一个空列表。但是,如果我有:

e = xs \\ modArray n m  --WORKS for one iteration

我从1到10得到所有奇数。

我的问题:为什么这不按照我期望的方式工作?我希望递归堆栈会达到空数组条件并返回一个空数组,该数组不会从调用数组中删除,它会继续只返回素数?

2 个答案:

答案 0 :(得分:5)

我复制了您的目标说明:

-- assume n is 10 for this question
n=10

-- create a list of all natural numbers from 1 to n (variable is 'allNumbers' is code)
allNumbers = [1..n]

-- create another list of all natural numbers from 1 to n (variable is 'allFactors' is code)
allFactors = [2..n] -- i suspect you really wanted this rather than [1..n]

-- take the first element in 'allFactors' and
-- multiply the rest of the numbers of 'allFactors' by this number.
-- (this generates an array of numbers)
-- continue from 1 to n until 'allFactors' is empty
factorProducts = [ x*y | x <- allFactors, y <- allFactors]

--  remove all these numbers from 'allNumbers'
whatYouWanted = allNumbers \\ factorProducts

此刻,你似乎还在思考一种相当强制性的思维模式。尝试更多地考虑你想要的东西,而不是如何得到它:)

答案 1 :(得分:1)

modArray n m创建一个m的倍数列表,然后将其从整数的“主列表”中删除。但modArray n m包含1*m,因此每个号码都会被移除,因为它本身就是“倍数”。在您的测试用例中,您只得到奇数,而您希望2仍然在结果列表中。此外,1还包含在您的因子列表中,这将消除所有数字,因为它们都是1的倍数。

递归的终止案例是modArrayAll [] [] = [],因此返回一个空列表。然后在周围的递归调用中,此处使用此返回值:

(modArrayAll xs ys) \\ modArray n m

这会尝试从modArray n m返回的已空列表中删除其他元素(modArrayAll xs ys返回的元素)。不会在任何地方添加新元素,结果列表将保持为空。使用您的算法,您希望[] - case返回整个数字列表,而不是空数字。然后周围递归函数调用中的\\ modArray n m可以过滤掉越来越多的非素因子。