diff --git a/DIRECTORY.md b/DIRECTORY.md index 6aaeca9..101f9db 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -24,6 +24,12 @@ * [Euclidean Gcd](https://github.com/TheAlgorithms/Ruby/blob/master/discrete_mathematics/euclidean_gcd.rb) * [Lcm](https://github.com/TheAlgorithms/Ruby/blob/master/discrete_mathematics/lcm.rb) +## Maths + * [Absolute Value](https://github.com/TheAlgorithms/Ruby/blob/master/maths/abs.rb) + * [Aliquot Sum](https://github.com/TheAlgorithms/Ruby/blob/master/maths/aliquot.rb) + * [Ceil](https://github.com/TheAlgorithms/Ruby/blob/master/maths/ceil.rb) + * [Square Root](https://github.com/TheAlgorithms/Ruby/blob/master/maths/square_root.rb) + ## Other * [Fisher Yates](https://github.com/TheAlgorithms/Ruby/blob/master/other/fisher_yates.rb) diff --git a/maths/abs.rb b/maths/abs.rb new file mode 100644 index 0000000..fdbcd81 --- /dev/null +++ b/maths/abs.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Calculates the absolute value of a number +class Abs + def self.call(number) + return -number if number.negative? + + number + end +end diff --git a/maths/abs_test.rb b/maths/abs_test.rb new file mode 100644 index 0000000..2220f9a --- /dev/null +++ b/maths/abs_test.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'minitest/autorun' +require_relative './abs' + +class AbsTest < Minitest::Test + def test_positive_number + assert_equal Abs.call(4), 4 + end + + def test_zero + assert_equal Abs.call(0), 0 + end + + def test_negative_number + assert_equal Abs.call(-9), 9 + end +end diff --git a/maths/aliquot_sum.rb b/maths/aliquot_sum.rb new file mode 100644 index 0000000..910191d --- /dev/null +++ b/maths/aliquot_sum.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require_relative './square_root' +require_relative './ceil' + +# Calculates the aliquot sum of a number (the sum of all proper divisors of a number) +class AliquotSum + class << self + def call(number) + divisors(number).sum + end + + private + + def divisors(number) + low_divisors = (1..Ceil.call(SquareRoot.call(number))).select { |num| (number % num).zero? } + high_divisors = low_divisors.map { |div| number / div } + (low_divisors + high_divisors).uniq - [number] + end + end +end diff --git a/maths/aliquot_sum_test.rb b/maths/aliquot_sum_test.rb new file mode 100644 index 0000000..228838a --- /dev/null +++ b/maths/aliquot_sum_test.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'minitest/autorun' +require_relative './aliquot_sum' + +class AliquotSumTest < Minitest::Test + def test_zero + assert_equal AliquotSum.call(0), 0 + end + + def test_one + assert_equal Abs.call(1), 1 + end + + def test_many + (2..100).each do |number| + expected_aliquot_sum = (1...number).select { |num| (number % num).zero? }.sum + assert_equal AliquotSum.call(number), expected_aliquot_sum + end + end +end diff --git a/maths/ceil.rb b/maths/ceil.rb new file mode 100644 index 0000000..e8930a4 --- /dev/null +++ b/maths/ceil.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class Ceil + class << self + def call(number) + return number if number.is_a?(Integer) || number == number.to_i + + number.to_i + 1 + end + end +end diff --git a/maths/ceil_test.rb b/maths/ceil_test.rb new file mode 100644 index 0000000..11816ee --- /dev/null +++ b/maths/ceil_test.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'minitest/autorun' +require_relative './ceil' + +class CeilTest < Minitest::Test + def test_integer + assert_equal Ceil.call(4), 4 + end + + def test_float_at_integer + assert_equal Ceil.call(4.0), 4 + end + + def test_float_not_at_integer + assert_equal Ceil.call(4.01), 5 + end +end diff --git a/maths/square_root.rb b/maths/square_root.rb new file mode 100644 index 0000000..63f4774 --- /dev/null +++ b/maths/square_root.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# Calculates the square root of a number +class SquareRoot + class << self + EPSILON = 1E-10 + + def call(number) + raise DomainError, 'Cannot find square root of negative number' if number.negative? + return 0 if number.zero? + + find_root(number) + end + + private + + def find_root(x0, xn = x0) + xn1 = xn - ((xn * xn - x0) / (2.0 * xn)) + return xn1 if (xn1 - xn).abs <= EPSILON + + find_root(x0, xn1) + end + end +end + +class DomainError < StandardError; end diff --git a/maths/square_root_test.rb b/maths/square_root_test.rb new file mode 100644 index 0000000..36c097e --- /dev/null +++ b/maths/square_root_test.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'minitest/autorun' +require_relative './square_root' + +class SquareRootTest < Minitest::Test + def test_negative_number + assert_raises DomainError do + SquareRoot.call(-1) + end + end + + def test_zero + assert_equal 0, SquareRoot.call(0) + end + + def test_all_numbers_below_1024 + (1...1024).each do |num| + assert_in_delta SquareRoot.call(num), Math.sqrt(num), 1E-12 + end + end +end