-
-
Notifications
You must be signed in to change notification settings - Fork 402
[#724] New practice exercise rational-numbers
#755
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
angelikatyborska
merged 6 commits into
exercism:main
from
jiegillet:jie-rational-numbers
Jun 12, 2021
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
2867f5f
[#724] New practice exercise
jiegillet 8d30f5a
[#724] New practice exercise `rational-numbers`
jiegillet 8979e94
Merge branch 'jie-rational-numbers' of github.com:jiegillet/elixir in…
jiegillet 579b7ed
use assert_in_delta for float equality
jiegillet 3418d21
add contributor
jiegillet e91d02f
Higher delta
jiegillet File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Description | ||
|
||
A rational number is defined as the quotient of two integers `a` and `b`, called the numerator and denominator, respectively, where `b != 0`. | ||
|
||
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`. | ||
|
||
Assume that the programming language you are using does not have an implementation of rational numbers. | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Used by "mix format" | ||
[ | ||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] | ||
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"blurb": "Implement rational numbers.", | ||
"authors": [ | ||
"jiegillet" | ||
], | ||
"contributors": [ | ||
"angelikatyborska" | ||
], | ||
"files": { | ||
"solution": [ | ||
"lib/rational_numbers.ex" | ||
], | ||
"test": [ | ||
"test/rational_numbers_test.exs" | ||
], | ||
"example": [ | ||
".meta/example.ex" | ||
] | ||
}, | ||
"source": "Wikipedia", | ||
"source_url": "https://en.wikipedia.org/wiki/Rational_number" | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
defmodule RationalNumbers do | ||
@type rational :: {integer, integer} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
||
@doc """ | ||
Add two rational numbers | ||
""" | ||
@spec add(a :: rational, b :: rational) :: rational | ||
def add({a, b}, {c, d}), do: {a * d + c * b, b * d} |> reduce | ||
|
||
@doc """ | ||
Subtract two rational numbers | ||
""" | ||
@spec subtract(a :: rational, b :: rational) :: rational | ||
def subtract(a, {x, y}), do: add(a, {-x, y}) | ||
|
||
@doc """ | ||
Multiply two rational numbers | ||
""" | ||
@spec multiply(a :: rational, b :: rational) :: rational | ||
def multiply({a, b}, {c, d}), do: {a * c, b * d} |> reduce | ||
|
||
@doc """ | ||
Divide two rational numbers | ||
""" | ||
@spec divide_by(num :: rational, den :: rational) :: rational | ||
def divide_by(num, {a, b}), do: multiply(num, {b, a}) | ||
|
||
@doc """ | ||
Absolute value of a rational number | ||
""" | ||
@spec abs(a :: rational) :: rational | ||
def abs({a, b}), do: {Kernel.abs(a), Kernel.abs(b)} |> reduce | ||
|
||
@doc """ | ||
Exponentiation of a rational number by an integer | ||
""" | ||
@spec pow_rational(a :: rational, n :: integer) :: rational | ||
def pow_rational({a, b}, n) when n < 0, do: pow_rational({b, a}, -n) | ||
|
||
def pow_rational({a, b}, n), | ||
do: {:math.pow(a, n) |> round, :math.pow(b, n) |> round} |> reduce | ||
|
||
@doc """ | ||
Exponentiation of a real number by a rational number | ||
""" | ||
@spec pow_real(x :: float, n :: rational) :: float | ||
def pow_real(x, {a, b}), do: :math.pow(x, a / b) | ||
|
||
@doc """ | ||
Reduce a rational number to its lowest terms | ||
""" | ||
@spec reduce(a :: rational) :: rational | ||
def reduce({a, b}) when b < 0, do: reduce({-a, -b}) | ||
|
||
def reduce({a, b}) do | ||
gcd = Integer.gcd(a, b) | ||
{div(a, gcd), div(b, gcd)} | ||
end | ||
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
# This is an auto-generated file. Regular comments will be removed when this | ||
# file is regenerated. Regenerating will not touch any manually added keys, | ||
# so comments can be added in a "comment" key. | ||
|
||
[0ba4d988-044c-4ed5-9215-4d0bb8d0ae9f] | ||
description = "Add two positive rational numbers" | ||
|
||
[88ebc342-a2ac-4812-a656-7b664f718b6a] | ||
description = "Add a positive rational number and a negative rational number" | ||
|
||
[92ed09c2-991e-4082-a602-13557080205c] | ||
description = "Add two negative rational numbers" | ||
|
||
[6e58999e-3350-45fb-a104-aac7f4a9dd11] | ||
description = "Add a rational number to its additive inverse" | ||
|
||
[47bba350-9db1-4ab9-b412-4a7e1f72a66e] | ||
description = "Subtract two positive rational numbers" | ||
|
||
[93926e2a-3e82-4aee-98a7-fc33fb328e87] | ||
description = "Subtract a positive rational number and a negative rational number" | ||
|
||
[a965ba45-9b26-442b-bdc7-7728e4b8d4cc] | ||
description = "Subtract two negative rational numbers" | ||
|
||
[0df0e003-f68e-4209-8c6e-6a4e76af5058] | ||
description = "Subtract a rational number from itself" | ||
|
||
[34fde77a-75f4-4204-8050-8d3a937958d3] | ||
description = "Multiply two positive rational numbers" | ||
|
||
[6d015cf0-0ea3-41f1-93de-0b8e38e88bae] | ||
description = "Multiply a negative rational number by a positive rational number" | ||
|
||
[d1bf1b55-954e-41b1-8c92-9fc6beeb76fa] | ||
description = "Multiply two negative rational numbers" | ||
|
||
[a9b8f529-9ec7-4c79-a517-19365d779040] | ||
description = "Multiply a rational number by its reciprocal" | ||
|
||
[d89d6429-22fa-4368-ab04-9e01a44d3b48] | ||
description = "Multiply a rational number by 1" | ||
|
||
[0d95c8b9-1482-4ed7-bac9-b8694fa90145] | ||
description = "Multiply a rational number by 0" | ||
|
||
[1de088f4-64be-4e6e-93fd-5997ae7c9798] | ||
description = "Divide two positive rational numbers" | ||
|
||
[7d7983db-652a-4e66-981a-e921fb38d9a9] | ||
description = "Divide a positive rational number by a negative rational number" | ||
|
||
[1b434d1b-5b38-4cee-aaf5-b9495c399e34] | ||
description = "Divide two negative rational numbers" | ||
|
||
[d81c2ebf-3612-45a6-b4e0-f0d47812bd59] | ||
description = "Divide a rational number by 1" | ||
|
||
[5fee0d8e-5955-4324-acbe-54cdca94ddaa] | ||
description = "Absolute value of a positive rational number" | ||
|
||
[3cb570b6-c36a-4963-a380-c0834321bcaa] | ||
description = "Absolute value of a positive rational number with negative numerator and denominator" | ||
|
||
[6a05f9a0-1f6b-470b-8ff7-41af81773f25] | ||
description = "Absolute value of a negative rational number" | ||
|
||
[5d0f2336-3694-464f-8df9-f5852fda99dd] | ||
description = "Absolute value of a negative rational number with negative denominator" | ||
|
||
[f8e1ed4b-9dca-47fb-a01e-5311457b3118] | ||
description = "Absolute value of zero" | ||
|
||
[ea2ad2af-3dab-41e7-bb9f-bd6819668a84] | ||
description = "Raise a positive rational number to a positive integer power" | ||
|
||
[8168edd2-0af3-45b1-b03f-72c01332e10a] | ||
description = "Raise a negative rational number to a positive integer power" | ||
|
||
[e2f25b1d-e4de-4102-abc3-c2bb7c4591e4] | ||
description = "Raise zero to an integer power" | ||
|
||
[431cac50-ab8b-4d58-8e73-319d5404b762] | ||
description = "Raise one to an integer power" | ||
|
||
[7d164739-d68a-4a9c-b99f-dd77ce5d55e6] | ||
description = "Raise a positive rational number to the power of zero" | ||
|
||
[eb6bd5f5-f880-4bcd-8103-e736cb6e41d1] | ||
description = "Raise a negative rational number to the power of zero" | ||
|
||
[30b467dd-c158-46f5-9ffb-c106de2fd6fa] | ||
description = "Raise a real number to a positive rational number" | ||
|
||
[6e026bcc-be40-4b7b-ae22-eeaafc5a1789] | ||
description = "Raise a real number to a negative rational number" | ||
|
||
[9f866da7-e893-407f-8cd2-ee85d496eec5] | ||
description = "Raise a real number to a zero rational number" | ||
|
||
[0a63fbde-b59c-4c26-8237-1e0c73354d0a] | ||
description = "Reduce a positive rational number to lowest terms" | ||
|
||
[f87c2a4e-d29c-496e-a193-318c503e4402] | ||
description = "Reduce a negative rational number to lowest terms" | ||
|
||
[3b92ffc0-5b70-4a43-8885-8acee79cdaaf] | ||
description = "Reduce a rational number with a negative denominator to lowest terms" | ||
|
||
[c9dbd2e6-5ac0-4a41-84c1-48b645b4f663] | ||
description = "Reduce zero to lowest terms" | ||
|
||
[297b45ad-2054-4874-84d4-0358dc1b8887] | ||
description = "Reduce an integer to lowest terms" | ||
|
||
[a73a17fe-fe8c-4a1c-a63b-e7579e333d9e] | ||
description = "Reduce one to lowest terms" |
59 changes: 59 additions & 0 deletions
59
exercises/practice/rational-numbers/lib/rational_numbers.ex
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
defmodule RationalNumbers do | ||
@type rational :: {integer, integer} | ||
|
||
@doc """ | ||
Add two rational numbers | ||
""" | ||
@spec add(a :: rational, b :: rational) :: rational | ||
def add(a, b) do | ||
end | ||
|
||
@doc """ | ||
Subtract two rational numbers | ||
""" | ||
@spec subtract(a :: rational, b :: rational) :: rational | ||
def subtract(a, b) do | ||
end | ||
|
||
@doc """ | ||
Multiply two rational numbers | ||
""" | ||
@spec multiply(a :: rational, b :: rational) :: rational | ||
def multiply(a, b) do | ||
end | ||
|
||
@doc """ | ||
Divide two rational numbers | ||
""" | ||
@spec divide_by(num :: rational, den :: rational) :: rational | ||
def divide_by(num, den) do | ||
end | ||
|
||
@doc """ | ||
Absolute value of a rational number | ||
""" | ||
@spec abs(a :: rational) :: rational | ||
def abs(a) do | ||
end | ||
|
||
@doc """ | ||
Exponentiation of a rational number by an integer | ||
""" | ||
@spec pow_rational(a :: rational, n :: integer) :: rational | ||
def pow_rational(a, n) do | ||
end | ||
|
||
@doc """ | ||
Exponentiation of a real number by a rational number | ||
""" | ||
@spec pow_real(x :: float, n :: rational) :: float | ||
def pow_real(x, n) do | ||
end | ||
|
||
@doc """ | ||
Reduce a rational number to its lowest terms | ||
""" | ||
@spec reduce(a :: rational) :: rational | ||
def reduce(a) do | ||
end | ||
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
defmodule RationalNumbers.MixProject do | ||
use Mix.Project | ||
|
||
def project do | ||
[ | ||
app: :rational_numbers, | ||
version: "0.1.0", | ||
# elixir: "~> 1.8", | ||
start_permanent: Mix.env() == :prod, | ||
deps: deps() | ||
] | ||
end | ||
|
||
# Run "mix help compile.app" to learn about applications. | ||
def application do | ||
[ | ||
extra_applications: [:logger] | ||
] | ||
end | ||
|
||
# Run "mix help deps" to learn about dependencies. | ||
defp deps do | ||
[ | ||
# {:dep_from_hexpm, "~> 0.3.0"}, | ||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} | ||
] | ||
end | ||
end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the solution requires
:math.pow
, we have those options:erlang-libraries
, assuming the student will use:math.pow
:math.pow
yourself, I'm guessing that would be eitherrecursion
orenum
withranges
?Integer.pow
andFloat.pow
are available@neenjaw opinions? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think option 2 is the weakest, because
Float.pow
would be too hard to implement, people would search for it and find either:math.pow
or the 1.12 functions.I also think that not all students will have 1.12, that being said, one could understand
basics
as including basic math functions, so I don't really know which option to pick either.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The concern when Elixir was a lot smaller was that distro's didn't update their binaries very often. I think with Elixir's growing popularity distro , I'm personally of a stance not worrying too much about supporting legacy versions. I think options 1/3 are both reasonable. If we are looking at v3 in august, by then 1.12 will have been out for a few months making it much more reasonable to assume new comers would be using it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, let's go with option 3. I'm convinced by:
For the record:
The way we defined concepts,
basics
includes using integer literals and basic math operators defined in theKernel
module (+
,-
,*
,/
), but using theInteger
module is part of theintegers
concept 🙂.