Haskell - ремесло функционального программирования (упражнение 4.3) - PullRequest
4 голосов
/ 13 мая 2011

У меня следующий вопрос (Haskell - Ремесло функционального программирования):

Дайте определение функции

howManyEqua1 :: Int -> Int -> Int -> Int

, который возвращает, сколько из его трех аргументов равны, так что

howManyEqua1 :: 34 25 36 = 0
howManyEqual :: 34 25 34 = 2
howManyEqual :: 34 34 34 = 3

Ответ, который я дал:

howManyEqual :: Int -> Int -> Int -> Int
howManyEqual    a      b      c
    | a == b && b == c            = 3
    | a == b                      = 2
    | b == c                      = 2
    | a == c                      = 2
    | otherwise                   = 0

Однако я считаю, что есть лучший способ его классифицировать, но я не уверен, как именно.

Ответы [ 6 ]

7 голосов
/ 13 мая 2011

Как насчет:

howManyEqual a b c
    | a == b && b == c           = 3
    | a /= b && a /= c && b /= c = 0
    | otherwise                  = 2
5 голосов
/ 13 мая 2011

Или:

howManyEqual a b c = case length.nub $ [a,b,c] of
    1 -> 3
    2 -> 2
    3 -> 0

Обновление:

Используя ответ Райанера в качестве отправной точки и определение обобщения Луки, мы также можем использовать этот один вкладыш и иметь общее решение со сложностью O (n log n) .:

howManyEqualG = sum.filter (>1).map length.group.sort
-- Now, specialized to three:
howManyEqual a b c = howManyEqualG [a,b,c]
2 голосов
/ 13 мая 2011

Чуть смешное решение:

howManyEqual a b c = [0,2,42,3] !! (length $ filter id [a == b, b == c, a == c])

[Изменить]

Короче:

import Data.List
howManyEqual a b c = [42,3,2,0] !! (length $ nub [a,b,c])
2 голосов
/ 13 мая 2011

Я думаю:

howManyEqual a b c
  | a == b && b == c           = 3
  | a == b || b == c || a == c = 2
  | otherwise                  = 0

Я не уверен, что это лучше / хуже, чем у Шона.

У меня может быть меньше тестов в среднем из-за лени ||.

1 голос
/ 13 мая 2011

Один лайнер, о котором я могу думать, избегает охранников:

import Data.List

howManyEqual :: Int -> Int -> Int -> Int
howManyEqual a b c      = maximum $ 0 : (filter (> 1) . map length . group . sort) [a,b,c]

Это явно менее эффективно и кажется излишним использованием композиции функций.

Вероятно, имеет смысл использовать алгоритм, подобный этому, только если вы вводите огромный список, в котором вы хотите подсчитать, сколько элементов больше всего равно. Это O (n log n).

1 голос
/ 13 мая 2011
...