Rational numbers

This commit is contained in:
2023-07-22 23:25:53 +02:00
parent 262dca3a4d
commit 7ee6d469b4
13 changed files with 16515 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
!.meta
# Protected or generated
.git
.vscode
# When using npm
node_modules/*
# Configuration files
.eslintrc.cjs
babel.config.cjs
jest.config.cjs
+41
View File
@@ -0,0 +1,41 @@
module.exports = {
root: true,
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
},
overrides: [
// Student provided files
{
files: ['*.ts'],
excludedFiles: ['.meta/proof.ci.ts', '.meta/exemplar.ts', '*.test.ts'],
extends: '@exercism/eslint-config-typescript',
},
// Exercism given tests
{
files: ['*.test.ts'],
excludedFiles: ['custom.test.ts'],
env: {
jest: true,
},
extends: '@exercism/eslint-config-typescript/maintainers',
},
// Student provided tests
{
files: ['custom.test.ts'],
env: {
jest: true,
},
extends: '@exercism/eslint-config-typescript',
},
// Exercism provided files
{
files: ['.meta/proof.ci.ts', '.meta/exemplar.ts', '*.test.ts'],
excludedFiles: ['custom.test.ts'],
extends: '@exercism/eslint-config-typescript/maintainers',
rules: {
"@typescript-eslint/semi": 0,
},
},
],
}
@@ -0,0 +1,12 @@
{
"blurb": "Implement rational numbers.",
"authors": ["CRivasGomez"],
"contributors": ["masters3d", "SleeplessByte"],
"files": {
"solution": ["rational-numbers.ts"],
"test": ["rational-numbers.test.ts"],
"example": [".meta/proof.ci.ts"]
},
"source": "Wikipedia",
"source_url": "https://en.wikipedia.org/wiki/Rational_number"
}
@@ -0,0 +1 @@
{"track":"typescript","exercise":"rational-numbers","id":"9080cb32b0404fe18481d2b6cf5f37a5","url":"https://exercism.org/tracks/typescript/exercises/rational-numbers","handle":"briemens","is_requester":true,"auto_approve":false}
+44
View File
@@ -0,0 +1,44 @@
# Help
## Running the tests
Execute the tests with:
```bash
$ yarn test
```
## Skipped tests
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 `xit` to
`it`.
## Submitting your solution
You can submit your solution using the `exercism submit rational-numbers.ts` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [TypeScript track's documentation](https://exercism.org/docs/tracks/typescript)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [TypeScript QuickStart](https://www.typescriptlang.org/docs/handbook/release-notes/overview.html)
- [ECMAScript 2015 Language Specification](https://www.ecma-international.org/wp-content/uploads/ECMA-262_6th_edition_june_2015.pdf) (pdf)
- [Mozilla JavaScript Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference)
- [/r/typescript](https://www.reddit.com/r/typescript) is the TypeScript subreddit.
- [StackOverflow](https://stackoverflow.com/questions/tagged/typescript) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.
+50
View File
@@ -0,0 +1,50 @@
# Rational Numbers
Welcome to Rational Numbers on Exercism's TypeScript Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
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.
## Source
### Created by
- @CRivasGomez
### Contributed to by
- @masters3d
- @SleeplessByte
### Based on
Wikipedia - https://en.wikipedia.org/wiki/Rational_number
@@ -0,0 +1,4 @@
module.exports = {
presets: ['@exercism/babel-preset-typescript'],
plugins: [],
}
@@ -0,0 +1,19 @@
module.exports = {
verbose: true,
projects: ['<rootDir>'],
testMatch: [
'**/__tests__/**/*.[jt]s?(x)',
'**/test/**/*.[jt]s?(x)',
'**/?(*.)+(spec|test).[jt]s?(x)',
],
testPathIgnorePatterns: [
'/(?:production_)?node_modules/',
'.d.ts$',
'<rootDir>/test/fixtures',
'<rootDir>/test/helpers',
'__mocks__',
],
transform: {
'^.+\\.[jt]sx?$': 'babel-jest',
},
}
File diff suppressed because it is too large Load Diff
+31
View File
@@ -0,0 +1,31 @@
{
"name": "@exercism/typescript-rational-numbers",
"version": "1.0.0",
"description": "Exercism exercises in Typescript.",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/exercism/typescript"
},
"type": "module",
"engines": {
"node": "^14.13.1 || >=16.0.0"
},
"devDependencies": {
"@exercism/babel-preset-typescript": "^0.1.0",
"@exercism/eslint-config-typescript": "^0.4.1",
"@types/jest": "^27.4.0",
"@types/node": "^16.11.24",
"babel-jest": "^27.5.1",
"core-js": "^3.21.0",
"eslint": "^8.9.0",
"jest": "^27.5.1",
"typescript": "^4.5.4"
},
"scripts": {
"test": "yarn lint:types && jest --no-cache",
"lint": "yarn lint:types && yarn lint:ci",
"lint:types": "yarn tsc --noEmit -p .",
"lint:ci": "eslint . --ext .tsx,.ts"
}
}
@@ -0,0 +1,197 @@
import { Rational } from "./rational-numbers";
describe("Addition", () => {
it("Add two positive rational numbers", () => {
const expected = new Rational(7, 6);
expect(new Rational(1, 2).add(new Rational(2, 3))).toEqual(expected);
});
it("Add a positive rational number and a negative rational number", () => {
const expected = new Rational(-1, 6);
expect(new Rational(1, 2).add(new Rational(-2, 3))).toEqual(expected);
});
it("Add two negative rational numbers", () => {
const expected = new Rational(-7, 6);
expect(new Rational(-1, 2).add(new Rational(-2, 3))).toEqual(expected);
});
it("Add a rational number to its additive inverse", () => {
const expected = new Rational(0, 1);
expect(new Rational(1, 2).add(new Rational(-1, 2))).toEqual(expected);
});
});
describe("Subtraction", () => {
xit("Subtract two positive rational numbers", () => {
const expected = new Rational(-1, 6);
expect(new Rational(1, 2).sub(new Rational(2, 3))).toEqual(expected);
});
xit("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);
});
xit("Subtract two negative rational numbers", () => {
const expected = new Rational(1, 6);
expect(new Rational(-1, 2).sub(new Rational(-2, 3))).toEqual(expected);
});
xit("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", () => {
xit("Multiply two positive rational numbers", () => {
const expected = new Rational(1, 3);
expect(new Rational(1, 2).mul(new Rational(2, 3))).toEqual(expected);
});
xit("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);
});
xit("Multiply two negative rational numbers", () => {
const expected = new Rational(1, 3);
expect(new Rational(-1, 2).mul(new Rational(-2, 3))).toEqual(expected);
});
xit("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);
});
xit("Multiply a rational number by 1", () => {
const expected = new Rational(1, 2);
expect(new Rational(1, 2).mul(new Rational(1, 1))).toEqual(expected);
});
xit("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", () => {
xit("Divide two positive rational numbers", () => {
const expected = new Rational(3, 4);
expect(new Rational(1, 2).div(new Rational(2, 3))).toEqual(expected);
});
xit("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);
});
xit("Divide two negative rational numbers", () => {
const expected = new Rational(3, 4);
expect(new Rational(-1, 2).div(new Rational(-2, 3))).toEqual(expected);
});
xit("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", () => {
xit("Absolute value of a positive rational number", () => {
const expected = new Rational(1, 2);
expect(new Rational(1, 2).abs()).toEqual(expected);
});
xit("Absolute value of a negative rational number", () => {
const expected = new Rational(1, 2);
expect(new Rational(-1, 2).abs()).toEqual(expected);
});
xit("Absolute value of zero", () => {
const expected = new Rational(0, 1);
expect(new Rational(0, 1).abs()).toEqual(expected);
});
});
describe("Exponentiation of a rational number", () => {
xit("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);
});
xit("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);
});
xit("Raise zero to an integer power", () => {
const expected = new Rational(0, 1);
expect(new Rational(0, 1).exprational(5)).toEqual(expected);
});
xit("Raise one to an integer power", () => {
const expected = new Rational(1, 1);
expect(new Rational(1, 1).exprational(4)).toEqual(expected);
});
xit("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);
});
xit("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", () => {
xit("Raise a real number to a positive rational number", () => {
const expected = 16.0;
expect(new Rational(4, 3).expreal(8)).toEqual(expected);
});
xit("Raise a real number to a negative rational number", () => {
const expected = 1.0 / 3.0;
expect(new Rational(-1, 2).expreal(9)).toBeCloseTo(expected, 15);
});
xit("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", () => {
xit("Reduce a positive rational number to lowest terms", () => {
const expected = new Rational(1, 2);
expect(new Rational(2, 4).reduce()).toEqual(expected);
});
xit("Reduce a negative rational number to lowest terms", () => {
const expected = new Rational(-2, 3);
expect(new Rational(-4, 6).reduce()).toEqual(expected);
});
xit("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);
});
xit("Reduce zero to lowest terms", () => {
const expected = new Rational(0, 1);
expect(new Rational(0, 6).reduce()).toEqual(expected);
});
xit("Reduce an integer to lowest terms", () => {
const expected = new Rational(-2, 1);
expect(new Rational(-14, 7).reduce()).toEqual(expected);
});
xit("Reduce one to lowest terms", () => {
const expected = new Rational(1, 1);
expect(new Rational(13, 13).reduce()).toEqual(expected);
});
});
@@ -0,0 +1,79 @@
function isPrime(n: number): boolean {
if (n === 2) {
return true;
}
if (n < 2 || n % 2 === 0) {
return false;
}
for (var i = 3; i <= Math.sqrt(n); i += 2) {
if (n % i === 0) {
return false;
}
}
return true;
}
function* primes(): Generator<number> {
let i = 0;
while (true) {
if (!isPrime(i)) {
i++;
continue;
}
yield i++;
}
}
for (let prime of primes()) {
console.log("prime", prime);
if (prime > 1000) {
break;
}
}
export class Rational {
constructor(public numerator: number, public denominator: number) {
if (denominator < 0) {
this.numerator = numerator * -1;
this.denominator = denominator;
}
}
add(rational: Rational): Rational {
/* 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₂)`. */
return new Rational(
this.numerator * rational.denominator +
this.denominator * rational.numerator,
rational.numerator * rational.denominator
);
}
sub(rational: Rational): Rational {
throw new Error("Remove this statement and implement this function");
}
mul(rational: Rational): Rational {
throw new Error("Remove this statement and implement this function");
}
div(rational: Rational): Rational {
throw new Error("Remove this statement and implement this function");
}
abs(): Rational {
throw new Error("Remove this statement and implement this function");
}
exprational(amount: number): Rational {
throw new Error("Remove this statement and implement this function");
}
expreal(amount: number): Rational {
throw new Error("Remove this statement and implement this function");
}
reduce(): Rational {
throw new Error("Remove this statement and implement this function");
}
}
+28
View File
@@ -0,0 +1,28 @@
{
"display": "Configuration for Exercism TypeScript Exercises",
"compilerOptions": {
// Allows you to use the newest syntax, and have access to console.log
// https://www.typescriptlang.org/tsconfig#lib
"lib": ["ESNEXT", "dom"],
// Make sure typescript is configured to output ESM
// https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c#how-can-i-make-my-typescript-project-output-esm
"module": "ES2020",
// Since this project is using babel, TypeScript may target something very
// high, and babel will make sure it runs on your local Node version.
// https://babeljs.io/docs/en/
"target": "ESNext", // ESLint doesn't support this yet: "es2022",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
// Because we'll be using babel: ensure that Babel can safely transpile
// files in the TypeScript project.
//
// https://babeljs.io/docs/en/babel-plugin-transform-typescript/#caveats
"isolatedModules": true
},
"include": ["*.ts", "*.tsx", ".meta/*.ts", ".meta/*.tsx"],
"exclude": ["node_modules"]
}