Haskell函数关于偶数和奇数

4

我不久前开始学习Haskell,对一个我正在尝试创建的函数有疑问。

我想要创建一个函数,验证x是否是n的因数(例如:375的因数为1、3、5、15、25、75、125和375),接着移除1和该数字本身,然后验证该列表中奇数的数量是否等于偶数的数量!

我考虑创建以下函数来计算第一部分:

factor n = [x | x <- [1..n], n `mod`x == 0]

但如果我在提示符上输入这个,它会说“未定义'n'”。我的想法是输入一个数字,比如375,然后计算列表。我做错了什么?我看过书中将函数放在提示符中的例子。
然后,为了获取我所说的元素,我考虑使用tail和init来获取列表。你认为这是个好主意吗?
最后,我想用if语句来验证最后一部分。例如,在Java中,我们会做出类似以下的内容:
(x % 2 == 0)? even++ : odd++; // (I'm a beginner to Java as well)

如果偶数等于奇数,那么就会说所有条件都得到了验证(我们有相同数量的偶数和奇数)。

但在Haskell中,由于变量是不可变的,我该如何执行something++操作呢?

感谢您能给予的任何帮助:)


你必须使用递归。http://learnyouahaskell.com/recursion - elimirks
5个回答

5
这个小函数可以完成你想要实现的所有功能:
f n = length evenFactors == length oddFactors
  where evenFactors = [x | x <- [2, 4..(n-1)], n `mod` x == 0]
        oddFactors  = [x | x <- [3, 5..(n-1)], n `mod` x == 0]

4
如果“命令行”是ghci,则需要执行以下操作:
let factor n = [x | x <- [2..(n-1)], n `mod` x == 0]

在这种情况下,您不需要范围为[1..n]而只是跳过1和n - 范围从2到(n-1)。
然后,您可以使用分区来使用布尔谓词拆分约数列表。
import Data.List
partition odd $ factor 10

为了学习如何编写像partition这样的函数,请学习递归。
例如:
partition p = foldr f ([],[]) where
  f x ~(ys,ns) | p x = (x:ys,ns)
  f x ~(ys,ns) = (ys, x:ns)

在这里,我们需要使用“~”来惰性地模式匹配元组,以确保在右侧创建元组之前不会评估模式。

甚至可以更加简单地实现简单计数:

let y = factor 375
(length $ filter odd y) == (length y - (length $ filter odd y))

所以,我可以直接应用最后一部分,而不是分区,对吧?“让 y = factor 375(length $ filter odd y)==(length y -(length $ filter odd y))”?感谢您的回答:D - BVCGAAV
是的,但是分区可能会有更高的成本,因为我们要遍历y两次(一次用于过滤,一次用于长度),并且遍历过滤后的列表一次;而分区将遍历y两次(一次用于分区,一次用于计算长度)。我已经进行了编辑,以惰性地匹配成对项,这对于分区长列表是必要的。 - Sassa NF

2
创建一个文件source.hs,然后在ghci命令行中调用:l source来加载source.hs中定义的函数。
为解决您的问题,按照以下步骤进行操作可能是一种解决方案:
-- computers the factors of n, gets the tail (strips 1)
-- the filter functions removes n from the list
factor n = filter (/= n) (tail [x | x <- [1..n], n `mod` x == 0])

-- checks if the number of odd and even factors is equal
oe n = let factors = factor n in 
           length (filter odd factors) == length (filter even factors)

调用 oe 10 返回 True,调用 oe 15 返回 False


专注于这个想法:mytest n = length (evenNumbers (chopEnds (factors n))) == length (oddNumbers (chopEnds (factors n))) - SomeName
@pNre 我有一个小问题,在这段代码中:oe n = let factors = factor n in,'in' 的作用是什么?谢谢 :) - BVCGAAV
我相信这个教程会有帮助。 - pNre
“let”和“in”只是给一些表达式另一个名称,这样您就不必输入那么多。您还可以使用它来使某些内容更清晰。另一个例子:mytest n = let choppedFactors = chopEnds (factors n) in length (evenNumbers choppedFactors) == length (oddNumbers choppedFactors)。请阅读http://learnyouahaskell.com/。里面都有。 - SomeName

2
(x % 2 == 0)? even++ : odd++;

我们在 Data.List 中有一个 partition :: (a -> Bool) -> [a] -> ([a], [a]) 函数。因此,我们可以像这样分割奇数:
> let (odds,evens) = partition odd [1..]

> take 10 odds
 [1,3,5,7,9,11,13,15,17,19]
> take 10 evens
 [2,4,6,8,10,12,14,16,18,20]

0

这里是使用推导式对您的factor尝试进行最小修复的方法:

factor nn = [x | n <- [1..nn], x <- [1..n], n `mod`x == 0]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接