Skip to content

Commit 96cede9

Browse files
committed
Merge pull requests #531, #532, #533, #534, and #535
* bowling 1.0.0.2: drop unneeded rolls, edit a description * leap 1.0.0.2: explain criteria in descriptions, put in progress order * luhn 1.0.0.2: only test isValid, use (most) x-common cases * phone-number 1.2.0.3: enforce area/exchange not starting with 1 * roman-numerals 1.0.0.2: add descriptions
5 parents d010efd + f00dab6 + 610ba69 + 0ed4ac7 + 11963b4 commit 96cede9

File tree

11 files changed

+183
-188
lines changed

11 files changed

+183
-188
lines changed

exercises/leap/package.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: leap
2-
version: 0.9.0.1 # 2016-07-27
2+
version: 1.0.0.2
33

44
dependencies:
55
- base

exercises/leap/test/Tests.hs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,31 +26,19 @@ data Case = Case { description :: String
2626
}
2727

2828
cases :: [Case]
29-
cases = [ Case { description = "leap year"
30-
, input = 1996
31-
, expected = True
32-
}
33-
, Case { description = "standard and odd year"
34-
, input = 1997
35-
, expected = False
36-
}
37-
, Case { description = "standard even year"
38-
, input = 1998
29+
cases = [ Case { description = "year not divisible by 4: common year"
30+
, input = 2015
3931
, expected = False
4032
}
41-
, Case { description = "standard nineteenth century"
42-
, input = 1900
43-
, expected = False
33+
, Case { description = "year divisible by 4, not divisible by 100: leap year"
34+
, input = 2016
35+
, expected = True
4436
}
45-
, Case { description = "standard eighteenth century"
46-
, input = 1800
37+
, Case { description = "year divisible by 100, not divisible by 400: common year"
38+
, input = 2100
4739
, expected = False
4840
}
49-
, Case { description = "leap twenty fourth century"
50-
, input = 2400
51-
, expected = True
52-
}
53-
, Case { description = "leap y2k"
41+
, Case { description = "year divisible by 400: leap year"
5442
, input = 2000
5543
, expected = True
5644
}
Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,17 @@
1-
module Luhn (checkDigit, addends, checksum, isValid, create) where
1+
module Luhn (isValid) where
22

3-
revDigits :: Integral a => a -> [a]
4-
revDigits n = rem10 : digits
5-
where (quot10, rem10) = n `quotRem` 10
6-
digits | quot10 == 0 = []
7-
| otherwise = revDigits quot10
3+
import Data.Char (digitToInt)
84

95
luhnDouble :: Integral a => a -> a
106
luhnDouble n | n < 5 = n * 2
117
| otherwise = n * 2 - 9
128

13-
luhnDigits :: Integral a => a -> [a]
14-
luhnDigits = zipWith ($) (cycle [id, luhnDouble]) . revDigits
9+
luhnDigits :: Integral a => [a] -> [a]
10+
luhnDigits = zipWith ($) (cycle [id, luhnDouble]) . reverse
1511

16-
checkDigit :: Integral a => a -> a
17-
checkDigit = head . revDigits
18-
19-
addends :: Integral a => a -> [a]
20-
addends = reverse . luhnDigits
21-
22-
checksum :: Integral a => a -> a
12+
checksum :: Integral a => [a] -> a
2313
checksum = (`rem` 10) . sum . luhnDigits
2414

25-
isValid :: Integral a => a -> Bool
26-
isValid = (0 ==) . checksum
27-
28-
create :: Integral a => a -> a
29-
create n | chk == 0 = n10
30-
| otherwise = n10 + (10 - chk)
31-
where n10 = n * 10
32-
chk = checksum n10 `rem` 10
15+
isValid :: String -> Bool
16+
isValid s = length digits > 1 && checksum digits == 0
17+
where digits = map digitToInt $ filter (/= ' ') s

exercises/luhn/package.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: luhn
2-
version: 0.9.0.1 # 2016-08-04
2+
version: 1.0.0.2
33

44
dependencies:
55
- base

exercises/luhn/src/Luhn.hs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,4 @@
1-
module Luhn (addends, checkDigit, checksum, create, isValid) where
1+
module Luhn (isValid) where
22

3-
addends :: Integer -> [Integer]
4-
addends n = error "You need to implement this function."
5-
6-
checkDigit :: Integer -> Integer
7-
checkDigit n = error "You need to implement this function."
8-
9-
checksum :: Integer -> Integer
10-
checksum n = error "You need to implement this function."
11-
12-
create :: Integer -> Integer
13-
create n = error "You need to implement this function."
14-
15-
isValid :: Integer -> Bool
3+
isValid :: String -> Bool
164
isValid n = error "You need to implement this function."

exercises/luhn/test/Tests.hs

Lines changed: 68 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,77 @@
1-
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
1+
{-# LANGUAGE RecordWildCards #-}
22

3+
import Data.Foldable (for_)
34
import Test.Hspec (Spec, describe, it, shouldBe)
45
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
56

6-
import Luhn (addends, checkDigit, checksum, create, isValid)
7+
import Luhn (isValid)
78

89
main :: IO ()
910
main = hspecWith defaultConfig {configFastFail = True} specs
1011

1112
specs :: Spec
12-
specs = describe "luhn" $ do
13-
describe "standard tests" $ do
14-
15-
it "check digit" $
16-
checkDigit 34567 `shouldBe` 7
17-
18-
it "check digit with input ending in zero" $
19-
checkDigit 91370 `shouldBe` 0
20-
21-
it "check addends" $
22-
addends 12121 `shouldBe` [1, 4, 1, 4, 1]
23-
24-
it "check too large addends" $
25-
addends 8631 `shouldBe` [7, 6, 6, 1]
26-
27-
-- The reference test cases expect the checksum function to return
28-
-- the simple sum of the transformed digits, not their `mod 10` sum.
29-
-- In this track, we insist on the `mod 10`. :)
30-
31-
it "checksum" $
32-
checksum 4913 `shouldBe` 2 -- The reference test expects 22.
33-
34-
it "checksum of larger number" $
35-
checksum 201773 `shouldBe` 1 -- The reference test expects 21.
36-
37-
it "check invalid number" $
38-
isValid 738 `shouldBe` False
39-
40-
it "check valid number" $
41-
isValid 8739567 `shouldBe` True
42-
43-
it "create valid number" $
44-
create 123 `shouldBe` 1230
45-
46-
it "create larger valid number" $
47-
create 873956 `shouldBe` 8739567
48-
49-
it "create even larger valid number" $
50-
create 837263756 `shouldBe` 8372637564
51-
52-
describe "track-specific tests" $ do
53-
54-
-- This track has some tests that were not included in the
55-
-- reference test cases from `exercism/x-common/leap.json`.
56-
57-
it "checksum 1111" $
58-
checksum 1111 `shouldBe` 6
59-
60-
it "checksum 8763" $
61-
checksum 8763 `shouldBe` 0
62-
63-
it "checksum 8739567" $
64-
checksum 8739567 `shouldBe` 0
65-
66-
it "checksum 2323200577663554" $
67-
checksum 2323200577663554 `shouldBe` 0
68-
69-
it "isValid 1111" $
70-
isValid 1111 `shouldBe` False
71-
72-
it "isValid 8763" $
73-
isValid 8763 `shouldBe` True
74-
75-
it "isValid 2323200577663554" $
76-
isValid 2323200577663554 `shouldBe` True
77-
78-
it "create 232320057766355" $
79-
create 232320057766355 `shouldBe` 2323200577663554
13+
specs = describe "valid" $ for_ cases test
14+
where
15+
test Case{..} = it description $ isValid input `shouldBe` expected
16+
17+
data Case = Case { description :: String
18+
, input :: String
19+
, expected :: Bool
20+
}
21+
22+
cases :: [Case]
23+
cases = [ Case { description = "single digit strings can not be valid"
24+
, input = "1"
25+
, expected = False
26+
}
27+
, Case { description = "A single zero is invalid"
28+
, input = "0"
29+
, expected = False
30+
}
31+
, Case { description = "a simple valid SIN that remains valid if reversed"
32+
, input = "059"
33+
, expected = True
34+
}
35+
, Case { description = "a simple valid SIN that becomes invalid if reversed"
36+
, input = "59"
37+
, expected = True
38+
}
39+
, Case { description = "a valid Canadian SIN"
40+
, input = "055 444 285"
41+
, expected = True
42+
}
43+
, Case { description = "invalid Canadian SIN"
44+
, input = "055 444 286"
45+
, expected = False
46+
}
47+
, Case { description = "invalid credit card"
48+
, input = "8273 1232 7352 0569"
49+
, expected = False
50+
}
51+
-- This track is not testing these cases, since we would rather focus on the algorithm,
52+
-- and because it seems strange to be unable to distinguish between well-formed invalid input and malformed input.
53+
-- , Case { description = "valid strings with a non-digit included become invalid"
54+
-- , input = "055a 444 285"
55+
-- , expected = False
56+
-- }
57+
-- , Case { description = "valid strings with punctuation included become invalid"
58+
-- , input = "055-444-285"
59+
-- , expected = False
60+
-- }
61+
-- , Case { description = "valid strings with symbols included become invalid"
62+
-- , input = "055£ 444$ 285"
63+
-- , expected = False
64+
-- }
65+
, Case { description = "single zero with space is invalid"
66+
, input = " 0"
67+
, expected = False
68+
}
69+
, Case { description = "more than a single zero is valid"
70+
, input = "0000 0"
71+
, expected = True
72+
}
73+
, Case { description = "input digit 9 is correctly converted to output digit 9"
74+
, input = "091"
75+
, expected = True
76+
}
77+
]

exercises/phone-number/examples/success-standard/src/Phone.hs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
module Phone (number) where
2-
import Data.Char (isDigit, isLetter)
2+
import Data.Char (isDigit)
33

44
number :: String -> Maybe String
5-
number input
6-
| any isLetter input = Nothing
5+
number input = clean input >>= check
6+
7+
check :: String -> Maybe String
8+
check ('0':_) = Nothing
9+
check ('1':_) = Nothing
10+
check (_:_:_:'0':_) = Nothing
11+
check (_:_:_:'1':_) = Nothing
12+
check s = Just s
13+
14+
clean :: String -> Maybe String
15+
clean input
716
| len == 10 = Just digits
817
| len == 11 && head digits == '1' = Just $ tail digits
918
| otherwise = Nothing

exercises/phone-number/package.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: phone-number
2-
version: 1.0.0.2
2+
version: 1.2.0.3
33

44
dependencies:
55
- base

exercises/phone-number/test/Tests.hs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,30 +23,34 @@ data Case = Case { description :: String
2323
cases :: [Case]
2424
cases =
2525
[ Case { description = "cleans the number"
26-
, input = "(123) 456-7890"
27-
, expected = Just "1234567890"
26+
, input = "(223) 456-7890"
27+
, expected = Just "2234567890"
2828
}
29-
, Case { description = "cleans number with dots"
30-
, input = "123.456.7890"
31-
, expected = Just "1234567890"
29+
, Case { description = "cleans numbers with dots"
30+
, input = "223.456.7890"
31+
, expected = Just "2234567890"
3232
}
3333
, Case { description = "cleans numbers with multiple spaces"
34-
, input = "123 456 7890 "
35-
, expected = Just "1234567890"
34+
, input = "223 456 7890 "
35+
, expected = Just "2234567890"
3636
}
3737
, Case { description = "invalid when 9 digits"
3838
, input = "123456789"
3939
, expected = Nothing
4040
}
41-
, Case { description = "invalid when 11 digits"
42-
, input = "21234567890"
41+
, Case { description = "invalid when 11 digits does not start with a 1"
42+
, input = "22234567890"
4343
, expected = Nothing
4444
}
45-
, Case { description = "valid when 11 digits and first is 1"
46-
, input = "11234567890"
47-
, expected = Just "1234567890"
45+
, Case { description = "valid when 11 digits and starting with 1"
46+
, input = "12234567890"
47+
, expected = Just "2234567890"
48+
}
49+
, Case { description = "valid when 11 digits and starting with 1 even with punctuation"
50+
, input = "+1 (223) 456-7890"
51+
, expected = Just "2234567890"
4852
}
49-
, Case { description = "invalid when 12 digits"
53+
, Case { description = "invalid when more than 11 digits"
5054
, input = "321234567890"
5155
, expected = Nothing
5256
}
@@ -58,8 +62,12 @@ cases =
5862
, input = "123-@:!-7890"
5963
, expected = Nothing
6064
}
61-
, Case { description = "invalid with right number of digits but letters mixed in"
62-
, input = "1a2b3c4d5e6f7g8h9i0j"
65+
, Case { description = "invalid if area code does not start with 2-9"
66+
, input = "(123) 456-7890"
67+
, expected = Nothing
68+
}
69+
, Case { description = "invalid if exchange code does not start with 2-9"
70+
, input = "(223) 056-7890"
6371
, expected = Nothing
6472
}
6573
]

exercises/roman-numerals/package.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: roman-numerals
2-
version: 0.9.0.1 # 2016-07-26
2+
version: 1.0.0.2
33

44
dependencies:
55
- base

0 commit comments

Comments
 (0)