Question

I have the following question (Haskell - The Craft of Functional Programming):

Give a definition of the function

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

which returns how many of its three arguments are equal, so that

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

The answer I gave is:

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

However, I believe there is a better way to classify it but am not sure of how.

Was it helpful?

Solution

How about:

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

OTHER TIPS

Or:

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

Update:

Using ryaner's answer as a starting point and luqui's generalization definition, we can also use this one liner and have a general solution with O(n log n) complexity.:

howManyEqualG = sum.filter (>1).map length.group.sort
-- Now, specialized to three:
howManyEqual a b c = howManyEqualG [a,b,c]

I'm thinking:

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

I'm not sure if it's better/worse than Sean's.

I might have fewer tests in average due to || laziness.

Slightly funny solution:

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

[Edit]

Shorter:

import Data.List
howManyEqual a b c = [42,3,2,0] !! (length $ nub [a,b,c])

A one liner I can think of that avoids guards:

import Data.List

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

This is clearly less efficient though and seems like an overkill of function composition use.

It probably only makes sense to use an algorithm like this if your input is a huge list, where you want to count how many elements are equal the most. This is O(n log n).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top