【问题标题】:How to express {2n+3m+1|n,m∈N} in list comprehension form? (N is the set of natural numbers including 0){2n+3m+1|n,m∈N} 如何以列表理解的形式表达? (N是包括0的自然数集)
【发布时间】:2009-04-17 08:35:34
【问题描述】:

如何以列表理解的形式表达 {2n+3m+1|n,m∈N}? N是自然数的集合,包括0。

【问题讨论】:

标签: haskell list-comprehension


【解决方案1】:

很快:

1:[3..]

【讨论】:

  • 被要求使用列表理解。
【解决方案2】:

难道不是 {2n+3m+1|n,m ∈ ℕ} = ℕ - {0,2}?

【讨论】:

  • 和 2。你不能从 2*n + 3*m 得到 1
  • 是的,你是对的。但是除了这两个之外,任何 x > 2 ∈ N 都可以表示为 2n+3m+1
【解决方案3】:

以下 Haskell 函数将为您提供两个列表中的所有对,即使其中一个或两个是无限的。每对只出现一次:

allPairs :: [a] -> [b] -> [(a, b)]
allPairs _ [] = []
allPairs [] _ = []
allPairs (a:as) (b:bs) = 
   (a, b) : ([(a, b) | b <- bs] `merge` 
             [(a, b) | a <- as] `merge` 
             allPairs as bs)
  where merge (x:xs) l = x : merge l xs
        merge []     l = l

然后你可以把你的列表写成

[2 * n + 3 * m + 1 | (n,m) <- allPairs [0..] [0..] ]

要了解它的工作原理,请绘制一个无限的四分之一平面,然后查看结果

take 100 $ allPairs [0..] [0..]

【讨论】:

  • 或许值得澄清一下,Haskell 中的默认固定性是 infixl 9,因此此答案中的嵌套 merge 表达式与左侧相关联,即它被解析为 ( ( [(a, b) | b &lt;- bs] `merge` [(a, b) | a &lt;- as] ) `merge` allPairs as bs)。跨度>
【解决方案4】:

[2*n + 3*m +1 | m &lt;- [0..], n &lt;- [0..]] 不起作用,因为它以m = 0 开头并遍历所有n,然后具有m = 1 并遍历所有n 等。但只有m = 0 部分是无限的, 所以你永远不会得到 m = 1 或 2 或 3 等。所以[2*n + 3*m +1 | m &lt;- [0..], n &lt;- [0..]][2*n + 3*0 +1 | n &lt;- [0..]] 完全相同。

要生成所有数字,您需要像用户 vartec 和 Hynek -Pichi- Vychodil 一样意识到,您想要的数字集只是自然数 - {0,2}。或者您需要以某种方式枚举所有对 (m,n) 以使 m,n 为非负数。一种方法是沿着m + n 相同的每个“对角线”。所以我们从m + n = 0 的数字开始,然后是m + n = 1 的数字,等等。这些对角线中的每一个都有有限数量的对,所以你总是会继续下一个,所有对(m ,n) 最终会被计算在内。

如果我们让i = m + nj = m,那么[(m, n) | m &lt;- [0..], n &lt;- [0..]] 变成[(j, i - j) | i &lt;- [0..], j &lt;- [0..i]]

所以对你来说,你可以这样做

[2*(i-j) + 3*j +1 | i <- [0..], j <- [0..i]]

(当然,这种方法也会为您生成重复项,因为在您的表达式中有多个 (m,n) 对生成相同的数字。)

【讨论】:

  • 不知道当我发布那个答案时我在喝什么 :P 谢谢你的解释 :) 我会删除我没用的帖子
  • 您可以随时nub 列表以消除重复项,但严格意义上说,它不仅仅是列表理解,而且会占用过多的内存。
【解决方案5】:

我的 0.2:

trans = concat [ f n | n <- [1..]]
 where 
  mklst x = (\(a,b) -> a++b).unzip.(take x).repeat
  f n | n `mod` 2 == 0 = r:(mklst n (u,l))
      | otherwise      = u:(mklst n (r,d))
  u = \(a,b)->(a,b+1)
  d = \(a,b)->(a,b-1)
  l = \(a,b)->(a-1,b)
  r = \(a,b)->(a+1,b)

mkpairs acc (f:fs) = acc':mkpairs acc' fs
                  where acc' = f acc
allpairs = (0,0):mkpairs (0,0) trans          
result = [2*n + 3*m + 1 | (n,m) <- allpairs]

【讨论】:

    【解决方案6】:

    您可以尝试枚举所有整数对。 此代码基于University of California Berkeley 中描述的枚举(不包括 0)

    data Pair=Pair Int Int deriving Show
    
    instance Enum Pair where
        toEnum n=let l k=truncate (1/2 + sqrt(2.0*fromIntegral k-1))
                     m k=k-(l k-1)*(l k) `div` 2
                 in 
                   Pair (m n) (1+(l n)-(m n))
        fromEnum (Pair x y)=x+((x+y-1)*(x+y-2)) `div` 2
    

    但你可以使用另一个枚举。

    那么你可以这样做:

    [2*n+3*m+1|Pair n m<-map toEnum [1..]]
    

    【讨论】:

      猜你喜欢
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-18
      • 2021-08-31
      • 2021-03-31
      • 2018-10-21
      相关资源
      最近更新 更多