Найти треугольник на графике - PullRequest
2 голосов
/ 14 октября 2011

У меня есть такой график:

graph

В рамках домашнего задания я хочу найти треугольник (1->2->5).Я понятия не имею, как это найти.

В моем случае я определил свой график:

type Graph = (Int, Int -> Int -> Bool)

g 2 3 = True
g 3 2 = True
g 1 2 = True
g 2 1 = True
g 1 1 = True
g n m = False

Ответ на 2 комментария.

Я сделал это, и это работает, Я думаю.

triangles :: [(Int, Int, Int)]
triangles = [(x, y, z) | x <- [1..3], y <- [1..x], z <- [1..y], isTriangle (x, y, z)]

isTriangle :: (Int, Int, Int) -> Bool
isTriangle  (x, y, z) = g x y && g y z && g x z

Я удалил (_,g) и (n,g) (я не понимаю, зачем они нам нужны :) Я звоню trinagles и он возвращает (1,1,1) (2,1,1) (в моем случае).Это правильно?

1 Ответ

5 голосов
/ 14 октября 2011

Полагаю, что первый Int в Graph является границей для ваших узлов (например, 6, если узлы находятся в [1..6]).

Поэтому вам нужна функция, которая возвращает треугольники графа, поэтому тип может быть:

triangles :: Graph -> [(Int, Int, Int)]

Теперь треугольник существует всякий раз, когда для 3 узлов, скажем, x y и z, все комбинации возвращают значения True - g.

Итак, вы можете рассмотреть возможность создания всех этих комбинаций (возможно, избегая тех, которые эквивалентны через переупорядочение), и отфильтровывать только те, которые подтверждают критерий:

isTriangle :: Graph -> (Int, Int, Int) -> Bool
isTriangle (_, g) (x, y, z) == g x y && g y z && g x z

Для этого вы можете использовать список или функцию filter типа (a -> Bool) -> [a] -> [a]


Ответ на ваш первый комментарий:

Во-первых, вам нужно реализовать функцию triangles, которая является причиной ошибки. Но, как вы сделали в test, вы можете просто генерировать эти треугольники на лету.

Теперь вы написали:

test = filter (isTriangle) [(x,y,z) | x <- [1..3], y <- [1..3], z <- [1..3]]

Об этом две вещи:

  • Во-первых, вам не нужны круглые скобки вокруг isTriangle для того, что вы написали, но это неверно, поскольку isTriangle ожидает график в качестве первого параметра
  • Во-вторых, вы получите много дубликатов, и если вы хотите, вы можете предотвратить это, не создавая их в первую очередь:

    test = filter (isTriangle) [(x,y,z) | x <- [1..3], y <- [1..x], z <- [1..y]]
    

В качестве альтернативы, вы можете отключить функцию filter, предоставив защиту в синтаксисе понимания списка, например:

[(x, y, z) | x <- [1..3],  y <- [1..x], z <- [1..y], isTriangle yourGraph (x, y, z)]

Теперь я позволю вам продолжить с деталями. Вы захотите сделать это функцией, которая принимает график, и заменить это 3 числом узлов в графе, а yourGraph указанным графиком.

Поскольку вы решили использовать понимание списков, забудьте о генерирующей функции, о которой я писал ранее, ее целью было просто генерировать ввод для filter, но при подходе к пониманию списков она вам не обязательно понадобится.


Ответ на второй комментарий:

Вы хотите написать функцию:

triangles :: Graph -> [(Int, Int, Int)]
triangles (n, g) = [(x, y, z) | ...]

... должны быть заменены правильными вещами из более ранних (диапазоны для x, y и z, а также предикат isTriangle).

Кроме того, вы можете сократить это в двух функциях:

allTriangles :: Int -> [(Int, Int, Int)]
allTriangles n = [(x, y, z) | ...]

graphTriangles :: Graph -> [(Int, Int, Int)]
graphTriangles (n, g) = [t | t <- allTriangles n, isGraphTriangle t]
    where isGraphTriangle (x, y, z) = ...

Таким образом, вы можете потенциально использовать allTriangles для чего-то другого. Если вы не чувствуете в этом необходимости, вы можете придерживаться единого понимания triangles, так как это домашнее задание, которое вы, вероятно, не будете развивать на этом.

Я стараюсь не заполнять все ..., чтобы вы могли сделать это самостоятельно и, надеюсь, поняли:)


Исправление вашего решения:

Во-первых, моя ошибка в диапазонах, это должно быть x <- [1..n], y <- [x+1..n], z <- [y+1..n], где n обозначает количество узлов в вашем графике. Таким образом, вы снимаете только тройки, где x < y < z, что гарантирует, что вы видите только один случай каждого набора из трех точек.

Во-вторых, причина, по которой я помещаю график в качестве параметра для функций, заключается в том, что вы можете использовать эту же функцию для другого графика. Путем жесткого кодирования g и 6 в ваших функциях вы делаете их действительно специфичными для конкретного графика, который вы описали, но если вы хотите вычислить triangles для определенного числа графиков, вы не хотите писать одну функцию на граф!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...