如何在列表理解形式中表达{2n + 3m + 1 | n,m∈N}? N是一组自然数,包括0。
答案 0 :(得分:12)
不久:
1:[3..]
答案 1 :(得分:8)
不是{2n + 3m + 1 | n,m∈ℕ} =ℕ - {0,2}?
答案 2 :(得分:6)
以下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..]
答案 3 :(得分:4)
[2*n + 3*m +1 | m <- [0..], n <- [0..]]
无效,因为它以m = 0
开头并遍历所有n
,然后有m = 1
并通过所有n等等。但是只有m = 0
部分是无限的,所以你永远不会得到m = 1或2或3等等。所以[2*n + 3*m +1 | m <- [0..], n <- [0..]]
与[2*n + 3*0 +1 | n <- [0..]]
完全相同。
要生成所有这些,您需要像用户vartec和Hynek -Pichi- Vychodil一样意识到,您想要的数字集只是自然数 - {0,2}。或者你需要以某种方式枚举所有对(m,n),使得m,n是非负的。一种方法是沿着m + n
相同的每个“对角线”。所以我们从m + n = 0
的数字开始,然后是m + n = 1
等的数字。这些对角线中的每一对都有有限数量的对,所以你总是会继续下一个,所有对(m,n)最终将被计算。
如果我们允许i = m + n
和j = m
,则[(m, n) | m <- [0..], n <- [0..]]
会变为[(j, i - j) | i <- [0..], j <- [0..i]]
所以对你来说,你可以做到
[2*(i-j) + 3*j +1 | i <- [0..], j <- [0..i]]
(当然这个方法也会为你生成重复项,因为有多个(m,n)对在表达式中生成相同的数字。)
答案 4 :(得分:0)
您可以尝试枚举所有整数对。 此代码基于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..]]
答案 5 :(得分:0)
我的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]