Skip to content

Commit 4ed4068

Browse files
committed
Solve 'Find the sum of the roots of a quadratic equation' kata
1 parent 3f604e9 commit 4ed4068

File tree

2 files changed

+133
-0
lines changed

2 files changed

+133
-0
lines changed

src/Quadratic.hs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module Quadratic (roots) where
2+
3+
-- https://www.codewars.com/kata/57d448c6ba30875437000138/train/haskell
4+
5+
roots :: Double -> Double -> Double -> Maybe Double
6+
roots a b c
7+
| discriminant < 0 = Nothing
8+
| otherwise = Just $ root1 + root2
9+
where
10+
discriminant = b * b - 4 * a * c
11+
root1 = (-b - sqrt discriminant) / (2 * a)
12+
root2 = (-b + sqrt discriminant) / (2 * a)

test/QuadraticSpec.hs

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
module QuadraticSpec where
2+
3+
import Quadratic (roots)
4+
import Test.Hspec
5+
6+
spec :: Spec
7+
spec = do
8+
describe "Fixed Tests" $ do
9+
it "roots 1.0 (-35.0) (-23.0)" $
10+
roots 1.0 (-35.0) (-23.0) `shouldBeApproxMaybe` Just 35.0
11+
it "roots 6.0 0.0 (-24.0)" $
12+
roots 6.0 0.0 (-24.0) `shouldBeApproxMaybe` Just 0.0
13+
it "roots (-5.0) 21.0 0.0" $
14+
roots (-5.0) 21.0 0.0 `shouldBeApproxMaybe` Just 4.2
15+
it "roots 6.0 4.0 8.0" $
16+
roots 6.0 4.0 8.0 `shouldBeApproxMaybe` Nothing
17+
it "roots 1.0 5.0 (-24.0)" $
18+
roots 1.0 5.0 (-24.0) `shouldBeApproxMaybe` Just (-5.0)
19+
it "roots 3.0 11.0 6.0" $
20+
roots 3.0 11.0 6.0 `shouldBeApproxMaybe` Just (-3.6666666666666665)
21+
it "roots 2.0 2.0 9.0" $
22+
roots 2.0 2.0 9.0 `shouldBeApproxMaybe` Nothing
23+
it "roots 1.0 (-5/3) (-26.0)" $
24+
roots 1.0 (-5 / 3) (-26.0) `shouldBeApproxMaybe` Just 1.6666666666666667
25+
it "roots 1.0 6.0 10.0" $
26+
roots 1.0 6.0 10.0 `shouldBeApproxMaybe` Nothing
27+
it "roots 7.0 (-2.0) (-5.0)" $
28+
roots 7.0 (-2.0) (-5.0) `shouldBeApproxMaybe` Just 0.2857142857142857
29+
it "roots 1.0 8.0 20.0" $
30+
roots 1.0 8.0 20.0 `shouldBeApproxMaybe` Nothing
31+
it "roots 2.0 3.0 (-2.0)" $
32+
roots 2.0 3.0 (-2.0) `shouldBeApproxMaybe` Just (-1.5)
33+
it "roots 1.0 4.0 12.0" $
34+
roots 1.0 4.0 12.0 `shouldBeApproxMaybe` Nothing
35+
it "roots 3.0 (-2.0) (-5.0)" $
36+
roots 3.0 (-2.0) (-5.0) `shouldBeApproxMaybe` Just 0.6666666666666666
37+
it "roots 3.0 4.0 9.0" $
38+
roots 3.0 4.0 9.0 `shouldBeApproxMaybe` Nothing
39+
it "roots 5.0 4.0 0.0" $
40+
roots 5.0 4.0 0.0 `shouldBeApproxMaybe` Just (-0.8)
41+
it "roots 4.0 (-5.0) 0.0" $
42+
roots 4.0 (-5.0) 0.0 `shouldBeApproxMaybe` Just 1.25
43+
it "roots 1.0 4.0 9.0" $
44+
roots 1.0 4.0 9.0 `shouldBeApproxMaybe` Nothing
45+
it "roots 1.0 0.0 (-49.0)" $
46+
roots 1.0 0.0 (-49.0) `shouldBeApproxMaybe` Just 0.0
47+
it "roots 2.0 8.0 8.0" $
48+
roots 2.0 8.0 8.0 `shouldBeApproxMaybe` Just (-4.0)
49+
it "roots 1.0 0.0 (-0.16)" $
50+
roots 1.0 0.0 (-0.16) `shouldBeApproxMaybe` Just 0.0
51+
it "roots 1.0 6.0 12.0" $
52+
roots 1.0 6.0 12.0 `shouldBeApproxMaybe` Nothing
53+
it "roots 1.0 0.0 (-9.0)" $
54+
roots 1.0 0.0 (-9.0) `shouldBeApproxMaybe` Just 0.0
55+
it "roots (-3.0) 0.0 12.0" $
56+
roots (-3.0) 0.0 12.0 `shouldBeApproxMaybe` Just 0.0
57+
it "roots 1.0 3.0 9.0" $
58+
roots 1.0 3.0 9.0 `shouldBeApproxMaybe` Nothing
59+
it "roots 3.0 7.0 0.0" $
60+
roots 3.0 7.0 0.0 `shouldBeApproxMaybe` Just (-2.3333333333333335)
61+
it "roots 5.0 3.0 6.0" $
62+
roots 5.0 3.0 6.0 `shouldBeApproxMaybe` Nothing
63+
it "roots 1.0 4.0 4.0" $
64+
roots 1.0 4.0 4.0 `shouldBeApproxMaybe` Just (-4.0)
65+
it "roots (-1.0) 0.0 5.29" $
66+
roots (-1.0) 0.0 5.29 `shouldBeApproxMaybe` Just 0.0
67+
it "roots 1.0 12.0 36.0" $
68+
roots 1.0 12.0 36.0 `shouldBeApproxMaybe` Just (-12.0)
69+
it "roots 1.0 0.0 (-0.09)" $
70+
roots 1.0 0.0 (-0.09) `shouldBeApproxMaybe` Just 0.0
71+
it "roots 2.0 5.0 11.0" $
72+
roots 2.0 5.0 11.0 `shouldBeApproxMaybe` Nothing
73+
it "roots 3.0 0.0 (-15.0)" $
74+
roots 3.0 0.0 (-15.0) `shouldBeApproxMaybe` Just 0.0
75+
it "roots 1.0 (-3.0) 0.0" $
76+
roots 1.0 (-3.0) 0.0 `shouldBeApproxMaybe` Just 3.0
77+
it "roots 1.0 8.0 16.0" $
78+
roots 1.0 8.0 16.0 `shouldBeApproxMaybe` Just (-8.0)
79+
it "roots 2.0 6.0 9.0" $
80+
roots 2.0 6.0 9.0 `shouldBeApproxMaybe` Nothing
81+
it "roots (-1.0) 36.0 0.0" $
82+
roots (-1.0) 36.0 0.0 `shouldBeApproxMaybe` Just 36.0
83+
it "roots 5.0 (-8.0) 0.0" $
84+
roots 5.0 (-8.0) 0.0 `shouldBeApproxMaybe` Just 1.6
85+
it "roots 1.0 5.0 12.0" $
86+
roots 1.0 5.0 12.0 `shouldBeApproxMaybe` Nothing
87+
it "roots (-14.0) 0.0 0.0" $
88+
roots (-14.0) 0.0 0.0 `shouldBeApproxMaybe` Just 0.0
89+
it "roots 1.0 7.0 20.0" $
90+
roots 1.0 7.0 20.0 `shouldBeApproxMaybe` Nothing
91+
it "roots 1.0 (-6.0) 0.0" $
92+
roots 1.0 (-6.0) 0.0 `shouldBeApproxMaybe` Just 6.0
93+
it "roots 1.0 (-11.0) 30.0" $
94+
roots 1.0 (-11.0) 30.0 `shouldBeApproxMaybe` Just 11.0
95+
it "roots 1.0 3.0 12.0" $
96+
roots 1.0 3.0 12.0 `shouldBeApproxMaybe` Nothing
97+
it "roots 1.0 6.0 9.0" $
98+
roots 1.0 6.0 9.0 `shouldBeApproxMaybe` Just (-6.0)
99+
it "roots 8.0 47.0 41.0" $
100+
roots 8.0 47.0 41.0 `shouldBeApproxMaybe` Just (-5.875)
101+
102+
infix 1 `shouldBeApproxMaybe`
103+
104+
shouldBeApproxMaybe :: (Fractional a, Ord a, Show a) => Maybe a -> Maybe a -> Expectation
105+
shouldBeApproxMaybe a@(Just actual) e@(Just expected) =
106+
if abs (actual - expected) < margin * max 1 (abs expected)
107+
then return ()
108+
else expectationFailure message
109+
where
110+
margin = 1e-6
111+
message =
112+
concat
113+
[ "Test Failed",
114+
"\nexpected: ",
115+
show e,
116+
" within margin of ",
117+
show margin,
118+
"\n but got: ",
119+
show a
120+
]
121+
shouldBeApproxMaybe actual expected = actual `shouldBe` expected

0 commit comments

Comments
 (0)