From 050fe8b8d871fba3e38bda4d74bae3bdc82ab935 Mon Sep 17 00:00:00 2001 From: Tomas Fischer Date: Tue, 30 Jan 2024 07:59:13 +0100 Subject: [PATCH] Added Rational Numbers exercise (#1193) * Added Rational Numbers exercise * Incorporated review comments from #1193 --- config.json | 13 + .../rational-numbers/.docs/instructions.md | 42 +++ .../rational-numbers/.meta/config.json | 23 ++ .../examples/success-standard/package.yaml | 16 + .../success-standard/src/RationalNumbers.hs | 57 +++ .../rational-numbers/.meta/tests.toml | 139 ++++++++ .../practice/rational-numbers/package.yaml | 21 ++ .../rational-numbers/src/RationalNumbers.hs | 53 +++ .../practice/rational-numbers/stack.yaml | 1 + .../practice/rational-numbers/test/Tests.hs | 337 ++++++++++++++++++ 10 files changed, 702 insertions(+) create mode 100644 exercises/practice/rational-numbers/.docs/instructions.md create mode 100644 exercises/practice/rational-numbers/.meta/config.json create mode 100644 exercises/practice/rational-numbers/.meta/examples/success-standard/package.yaml create mode 100644 exercises/practice/rational-numbers/.meta/examples/success-standard/src/RationalNumbers.hs create mode 100644 exercises/practice/rational-numbers/.meta/tests.toml create mode 100644 exercises/practice/rational-numbers/package.yaml create mode 100644 exercises/practice/rational-numbers/src/RationalNumbers.hs create mode 100644 exercises/practice/rational-numbers/stack.yaml create mode 100644 exercises/practice/rational-numbers/test/Tests.hs diff --git a/config.json b/config.json index 413e79bee..4d2b7571c 100644 --- a/config.json +++ b/config.json @@ -1109,6 +1109,19 @@ "number_theory" ] }, + { + "slug": "rational-numbers", + "name": "Rational Numbers", + "uuid": "b4426fe9-2e49-48c5-9dea-c86032009687", + "practices": [], + "prerequisites": [], + "difficulty": 3, + "topics": [ + "define_type", + "math", + "number_theory" + ] + }, { "slug": "largest-series-product", "name": "Largest Series Product", diff --git a/exercises/practice/rational-numbers/.docs/instructions.md b/exercises/practice/rational-numbers/.docs/instructions.md new file mode 100644 index 000000000..f64fc0f28 --- /dev/null +++ b/exercises/practice/rational-numbers/.docs/instructions.md @@ -0,0 +1,42 @@ +# Instructions + +A rational number is defined as the quotient of two integers `a` and `b`, called the numerator and denominator, respectively, where `b != 0`. + +~~~~exercism/note +Note that mathematically, the denominator can't be zero. +However in many implementations of rational numbers, you will find that the denominator is allowed to be zero with behaviour similar to positive or negative infinity in floating point numbers. +In those cases, the denominator and numerator generally still can't both be zero at once. +~~~~ + +The absolute value `|r|` of the rational number `r = a/b` is equal to `|a|/|b|`. + +The sum of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ + r₂ = a₁/b₁ + a₂/b₂ = (a₁ * b₂ + a₂ * b₁) / (b₁ * b₂)`. + +The difference of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ - r₂ = a₁/b₁ - a₂/b₂ = (a₁ * b₂ - a₂ * b₁) / (b₁ * b₂)`. + +The product (multiplication) of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ * r₂ = (a₁ * a₂) / (b₁ * b₂)`. + +Dividing a rational number `r₁ = a₁/b₁` by another `r₂ = a₂/b₂` is `r₁ / r₂ = (a₁ * b₂) / (a₂ * b₁)` if `a₂` is not zero. + +Exponentiation of a rational number `r = a/b` to a non-negative integer power `n` is `r^n = (a^n)/(b^n)`. + +Exponentiation of a rational number `r = a/b` to a negative integer power `n` is `r^n = (b^m)/(a^m)`, where `m = |n|`. + +Exponentiation of a rational number `r = a/b` to a real (floating-point) number `x` is the quotient `(a^x)/(b^x)`, which is a real number. + +Exponentiation of a real number `x` to a rational number `r = a/b` is `x^(a/b) = root(x^a, b)`, where `root(p, q)` is the `q`th root of `p`. + +Implement the following operations: + +- addition, subtraction, multiplication and division of two rational numbers, +- absolute value, exponentiation of a given rational number to an integer power, exponentiation of a given rational number to a real (floating-point) power, exponentiation of a real number to a rational number. + +Your implementation of rational numbers should always be reduced to lowest terms. +For example, `4/4` should reduce to `1/1`, `30/60` should reduce to `1/2`, `12/8` should reduce to `3/2`, etc. +To reduce a rational number `r = a/b`, divide `a` and `b` by the greatest common divisor (gcd) of `a` and `b`. +So, for example, `gcd(12, 8) = 4`, so `r = 12/8` can be reduced to `(12/4)/(8/4) = 3/2`. +The reduced form of a rational number should be in "standard form" (the denominator should always be a positive integer). +If a denominator with a negative integer is present, multiply both numerator and denominator by `-1` to ensure standard form is reached. +For example, `3/-4` should be reduced to `-3/4` + +Assume that the programming language you are using does not have an implementation of rational numbers. diff --git a/exercises/practice/rational-numbers/.meta/config.json b/exercises/practice/rational-numbers/.meta/config.json new file mode 100644 index 000000000..5c02fd8f9 --- /dev/null +++ b/exercises/practice/rational-numbers/.meta/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "tofische" + ], + "files": { + "solution": [ + "src/RationalNumbers.hs", + "package.yaml" + ], + "test": [ + "test/Tests.hs" + ], + "example": [ + ".meta/examples/success-standard/src/RationalNumbers.hs" + ], + "invalidator": [ + "stack.yaml" + ] + }, + "blurb": "Implement rational numbers.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Rational_number" +} diff --git a/exercises/practice/rational-numbers/.meta/examples/success-standard/package.yaml b/exercises/practice/rational-numbers/.meta/examples/success-standard/package.yaml new file mode 100644 index 000000000..e55cce9f0 --- /dev/null +++ b/exercises/practice/rational-numbers/.meta/examples/success-standard/package.yaml @@ -0,0 +1,16 @@ +name: rational-numbers + +dependencies: + - base + +library: + exposed-modules: RationalNumbers + source-dirs: src + +tests: + test: + main: Tests.hs + source-dirs: test + dependencies: + - rational-numbers + - hspec diff --git a/exercises/practice/rational-numbers/.meta/examples/success-standard/src/RationalNumbers.hs b/exercises/practice/rational-numbers/.meta/examples/success-standard/src/RationalNumbers.hs new file mode 100644 index 000000000..1e2f6e7ec --- /dev/null +++ b/exercises/practice/rational-numbers/.meta/examples/success-standard/src/RationalNumbers.hs @@ -0,0 +1,57 @@ +module RationalNumbers +(Rational, + abs, + numerator, + denominator, + add, + sub, + mul, + div, + pow, + expRational, + expReal, + rational) where + +import Prelude hiding (div, abs, Rational) +import qualified Prelude as P + +-- Data definition ------------------------------------------------------------- +data Rational a = Rational a a deriving(Eq, Show) + +rational :: Integral a => (a, a) -> Rational a +rational (n, d) = Rational (n' `quot` g) (d' `quot` g) + where + g = gcd n d + (n', d') = if d < 0 then (-n, -d) else (n, d) + +-- unary operators ------------------------------------------------------------- +abs :: Integral a => Rational a -> Rational a +abs (Rational n d) = rational (P.abs n, P.abs d) + +numerator :: Integral a => Rational a -> a +numerator (Rational n _) = n + +denominator :: Integral a => Rational a -> a +denominator (Rational _ d) = d + +-- binary operators ------------------------------------------------------------ +add :: Integral a => Rational a -> Rational a -> Rational a +add (Rational n1 d1) (Rational n2 d2) = let dd = d1*d2 in rational (n1*d2 + n2*d1, dd) + +sub :: Integral a => Rational a -> Rational a -> Rational a +sub (Rational n1 d1) (Rational n2 d2) = let dd = d1*d2 in rational (n1*d2 - n2*d1, dd) + +mul :: Integral a => Rational a -> Rational a -> Rational a +mul (Rational n1 d1) (Rational n2 d2) = rational (n1*n2, d1*d2) + +div :: Integral a => Rational a -> Rational a -> Rational a +div (Rational n1 d1) (Rational n2 d2) = rational (n1*d2, d1*n2) + +pow :: Integral a => Rational a -> a -> Rational a +pow (Rational n d) num = if num >= 0 then rational (n^num, d^num) else rational (d^(-num), n^(-num)) + +expRational :: Integral a => Floating b => Rational a -> b -> b +expRational (Rational n d) num = (fromIntegral n / fromIntegral d) ** num + +expReal :: Floating a => Integral b => a -> Rational b -> a +expReal num (Rational n d) = num ** (fromIntegral n / fromIntegral d) diff --git a/exercises/practice/rational-numbers/.meta/tests.toml b/exercises/practice/rational-numbers/.meta/tests.toml new file mode 100644 index 000000000..ddea7145c --- /dev/null +++ b/exercises/practice/rational-numbers/.meta/tests.toml @@ -0,0 +1,139 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[0ba4d988-044c-4ed5-9215-4d0bb8d0ae9f] +description = "Arithmetic -> Addition -> Add two positive rational numbers" + +[88ebc342-a2ac-4812-a656-7b664f718b6a] +description = "Arithmetic -> Addition -> Add a positive rational number and a negative rational number" + +[92ed09c2-991e-4082-a602-13557080205c] +description = "Arithmetic -> Addition -> Add two negative rational numbers" + +[6e58999e-3350-45fb-a104-aac7f4a9dd11] +description = "Arithmetic -> Addition -> Add a rational number to its additive inverse" + +[47bba350-9db1-4ab9-b412-4a7e1f72a66e] +description = "Arithmetic -> Subtraction -> Subtract two positive rational numbers" + +[93926e2a-3e82-4aee-98a7-fc33fb328e87] +description = "Arithmetic -> Subtraction -> Subtract a positive rational number and a negative rational number" + +[a965ba45-9b26-442b-bdc7-7728e4b8d4cc] +description = "Arithmetic -> Subtraction -> Subtract two negative rational numbers" + +[0df0e003-f68e-4209-8c6e-6a4e76af5058] +description = "Arithmetic -> Subtraction -> Subtract a rational number from itself" + +[34fde77a-75f4-4204-8050-8d3a937958d3] +description = "Arithmetic -> Multiplication -> Multiply two positive rational numbers" + +[6d015cf0-0ea3-41f1-93de-0b8e38e88bae] +description = "Arithmetic -> Multiplication -> Multiply a negative rational number by a positive rational number" + +[d1bf1b55-954e-41b1-8c92-9fc6beeb76fa] +description = "Arithmetic -> Multiplication -> Multiply two negative rational numbers" + +[a9b8f529-9ec7-4c79-a517-19365d779040] +description = "Arithmetic -> Multiplication -> Multiply a rational number by its reciprocal" + +[d89d6429-22fa-4368-ab04-9e01a44d3b48] +description = "Arithmetic -> Multiplication -> Multiply a rational number by 1" + +[0d95c8b9-1482-4ed7-bac9-b8694fa90145] +description = "Arithmetic -> Multiplication -> Multiply a rational number by 0" + +[1de088f4-64be-4e6e-93fd-5997ae7c9798] +description = "Arithmetic -> Division -> Divide two positive rational numbers" + +[7d7983db-652a-4e66-981a-e921fb38d9a9] +description = "Arithmetic -> Division -> Divide a positive rational number by a negative rational number" + +[1b434d1b-5b38-4cee-aaf5-b9495c399e34] +description = "Arithmetic -> Division -> Divide two negative rational numbers" + +[d81c2ebf-3612-45a6-b4e0-f0d47812bd59] +description = "Arithmetic -> Division -> Divide a rational number by 1" + +[5fee0d8e-5955-4324-acbe-54cdca94ddaa] +description = "Absolute value -> Absolute value of a positive rational number" + +[3cb570b6-c36a-4963-a380-c0834321bcaa] +description = "Absolute value -> Absolute value of a positive rational number with negative numerator and denominator" + +[6a05f9a0-1f6b-470b-8ff7-41af81773f25] +description = "Absolute value -> Absolute value of a negative rational number" + +[5d0f2336-3694-464f-8df9-f5852fda99dd] +description = "Absolute value -> Absolute value of a negative rational number with negative denominator" + +[f8e1ed4b-9dca-47fb-a01e-5311457b3118] +description = "Absolute value -> Absolute value of zero" + +[4a8c939f-f958-473b-9f88-6ad0f83bb4c4] +description = "Absolute value -> Absolute value of a rational number is reduced to lowest terms" + +[ea2ad2af-3dab-41e7-bb9f-bd6819668a84] +description = "Exponentiation of a rational number -> Raise a positive rational number to a positive integer power" + +[8168edd2-0af3-45b1-b03f-72c01332e10a] +description = "Exponentiation of a rational number -> Raise a negative rational number to a positive integer power" + +[c291cfae-cfd8-44f5-aa6c-b175c148a492] +description = "Exponentiation of a rational number -> Raise a positive rational number to a negative integer power" + +[45cb3288-4ae4-4465-9ae5-c129de4fac8e] +description = "Exponentiation of a rational number -> Raise a negative rational number to an even negative integer power" + +[2d47f945-ffe1-4916-a399-c2e8c27d7f72] +description = "Exponentiation of a rational number -> Raise a negative rational number to an odd negative integer power" + +[e2f25b1d-e4de-4102-abc3-c2bb7c4591e4] +description = "Exponentiation of a rational number -> Raise zero to an integer power" + +[431cac50-ab8b-4d58-8e73-319d5404b762] +description = "Exponentiation of a rational number -> Raise one to an integer power" + +[7d164739-d68a-4a9c-b99f-dd77ce5d55e6] +description = "Exponentiation of a rational number -> Raise a positive rational number to the power of zero" + +[eb6bd5f5-f880-4bcd-8103-e736cb6e41d1] +description = "Exponentiation of a rational number -> Raise a negative rational number to the power of zero" + +[30b467dd-c158-46f5-9ffb-c106de2fd6fa] +description = "Exponentiation of a real number to a rational number -> Raise a real number to a positive rational number" + +[6e026bcc-be40-4b7b-ae22-eeaafc5a1789] +description = "Exponentiation of a real number to a rational number -> Raise a real number to a negative rational number" + +[9f866da7-e893-407f-8cd2-ee85d496eec5] +description = "Exponentiation of a real number to a rational number -> Raise a real number to a zero rational number" + +[0a63fbde-b59c-4c26-8237-1e0c73354d0a] +description = "Reduction to lowest terms -> Reduce a positive rational number to lowest terms" + +[5ed6f248-ad8d-4d4e-a545-9146c6727f33] +description = "Reduction to lowest terms -> Reduce places the minus sign on the numerator" + +[f87c2a4e-d29c-496e-a193-318c503e4402] +description = "Reduction to lowest terms -> Reduce a negative rational number to lowest terms" + +[3b92ffc0-5b70-4a43-8885-8acee79cdaaf] +description = "Reduction to lowest terms -> Reduce a rational number with a negative denominator to lowest terms" + +[c9dbd2e6-5ac0-4a41-84c1-48b645b4f663] +description = "Reduction to lowest terms -> Reduce zero to lowest terms" + +[297b45ad-2054-4874-84d4-0358dc1b8887] +description = "Reduction to lowest terms -> Reduce an integer to lowest terms" + +[a73a17fe-fe8c-4a1c-a63b-e7579e333d9e] +description = "Reduction to lowest terms -> Reduce one to lowest terms" diff --git a/exercises/practice/rational-numbers/package.yaml b/exercises/practice/rational-numbers/package.yaml new file mode 100644 index 000000000..61207f272 --- /dev/null +++ b/exercises/practice/rational-numbers/package.yaml @@ -0,0 +1,21 @@ +name: rational-numbers +version: 1.0.0.0 + +dependencies: + - base + +library: + exposed-modules: RationalNumbers + source-dirs: src + ghc-options: -Wall + # dependencies: + # - foo # List here the packages you + # - bar # want to use in your solution. + +tests: + test: + main: Tests.hs + source-dirs: test + dependencies: + - rational-numbers + - hspec diff --git a/exercises/practice/rational-numbers/src/RationalNumbers.hs b/exercises/practice/rational-numbers/src/RationalNumbers.hs new file mode 100644 index 000000000..7685c2d48 --- /dev/null +++ b/exercises/practice/rational-numbers/src/RationalNumbers.hs @@ -0,0 +1,53 @@ +module RationalNumbers +(Rational, + abs, + numerator, + denominator, + add, + sub, + mul, + div, + pow, + expRational, + expReal, + rational) where + +import Prelude hiding (div, abs, Rational) + +-- Data definition ------------------------------------------------------------- +data Rational a = Dummy deriving(Eq, Show) + +rational :: Integral a => (a, a) -> Rational a +rational = error "You need to implement this function" + +-- unary operators ------------------------------------------------------------- +abs :: Integral a => Rational a -> Rational a +abs = error "You need to implement this function" + +numerator :: Integral a => Rational a -> a +numerator = error "You need to implement this function" + +denominator :: Integral a => Rational a -> a +denominator = error "You need to implement this function" + +-- binary operators ------------------------------------------------------------ +add :: Integral a => Rational a -> Rational a -> Rational a +add = error "You need to implement this function" + +sub :: Integral a => Rational a -> Rational a -> Rational a +sub = error "You need to implement this function" + +mul :: Integral a => Rational a -> Rational a -> Rational a +mul = error "You need to implement this function" + +div :: Integral a => Rational a -> Rational a -> Rational a +div = error "You need to implement this function" + +pow :: Integral a => Rational a -> a -> Rational a +pow = error "You need to implement this function" + +expRational :: Integral a => Floating b => Rational a -> b -> b +expRational = error "You need to implement this function" + +expReal :: Floating a => Integral b => a -> Rational b -> a +expReal = error "You need to implement this function" diff --git a/exercises/practice/rational-numbers/stack.yaml b/exercises/practice/rational-numbers/stack.yaml new file mode 100644 index 000000000..115878212 --- /dev/null +++ b/exercises/practice/rational-numbers/stack.yaml @@ -0,0 +1 @@ +resolver: lts-20.18 diff --git a/exercises/practice/rational-numbers/test/Tests.hs b/exercises/practice/rational-numbers/test/Tests.hs new file mode 100644 index 000000000..9704d7254 --- /dev/null +++ b/exercises/practice/rational-numbers/test/Tests.hs @@ -0,0 +1,337 @@ +{-# LANGUAGE RecordWildCards #-} + +import Prelude hiding (abs, div, Rational) +import Data.Function (on) +import Data.Foldable (for_) +import Test.Hspec (Spec, describe, it, shouldBe) +import Test.Hspec.Runner (configFailFast, defaultConfig, hspecWith) + +import RationalNumbers + ( Rational + , abs + , numerator + , denominator + , add + , sub + , mul + , div + , pow + , expRational + , expReal + , rational + ) + +main :: IO () +main = hspecWith defaultConfig {configFailFast = True} specs + +specs :: Spec +specs = do + describe "rational" $ for_ rationalCases $ testU rational + describe "numerator" $ for_ numeratorCases $ testU numerator + describe "denominator" $ for_ denominatorCases $ testU denominator + describe "abs" $ for_ absCases $ testU abs + describe "add" $ for_ addCases $ testB add + describe "sub" $ for_ subCases $ testB sub + describe "mul" $ for_ mulCases $ testB mul + describe "div" $ for_ divCases $ testB div + describe "pow" $ for_ powCases $ testB pow + describe "expRational" $ for_ expRationalCases $ testR expRational + describe "expReal" $ for_ expRealCases $ testR expReal + where + testU f CaseU{..} = it descriptionU $ f number1U `shouldBe` expectedU + testB f CaseB{..} = it descriptionB $ f number1B number2B `shouldBe` expectedB + testR f CaseB{..} = it descriptionB $ f number1B number2B `shouldBeAround` expectedB + shouldBeAround = shouldBe `on` roundTo 2 + + roundTo :: Int -> Float -> Float + roundTo n = (/ 10 ^ n) . (fromInteger :: Integer -> Float) . round . (* 10 ^ n) + +data CaseU a b = CaseU { descriptionU :: String + , number1U :: a + , expectedU :: b + } + +data CaseB a b c = CaseB { descriptionB :: String + , number1B :: a + , number2B :: b + , expectedB :: c + } + +rationalCases :: [CaseU (Integer, Integer) (Rational Integer)] +rationalCases = + [ CaseU { descriptionU = "Reduce a positive rational number to lowest terms" + , number1U = (2, 4) + , expectedU = rational (1, 2) + } + , CaseU { descriptionU = "Reduce places the minus sign on the numerator" + , number1U = (3, -4) + , expectedU = rational (-3, 4) + } + , CaseU { descriptionU = "Reduce a negative rational number to lowest terms" + , number1U = (-4, 6) + , expectedU = rational (-2, 3) + } + , CaseU { descriptionU = "Reduce a rational number with a negative denominator to lowest terms" + , number1U = (3, -9) + , expectedU = rational (-1, 3) + } + , CaseU { descriptionU = "Reduce zero to lowest terms" + , number1U = (0, 6) + , expectedU = rational (0, 1) + } + , CaseU { descriptionU = "Reduce an integer to lowest terms" + , number1U = (-14, 7) + , expectedU = rational (-2, 1) + } + , CaseU { descriptionU = "Reduce one to lowest terms" + , number1U = (13, 13) + , expectedU = rational (1, 1) + } + ] + +numeratorCases :: [CaseU (Rational Integer) Integer] +numeratorCases = + [ CaseU { descriptionU = "Numerator of a reduced rational number" + , number1U = rational (3, -4) + , expectedU = -3 + } + ] + +denominatorCases :: [CaseU (Rational Integer) Integer] +denominatorCases = + [ CaseU { descriptionU = "Denominator of a reduced rational number" + , number1U = rational (3, -4) + , expectedU = 4 + } + ] + +absCases :: [CaseU (Rational Integer) (Rational Integer)] +absCases = + [ CaseU { descriptionU = "Absolute value of a positive rational number" + , number1U = rational (1, 2) + , expectedU = rational (1, 2) + } + , CaseU { descriptionU = "Absolute value of a positive rational number with negative numerator and denominator" + , number1U = rational (-1, -2) + , expectedU = rational (1, 2) + } + , CaseU { descriptionU = "Absolute value of a negative rational number" + , number1U = rational (-1, 2) + , expectedU = rational (1, 2) + } + , CaseU { descriptionU = "Absolute value of a negative rational number with negative denominator" + , number1U = rational (1, -2) + , expectedU = rational (1, 2) + } + , CaseU { descriptionU = "Absolute value of zero" + , number1U = rational (0, 1) + , expectedU = rational (0, 1) + } + , CaseU { descriptionU = "Absolute value of a rational number is reduced to lowest terms" + , number1U = rational (2, 4) + , expectedU = rational (1, 2) + } + ] + +addCases :: [CaseB (Rational Integer) (Rational Integer) (Rational Integer)] +addCases = + [ CaseB { descriptionB = "Add two positive rational numbers" + , number1B = rational (1, 2) + , number2B = rational (2, 3) + , expectedB = rational (7, 6) + } + , CaseB { descriptionB = "Add a positive rational number and a negative rational number" + , number1B = rational (1, 2) + , number2B = rational (-2, 3) + , expectedB = rational (-1, 6) + } + , CaseB { descriptionB = "Add two negative rational numbers" + , number1B = rational (-1, 2) + , number2B = rational (-2, 3) + , expectedB = rational (-7, 6) + } + , CaseB { descriptionB = "Add a rational number to its additive inverse" + , number1B = rational (1, 2) + , number2B = rational (-1, 2) + , expectedB = rational (0, 1) + } + ] + +subCases :: [CaseB (Rational Integer) (Rational Integer) (Rational Integer)] +subCases = + [ CaseB { descriptionB = "Subtract two positive rational numbers" + , number1B = rational (1, 2) + , number2B = rational (2, 3) + , expectedB = rational (-1, 6) + } + , CaseB { descriptionB = "Subtract a positive rational number and a negative rational number" + , number1B = rational (1, 2) + , number2B = rational (-2, 3) + , expectedB = rational (7, 6) + } + , CaseB { descriptionB = "Subtract two negative rational numbers" + , number1B = rational (-1, 2) + , number2B = rational (-2, 3) + , expectedB = rational (1, 6) + } + , CaseB { descriptionB = "Subtract a rational number from itself" + , number1B = rational (1, 2) + , number2B = rational (1, 2) + , expectedB = rational (0, 1) + } + ] + +mulCases :: [CaseB (Rational Integer) (Rational Integer) (Rational Integer)] +mulCases = + [ CaseB { descriptionB = "Multiply two positive rational numbers" + , number1B = rational (1, 2) + , number2B = rational (2, 3) + , expectedB = rational (1, 3) + } + , CaseB { descriptionB = "Multiply a negative rational number by a positive rational number" + , number1B = rational (-1, 2) + , number2B = rational (2, 3) + , expectedB = rational (-1, 3) + } + , CaseB { descriptionB = "Multiply two negative rational numbers" + , number1B = rational (-1, 2) + , number2B = rational (-2, 3) + , expectedB = rational (1, 3) + } + , CaseB { descriptionB = "Multiply a rational number by its reciprocal" + , number1B = rational (1, 2) + , number2B = rational (2, 1) + , expectedB = rational (1, 1) + } + , CaseB { descriptionB = "Multiply a rational number by 1" + , number1B = rational (1, 2) + , number2B = rational (1, 1) + , expectedB = rational (1, 2) + } + , CaseB { descriptionB = "Multiply a rational number by 0" + , number1B = rational (1, 2) + , number2B = rational (0, 1) + , expectedB = rational (0, 1) + } + ] + +divCases :: [CaseB (Rational Integer) (Rational Integer) (Rational Integer)] +divCases = + [ CaseB { descriptionB = "Divide two positive rational numbers" + , number1B = rational (1, 2) + , number2B = rational (2, 3) + , expectedB = rational (3, 4) + } + , CaseB { descriptionB = "Divide a positive rational number by a negative rational number" + , number1B = rational (1, 2) + , number2B = rational (-2, 3) + , expectedB = rational (-3, 4) + } + , CaseB { descriptionB = "Divide two negative rational numbers" + , number1B = rational (-1, 2) + , number2B = rational (-2, 3) + , expectedB = rational (3, 4) + } + , CaseB { descriptionB = "Divide a rational number by 1" + , number1B = rational (1, 2) + , number2B = rational (1, 1) + , expectedB = rational (1, 2) + } + ] + +powCases :: [CaseB (Rational Integer) Integer (Rational Integer)] +powCases = + [ CaseB { descriptionB = "Raise a positive rational number to a positive integer power" + , number1B = rational (1, 2) + , number2B = 3 + , expectedB = rational (1, 8) + } + , CaseB { descriptionB = "Raise a negative rational number to a positive integer power" + , number1B = rational (-1, 2) + , number2B = 3 + , expectedB = rational (-1, 8) + } + , CaseB { descriptionB = "Raise a positive rational number to a negative integer power" + , number1B = rational (3, 5) + , number2B = -2 + , expectedB = rational (25, 9) + } + , CaseB { descriptionB = "Raise a negative rational number to an even negative integer power" + , number1B = rational (-3, 5) + , number2B = -2 + , expectedB = rational (25, 9) + } + , CaseB { descriptionB = "Raise a negative rational number to an odd negative integer power" + , number1B = rational (-3, 5) + , number2B = -3 + , expectedB = rational (-125, 27) + } + , CaseB { descriptionB = "Raise zero to an integer power" + , number1B = rational (0, 1) + , number2B = 5 + , expectedB = rational (0, 1) + } + , CaseB { descriptionB = "Raise one to an integer power" + , number1B = rational (1, 1) + , number2B = 4 + , expectedB = rational (1, 1) + } + , CaseB { descriptionB = "Raise a positive rational number to the power of zero" + , number1B = rational (1, 2) + , number2B = 0 + , expectedB = rational (1, 1) + } + , CaseB { descriptionB = "Raise a negative rational number to the power of zero" + , number1B = rational (-1, 2) + , number2B = 0 + , expectedB = rational (1, 1) + } + ] + +expRationalCases :: [CaseB (Rational Integer) Float Float] +expRationalCases = + [ CaseB { descriptionB = "Raise a rational number to a positive real number bigger than 1" + , number1B = rational (1, 2) + , number2B = 3 + , expectedB = 0.125 + } + , CaseB { descriptionB = "Raise a rational number to a positive real number smaller than 1" + , number1B = rational (1, 2) + , number2B = 0.5 + , expectedB = 0.707 + } + , CaseB { descriptionB = "Raise a rational number to a negative real number bigger than 1" + , number1B = rational (1, 2) + , number2B = -3 + , expectedB = 8.0 + } + , CaseB { descriptionB = "Raise a rational number to a negative real number smaller than 1" + , number1B = rational (1, 2) + , number2B = -0.5 + , expectedB = 1.41 + } + , CaseB { descriptionB = "Raise a rational number to a zero real number" + , number1B = rational (4, 3) + , number2B = 0 + , expectedB = 1.0 + } + ] + +expRealCases :: [CaseB Float (Rational Integer) Float] +expRealCases = + [ CaseB { descriptionB = "Raise a real number to a positive rational number" + , number1B = 8 + , number2B = rational (4, 3) + , expectedB = 16.0 + } + , CaseB { descriptionB = "Raise a real number to a negative rational number" + , number1B = 9 + , number2B = rational (-1, 2) + , expectedB = 0.3333333333333333 + } + , CaseB { descriptionB = "Raise a real number to a zero rational number" + , number1B = 2 + , number2B = rational (0, 1) + , expectedB = 1.0 + } + ]