01 July, 2006

[Haskell] Exercise 4.1 - 4.4

○ Exercise 4.1
maxFourを3通りの方法で書く。maxは自分の書いた物を使う様に指定。

import Prelude hiding (max)
max :: Int -> Int -> Int
max x y
| x >= y = x
| otherwise = y

maxThree :: Int -> Int -> Int -> Int
maxThree x y z = max (max x y) z

maxFour1 :: Int -> Int -> Int -> Int -> Int
maxFour1 x y z w = max (max (max x y) z) w

maxFour2 :: Int -> Int -> Int -> Int -> Int
maxFour2 x y z w = max (max x y) (max z w)

maxFour3 :: Int -> Int -> Int -> Int -> Int
maxFour3 x y z w = max (maxThree x y z) w

○ Exercise 4.2
betweenは昇順でも降順でもTrueになる様に作る。

between :: Int -> Int -> Int -> Bool
between x y z = (weakAscendingOrder x y z)
|| (weakAscendingOrder z y x)

weakAscendingOrder :: Int -> Int -> Int -> Bool
weakAscendingOrder x y z = (x<=y) && (y<=z)

Main> between 1 2 3
True
Main> between 3 2 1
True
Main> between 3 2 2
True
Main> between 3 1 2
False
Main> between 1 3 2
False
Main> between 1 3 3
True
Main>

○ Exercise 4.3
指示通り Exercise 3.7, 3.8 で作った関数を再利用する。

-- from Ex3.8
threeEquals :: Int -> Int -> Int -> Bool
threeEquals m n p = (m==n) && (n==p)

-- from Ex3.7
threeDifferent :: Int -> Int -> Int -> Bool
threeDifferent m n p = (m /= n) && (n /= p) && (p /= m)

howManyEquals :: Int -> Int -> Int -> Int
howManyEquals x y z
| threeEquals x y z = 3
| threeDifferent x y z = 0
| otherwise = 2

Main> howManyEquals 34 25 36
0
Main> howManyEquals 34 25 34
2
Main> howManyEquals 34 34 34
3
Main>

○ Exercise 4.4
とりあえずの回答。

howManyOfFourEqual :: Int -> Int -> Int -> Int -> Int
howManyOfFourEqual x y z w
| (x == y) && (y == z) && (z == w) = 4
| threeEquals x y z = 3
| threeEquals y z w = 3
| threeEquals z x y = 3
| threeEquals w x y = 3
| x == y = 2
| x == z = 2
| x == w = 2
| y == z = 2
| y == w = 2
| z == w = 2
| otherwise = 0

Main> howManyOfFourEqual 1 2 3 4
0
Main> howManyOfFourEqual 1 2 3 3
2
Main> howManyOfFourEqual 1 3 3 3
3
Main> howManyOfFourEqual 3 3 3 3
4
Main> howManyOfFourEqual 1 3 3 1
2
Main>

別解:比較の6個の組み合わせの等号の数を数える。(Haskellっぽくない?)

isEq :: Int -> Int -> Int
isEq x y
| x == y = 1
| otherwise = 0

howManyOf4Equal :: Int -> Int -> Int -> Int -> Int
howManyOf4Equal x y z w =
case (count x y z w) of
6 -> 4 -- all combination ==
3 -> 3 -- x == y == z == x
2 -> 2 -- example x == y /= z == w
1 -> 2 -- example x == y only
0 -> 0
where count x y z w = (isEq x y) + (isEq x z) + (isEq x w)
+ (isEq y z) + (isEq y w) + (isEq z w)

Main> howManyOf4Equal 1 2 3 4
0
Main> howManyOf4Equal 1 2 3 3
2
Main> howManyOf4Equal 1 3 3 3
3
Main> howManyOf4Equal 3 3 3 3
4
Main> howManyOf4Equal 1 3 3 1
2
Main>

1 comment:

Tom Weeks said...

howManyOfFourEqual :: Int -> Int -> Int -> Int -> Int
howManyOfFourEqual m n p q
| fourEqual m n p q = 4
| fourDifferent m n p q = 0
| otherwise = case howManyEqual m n p of
3 -> 3
0 -> 2
2 -> if middleNumber m n p == q then 3 else 2


prop_howManyOfFourEqual :: Int -> Int -> Int -> Int -> Bool
prop_howManyOfFourEqual x y z w =
howManyOfFourEqual x y z w == if longestGroup > 1 then longestGroup else 0
where longestGroup = maximum $ map length $ group $ sort [x,y,z,w]

fourDifferent :: Int -> Int -> Int -> Int -> Bool
fourDifferent m n p q = threeDifferent m n p && q /= m && q /= n && q /= p

fourEqual :: Int -> Int -> Int -> Int -> Bool
fourEqual m n p q = m == n && n == p && p == q