Haskell бесконечный список увеличивающихся пар

Создайте бесконечный список пар :: [(Integer, Integer)], содержащий пары вида (m,n), где каждый из m и n является членом [0 ..]. Дополнительным требованием является то, что если (m,n) является допустимым членом списка, то (elem (m,n) pairs) должен вернуть True за конечное время. Реализация пар, нарушающая это требование, считается нерешением.

**** Свежее редактирование Спасибо за комментарии, посмотрим, смогу ли я добиться какого-то прогресса****

    pairs :: [(Integer, Integer)]
    pairs = [(m,n) | t <- [0..], m <- [0..], n <-[0..], m+n == t]

Что-то вроде этого? Я просто не знаю, где он вернет True за конечное время.

Я чувствую, что формулировка вопроса не должна быть частью моего ответа. Просто если вы вызовете (elem (m,n) pairs), он должен вернуть true. Звучит правильно?


person john stamos    schedule 23.03.2013    source источник
comment
Подсказка: генерируйте их по одной диагонали за раз. Установите t = x + y и сгенерируйте все пары (x, y) для каждого t в [0..]. Поскольку для каждого t существует только конечное число пар, это удовлетворит требованиям.   -  person hammar    schedule 23.03.2013
comment
Мне нравится этот метод. За исключением того, что я не уверен, как это реализовать.   -  person john stamos    schedule 23.03.2013
comment
Вместо фильтрации сгенерируйте только возможные значения для m и n. Какое максимальное значение может иметь m для фиксированного t? После того, как вы выбрали t и m, вы можете использовать t = m + n для прямого вычисления n.   -  person hammar    schedule 23.03.2013
comment
Вы уверены, что правильно объясняете проблему? Для чего предназначен список (m,n)? Возможно, проблема заключается в том, чтобы сгенерировать все пары (m,n), где m и n удовлетворяют helper m n == True (т. е. вы знаете, что такое helper, когда составляете список)?   -  person Andrew Jaffe    schedule 23.03.2013
comment
Это просто создать бесконечный список пар. Весь вопрос в этом. Как я уже сказал выше, я не уверен, что мне действительно нужно реализовать пары (elem (m, n)). Похоже, он должен просто вернуть true, если это было вызвано.   -  person john stamos    schedule 23.03.2013
comment
Откуда взялось условие m+n==t? Это часть вопроса? Я почти уверен, что ваш список в конце концов содержит все возможные пары целых чисел, и в этом случае ответ всегда будет True!   -  person Andrew Jaffe    schedule 23.03.2013
comment
m+n==t — это фильтр для t, поэтому m и n получают все возможные пары, такие как [(0,0), (0,1), (1,0), (0,2), (1, 1), (2,0), ...]. В противном случае это просто ушло бы [(0, _), (1, _), (2, _), (3, _), (4, _), ...] до бесконечности. Это неправильно?   -  person john stamos    schedule 23.03.2013
comment
Правильный. Но у него по-прежнему есть все возможные пары. Так что elem всегда должен просто возвращать true. Что не очень интересно, и поэтому (извините) я все еще думаю, что вы неправильно сформулировали проблему. (И наоборот, нет способа, которым вы могли бы фактически выполнить поиск в списке, содержащем произвольное и неизвестное ограниченное подмножество всех возможных пар, за постоянное время.)   -  person Andrew Jaffe    schedule 23.03.2013
comment
Я просто скопировал и вставил вопрос. Они не всегда очень интересны. Подумайте, это то, что было задумано. Да, наш проф сказал что-то о том, что он оценивает столько, сколько вам нужно, поэтому, если вы вызовете это с ситуацией, которая требует (10,_), он будет оцениваться там, но имеет возможность продолжать бесконечно. Это правильно?   -  person john stamos    schedule 23.03.2013
comment
В вашей последней редакции вопрос больше не имел смысла (поскольку почти все было удалено). Я откатил его назад; не уверен, каково было ваше намерение (если вы действительно хотели сказать, что это здесь сделано, больше нет ответов, пожалуйста, не изменяйте свой вопрос, а просто примите самый полезный ответ).   -  person leftaroundabout    schedule 23.03.2013


Ответы (4)


Игнорируя метод helper, понимание списка, которое у вас есть, будет перечислять все пары, но порядок элементов является проблемой. У вас будет бесконечно много пар, таких как (0, m), за которыми за которыми следует бесконечное количество пар, таких как (1, m). Конечно, elem будет постоянно перебирать все пары (0, m), никогда не достигая (1, m) или (2, m) и т. д.

Я не уверен, почему у вас есть метод helper — с его помощью вы только строите список пар, таких как [(0,0), (1,1), (2,2), ...], потому что вы отфильтровали m = n. Это было частью требований?

Как предложил @hammar, начните с 0 = m + n и перечислите пары (m, n). Затем перечислите пары (m, n), где 1 = m + n. Тогда ваш список будет выглядеть как [(0,0), (0,1), (1,0), (0,2), (1,1), (2,0), ...].

person kputnam    schedule 23.03.2013
comment
Указаны только требования. Я не думаю, что мне это нужно. Как мне реализовать список, который делает это??? используя list comp и заставляя 't' идти вверх по шагу, удерживая m и n назад по мере их увеличения? - person john stamos; 23.03.2013
comment
Да, скорее всего, у вас будет [(m,_) | t <- [0..], m <- _]. Попробуйте начать с этого и посмотрите, сможете ли вы заполнить пробелы. - person kputnam; 23.03.2013
comment
Пробовал, обеспокоен истинным значением. - person john stamos; 23.03.2013

Вспомогательная функция гарантирует, что пары представляют собой список в форме [ (0,0) , (1,1) , (2,2) ... ].

Таким образом, пары elem ( m , n ) могут быть реализованы как:

elem (m , n) _ |  m == n    = True
               |  otherwise = False

Это реализация с постоянным временем.

person Aviral Goel    schedule 23.03.2013
comment
Какова функция подчеркивания здесь? Я обновлю свой код сейчас. - person john stamos; 23.03.2013
comment
@johnstamos: это шаблон подстановочных знаков, который не связывает второй аргумент elem с именем. Это связано с тем, что этой реализации на самом деле не нужно видеть список для проверки членства. - person kputnam; 23.03.2013
comment
Вы можете устранить охрану в сопоставлении с образцом здесь: elem (m, n) _ = m == n будет достаточно. - person kputnam; 23.03.2013
comment
Это все еще часть помощника? - person john stamos; 23.03.2013
comment
Если это домашнее задание, я полагаю, что вам не разрешено давать собственное определение elem. Вместо этого вы, вероятно, должны написать pairs, чтобы удовлетворить требования, используя elem из Prelude. - person kputnam; 23.03.2013
comment
Правильный. как моя первоначальная попытка выше. Мне нравится намек на хаммарс. Поверьте, именно так мы должны это делать. - person john stamos; 23.03.2013

я первый написал

Prelude> let pairs = [(m, n) | t <- [0..]
                     , let m = head $ take 1 $ drop t [0..] 
                     , let n = head $ take 1 $ drop (t + 1) [0..]]

Что, как мне казалось, отвечало трем условиям, поставленным профессором. Но Хаммар указал, что если я выбрал в качестве ответа этот список, то есть список пар вида (t, t+1), то я мог бы также выбрать список

repeat [(0,0)] 

Что ж, оба они, кажется, отвечают на вопрос профессора, учитывая, что, кажется, нет упоминания о том, что список должен содержать все комбинации [0..] и [0..].

Помимо этого, Hammer помог мне увидеть, как можно составить список всех комбинаций, облегчив вычисление elem за конечное время путем построения бесконечного списка из конечных списков. Вот два других конечных списка — менее лаконичных, чем предложение Хаммара о диагоналях, — которые, кажется, строят все комбинации [0..] и [0..]:

edges = concat [concat [[(m,n),(n,m)] | let m = t, n <- take m [0..]] ++ [(t,t)] 
      | t <- [0..]]


*Main> take 9 edges
[(0,0),(1,0),(0,1),(1,1),(2,0),(0,2),(2,1),(1,2),(2,2)]

которые строят ребра (t, 0..t) (0..t, t), и

oddSpirals size = concat [spiral m size' | m <- n] where
  size' = if size < 3 then 3 else if even size then size - 1 else size
  n = map (\y -> (fst y * size' + div size' 2, snd y * size' + div size' 2)) 
          [(x, t-x) | let size' = 5, t <- [0..], x <- [0..t]]
  spiral seed size = spiral' (size - 1) "-" 1 [seed]
  spiral' limit op count result
    | count == limit =
       let op' = if op == "-" then (-) else (+)
           m = foldl (\a b -> a ++ [(op' (fst $ last a) b, snd $ last a)]) result (replicate count 1)
           nextOp = if op == "-" then "+" else "-"
           nextOp' = if op == "-" then (+) else (-)
           n = foldl (\a b -> a ++ [(fst $ last a, nextOp' (snd $ last a) b)]) m (replicate count 1)
           n' = foldl (\a b -> a ++ [(nextOp' (fst $ last a) b, snd $ last a)]) n (replicate count 1)
       in n'
    | otherwise      =
        let op' = if op == "-" then (-) else (+)
            m = foldl (\a b -> a ++ [(op' (fst $ last a) b, snd $ last a)]) result (replicate count 1)
            nextOp = if op == "-" then "+" else "-"
            nextOp' = if op == "-" then (+) else (-)
            n = foldl (\a b -> a ++ [(fst $ last a, nextOp' (snd $ last a) b)]) m (replicate count 1)
        in spiral' limit nextOp (count + 1) n


*Main> take 9 $ oddSpirals 3
[(1,1),(0,1),(0,2),(1,2),(2,2),(2,1),(2,0),(1,0),(0,0)]

которые строят спирали по часовой стрелке длины «размера» в квадрате, наложенные на алгоритм диагоналей Хаммара.

person גלעד ברקן    schedule 23.03.2013
comment
Это генерирует только пары формы (t, t+1). - person hammar; 23.03.2013
comment
Задача состоит в том, чтобы сгенерировать все пары натуральных чисел так, чтобы любая заданная пара находилась в некотором конечном индексе в списке. - person hammar; 23.03.2013
comment
@hammar Кажется, я ответил на три условия: (1) бесконечные пары списков :: [(Целое число, целое число)], (2) содержащие пары вида (m,n), где каждый из m и n является членом [0 ..] и (3) пары elem (m,n) должны возвращать True за конечное время. Разве я не? - person גלעד ברקן; 23.03.2013
comment
Например, elem (0, 0) pairs не возвращает True за конечное время. - person hammar; 23.03.2013
comment
@hammar, потому что это неправда. Если это правда, то так и есть. - person גלעד ברקן; 23.03.2013
comment
Если бы это была задача, любой бесконечный список соответствующего типа сработал бы. - person hammar; 23.03.2013
comment
repeat (0, 0), например, или даже pairs = pairs. elem всегда будет возвращать False только для конечного списка. - person hammar; 23.03.2013
comment
@hammar Я понимаю, что ты имеешь в виду. Вы можете сгенерировать (потенциально) все комбинации и получить ответ на elem за конечное время? кстати, где m и n в вашем примере? - person גלעד ברקן; 23.03.2013
comment
Поскольку это явно домашнее задание, я старался не давать решения, но вот оно: [(x, t-x) | t <- [0..], x <- [0..t]]. - person hammar; 23.03.2013
comment
@хаммар мило. похоже, что n в данном случае взято из [0..m], хотя и не из [0..] - person גלעד ברקן; 23.03.2013
comment
Нет, это поразит все пары. Если вы представляете (m, n) как декартовы координаты в бесконечной квадратной сетке, это понимание списка охватывает их все по одной диагонали за раз. Каждая диагональ соответствует значению t, которое мы затем проходим от (0, t) до (t, 0). Попробуйте нарисовать это на бумаге, если у вас возникли проблемы. - person hammar; 23.03.2013
comment
@hammar hammar, я понимаю, что он сгенерирует все пары, я просто указываю, что технически n в вашем решении исходит из [0..m], а не из [0..] - person גלעד ברקן; 23.03.2013
comment
Нет, это означало бы, что я генерирую только пары, где n <= m, что не так. - person hammar; 23.03.2013
comment
@hammar моя ошибка, в вашем решении m определяется как от [0..t], n определяется как tm. Но это формальность; m и n действительно являются членами [0..] в вашем решении. Я сосредоточился на технической части, думая, что m и n должны быть выражены непосредственно из [0..] - person גלעד ברקן; 23.03.2013
comment
@hammar Кстати, ваше решение, похоже, обрабатывает False так же, как и мое. Попробуйте пары elem (-1,2) - person גלעד ברקן; 23.03.2013
comment
Да, но -1 не является членом [0..]. - person hammar; 23.03.2013
comment
@hammar спасибо за ценный урок, мне было весело пробовать разные конечные списки «бесконечный список хаскелл увеличивающихся пар»> stackoverflow.com/questions/15583975/ - person גלעד ברקן; 24.03.2013

Я считаю, что решение вашей задачи:

pairs = [(x,y) | u <- [0..], x <- [0..u], y <-[0..u] , u == x+y]

person Ali Homsi    schedule 22.05.2020
comment
@ali_homsi Шаблон вывода ваших функций: 1-я цифра: 0, 0 1, 0 1 2, 0 1 2 3 и 2-я цифра 0, 1 0, 2 1 0, 3 2 1 0. В заархивированном виде они являются вашим выходом. Это декартово произведение и идеально подходит. diag xs ys = [ (m,n) | i<- [1..], (m,n) <- zip [0..i] [i,i-1..0] ] - person fp_mora; 24.03.2021