Как выразить {2n + 3m + 1 | n, m∈N} в форме понимания списка? (N - это множество натуральных чисел, включая 0) - PullRequest
3 голосов
/ 17 апреля 2009

Как мне выразить {2n + 3m + 1 | n, m∈N} в форме понимания списка? N - множество натуральных чисел, включая 0.

Ответы [ 6 ]

12 голосов
/ 17 апреля 2009

Коротко:

1:[3..]
8 голосов
/ 17 апреля 2009

Разве {2n + 3m + 1 | n, m ∈ ℕ} = ℕ - {0,2}?

6 голосов
/ 18 апреля 2009

Следующая функция 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..]
4 голосов
/ 17 апреля 2009

[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 , п) в конечном итоге будет засчитано.

Если мы допустим 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) пар, которые генерируют одинаковое число.)

0 голосов
/ 25 декабря 2009

мой 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]
0 голосов
/ 20 апреля 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..]]
...