【问题标题】:Haskell function about even and odd numbers关于偶数和奇数的 Haskell 函数
【发布时间】:2013-09-22 17:17:28
【问题描述】:

我是 Haskell 的新手,几天前开始学习,我有一个关于我正在尝试制作的函数的问题。

我想创建一个函数来验证 x 是否是 n 的因子(例如:375 具有以下因子:1、3、5、15、25、 75、125 和 375),然后删除 1,然后删除数字本身,最后验证该列表中的奇数个数是否等于偶数个数!

我想制作一个这样的函数来计算第一部分:

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

但如果我把它放在提示符上,它会说Not in scope 'n'。这个想法是输入一个像 375 这样的数字,以便计算列表。我做错了什么?我在书中看到过类似这样的提示中的函数。

然后,为了获取我所说的元素,我正在考虑做 tail 然后 init 到列表中。你认为这是个好主意吗?

最后我想到了做一个 if 语句来验证最后一部分。例如,在 Java 中,我们会做这样的事情:

(x % 2 == 0)? even++ : odd++; // (I'm a beginner to Java as well)

然后如果偶数 = 奇数,那么它会说所有条件都已验证(我们的偶数数量等于奇数)

但是在 Haskell 中,由于变量是不可变的,我该怎么做 something++ 的事情?

感谢您提供的任何帮助:)

【问题讨论】:

标签: function haskell numbers


【解决方案1】:

这个小功能可以完成您想要实现的一切:

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]

【讨论】:

    【解决方案2】:

    如果“命令行”是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 =因子375(长度$过滤奇数y)==(长度y-(长度$过滤奇数y))”?并感谢您的回答:D
    • 是的,但是可能比分区成本更高,因为我们遍历 y 两次(一次用于过滤器,一次用于长度)并遍历过滤后的列表一次;而 partition 将遍历 y 两次(一次进行分区,一次两个分区都计算出长度)。我已经编辑以懒惰地对这些对进行模式匹配,这对于划分长列表是必要的。
    • 我明白了...谢谢 :D 这是一个非常有趣的解决方案
    【解决方案3】:

    创建一个文件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返回Trueoe 15返回False

    【讨论】:

    • 专注思路:mytest n = length (evenNumbers (chopEnds (factors n))) == length (oddNumbers (chopEnds (factors n)))
    • @pNre 在这一部分中我不太明白一件事:oe n = let factor = factor n in,它有什么作用?我的意思是,'in' 是做什么的?谢谢:)
    • 我相信this tutorial 会有所帮助
    • 'let' 和 'in' 只是给某个表达式取另一个名字,所以你不必输入太多。你也可以用它来使事情更清楚。另一个例子:mytest n = letchoppedFactors =choppedEnds (factors n) in length (evenNumbers ChoppedFactors) == length (oddNumbers ChoppedFactors) 就读learnyouahaskell.com 里面都有。
    【解决方案4】:
    (x % 2 == 0)? even++ : odd++;
    

    我们在Data.List 有一个partition :: (a -&gt; Bool) -&gt; [a] -&gt; ([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]
    

    【讨论】:

      【解决方案5】:

      以下是针对您的 factor 尝试使用推导式的最小修复:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-10
        • 1970-01-01
        • 1970-01-01
        • 2016-04-04
        • 1970-01-01
        • 1970-01-01
        • 2014-06-01
        • 1970-01-01
        相关资源
        最近更新 更多