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

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


person gray    schedule 17.04.2009    source источник
comment
Похоже, это вопрос домашнего задания, но он не помечен как таковой. Прочтите соответствующий FAQ: stackoverflow.com/questions/230510/homework-on-stackoverflow   -  person nominolo    schedule 17.04.2009
comment
Это занижено. Вы хотите установить семантику (т. Е. Без дубликатов) в своем ответе? Имеет ли значение порядок?   -  person Chris Conway    schedule 17.04.2009


Ответы (5)


Коротко:

1:[3..]
person Hynek -Pichi- Vychodil    schedule 17.04.2009
comment
Было предложено использовать понимание списка. - person Romildo; 26.09.2012

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

person vartec    schedule 17.04.2009
comment
и 2. Вы не можете получить 1 из 2*n + 3*m - person FryGuy; 17.04.2009
comment
Да, ты прав. но кроме этих двух, любой x › 2 ∈ N можно представить как 2n+3m+1 - person vartec; 17.04.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..]
person Norman Ramsey    schedule 18.04.2009
comment
возможно, стоит уточнить, что фиксированность по умолчанию в Haskell - 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), которые генерируют одно и то же число в вашем выражении.)

person newacct    schedule 17.04.2009
comment
не знаю, что я пил, когда публиковал этот ответ: P, спасибо за объяснение, хотя :) и я удалю свой бесполезный пост - person Sujoy; 17.04.2009
comment
Вы всегда можете 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..]]
person hiena    schedule 19.04.2009