ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# LordNahuel's solution

## to Rational Numbers in the JavaScript Track

Published at Oct 13 2020 · 0 comments
Instructions
Test suite
Solution

#### Note:

This exercise has changed since this solution was written.

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 r1 = a1/b1 and r2 = a2/b2 is r1 + r2 = a1/b1 + a2/b2 = (a1 * b2 + a2 * b1) / (b1 * b2).

The difference of two rational numbers r1 = a1/b1 and r2 = a2/b2 is r1 - r2 = a1/b1 - a2/b2 = (a1 * b2 - a2 * b1) / (b1 * b2).

The product (multiplication) of two rational numbers r1 = a1/b1 and r2 = a2/b2 is r1 * r2 = (a1 * a2) / (b1 * b2).

Dividing a rational number r1 = a1/b1 by another r2 = a2/b2 is r1 / r2 = (a1 * b2) / (a2 * b1) if a2 * b1 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 qth 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.

## Setup

Go through the setup instructions for Javascript to install the necessary dependencies:

https://exercism.io/tracks/javascript/installation

## Requirements

Please cd into exercise directory before running all below commands.

Install assignment dependencies:

\$ npm install

## Making the test suite pass

Execute the tests with:

\$ npm test

In the test suites all tests but the first have been skipped.

Once you get a test passing, you can enable the next one by changing xtest to test.

## Submitting Solutions

Once you have a solution ready, you can submit it using:

exercism submit rational-numbers.js

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

## Exercise Source Credits

### rational-numbers.spec.js

import { Rational } from './rational-numbers';

test('Add two positive rational numbers', () => {
const expected = new Rational(7, 6);
});

xtest('Add a positive rational number and a negative rational number', () => {
const expected = new Rational(-1, 6);
});

xtest('Add two negative rational numbers', () => {
const expected = new Rational(-7, 6);
});

const expected = new Rational(0, 1);
});
});

describe('Subtraction', () => {
xtest('Subtract two positive rational numbers', () => {
const expected = new Rational(-1, 6);
expect(new Rational(1, 2).sub(new Rational(2, 3))).toEqual(expected);
});

xtest('Subtract a positive rational number and a negative rational number', () => {
const expected = new Rational(7, 6);
expect(new Rational(1, 2).sub(new Rational(-2, 3))).toEqual(expected);
});

xtest('Subtract two negative rational numbers', () => {
const expected = new Rational(1, 6);
expect(new Rational(-1, 2).sub(new Rational(-2, 3))).toEqual(expected);
});

xtest('Subtract a rational number from itself', () => {
const expected = new Rational(0, 1);
expect(new Rational(1, 2).sub(new Rational(1, 2))).toEqual(expected);
});
});

describe('Multiplication', () => {
xtest('Multiply two positive rational numbers', () => {
const expected = new Rational(1, 3);
expect(new Rational(1, 2).mul(new Rational(2, 3))).toEqual(expected);
});

xtest('Multiply a negative rational number by a positive rational number', () => {
const expected = new Rational(-1, 3);
expect(new Rational(-1, 2).mul(new Rational(2, 3))).toEqual(expected);
});

xtest('Multiply two negative rational numbers', () => {
const expected = new Rational(1, 3);
expect(new Rational(-1, 2).mul(new Rational(-2, 3))).toEqual(expected);
});

xtest('Multiply a rational number by its reciprocal', () => {
const expected = new Rational(1, 1);
expect(new Rational(1, 2).mul(new Rational(2, 1))).toEqual(expected);
});

xtest('Multiply a rational number by 1', () => {
const expected = new Rational(1, 2);
expect(new Rational(1, 2).mul(new Rational(1, 1))).toEqual(expected);
});

xtest('Multiply a rational number by 0', () => {
const expected = new Rational(0, 1);
expect(new Rational(1, 2).mul(new Rational(0, 1))).toEqual(expected);
});
});

describe('Division', () => {
xtest('Divide two positive rational numbers', () => {
const expected = new Rational(3, 4);
expect(new Rational(1, 2).div(new Rational(2, 3))).toEqual(expected);
});

xtest('Divide a positive rational number by a negative rational number', () => {
const expected = new Rational(-3, 4);
expect(new Rational(1, 2).div(new Rational(-2, 3))).toEqual(expected);
});

xtest('Divide two negative rational numbers', () => {
const expected = new Rational(3, 4);
expect(new Rational(-1, 2).div(new Rational(-2, 3))).toEqual(expected);
});

xtest('Divide a rational number by 1', () => {
const expected = new Rational(1, 2);
expect(new Rational(1, 2).div(new Rational(1, 1))).toEqual(expected);
});
});

describe('Absolute value', () => {
xtest('Absolute value of a positive rational number', () => {
const expected = new Rational(1, 2);
expect(new Rational(1, 2).abs()).toEqual(expected);
});

xtest('Absolute value of a negative rational number', () => {
const expected = new Rational(1, 2);
expect(new Rational(-1, 2).abs()).toEqual(expected);
});

xtest('Absolute value of zero', () => {
const expected = new Rational(0, 1);
expect(new Rational(0, 1).abs()).toEqual(expected);
});
});

describe('Exponentiation of a rational number', () => {
xtest('Raise a positive rational number to a positive integer power', () => {
const expected = new Rational(1, 8);
expect(new Rational(1, 2).exprational(3)).toEqual(expected);
});

xtest('Raise a negative rational number to a positive integer power', () => {
const expected = new Rational(-1, 8);
expect(new Rational(-1, 2).exprational(3)).toEqual(expected);
});

xtest('Raise zero to an integer power', () => {
const expected = new Rational(0, 1);
expect(new Rational(0, 1).exprational(5)).toEqual(expected);
});

xtest('Raise one to an integer power', () => {
const expected = new Rational(1, 1);
expect(new Rational(1, 1).exprational(4)).toEqual(expected);
});

xtest('Raise a positive rational number to the power of zero', () => {
const expected = new Rational(1, 1);
expect(new Rational(1, 2).exprational(0)).toEqual(expected);
});

xtest('Raise a negative rational number to the power of zero', () => {
const expected = new Rational(1, 1);
expect(new Rational(-1, 2).exprational(0)).toEqual(expected);
});
});

describe('Exponentiation of a real number to a rational number', () => {
xtest('Raise a real number to a positive rational number', () => {
const expected = 16.0;
expect(new Rational(4, 3).expreal(8)).toEqual(expected);
});

xtest('Raise a real number to a negative rational number', () => {
expect(new Rational(-1, 2).expreal(9)).toBeCloseTo(0.33, 2);
});

xtest('Raise a real number to a zero rational number', () => {
const expected = 1.0;
expect(new Rational(0, 1).expreal(2)).toEqual(expected);
});
});

describe('Reduction to lowest terms', () => {
xtest('Reduce a positive rational number to lowest terms', () => {
const expected = new Rational(1, 2);
expect(new Rational(2, 4).reduce()).toEqual(expected);
});

xtest('Reduce a negative rational number to lowest terms', () => {
const expected = new Rational(-2, 3);
expect(new Rational(-4, 6).reduce()).toEqual(expected);
});

xtest('Reduce a rational number with a negative denominator to lowest terms', () => {
const expected = new Rational(-1, 3);
expect(new Rational(3, -9).reduce()).toEqual(expected);
});

xtest('Reduce zero to lowest terms', () => {
const expected = new Rational(0, 1);
expect(new Rational(0, 6).reduce()).toEqual(expected);
});

xtest('Reduce an integer to lowest terms', () => {
const expected = new Rational(-2, 1);
expect(new Rational(-14, 7).reduce()).toEqual(expected);
});

xtest('Reduce one to lowest terms', () => {
const expected = new Rational(1, 1);
expect(new Rational(13, 13).reduce()).toEqual(expected);
});
});
//
// This is only a SKELETON file for the 'Rational Numbers' exercise. It's been provided as a
// convenience to get you started writing code faster.
//

class Rational {
constructor(a1 = 0, a2 = 0) {
this.a1 = a1;
this.a2 = a2;
}

let a1 = ((this.a1 * b2) + (this.a2 * b1))
let a2 = (b1 * b2);

(a2 < 0) ? a2 = a2 * -1: a2 = a2;

this.a1 = a1;
this.a2 = a2;

return this;
}

sub(b1, b2) {
let a1 = ((this.a1 * b2) - (this.a2 * b1))
let a2 = (b1 * b2);

(a2 < 0) ? a2 = a2 * -1: a2 = a2;

this.a1 = a1;
this.a2 = a2;

return this;
}

mul(b1, b2) {
let a1 = (this.a1 * this.a2);
let a2 = (b1 * b2);

if ((a2 % a1) === 0 && (a1 % a1) === 0) {
let num = a1;
let negative = 0;

(a1 < 0 && a2 > 0) ? negative = -1 : negative = 1;

a1 = a1 / num * negative;
a2 = a2 / num;
}

(a2 < 0) ? a2 = a2 * -1: a2 = a2;

this.a1 = a1;
this.a2 = a2;

return this;
}

div(b1, b2) {
if (this.a2 != 0 && b1 != 0) {
let a1 = (this.a1 * b2);
let a2 = (this.a2 * b1);

let negative = 0;

(a2 < 0 && b1 > 0) ? negative = -1 : negative = 1;

this.a1 = a1 * negative;
this.a2 = a2 * negative;

return this;
}

return this;
}

abs() {
let a1 = 0;
let a2 = 0;

(this.a1 < 0) ? a1 = this.a1 * -1: a1 = this.a1;
(this.a2 < 0) ? a2 = this.a2 * -1: a2 = this.a2;

this.a1 = a1;
this.a2 = a2;

return this;
}

exprational(exponent) {
let a1 = 0;
let a2 = 0;

if (exponent > 0) {
a1 = Math.pow(this.a1, exponent);
a2 = Math.pow(this.a2, exponent);

this.a1 = a1;
this.a2 = a2;

return this;
} else {
a1 = Math.pow(this.a1, exponent);
a2 = Math.pow(this.a2, exponent);

this.a1 = a1;
this.a2 = a2;

return this;
}
}

reduce() {
let a1 = 0;
let a2 = 0;
let nominator = 0;

if (this.a2 === this.a1) {
if (this.a1 % this.a1 === 0 && this.a2 % this.a2 === 0) {
nominator = this.a1;
a1 = this.a1 / nominator;
a2 = this.a2 / nominator;
}
}

if (this.a1 > this.a2) {
if (this.a1 % this.a2 === 0 && this.a2 % this.a2 === 0) {
nominator = this.a2;
a1 = this.a1 / nominator;
a2 = this.a2 / nominator;
}
} else {
if (this.a2 % this.a1 === 0 && this.a2 % this.a2 === 0) {
nominator = this.a1;
a1 = this.a1 / nominator;
a2 = this.a2 / nominator;
}
}

this.a1 = a1;
this.a2 = a2;

return this;
}
}

const ration1 = new Rational();
console.log(ration1.reduce());