Как выразить {2n+3m+1|n,m∈N} в форме понимания списка? N — множество натуральных чисел, включая 0.
Как выразить {2n+3m+1|n,m∈N} в форме понимания списка? (N — множество натуральных чисел, включая 0)
Ответы (5)
Коротко:
1:[3..]
Разве {2n+3m+1|n,m ∈ ℕ} = ℕ - {0,2}?
Следующая функция 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..]
infixl 9
, поэтому вложенное выражение merge
в этом ответе связано с левым, то есть оно анализируется как ( ( [(a, b) | b <- bs] `merge` [(a, b) | a <- as] ) `merge` allPairs as bs)
.
- person Will Ness; 03.01.2021
[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), которые генерируют одно и то же число в вашем выражении.)
nub
список, чтобы устранить дубликаты, хотя тогда это не строго только понимание списка, и он будет использовать чрезмерное количество памяти.
- person ephemient; 17.04.2009
Вы можете попробовать перечислить все пары целых чисел. Этот код основан на перечислении, описанном в Калифорнийском университете в Беркли. (не включает 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..]]