2016-03-18 3 views
0

В настоящее время я работаю над списками списков (которые мы используем для представления сетки). У меня есть одна функция, которая получает 2 аргумента (моя сетка и кортеж из 4 целых чисел) и возвращает логическое значение.Создайте список из другой функции, которая возвращает Bool в Haskell.

Теперь с новой функцией мне нужно сгенерировать список всех кортежей, который возвращает True для определенной сетки. Например, function1 (1,3,2,2) grid1 вернет True, поэтому мне нужно получить (1,3,2,2) в моем списке.

Другая проблема состоит в том, что у меня есть несколько условий, уважать мой кортеж (a,b,c,d) из 4 Целых, таких как: 1 <= a < a+c <= n and 1 <= b < b+d <= m где n этого количества линий (около длиной сетки) и m этого числа столбцов (так длина (голова сетка)).

У меня была идея использовать карту, но до сих пор я никогда не использовал ее в такой ситуации, и все, что я пробовал, не удалось.

Благодаря

+1

Это звучит как работа для понимания списка. Вы узнали о них еще? – dfeuer

+0

У меня действительно, но я использовал их только в простых ситуациях, когда повторяется только одна переменная.Как я могу сделать это с помощью 4 разных переменных, также имея в виду, что мне нужно проверить каждую возможность (так, не только (1,1,1,1), (2,2,2,2), но (3, 4,1,2), а также (4,3,1,2) для примера), и мне также необходимо указать где-то условия, изложенные в моем первоначальном посте. – Naleg

ответ

2

Там два основных подхода к делать это в Haskell.

  1. Генерация потока кортежей, которые удовлетворяют constaints вы в списке, но не обязательно возвращает истину в соответствии с функцией
  2. Использование filter к номиналу вниз по списку

Или мы можем попытаться избежать генерируя все эти избыточные данные и просто имеет что-то вроде

  1. Используйте наши знания о предикате только для генерации потока правильных кортежей в первую очередь

Поскольку мы работаем с произвольной функцией, мы не можем сделать вторую, поэтому мы предпочтем первое. Таким образом, мы начинаем с создания всех наборов, удовлетворяющих константам 1 <= a < a + c <= n и 1 <= b < b + d <= m.

Теперь ясно, что a находится в диапазоне [1 .. n] и b находится в [1 .. m]. Кроме того, для каждого a мы можем иметь c в [a + 1 .. n - a], и для каждого b мы можем иметь [b + 1 .. m - b]. Мы будем использовать Haskell's list comprehensions для кодирования это очень эффектный способ

allTuples :: Int -> Int -> [(Int, Int, Int, Int)] 
allTuples n m = -- First we take in n, m 
    [(a, b, c, d) | 
    a <- [1 .. n], 
    b <- [1 .. m], 
    c <- [a + 1 .. n - a], 
    d <- [b + 1 .. m - b]] 

Вот эти <- будут делать правильные вещи, и принять все возможные комбинации. Дальше все, что нам нужно, это использовать filter для удаления элементов.

prune :: Grid -> [(Int, Int, Int, Int)] -> [(Int, Int, Int, Int)] 
prune grid tuples = filter (\t -> f grid t) tuples 
-- could have written: 
-- prune grid = filter (f grid) 
-- prune = filter . f 

Тогда мы можем склеить их вместе, но я оставлю это последний шаг к вам, потому что я не знаю, как вы будете использовать его в своем приложении. Вы также можете объединить эти шаги в единое понимание списка:

allTuples :: Int -> Int -> [(Int, Int, Int, Int)] 
allTuples n m = -- First we take in n, m 
    [(a, b, c, d) | 
    a <- [1 .. n], 
    b <- [1 .. m], 
    c <- [a + 1 .. n - a], 
    d <- [b + 1 .. m - b], 
    f grid (a, b, c, d)] 
+0

Вы можете так же легко интегрировать фильтрацию в понимание. В зависимости от фильтра (ов), это может быть даже намного более эффективным. – dfeuer

+0

@dfeuer Абсолютно, я думаю, что концептуально более четкое разделение этих двух, хотя оно должно выполняться одинаково в этом использовании, потому что результаты будут хорошо передаваться. Я обновил с запиской, хотя – jozefg

+0

Моя точка зрения об эффективности заключается в том, что условия прилипания * между * перечислениями могут избежать большого количества потраченной впустую работы. – dfeuer

Смежные вопросы