mirror of
https://github.com/TheAlgorithms/JavaScript.git
synced 2025-07-08 21:23:32 +08:00
feat: Test running overhaul, switch to Prettier & reformat everything (#1407)
* chore: Switch to Node 20 + Vitest * chore: migrate to vitest mock functions * chore: code style (switch to prettier) * test: re-enable long-running test Seems the switch to Node 20 and Vitest has vastly improved the code's and / or the test's runtime! see #1193 * chore: code style * chore: fix failing tests * Updated Documentation in README.md * Update contribution guidelines to state usage of Prettier * fix: set prettier printWidth back to 80 * chore: apply updated code style automatically * fix: set prettier line endings to lf again * chore: apply updated code style automatically --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
This commit is contained in:
7
.github/workflows/Ci.yml
vendored
7
.github/workflows/Ci.yml
vendored
@ -15,20 +15,15 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 20
|
||||||
cache: npm
|
cache: npm
|
||||||
|
|
||||||
- name: 📦 Install dependencies
|
- name: 📦 Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: 🧪 Run all tests
|
- name: 🧪 Run all tests
|
||||||
if: ${{ github.event_name == 'push' }}
|
|
||||||
run: npm run test
|
run: npm run test
|
||||||
|
|
||||||
- name: 🧪 Run tests for changed files only
|
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
|
||||||
run: npm run test-changed
|
|
||||||
|
|
||||||
- name: 💄 Code style
|
- name: 💄 Code style
|
||||||
run: npm run style
|
run: npm run style
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ globby([
|
|||||||
"!**/test/**/*",
|
"!**/test/**/*",
|
||||||
'!**/*.test.js',
|
'!**/*.test.js',
|
||||||
'!**/*.manual-test.js',
|
'!**/*.manual-test.js',
|
||||||
'!babel.config.js'
|
'!vitest.config.ts'
|
||||||
])
|
])
|
||||||
// create markdown content
|
// create markdown content
|
||||||
.then(pathsToMarkdown)
|
.then(pathsToMarkdown)
|
5
.github/workflows/UpdateDirectory.yml
vendored
5
.github/workflows/UpdateDirectory.yml
vendored
@ -11,16 +11,17 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 20
|
||||||
cache: npm
|
cache: npm
|
||||||
|
|
||||||
- name: 📦 Install dependencies
|
- name: 📦 Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
|
||||||
- name: 🗄️ Create Directory from JS files
|
- name: 🗄️ Create Directory from JS files
|
||||||
run: node .github/workflows/UpdateDirectory.mjs
|
run: node .github/workflows/UpdateDirectory.js
|
||||||
|
|
||||||
- name: Configure Github Action
|
- name: Configure Github Action
|
||||||
run: |
|
run: |
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
. "$(dirname "$0")/_/husky.sh"
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
npm run style
|
npm run style
|
||||||
npm run test-changed
|
npm run test
|
||||||
|
2
.prettierignore
Normal file
2
.prettierignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.github
|
||||||
|
DIRECTORY.md
|
@ -10,14 +10,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const swap = (arr, i, j) => {
|
const swap = (arr, i, j) => {
|
||||||
const newArray = [...arr];
|
const newArray = [...arr]
|
||||||
|
|
||||||
[newArray[i], newArray[j]] = [newArray[j], newArray[i]] // Swapping elements ES6 way
|
;[newArray[i], newArray[j]] = [newArray[j], newArray[i]] // Swapping elements ES6 way
|
||||||
|
|
||||||
return newArray
|
return newArray
|
||||||
}
|
}
|
||||||
|
|
||||||
const permutations = arr => {
|
const permutations = (arr) => {
|
||||||
const P = []
|
const P = []
|
||||||
const permute = (arr, low, high) => {
|
const permute = (arr, low, high) => {
|
||||||
if (low === high) {
|
if (low === high) {
|
||||||
|
@ -19,12 +19,14 @@ class OpenKnightTour {
|
|||||||
[i - 1, j + 2]
|
[i - 1, j + 2]
|
||||||
]
|
]
|
||||||
|
|
||||||
return moves.filter(([y, x]) => y >= 0 && y < this.size && x >= 0 && x < this.size)
|
return moves.filter(
|
||||||
|
([y, x]) => y >= 0 && y < this.size && x >= 0 && x < this.size
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
isComplete() {
|
isComplete() {
|
||||||
// helper function to check if the board is complete
|
// helper function to check if the board is complete
|
||||||
return !this.board.map(row => row.includes(0)).includes(true)
|
return !this.board.map((row) => row.includes(0)).includes(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
solve() {
|
solve() {
|
||||||
@ -52,7 +54,7 @@ class OpenKnightTour {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
printBoard (output = value => console.log(value)) {
|
printBoard(output = (value) => console.log(value)) {
|
||||||
// utility function to display the board
|
// utility function to display the board
|
||||||
for (const row of this.board) {
|
for (const row of this.board) {
|
||||||
let string = ''
|
let string = ''
|
||||||
|
@ -54,7 +54,7 @@ class NQueens {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
printBoard (output = value => console.log(value)) {
|
printBoard(output = (value) => console.log(value)) {
|
||||||
if (!output._isMockFunction) {
|
if (!output._isMockFunction) {
|
||||||
output('\n')
|
output('\n')
|
||||||
}
|
}
|
||||||
|
@ -22,15 +22,19 @@
|
|||||||
* @throws TypeError When the given grid is invalid.
|
* @throws TypeError When the given grid is invalid.
|
||||||
*/
|
*/
|
||||||
function validateGrid(grid) {
|
function validateGrid(grid) {
|
||||||
if (!Array.isArray(grid) || grid.length === 0) throw new TypeError('Grid must be a non-empty array')
|
if (!Array.isArray(grid) || grid.length === 0)
|
||||||
|
throw new TypeError('Grid must be a non-empty array')
|
||||||
|
|
||||||
const allRowsHaveCorrectLength = grid.every(row => row.length === grid.length)
|
const allRowsHaveCorrectLength = grid.every(
|
||||||
|
(row) => row.length === grid.length
|
||||||
|
)
|
||||||
if (!allRowsHaveCorrectLength) throw new TypeError('Grid must be a square')
|
if (!allRowsHaveCorrectLength) throw new TypeError('Grid must be a square')
|
||||||
|
|
||||||
const allCellsHaveValidValues = grid.every(row => {
|
const allCellsHaveValidValues = grid.every((row) => {
|
||||||
return row.every(cell => cell === 0 || cell === 1)
|
return row.every((cell) => cell === 0 || cell === 1)
|
||||||
})
|
})
|
||||||
if (!allCellsHaveValidValues) throw new TypeError('Grid must only contain 0s and 1s')
|
if (!allCellsHaveValidValues)
|
||||||
|
throw new TypeError('Grid must only contain 0s and 1s')
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSafe(grid, x, y) {
|
function isSafe(grid, x, y) {
|
||||||
|
@ -29,8 +29,8 @@ class Sudoku {
|
|||||||
// checking through the 3x3 block of the cell
|
// checking through the 3x3 block of the cell
|
||||||
const secRow = Math.floor(y / 3)
|
const secRow = Math.floor(y / 3)
|
||||||
const secCol = Math.floor(x / 3)
|
const secCol = Math.floor(x / 3)
|
||||||
for (let i = (secRow * 3); i < ((secRow * 3) + 3); i++) {
|
for (let i = secRow * 3; i < secRow * 3 + 3; i++) {
|
||||||
for (let j = (secCol * 3); j < ((secCol * 3) + 3); j++) {
|
for (let j = secCol * 3; j < secCol * 3 + 3; j++) {
|
||||||
if (y !== i && x !== j && this.board[i][j] === value) return false
|
if (y !== i && x !== j && this.board[i][j] === value) return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,9 +67,12 @@ class Sudoku {
|
|||||||
output('- - - - - - - - - - - -')
|
output('- - - - - - - - - - - -')
|
||||||
}
|
}
|
||||||
output(
|
output(
|
||||||
...this.getSection(i, [0, 3]), ' | ',
|
...this.getSection(i, [0, 3]),
|
||||||
...this.getSection(i, [3, 6]), ' | ',
|
' | ',
|
||||||
...this.getSection(i, [6, 9]))
|
...this.getSection(i, [3, 6]),
|
||||||
|
' | ',
|
||||||
|
...this.getSection(i, [6, 9])
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,22 @@ import { Combinations } from '../AllCombinationsOfSizeK'
|
|||||||
describe('AllCombinationsOfSizeK', () => {
|
describe('AllCombinationsOfSizeK', () => {
|
||||||
it('should return 3x2 matrix solution for n = 3 and k = 2', () => {
|
it('should return 3x2 matrix solution for n = 3 and k = 2', () => {
|
||||||
const test1 = new Combinations(3, 2)
|
const test1 = new Combinations(3, 2)
|
||||||
expect(test1.findCombinations()).toEqual([[1, 2], [1, 3], [2, 3]])
|
expect(test1.findCombinations()).toEqual([
|
||||||
|
[1, 2],
|
||||||
|
[1, 3],
|
||||||
|
[2, 3]
|
||||||
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return 6x2 matrix solution for n = 4 and k = 2', () => {
|
it('should return 6x2 matrix solution for n = 4 and k = 2', () => {
|
||||||
const test2 = new Combinations(4, 2)
|
const test2 = new Combinations(4, 2)
|
||||||
expect(test2.findCombinations()).toEqual([[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]])
|
expect(test2.findCombinations()).toEqual([
|
||||||
|
[1, 2],
|
||||||
|
[1, 3],
|
||||||
|
[1, 4],
|
||||||
|
[2, 3],
|
||||||
|
[2, 4],
|
||||||
|
[3, 4]
|
||||||
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
import { generateParentheses } from '../generateParentheses'
|
import { generateParentheses } from '../generateParentheses'
|
||||||
|
|
||||||
test('generate all valid parentheses of input 3', () => {
|
test('generate all valid parentheses of input 3', () => {
|
||||||
expect(generateParentheses(3)).toStrictEqual(['((()))', '(()())', '(())()', '()(())', '()()()'])
|
expect(generateParentheses(3)).toStrictEqual([
|
||||||
|
'((()))',
|
||||||
|
'(()())',
|
||||||
|
'(())()',
|
||||||
|
'()(())',
|
||||||
|
'()()()'
|
||||||
|
])
|
||||||
})
|
})
|
||||||
|
@ -14,6 +14,8 @@ describe('NQueens', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should throw RangeError for negative size board', () => {
|
it('should throw RangeError for negative size board', () => {
|
||||||
expect(() => { return new NQueens(-1) }).toThrow(RangeError)
|
expect(() => {
|
||||||
|
return new NQueens(-1)
|
||||||
|
}).toThrow(RangeError)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -7,14 +7,18 @@ describe('RatInAMaze', () => {
|
|||||||
for (const value of values) {
|
for (const value of values) {
|
||||||
// we deliberately want to check whether this constructor call fails or not
|
// we deliberately want to check whether this constructor call fails or not
|
||||||
// eslint-disable-next-line no-new
|
// eslint-disable-next-line no-new
|
||||||
expect(() => { new RatInAMaze(value) }).toThrow()
|
expect(() => {
|
||||||
|
new RatInAMaze(value)
|
||||||
|
}).toThrow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should fail for an empty array', () => {
|
it('should fail for an empty array', () => {
|
||||||
// we deliberately want to check whether this constructor call fails or not
|
// we deliberately want to check whether this constructor call fails or not
|
||||||
// eslint-disable-next-line no-new
|
// eslint-disable-next-line no-new
|
||||||
expect(() => { new RatInAMaze([]) }).toThrow()
|
expect(() => {
|
||||||
|
new RatInAMaze([])
|
||||||
|
}).toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should fail for a non-square array', () => {
|
it('should fail for a non-square array', () => {
|
||||||
@ -25,7 +29,9 @@ describe('RatInAMaze', () => {
|
|||||||
|
|
||||||
// we deliberately want to check whether this constructor call fails or not
|
// we deliberately want to check whether this constructor call fails or not
|
||||||
// eslint-disable-next-line no-new
|
// eslint-disable-next-line no-new
|
||||||
expect(() => { new RatInAMaze(array) }).toThrow()
|
expect(() => {
|
||||||
|
new RatInAMaze(array)
|
||||||
|
}).toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should fail for arrays containing invalid values', () => {
|
it('should fail for arrays containing invalid values', () => {
|
||||||
@ -34,7 +40,9 @@ describe('RatInAMaze', () => {
|
|||||||
for (const value of values) {
|
for (const value of values) {
|
||||||
// we deliberately want to check whether this constructor call fails or not
|
// we deliberately want to check whether this constructor call fails or not
|
||||||
// eslint-disable-next-line no-new
|
// eslint-disable-next-line no-new
|
||||||
expect(() => { new RatInAMaze(value) }).toThrow()
|
expect(() => {
|
||||||
|
new RatInAMaze(value)
|
||||||
|
}).toThrow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -51,13 +59,20 @@ describe('RatInAMaze', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should work for a simple 3x3 maze', () => {
|
it('should work for a simple 3x3 maze', () => {
|
||||||
const maze = new RatInAMaze([[1, 1, 0], [0, 1, 0], [0, 1, 1]])
|
const maze = new RatInAMaze([
|
||||||
|
[1, 1, 0],
|
||||||
|
[0, 1, 0],
|
||||||
|
[0, 1, 1]
|
||||||
|
])
|
||||||
expect(maze.solved).toBe(true)
|
expect(maze.solved).toBe(true)
|
||||||
expect(maze.path).toBe('RDDR')
|
expect(maze.path).toBe('RDDR')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should work for a simple 2x2 that can not be solved', () => {
|
it('should work for a simple 2x2 that can not be solved', () => {
|
||||||
const maze = new RatInAMaze([[1, 0], [0, 1]])
|
const maze = new RatInAMaze([
|
||||||
|
[1, 0],
|
||||||
|
[0, 1]
|
||||||
|
])
|
||||||
expect(maze.solved).toBe(false)
|
expect(maze.solved).toBe(false)
|
||||||
expect(maze.path).toBe('')
|
expect(maze.path).toBe('')
|
||||||
})
|
})
|
||||||
|
@ -28,7 +28,9 @@ describe('Sudoku', () => {
|
|||||||
it('should create a valid board successfully', () => {
|
it('should create a valid board successfully', () => {
|
||||||
// we deliberately want to check whether this constructor call fails or not
|
// we deliberately want to check whether this constructor call fails or not
|
||||||
// eslint-disable-next-line no-new
|
// eslint-disable-next-line no-new
|
||||||
expect(() => { new Sudoku(data) }).not.toThrow()
|
expect(() => {
|
||||||
|
new Sudoku(data)
|
||||||
|
}).not.toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should find an empty cell', () => {
|
it('should find an empty cell', () => {
|
||||||
|
@ -12,6 +12,6 @@
|
|||||||
* const result = isPowerOfFour(16); // Returns true (16 is 4^2)
|
* const result = isPowerOfFour(16); // Returns true (16 is 4^2)
|
||||||
* const result2 = isPowerOfFour(5); // Returns false (5 is not a power of four)
|
* const result2 = isPowerOfFour(5); // Returns false (5 is not a power of four)
|
||||||
*/
|
*/
|
||||||
const isPowerOfFour = (n) => ((n > 0) && ((n & n - 1) === 0) && (n % 3 === 1))
|
const isPowerOfFour = (n) => n > 0 && (n & (n - 1)) === 0 && n % 3 === 1
|
||||||
|
|
||||||
export { isPowerOfFour }
|
export { isPowerOfFour }
|
||||||
|
@ -94,8 +94,8 @@ Be confident that your code works. When was the last time you committed a code c
|
|||||||
your app stopped working? Mine was last week. Writing tests for our Algorithms will help us ensure the implementations
|
your app stopped working? Mine was last week. Writing tests for our Algorithms will help us ensure the implementations
|
||||||
are airtight even after multiple fixes and code changes.
|
are airtight even after multiple fixes and code changes.
|
||||||
|
|
||||||
We use [Jest](https://jestjs.io/) to run unit tests on our algorithms. It provides a very readable and expressive way to
|
We use [Vitest](https://vitest.dev/) to run unit tests on our algorithms. It provides a very readable and expressive
|
||||||
structure your test code.
|
way to structure your test code.
|
||||||
|
|
||||||
It is advised that the algorithm file (module) does not contain any "live" code but rather just exports the function(s)
|
It is advised that the algorithm file (module) does not contain any "live" code but rather just exports the function(s)
|
||||||
needed to execute the algorithm. Your test code can import those function(s), call them with the appropriate parameters
|
needed to execute the algorithm. Your test code can import those function(s), call them with the appropriate parameters
|
||||||
@ -122,34 +122,23 @@ If you want to save some time and just run a specific test:
|
|||||||
npm test -- koch
|
npm test -- koch
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also start Jest in "watch" mode:
|
You can also start Vitest in "watch" mode:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm test -- --watchAll
|
npm test-watch
|
||||||
```
|
|
||||||
|
|
||||||
We also prepared a helper script that runs tests only for changed files:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run test-changed
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This will run all tests and watch source and test files for changes. When a change is made, the tests will run again.
|
This will run all tests and watch source and test files for changes. When a change is made, the tests will run again.
|
||||||
|
|
||||||
#### Coding Style
|
#### Coding Style
|
||||||
|
|
||||||
To maximize the readability and correctness of our code, we require that new submissions follow the
|
For consistency and readability, we require that new submissions follow the [Prettier Style](https://prettier.io/).
|
||||||
[JavaScript Standard Style](https://standardjs.com/).
|
Before committing, please format your code automatically using Prettier by running the following command:
|
||||||
|
|
||||||
Before committing, please run:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run style
|
npm run style
|
||||||
```
|
```
|
||||||
|
|
||||||
In order to apply the coding style (where it can be done automatically). If an error is shown, please figure out what's
|
|
||||||
wrong, fix it and run standard again.
|
|
||||||
|
|
||||||
A few (but not all) of the things to keep in mind:
|
A few (but not all) of the things to keep in mind:
|
||||||
|
|
||||||
- Use camelCase with the leading character as lowercase for identifier names (variables and functions).
|
- Use camelCase with the leading character as lowercase for identifier names (variables and functions).
|
||||||
|
@ -10,8 +10,12 @@ class CacheNode {
|
|||||||
|
|
||||||
// This frequency map class will act like javascript Map DS with more two custom method refresh & insert
|
// This frequency map class will act like javascript Map DS with more two custom method refresh & insert
|
||||||
class FrequencyMap extends Map {
|
class FrequencyMap extends Map {
|
||||||
static get [Symbol.species] () { return Map } // for using Symbol.species we can access Map constructor @see -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@species
|
static get [Symbol.species]() {
|
||||||
get [Symbol.toStringTag] () { return '' }
|
return Map
|
||||||
|
} // for using Symbol.species we can access Map constructor @see -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@species
|
||||||
|
get [Symbol.toStringTag]() {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @method refresh
|
* @method refresh
|
||||||
|
@ -15,11 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
const memoize = (func, cache = new Map()) => {
|
const memoize = (func, cache = new Map()) => {
|
||||||
const jsonReplacer = (_, value) => {
|
const jsonReplacer = (_, value) => {
|
||||||
if (value instanceof Set) { // if the value is Set it's converted to Array cause JSON.stringify can't convert Set
|
if (value instanceof Set) {
|
||||||
|
// if the value is Set it's converted to Array cause JSON.stringify can't convert Set
|
||||||
return [...value]
|
return [...value]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value instanceof Map) { // if the value is Map it's converted to Object cause JSON.stringify can't convert Map
|
if (value instanceof Map) {
|
||||||
|
// if the value is Map it's converted to Object cause JSON.stringify can't convert Map
|
||||||
return Object.fromEntries(value)
|
return Object.fromEntries(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,8 @@ describe('Testing LFUCache class', () => {
|
|||||||
leastFrequency: 2
|
leastFrequency: 2
|
||||||
})
|
})
|
||||||
|
|
||||||
const json = '{"misses":3,"hits":6,"cache":{"2":{"key":"2","value":2,"frequency":4},"4":{"key":"4","value":4,"frequency":2}}}'
|
const json =
|
||||||
|
'{"misses":3,"hits":6,"cache":{"2":{"key":"2","value":2,"frequency":4},"4":{"key":"4","value":4,"frequency":2}}}'
|
||||||
expect(cache.toString()).toBe(json)
|
expect(cache.toString()).toBe(json)
|
||||||
|
|
||||||
const cacheInstance = cache.parse(json) // again merge the json
|
const cacheInstance = cache.parse(json) // again merge the json
|
||||||
@ -45,7 +46,8 @@ describe('Testing LFUCache class', () => {
|
|||||||
|
|
||||||
cache.capacity = 1 // decrease the capacity
|
cache.capacity = 1 // decrease the capacity
|
||||||
|
|
||||||
expect(cache.info).toEqual({ // after merging the info
|
expect(cache.info).toEqual({
|
||||||
|
// after merging the info
|
||||||
misses: 6,
|
misses: 6,
|
||||||
hits: 12,
|
hits: 12,
|
||||||
capacity: 1,
|
capacity: 1,
|
||||||
|
@ -43,11 +43,7 @@ describe('Testing Memoize', () => {
|
|||||||
|
|
||||||
it('expects the union function to use the cache on the second call', () => {
|
it('expects the union function to use the cache on the second call', () => {
|
||||||
const memoUnion = memoize(union)
|
const memoUnion = memoize(union)
|
||||||
const inputs = [
|
const inputs = [new Set([1, 2, 3]), new Set([4, 3, 2]), new Set([5, 3, 6])]
|
||||||
new Set([1, 2, 3]),
|
|
||||||
new Set([4, 3, 2]),
|
|
||||||
new Set([5, 3, 6])
|
|
||||||
]
|
|
||||||
|
|
||||||
expect(memoUnion(...inputs)).toEqual(new Set([1, 2, 3, 4, 5, 6]))
|
expect(memoUnion(...inputs)).toEqual(new Set([1, 2, 3, 4, 5, 6]))
|
||||||
expect(memoUnion(...inputs)).toEqual(union(...inputs))
|
expect(memoUnion(...inputs)).toEqual(union(...inputs))
|
||||||
|
@ -31,7 +31,5 @@ export const fibonacciCache = (n, cache = null) => {
|
|||||||
* @return {new Set}
|
* @return {new Set}
|
||||||
*/
|
*/
|
||||||
export const union = (...sets) => {
|
export const union = (...sets) => {
|
||||||
return new Set(
|
return new Set(sets.reduce((flatArray, set) => [...flatArray, ...set], []))
|
||||||
sets.reduce((flatArray, set) => [...flatArray, ...set], [])
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,14 @@ export function newGeneration (cells) {
|
|||||||
let neighbourCount = 0
|
let neighbourCount = 0
|
||||||
if (i > 0 && j > 0) neighbourCount += cells[i - 1][j - 1]
|
if (i > 0 && j > 0) neighbourCount += cells[i - 1][j - 1]
|
||||||
if (i > 0) neighbourCount += cells[i - 1][j]
|
if (i > 0) neighbourCount += cells[i - 1][j]
|
||||||
if (i > 0 && j < cells[i].length - 1) neighbourCount += cells[i - 1][j + 1]
|
if (i > 0 && j < cells[i].length - 1)
|
||||||
|
neighbourCount += cells[i - 1][j + 1]
|
||||||
if (j > 0) neighbourCount += cells[i][j - 1]
|
if (j > 0) neighbourCount += cells[i][j - 1]
|
||||||
if (j < cells[i].length - 1) neighbourCount += cells[i][j + 1]
|
if (j < cells[i].length - 1) neighbourCount += cells[i][j + 1]
|
||||||
if (i < cells.length - 1 && j > 0) neighbourCount += cells[i + 1][j - 1]
|
if (i < cells.length - 1 && j > 0) neighbourCount += cells[i + 1][j - 1]
|
||||||
if (i < cells.length - 1) neighbourCount += cells[i + 1][j]
|
if (i < cells.length - 1) neighbourCount += cells[i + 1][j]
|
||||||
if (i < cells.length - 1 && j < cells[i].length - 1) neighbourCount += cells[i + 1][j + 1]
|
if (i < cells.length - 1 && j < cells[i].length - 1)
|
||||||
|
neighbourCount += cells[i + 1][j + 1]
|
||||||
|
|
||||||
// Decide whether the cell is alive or dead
|
// Decide whether the cell is alive or dead
|
||||||
const alive = cells[i][j] === 1
|
const alive = cells[i][j] === 1
|
||||||
|
@ -70,14 +70,20 @@ export function getNextElementaryGeneration (generation, rule) {
|
|||||||
const MAX_RULE = 255
|
const MAX_RULE = 255
|
||||||
|
|
||||||
if (!Number.isInteger(rule)) {
|
if (!Number.isInteger(rule)) {
|
||||||
throw new Error(`Rule must be an integer between the values 0 and 255 (got ${rule})`)
|
throw new Error(
|
||||||
|
`Rule must be an integer between the values 0 and 255 (got ${rule})`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (rule < MIN_RULE || rule > MAX_RULE) {
|
if (rule < MIN_RULE || rule > MAX_RULE) {
|
||||||
throw new RangeError(`Rule must be an integer between the values 0 and 255 (got ${rule})`)
|
throw new RangeError(
|
||||||
|
`Rule must be an integer between the values 0 and 255 (got ${rule})`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const binaryRule = rule.toString(2).padStart(NUM_ELEMENTARY_NEIGHBORHOOD_STATES, '0')
|
const binaryRule = rule
|
||||||
const ruleData = binaryRule.split('').map(bit => Number.parseInt(bit)) // note that ruleData[0] represents "all alive" while ruleData[7] represents "all dead"
|
.toString(2)
|
||||||
|
.padStart(NUM_ELEMENTARY_NEIGHBORHOOD_STATES, '0')
|
||||||
|
const ruleData = binaryRule.split('').map((bit) => Number.parseInt(bit)) // note that ruleData[0] represents "all alive" while ruleData[7] represents "all dead"
|
||||||
const output = new Array(generation.length)
|
const output = new Array(generation.length)
|
||||||
const LEFT_DEAD = 4 // 100 in binary
|
const LEFT_DEAD = 4 // 100 in binary
|
||||||
const MIDDLE_DEAD = 2 // 010 in binary
|
const MIDDLE_DEAD = 2 // 010 in binary
|
||||||
|
@ -2,7 +2,16 @@ import { newGeneration } from '../ConwaysGameOfLife'
|
|||||||
|
|
||||||
describe('newGeneration', () => {
|
describe('newGeneration', () => {
|
||||||
it('should produce the next generation according to the rules', () => {
|
it('should produce the next generation according to the rules', () => {
|
||||||
expect(newGeneration([[0, 1, 0], [0, 1, 0], [0, 1, 0]]))
|
expect(
|
||||||
.toEqual([[0, 0, 0], [1, 1, 1], [0, 0, 0]])
|
newGeneration([
|
||||||
|
[0, 1, 0],
|
||||||
|
[0, 1, 0],
|
||||||
|
[0, 1, 0]
|
||||||
|
])
|
||||||
|
).toEqual([
|
||||||
|
[0, 0, 0],
|
||||||
|
[1, 1, 1],
|
||||||
|
[0, 0, 0]
|
||||||
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -3,91 +3,137 @@ import { getNextElementaryGeneration } from '../Elementary'
|
|||||||
describe('Elementary Cellular Automata', () => {
|
describe('Elementary Cellular Automata', () => {
|
||||||
describe('Rule Errors', () => {
|
describe('Rule Errors', () => {
|
||||||
it('Correct', () => {
|
it('Correct', () => {
|
||||||
expect(() => getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 128)).not.toThrow()
|
expect(() =>
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 128)
|
||||||
|
).not.toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Less than 0', () => {
|
it('Less than 0', () => {
|
||||||
expect(() => getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], -1)).toThrow()
|
expect(() =>
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], -1)
|
||||||
|
).toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Greater than 255', () => {
|
it('Greater than 255', () => {
|
||||||
expect(() => getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 256)).toThrow()
|
expect(() =>
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 256)
|
||||||
|
).toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Decimal', () => {
|
it('Decimal', () => {
|
||||||
expect(() => getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 100.4)).toThrow()
|
expect(() =>
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 100.4)
|
||||||
|
).toThrow()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Rule 54 Iterations', () => {
|
describe('Rule 54 Iterations', () => {
|
||||||
it('Generation 1', () => {
|
it('Generation 1', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 54)).toEqual([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 54)
|
||||||
|
).toEqual([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 2', () => {
|
it('Generation 2', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 54)).toEqual([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 54)
|
||||||
|
).toEqual([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 3', () => {
|
it('Generation 3', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0], 54)).toEqual([0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0], 54)
|
||||||
|
).toEqual([0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 4', () => {
|
it('Generation 4', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0], 54)).toEqual([0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0], 54)
|
||||||
|
).toEqual([0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Rule 222 Iterations', () => {
|
describe('Rule 222 Iterations', () => {
|
||||||
it('Generation 1', () => {
|
it('Generation 1', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 222)).toEqual([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 222)
|
||||||
|
).toEqual([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 2', () => {
|
it('Generation 2', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 222)).toEqual([0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 222)
|
||||||
|
).toEqual([0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 3', () => {
|
it('Generation 3', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], 222)).toEqual([0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], 222)
|
||||||
|
).toEqual([0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 4', () => {
|
it('Generation 4', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0], 222)).toEqual([0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0], 222)
|
||||||
|
).toEqual([0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Rule 60 Iterations', () => {
|
describe('Rule 60 Iterations', () => {
|
||||||
it('Generation 1', () => {
|
it('Generation 1', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 60)).toEqual([0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 60)
|
||||||
|
).toEqual([0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 2', () => {
|
it('Generation 2', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], 60)).toEqual([0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], 60)
|
||||||
|
).toEqual([0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 3', () => {
|
it('Generation 3', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0], 60)).toEqual([0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0], 60)
|
||||||
|
).toEqual([0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 4', () => {
|
it('Generation 4', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0], 60)).toEqual([0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0], 60)
|
||||||
|
).toEqual([0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Rule 90 Iterations', () => {
|
describe('Rule 90 Iterations', () => {
|
||||||
it('Generation 1', () => {
|
it('Generation 1', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 90)).toEqual([0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 90)
|
||||||
|
).toEqual([0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 2', () => {
|
it('Generation 2', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0], 90)).toEqual([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0], 90)
|
||||||
|
).toEqual([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 3', () => {
|
it('Generation 3', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0], 90)).toEqual([0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0], 90)
|
||||||
|
).toEqual([0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 4', () => {
|
it('Generation 4', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], 90)).toEqual([0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], 90)
|
||||||
|
).toEqual([0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Rule 30 Iterations', () => {
|
describe('Rule 30 Iterations', () => {
|
||||||
it('Generation 1', () => {
|
it('Generation 1', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 30)).toEqual([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], 30)
|
||||||
|
).toEqual([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 2', () => {
|
it('Generation 2', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 30)).toEqual([0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0], 30)
|
||||||
|
).toEqual([0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0])
|
||||||
})
|
})
|
||||||
it('Generation 3', () => {
|
it('Generation 3', () => {
|
||||||
expect(getNextElementaryGeneration([0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0], 30)).toEqual([0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0])
|
expect(
|
||||||
|
getNextElementaryGeneration([0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0], 30)
|
||||||
|
).toEqual([0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -58,7 +58,7 @@ function isCorrectFormat (str, a, b) {
|
|||||||
* @return {Boolean} Character index
|
* @return {Boolean} Character index
|
||||||
*/
|
*/
|
||||||
function findCharIndex(char) {
|
function findCharIndex(char) {
|
||||||
return char.toUpperCase().charCodeAt(0) - ('A').charCodeAt(0)
|
return char.toUpperCase().charCodeAt(0) - 'A'.charCodeAt(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
Find and retrieve the encryption key automatically
|
Find and retrieve the encryption key automatically
|
||||||
Note: This is a draft version, please help to modify, Thanks!
|
Note: This is a draft version, please help to modify, Thanks!
|
||||||
******************************************************/
|
******************************************************/
|
||||||
function keyFinder (str) { // str is used to get the input of encrypted string
|
function keyFinder(str) {
|
||||||
|
// str is used to get the input of encrypted string
|
||||||
const wordBank = [
|
const wordBank = [
|
||||||
'I ',
|
'I ',
|
||||||
'You ',
|
'You ',
|
||||||
@ -27,13 +28,15 @@ function keyFinder (str) { // str is used to get the input of encrypted string
|
|||||||
' may ',
|
' may ',
|
||||||
'May ',
|
'May ',
|
||||||
' be ',
|
' be ',
|
||||||
'Be ']
|
'Be '
|
||||||
|
]
|
||||||
// let wordbankelementCounter = 0;
|
// let wordbankelementCounter = 0;
|
||||||
// let key = 0; // return zero means the key can not be found
|
// let key = 0; // return zero means the key can not be found
|
||||||
const inStr = str.toString() // convert the input to String
|
const inStr = str.toString() // convert the input to String
|
||||||
let outStr = '' // store the output value
|
let outStr = '' // store the output value
|
||||||
let outStrElement = '' // temporary store the word inside the outStr, it is used for comparison
|
let outStrElement = '' // temporary store the word inside the outStr, it is used for comparison
|
||||||
for (let k = 0; k < 26; k++) { // try the number of key shifted, the sum of character from a-z or A-Z is 26
|
for (let k = 0; k < 26; k++) {
|
||||||
|
// try the number of key shifted, the sum of character from a-z or A-Z is 26
|
||||||
outStr = caesarCipherEncodeAndDecodeEngine(inStr, k) // use the encryption engine to decrypt the input string
|
outStr = caesarCipherEncodeAndDecodeEngine(inStr, k) // use the encryption engine to decrypt the input string
|
||||||
|
|
||||||
// loop through the whole input string
|
// loop through the whole input string
|
||||||
@ -69,7 +72,7 @@ function caesarCipherEncodeAndDecodeEngine (inStr, numShifted) {
|
|||||||
shiftedCharCode = charCode + shiftNum
|
shiftedCharCode = charCode + shiftNum
|
||||||
result = charCode
|
result = charCode
|
||||||
|
|
||||||
if ((charCode >= 48 && charCode <= 57)) {
|
if (charCode >= 48 && charCode <= 57) {
|
||||||
if (shiftedCharCode < 48) {
|
if (shiftedCharCode < 48) {
|
||||||
let diff = Math.abs(48 - 1 - shiftedCharCode) % 10
|
let diff = Math.abs(48 - 1 - shiftedCharCode) % 10
|
||||||
|
|
||||||
@ -95,11 +98,11 @@ function caesarCipherEncodeAndDecodeEngine (inStr, numShifted) {
|
|||||||
|
|
||||||
result = shiftedCharCode
|
result = shiftedCharCode
|
||||||
}
|
}
|
||||||
} else if ((charCode >= 65 && charCode <= 90)) {
|
} else if (charCode >= 65 && charCode <= 90) {
|
||||||
if (shiftedCharCode <= 64) {
|
if (shiftedCharCode <= 64) {
|
||||||
let diff = Math.abs(65 - 1 - shiftedCharCode) % 26
|
let diff = Math.abs(65 - 1 - shiftedCharCode) % 26
|
||||||
|
|
||||||
while ((diff % 26) >= 26) {
|
while (diff % 26 >= 26) {
|
||||||
diff = diff % 26
|
diff = diff % 26
|
||||||
}
|
}
|
||||||
shiftedCharCode = 90 - diff
|
shiftedCharCode = 90 - diff
|
||||||
@ -109,17 +112,17 @@ function caesarCipherEncodeAndDecodeEngine (inStr, numShifted) {
|
|||||||
} else if (shiftedCharCode > 90) {
|
} else if (shiftedCharCode > 90) {
|
||||||
let diff = Math.abs(shiftedCharCode - 1 - 90) % 26
|
let diff = Math.abs(shiftedCharCode - 1 - 90) % 26
|
||||||
|
|
||||||
while ((diff % 26) >= 26) {
|
while (diff % 26 >= 26) {
|
||||||
diff = diff % 26
|
diff = diff % 26
|
||||||
}
|
}
|
||||||
shiftedCharCode = 65 + diff
|
shiftedCharCode = 65 + diff
|
||||||
result = shiftedCharCode
|
result = shiftedCharCode
|
||||||
}
|
}
|
||||||
} else if ((charCode >= 97 && charCode <= 122)) {
|
} else if (charCode >= 97 && charCode <= 122) {
|
||||||
if (shiftedCharCode <= 96) {
|
if (shiftedCharCode <= 96) {
|
||||||
let diff = Math.abs(97 - 1 - shiftedCharCode) % 26
|
let diff = Math.abs(97 - 1 - shiftedCharCode) % 26
|
||||||
|
|
||||||
while ((diff % 26) >= 26) {
|
while (diff % 26 >= 26) {
|
||||||
diff = diff % 26
|
diff = diff % 26
|
||||||
}
|
}
|
||||||
shiftedCharCode = 122 - diff
|
shiftedCharCode = 122 - diff
|
||||||
@ -129,7 +132,7 @@ function caesarCipherEncodeAndDecodeEngine (inStr, numShifted) {
|
|||||||
} else if (shiftedCharCode > 122) {
|
} else if (shiftedCharCode > 122) {
|
||||||
let diff = Math.abs(shiftedCharCode - 1 - 122) % 26
|
let diff = Math.abs(shiftedCharCode - 1 - 122) % 26
|
||||||
|
|
||||||
while ((diff % 26) >= 26) {
|
while (diff % 26 >= 26) {
|
||||||
diff = diff % 26
|
diff = diff % 26
|
||||||
}
|
}
|
||||||
shiftedCharCode = 97 + diff
|
shiftedCharCode = 97 + diff
|
||||||
|
@ -16,7 +16,34 @@
|
|||||||
* Non alphabetical characters (space, exclamation mark, ...) are kept as they are
|
* Non alphabetical characters (space, exclamation mark, ...) are kept as they are
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
|
const alphabet = [
|
||||||
|
'a',
|
||||||
|
'b',
|
||||||
|
'c',
|
||||||
|
'd',
|
||||||
|
'e',
|
||||||
|
'f',
|
||||||
|
'g',
|
||||||
|
'h',
|
||||||
|
'i',
|
||||||
|
'j',
|
||||||
|
'k',
|
||||||
|
'l',
|
||||||
|
'm',
|
||||||
|
'n',
|
||||||
|
'o',
|
||||||
|
'p',
|
||||||
|
'q',
|
||||||
|
'r',
|
||||||
|
's',
|
||||||
|
't',
|
||||||
|
'u',
|
||||||
|
'v',
|
||||||
|
'w',
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
'z'
|
||||||
|
]
|
||||||
|
|
||||||
function checkKeywordValidity(keyword) {
|
function checkKeywordValidity(keyword) {
|
||||||
keyword.split('').forEach((char, index) => {
|
keyword.split('').forEach((char, index) => {
|
||||||
@ -42,8 +69,11 @@ function translate (sourceAlphabet, targetAlphabet, message) {
|
|||||||
return message.split('').reduce((encryptedMessage, char) => {
|
return message.split('').reduce((encryptedMessage, char) => {
|
||||||
const isUpperCase = char === char.toUpperCase()
|
const isUpperCase = char === char.toUpperCase()
|
||||||
const encryptedCharIndex = sourceAlphabet.indexOf(char.toLowerCase())
|
const encryptedCharIndex = sourceAlphabet.indexOf(char.toLowerCase())
|
||||||
const encryptedChar = encryptedCharIndex !== -1 ? targetAlphabet[encryptedCharIndex] : char
|
const encryptedChar =
|
||||||
encryptedMessage += isUpperCase ? encryptedChar.toUpperCase() : encryptedChar
|
encryptedCharIndex !== -1 ? targetAlphabet[encryptedCharIndex] : char
|
||||||
|
encryptedMessage += isUpperCase
|
||||||
|
? encryptedChar.toUpperCase()
|
||||||
|
: encryptedChar
|
||||||
return encryptedMessage
|
return encryptedMessage
|
||||||
}, '')
|
}, '')
|
||||||
}
|
}
|
||||||
@ -60,12 +90,20 @@ function checkInputs (keyword, message) {
|
|||||||
|
|
||||||
function encrypt(keyword, message) {
|
function encrypt(keyword, message) {
|
||||||
checkInputs(keyword, message)
|
checkInputs(keyword, message)
|
||||||
return translate(alphabet, getEncryptedAlphabet(keyword.toLowerCase()), message)
|
return translate(
|
||||||
|
alphabet,
|
||||||
|
getEncryptedAlphabet(keyword.toLowerCase()),
|
||||||
|
message
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function decrypt(keyword, message) {
|
function decrypt(keyword, message) {
|
||||||
checkInputs(keyword, message)
|
checkInputs(keyword, message)
|
||||||
return translate(getEncryptedAlphabet(keyword.toLowerCase()), alphabet, message)
|
return translate(
|
||||||
|
getEncryptedAlphabet(keyword.toLowerCase()),
|
||||||
|
alphabet,
|
||||||
|
message
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export { encrypt, decrypt }
|
export { encrypt, decrypt }
|
||||||
|
@ -50,7 +50,7 @@ const morse = (msg, dot = '*', dash = '-') => {
|
|||||||
',': '--**--',
|
',': '--**--',
|
||||||
'?': '**--**',
|
'?': '**--**',
|
||||||
'!': '-*-*--',
|
'!': '-*-*--',
|
||||||
'\'': '*----*',
|
"'": '*----*',
|
||||||
'"': '*-**-*',
|
'"': '*-**-*',
|
||||||
'(': '-*--*',
|
'(': '-*--*',
|
||||||
')': '-*--*-',
|
')': '-*--*-',
|
||||||
@ -68,9 +68,14 @@ const morse = (msg, dot = '*', dash = '-') => {
|
|||||||
|
|
||||||
let newMsg = ''
|
let newMsg = ''
|
||||||
|
|
||||||
msg.toString().split('').forEach((e) => {
|
msg
|
||||||
|
.toString()
|
||||||
|
.split('')
|
||||||
|
.forEach((e) => {
|
||||||
if (/[a-zA-Z]/.test(e)) {
|
if (/[a-zA-Z]/.test(e)) {
|
||||||
newMsg += key[e.toUpperCase()].replaceAll('*', dot).replaceAll('-', dash)
|
newMsg += key[e.toUpperCase()]
|
||||||
|
.replaceAll('*', dot)
|
||||||
|
.replaceAll('-', dash)
|
||||||
} else if (Object.keys(key).includes(e)) {
|
} else if (Object.keys(key).includes(e)) {
|
||||||
newMsg += key[e].replaceAll('*', dot).replaceAll('-', dash)
|
newMsg += key[e].replaceAll('*', dot).replaceAll('-', dash)
|
||||||
} else {
|
} else {
|
||||||
|
@ -34,9 +34,15 @@ function encrypt (message, key) {
|
|||||||
const c = message.charAt(i)
|
const c = message.charAt(i)
|
||||||
if (isLetter(c)) {
|
if (isLetter(c)) {
|
||||||
if (isUpperCase(c)) {
|
if (isUpperCase(c)) {
|
||||||
result += String.fromCharCode((c.charCodeAt(0) + key.toUpperCase().charCodeAt(j) - 2 * 65) % 26 + 65) // A: 65
|
result += String.fromCharCode(
|
||||||
|
((c.charCodeAt(0) + key.toUpperCase().charCodeAt(j) - 2 * 65) % 26) +
|
||||||
|
65
|
||||||
|
) // A: 65
|
||||||
} else {
|
} else {
|
||||||
result += String.fromCharCode((c.charCodeAt(0) + key.toLowerCase().charCodeAt(j) - 2 * 97) % 26 + 97) // a: 97
|
result += String.fromCharCode(
|
||||||
|
((c.charCodeAt(0) + key.toLowerCase().charCodeAt(j) - 2 * 97) % 26) +
|
||||||
|
97
|
||||||
|
) // a: 97
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result += c
|
result += c
|
||||||
@ -59,9 +65,14 @@ function decrypt (message, key) {
|
|||||||
const c = message.charAt(i)
|
const c = message.charAt(i)
|
||||||
if (isLetter(c)) {
|
if (isLetter(c)) {
|
||||||
if (isUpperCase(c)) {
|
if (isUpperCase(c)) {
|
||||||
result += String.fromCharCode(90 - (25 - (c.charCodeAt(0) - key.toUpperCase().charCodeAt(j))) % 26)
|
result += String.fromCharCode(
|
||||||
|
90 - ((25 - (c.charCodeAt(0) - key.toUpperCase().charCodeAt(j))) % 26)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
result += String.fromCharCode(122 - (25 - (c.charCodeAt(0) - key.toLowerCase().charCodeAt(j))) % 26)
|
result += String.fromCharCode(
|
||||||
|
122 -
|
||||||
|
((25 - (c.charCodeAt(0) - key.toLowerCase().charCodeAt(j))) % 26)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result += c
|
result += c
|
||||||
|
@ -14,8 +14,8 @@ const XORCipher = (str, key) => {
|
|||||||
throw new TypeError('Arguments type are invalid')
|
throw new TypeError('Arguments type are invalid')
|
||||||
}
|
}
|
||||||
|
|
||||||
return str.replace(
|
return str.replace(/./g, (char) =>
|
||||||
/./g, (char) => String.fromCharCode(char.charCodeAt() ^ key)
|
String.fromCharCode(char.charCodeAt() ^ key)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,14 @@ describe('Testing the caesarsCipher function', () => {
|
|||||||
|
|
||||||
it('Test - 2, Testing for valid string and rotation', () => {
|
it('Test - 2, Testing for valid string and rotation', () => {
|
||||||
expect(caesarCipher('middle-Outz', 2)).toBe('okffng-Qwvb')
|
expect(caesarCipher('middle-Outz', 2)).toBe('okffng-Qwvb')
|
||||||
expect(caesarCipher('abcdefghijklmnopqrstuvwxyz', 3)).toBe('defghijklmnopqrstuvwxyzabc')
|
expect(caesarCipher('abcdefghijklmnopqrstuvwxyz', 3)).toBe(
|
||||||
expect(caesarCipher('Always-Look-on-the-Bright-Side-of-Life', 5)).toBe('Fqbfdx-Qttp-ts-ymj-Gwnlmy-Xnij-tk-Qnkj')
|
'defghijklmnopqrstuvwxyzabc'
|
||||||
expect(caesarCipher('THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG', 23)).toBe('QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD')
|
)
|
||||||
|
expect(caesarCipher('Always-Look-on-the-Bright-Side-of-Life', 5)).toBe(
|
||||||
|
'Fqbfdx-Qttp-ts-ymj-Gwnlmy-Xnij-tk-Qnkj'
|
||||||
|
)
|
||||||
|
expect(
|
||||||
|
caesarCipher('THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG', 23)
|
||||||
|
).toBe('QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -2,12 +2,16 @@ import { morse } from '../MorseCode'
|
|||||||
|
|
||||||
describe('Testing morse function', () => {
|
describe('Testing morse function', () => {
|
||||||
it('should return an enciphered string with a given input string', () => {
|
it('should return an enciphered string with a given input string', () => {
|
||||||
expect(morse('Hello World!')).toBe('**** * *-** *-** --- *-- --- *-* *-** -** -*-*--')
|
expect(morse('Hello World!')).toBe(
|
||||||
|
'**** * *-** *-** --- *-- --- *-* *-** -** -*-*--'
|
||||||
|
)
|
||||||
expect(morse('1+1=2')).toBe('*---- *-*-* *---- -***- **---')
|
expect(morse('1+1=2')).toBe('*---- *-*-* *---- -***- **---')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should leave symbols that does not have its corresponding morse representation', () => {
|
it('should leave symbols that does not have its corresponding morse representation', () => {
|
||||||
expect(morse('© 2023 GitHub, Inc.')).toBe('© **--- ----- **--- ***-- --* ** - **** **- -*** --**-- ** -* -*-* *-*-*-')
|
expect(morse('© 2023 GitHub, Inc.')).toBe(
|
||||||
|
'© **--- ----- **--- ***-- --* ** - **** **- -*** --**-- ** -* -*-* *-*-*-'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be able to accept custom morse code symbols', () => {
|
it('should be able to accept custom morse code symbols', () => {
|
||||||
|
@ -12,7 +12,11 @@ describe('Testing ROT13 function', () => {
|
|||||||
|
|
||||||
it('Test - 2, passing a string as an argument', () => {
|
it('Test - 2, passing a string as an argument', () => {
|
||||||
expect(ROT13('Uryyb Jbeyq')).toBe('Hello World')
|
expect(ROT13('Uryyb Jbeyq')).toBe('Hello World')
|
||||||
expect(ROT13('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')).toBe('NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm')
|
expect(ROT13('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')).toBe(
|
||||||
expect(ROT13('The quick brown fox jumps over the lazy dog')).toBe('Gur dhvpx oebja sbk whzcf bire gur ynml qbt')
|
'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'
|
||||||
|
)
|
||||||
|
expect(ROT13('The quick brown fox jumps over the lazy dog')).toBe(
|
||||||
|
'Gur dhvpx oebja sbk whzcf bire gur ynml qbt'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -18,8 +18,16 @@ const floorDiv = (dividend, divisor) => {
|
|||||||
* @param {string} baseTwoCharacters Character set for the output base
|
* @param {string} baseTwoCharacters Character set for the output base
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
const convertArbitraryBase = (stringInBaseOne, baseOneCharacterString, baseTwoCharacterString) => {
|
const convertArbitraryBase = (
|
||||||
if ([stringInBaseOne, baseOneCharacterString, baseTwoCharacterString].map(arg => typeof arg).some(type => type !== 'string')) {
|
stringInBaseOne,
|
||||||
|
baseOneCharacterString,
|
||||||
|
baseTwoCharacterString
|
||||||
|
) => {
|
||||||
|
if (
|
||||||
|
[stringInBaseOne, baseOneCharacterString, baseTwoCharacterString]
|
||||||
|
.map((arg) => typeof arg)
|
||||||
|
.some((type) => type !== 'string')
|
||||||
|
) {
|
||||||
throw new TypeError('Only string arguments are allowed')
|
throw new TypeError('Only string arguments are allowed')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +36,9 @@ const convertArbitraryBase = (stringInBaseOne, baseOneCharacterString, baseTwoCh
|
|||||||
|
|
||||||
for (const charactersInBase of [baseOneCharacters, baseTwoCharacters]) {
|
for (const charactersInBase of [baseOneCharacters, baseTwoCharacters]) {
|
||||||
if (charactersInBase.length !== new Set(charactersInBase).size) {
|
if (charactersInBase.length !== new Set(charactersInBase).size) {
|
||||||
throw new TypeError('Duplicate characters in character set are not allowed')
|
throw new TypeError(
|
||||||
|
'Duplicate characters in character set are not allowed'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const reversedStringOneChars = [...stringInBaseOne].reverse()
|
const reversedStringOneChars = [...stringInBaseOne].reverse()
|
||||||
@ -40,7 +50,7 @@ const convertArbitraryBase = (stringInBaseOne, baseOneCharacterString, baseTwoCh
|
|||||||
if (digitNumber === -1) {
|
if (digitNumber === -1) {
|
||||||
throw new TypeError(`Not a valid character: ${digit}`)
|
throw new TypeError(`Not a valid character: ${digit}`)
|
||||||
}
|
}
|
||||||
value += (digitNumber * placeValue)
|
value += digitNumber * placeValue
|
||||||
placeValue *= stringOneBase
|
placeValue *= stringOneBase
|
||||||
}
|
}
|
||||||
const outputChars = []
|
const outputChars = []
|
||||||
@ -60,8 +70,16 @@ const convertArbitraryBase = (stringInBaseOne, baseOneCharacterString, baseTwoCh
|
|||||||
* @param {string} baseTwoCharacters Character set for the output base
|
* @param {string} baseTwoCharacters Character set for the output base
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
const convertArbitraryBaseBigIntVersion = (stringInBaseOne, baseOneCharacterString, baseTwoCharacterString) => {
|
const convertArbitraryBaseBigIntVersion = (
|
||||||
if ([stringInBaseOne, baseOneCharacterString, baseTwoCharacterString].map(arg => typeof arg).some(type => type !== 'string')) {
|
stringInBaseOne,
|
||||||
|
baseOneCharacterString,
|
||||||
|
baseTwoCharacterString
|
||||||
|
) => {
|
||||||
|
if (
|
||||||
|
[stringInBaseOne, baseOneCharacterString, baseTwoCharacterString]
|
||||||
|
.map((arg) => typeof arg)
|
||||||
|
.some((type) => type !== 'string')
|
||||||
|
) {
|
||||||
throw new TypeError('Only string arguments are allowed')
|
throw new TypeError('Only string arguments are allowed')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +88,9 @@ const convertArbitraryBaseBigIntVersion = (stringInBaseOne, baseOneCharacterStri
|
|||||||
|
|
||||||
for (const charactersInBase of [baseOneCharacters, baseTwoCharacters]) {
|
for (const charactersInBase of [baseOneCharacters, baseTwoCharacters]) {
|
||||||
if (charactersInBase.length !== new Set(charactersInBase).size) {
|
if (charactersInBase.length !== new Set(charactersInBase).size) {
|
||||||
throw new TypeError('Duplicate characters in character set are not allowed')
|
throw new TypeError(
|
||||||
|
'Duplicate characters in character set are not allowed'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const reversedStringOneChars = [...stringInBaseOne].reverse()
|
const reversedStringOneChars = [...stringInBaseOne].reverse()
|
||||||
@ -82,7 +102,7 @@ const convertArbitraryBaseBigIntVersion = (stringInBaseOne, baseOneCharacterStri
|
|||||||
if (digitNumber === -1n) {
|
if (digitNumber === -1n) {
|
||||||
throw new TypeError(`Not a valid character: ${digit}`)
|
throw new TypeError(`Not a valid character: ${digit}`)
|
||||||
}
|
}
|
||||||
value += (digitNumber * placeValue)
|
value += digitNumber * placeValue
|
||||||
placeValue *= stringOneBase
|
placeValue *= stringOneBase
|
||||||
}
|
}
|
||||||
const outputChars = []
|
const outputChars = []
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
*/
|
*/
|
||||||
function bufferToBase64(binaryData) {
|
function bufferToBase64(binaryData) {
|
||||||
// The base64 encoding uses the following set of characters to encode any binary data as text
|
// The base64 encoding uses the following set of characters to encode any binary data as text
|
||||||
const base64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
const base64Table =
|
||||||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||||
// Every 3 bytes translates to 4 base64 characters, if we have less than 3 bytes we must append '=' chars as padding
|
// Every 3 bytes translates to 4 base64 characters, if we have less than 3 bytes we must append '=' chars as padding
|
||||||
const padding = 3 - (binaryData.byteLength % 3)
|
const padding = 3 - (binaryData.byteLength % 3)
|
||||||
// Create an instance of Uint8Array, to read from the binaryData array buffer
|
// Create an instance of Uint8Array, to read from the binaryData array buffer
|
||||||
@ -31,7 +32,8 @@ function bufferToBase64 (binaryData) {
|
|||||||
|
|
||||||
// Add padding '=' chars if needed
|
// Add padding '=' chars if needed
|
||||||
if (padding !== 3) {
|
if (padding !== 3) {
|
||||||
const paddedResult = result.slice(0, result.length - padding) + '='.repeat(padding)
|
const paddedResult =
|
||||||
|
result.slice(0, result.length - padding) + '='.repeat(padding)
|
||||||
return paddedResult
|
return paddedResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
*/
|
*/
|
||||||
function base64ToBuffer(b64) {
|
function base64ToBuffer(b64) {
|
||||||
// The base64 encoding uses the following set of characters to encode any binary data as text
|
// The base64 encoding uses the following set of characters to encode any binary data as text
|
||||||
const base64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
const base64Table =
|
||||||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||||
// Find the index of char '=' first occurrence
|
// Find the index of char '=' first occurrence
|
||||||
const paddingIdx = b64.indexOf('=')
|
const paddingIdx = b64.indexOf('=')
|
||||||
// Remove padding chars from base64 string, if there are any
|
// Remove padding chars from base64 string, if there are any
|
||||||
|
@ -2,7 +2,7 @@ export default function binaryToDecimal (binaryString) {
|
|||||||
let decimalNumber = 0
|
let decimalNumber = 0
|
||||||
const binaryDigits = binaryString.split('').reverse() // Splits the binary number into reversed single digits
|
const binaryDigits = binaryString.split('').reverse() // Splits the binary number into reversed single digits
|
||||||
binaryDigits.forEach((binaryDigit, index) => {
|
binaryDigits.forEach((binaryDigit, index) => {
|
||||||
decimalNumber += binaryDigit * (Math.pow(2, index)) // Summation of all the decimal converted digits
|
decimalNumber += binaryDigit * Math.pow(2, index) // Summation of all the decimal converted digits
|
||||||
})
|
})
|
||||||
return decimalNumber
|
return decimalNumber
|
||||||
}
|
}
|
||||||
|
@ -9,22 +9,38 @@ const hexLookup = (bin) => {
|
|||||||
binary = pad(binary, 4)
|
binary = pad(binary, 4)
|
||||||
}
|
}
|
||||||
switch (binary) {
|
switch (binary) {
|
||||||
case '0000': return '0'
|
case '0000':
|
||||||
case '0001': return '1'
|
return '0'
|
||||||
case '0010': return '2'
|
case '0001':
|
||||||
case '0011': return '3'
|
return '1'
|
||||||
case '0100': return '4'
|
case '0010':
|
||||||
case '0101': return '5'
|
return '2'
|
||||||
case '0110': return '6'
|
case '0011':
|
||||||
case '0111': return '7'
|
return '3'
|
||||||
case '1000': return '8'
|
case '0100':
|
||||||
case '1001': return '9'
|
return '4'
|
||||||
case '1010': return 'A'
|
case '0101':
|
||||||
case '1011': return 'B'
|
return '5'
|
||||||
case '1100': return 'C'
|
case '0110':
|
||||||
case '1101': return 'D'
|
return '6'
|
||||||
case '1110': return 'E'
|
case '0111':
|
||||||
case '1111': return 'F'
|
return '7'
|
||||||
|
case '1000':
|
||||||
|
return '8'
|
||||||
|
case '1001':
|
||||||
|
return '9'
|
||||||
|
case '1010':
|
||||||
|
return 'A'
|
||||||
|
case '1011':
|
||||||
|
return 'B'
|
||||||
|
case '1100':
|
||||||
|
return 'C'
|
||||||
|
case '1101':
|
||||||
|
return 'D'
|
||||||
|
case '1110':
|
||||||
|
return 'E'
|
||||||
|
case '1111':
|
||||||
|
return 'F'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const binaryToHex = (binaryString) => {
|
const binaryToHex = (binaryString) => {
|
||||||
|
@ -14,7 +14,15 @@ const isLeap = (year) => {
|
|||||||
else return false
|
else return false
|
||||||
}
|
}
|
||||||
const DateToDay = (dd, mm, yyyy) => {
|
const DateToDay = (dd, mm, yyyy) => {
|
||||||
return Math.floor((365 * (yyyy - 1)) + ((yyyy - 1) / 4) - ((yyyy - 1) / 100) + ((yyyy - 1) / 400) + dd + (((367 * mm) - 362) / 12) + (mm <= 2 ? 0 : isLeap(yyyy) ? -1 : -2))
|
return Math.floor(
|
||||||
|
365 * (yyyy - 1) +
|
||||||
|
(yyyy - 1) / 4 -
|
||||||
|
(yyyy - 1) / 100 +
|
||||||
|
(yyyy - 1) / 400 +
|
||||||
|
dd +
|
||||||
|
(367 * mm - 362) / 12 +
|
||||||
|
(mm <= 2 ? 0 : isLeap(yyyy) ? -1 : -2)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const DateDayDifference = (date1, date2) => {
|
const DateDayDifference = (date1, date2) => {
|
||||||
@ -23,17 +31,30 @@ const DateDayDifference = (date1, date2) => {
|
|||||||
return new TypeError('Argument is not a string.')
|
return new TypeError('Argument is not a string.')
|
||||||
}
|
}
|
||||||
// extract the first date
|
// extract the first date
|
||||||
const [firstDateDay, firstDateMonth, firstDateYear] = date1.split('/').map((ele) => Number(ele))
|
const [firstDateDay, firstDateMonth, firstDateYear] = date1
|
||||||
|
.split('/')
|
||||||
|
.map((ele) => Number(ele))
|
||||||
// extract the second date
|
// extract the second date
|
||||||
const [secondDateDay, secondDateMonth, secondDateYear] = date2.split('/').map((ele) => Number(ele))
|
const [secondDateDay, secondDateMonth, secondDateYear] = date2
|
||||||
|
.split('/')
|
||||||
|
.map((ele) => Number(ele))
|
||||||
// check the both data are valid or not.
|
// check the both data are valid or not.
|
||||||
if (firstDateDay < 0 || firstDateDay > 31 ||
|
if (
|
||||||
firstDateMonth > 12 || firstDateMonth < 0 ||
|
firstDateDay < 0 ||
|
||||||
secondDateDay < 0 || secondDateDay > 31 ||
|
firstDateDay > 31 ||
|
||||||
secondDateMonth > 12 || secondDateMonth < 0) {
|
firstDateMonth > 12 ||
|
||||||
|
firstDateMonth < 0 ||
|
||||||
|
secondDateDay < 0 ||
|
||||||
|
secondDateDay > 31 ||
|
||||||
|
secondDateMonth > 12 ||
|
||||||
|
secondDateMonth < 0
|
||||||
|
) {
|
||||||
return new TypeError('Date is not valid.')
|
return new TypeError('Date is not valid.')
|
||||||
}
|
}
|
||||||
return Math.abs(DateToDay(secondDateDay, secondDateMonth, secondDateYear) - DateToDay(firstDateDay, firstDateMonth, firstDateYear))
|
return Math.abs(
|
||||||
|
DateToDay(secondDateDay, secondDateMonth, secondDateYear) -
|
||||||
|
DateToDay(firstDateDay, firstDateMonth, firstDateYear)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example : DateDayDifference('17/08/2002', '10/10/2020') => 6630
|
// Example : DateDayDifference('17/08/2002', '10/10/2020') => 6630
|
||||||
|
@ -13,7 +13,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Array holding name of the day: Saturday - Sunday - Friday => 0 - 1 - 6
|
// Array holding name of the day: Saturday - Sunday - Friday => 0 - 1 - 6
|
||||||
const daysNameArr = ['Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
|
const daysNameArr = [
|
||||||
|
'Saturday',
|
||||||
|
'Sunday',
|
||||||
|
'Monday',
|
||||||
|
'Tuesday',
|
||||||
|
'Wednesday',
|
||||||
|
'Thursday',
|
||||||
|
'Friday'
|
||||||
|
]
|
||||||
|
|
||||||
const DateToDay = (date) => {
|
const DateToDay = (date) => {
|
||||||
// firstly, check that input is a string or not.
|
// firstly, check that input is a string or not.
|
||||||
@ -53,7 +61,14 @@ const DateToDay = (date) => {
|
|||||||
Without the adaption, the formula yields `weekDay = -6` for the date 2/3/2014;
|
Without the adaption, the formula yields `weekDay = -6` for the date 2/3/2014;
|
||||||
With the adaption, it yields the positive result `weekDay = 7 - 6 = 1` (Sunday), which is what we need to index the array
|
With the adaption, it yields the positive result `weekDay = 7 - 6 = 1` (Sunday), which is what we need to index the array
|
||||||
*/
|
*/
|
||||||
const weekDay = (day + Math.floor((month + 1) * 2.6) + yearDigits + Math.floor(yearDigits / 4) + Math.floor(century / 4) + 5 * century) % 7
|
const weekDay =
|
||||||
|
(day +
|
||||||
|
Math.floor((month + 1) * 2.6) +
|
||||||
|
yearDigits +
|
||||||
|
Math.floor(yearDigits / 4) +
|
||||||
|
Math.floor(century / 4) +
|
||||||
|
5 * century) %
|
||||||
|
7
|
||||||
return daysNameArr[weekDay] // name of the weekday
|
return daysNameArr[weekDay] // name of the weekday
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
function intToHex(num) {
|
function intToHex(num) {
|
||||||
switch (num) {
|
switch (num) {
|
||||||
case 10: return 'A'
|
case 10:
|
||||||
case 11: return 'B'
|
return 'A'
|
||||||
case 12: return 'C'
|
case 11:
|
||||||
case 13: return 'D'
|
return 'B'
|
||||||
case 14: return 'E'
|
case 12:
|
||||||
case 15: return 'F'
|
return 'C'
|
||||||
|
case 13:
|
||||||
|
return 'D'
|
||||||
|
case 14:
|
||||||
|
return 'E'
|
||||||
|
case 15:
|
||||||
|
return 'F'
|
||||||
}
|
}
|
||||||
return num
|
return num
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ function decimalToOctal (num) {
|
|||||||
let c = 0
|
let c = 0
|
||||||
while (num > 0) {
|
while (num > 0) {
|
||||||
const r = num % 8
|
const r = num % 8
|
||||||
oct = oct + (r * Math.pow(10, c++))
|
oct = oct + r * Math.pow(10, c++)
|
||||||
num = Math.floor(num / 8) // basically /= 8 without remainder if any
|
num = Math.floor(num / 8) // basically /= 8 without remainder if any
|
||||||
}
|
}
|
||||||
return oct
|
return oct
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const binLookup = (key) => ({
|
const binLookup = (key) =>
|
||||||
|
({
|
||||||
0: '0000',
|
0: '0000',
|
||||||
1: '0001',
|
1: '0001',
|
||||||
2: '0010',
|
2: '0010',
|
||||||
@ -15,7 +16,7 @@ const binLookup = (key) => ({
|
|||||||
d: '1101',
|
d: '1101',
|
||||||
e: '1110',
|
e: '1110',
|
||||||
f: '1111'
|
f: '1111'
|
||||||
}[key.toLowerCase()]) // select the binary number by valid hex key with the help javascript object
|
})[key.toLowerCase()] // select the binary number by valid hex key with the help javascript object
|
||||||
|
|
||||||
const hexToBinary = (hexString) => {
|
const hexToBinary = (hexString) => {
|
||||||
if (typeof hexString !== 'string') {
|
if (typeof hexString !== 'string') {
|
||||||
@ -32,10 +33,7 @@ const hexToBinary = (hexString) => {
|
|||||||
2. Conversion goes by searching in the lookup table
|
2. Conversion goes by searching in the lookup table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return hexString.replace(
|
return hexString.replace(/[0-9a-f]/gi, (lexeme) => binLookup(lexeme))
|
||||||
/[0-9a-f]/gi,
|
|
||||||
lexeme => binLookup(lexeme)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default hexToBinary
|
export default hexToBinary
|
||||||
|
@ -2,13 +2,20 @@ function hexToInt (hexNum) {
|
|||||||
const numArr = hexNum.split('') // converts number to array
|
const numArr = hexNum.split('') // converts number to array
|
||||||
return numArr.map((item, index) => {
|
return numArr.map((item, index) => {
|
||||||
switch (item) {
|
switch (item) {
|
||||||
case 'A': return 10
|
case 'A':
|
||||||
case 'B': return 11
|
return 10
|
||||||
case 'C': return 12
|
case 'B':
|
||||||
case 'D': return 13
|
return 11
|
||||||
case 'E': return 14
|
case 'C':
|
||||||
case 'F': return 15
|
return 12
|
||||||
default: return parseInt(item)
|
case 'D':
|
||||||
|
return 13
|
||||||
|
case 'E':
|
||||||
|
return 14
|
||||||
|
case 'F':
|
||||||
|
return 15
|
||||||
|
default:
|
||||||
|
return parseInt(item)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -16,7 +23,9 @@ function hexToInt (hexNum) {
|
|||||||
function hexToDecimal(hexNum) {
|
function hexToDecimal(hexNum) {
|
||||||
const intItemsArr = hexToInt(hexNum)
|
const intItemsArr = hexToInt(hexNum)
|
||||||
return intItemsArr.reduce((accumulator, current, index) => {
|
return intItemsArr.reduce((accumulator, current, index) => {
|
||||||
return accumulator + (current * Math.pow(16, (intItemsArr.length - (1 + index))))
|
return (
|
||||||
|
accumulator + current * Math.pow(16, intItemsArr.length - (1 + index))
|
||||||
|
)
|
||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,4 @@ const lengthConversion = (length, fromUnit, toUnit) => {
|
|||||||
return convertedLength
|
return convertedLength
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { lengthConversion }
|
||||||
lengthConversion
|
|
||||||
}
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
const LowerCaseConversion = (inputString) => {
|
const LowerCaseConversion = (inputString) => {
|
||||||
// Take a string and split it into characters.
|
// Take a string and split it into characters.
|
||||||
const newString = inputString.split('').map(char => {
|
const newString = inputString.split('').map((char) => {
|
||||||
// Get a character code by the use charCodeAt method.
|
// Get a character code by the use charCodeAt method.
|
||||||
const presentCharCode = char.charCodeAt()
|
const presentCharCode = char.charCodeAt()
|
||||||
// If the character code lies between 65 to 90 it means they are in the upper case so convert it.
|
// If the character code lies between 65 to 90 it means they are in the upper case so convert it.
|
||||||
|
@ -4,7 +4,7 @@ function octalToDecimal (num) {
|
|||||||
while (num > 0) {
|
while (num > 0) {
|
||||||
const r = num % 10
|
const r = num % 10
|
||||||
num = Math.floor(num / 10)
|
num = Math.floor(num / 10)
|
||||||
dec = dec + (r * base)
|
dec = dec + r * base
|
||||||
base = base * 8
|
base = base * 8
|
||||||
}
|
}
|
||||||
return dec
|
return dec
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* @param {number} oz - Amount of ounces to convert to kilograms
|
* @param {number} oz - Amount of ounces to convert to kilograms
|
||||||
*/
|
*/
|
||||||
const ouncesToKilograms = (oz) => {
|
const ouncesToKilograms = (oz) => {
|
||||||
return oz * 28.3498 / 1000
|
return (oz * 28.3498) / 1000
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ouncesToKilograms
|
export default ouncesToKilograms
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
function RGBToHex(r, g, b) {
|
function RGBToHex(r, g, b) {
|
||||||
if (
|
if (typeof r !== 'number' || typeof g !== 'number' || typeof b !== 'number') {
|
||||||
typeof r !== 'number' ||
|
|
||||||
typeof g !== 'number' ||
|
|
||||||
typeof b !== 'number'
|
|
||||||
) {
|
|
||||||
throw new TypeError('argument is not a Number')
|
throw new TypeError('argument is not a Number')
|
||||||
}
|
}
|
||||||
|
|
||||||
const toHex = n => (n || '0').toString(16).padStart(2, '0')
|
const toHex = (n) => (n || '0').toString(16).padStart(2, '0')
|
||||||
|
|
||||||
return `#${toHex(r)}${toHex(g)}${toHex(b)}`
|
return `#${toHex(r)}${toHex(g)}${toHex(b)}`
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,23 @@ const RailwayTimeConversion = (timeString) => {
|
|||||||
// split the string by ':' character.
|
// split the string by ':' character.
|
||||||
const [hour, minute, secondWithShift] = timeString.split(':')
|
const [hour, minute, secondWithShift] = timeString.split(':')
|
||||||
// split second and shift value.
|
// split second and shift value.
|
||||||
const [second, shift] = [secondWithShift.substr(0, 2), secondWithShift.substr(2)]
|
const [second, shift] = [
|
||||||
|
secondWithShift.substr(0, 2),
|
||||||
|
secondWithShift.substr(2)
|
||||||
|
]
|
||||||
// convert shifted time to not-shift time(Railway time) by using the above explanation.
|
// convert shifted time to not-shift time(Railway time) by using the above explanation.
|
||||||
if (shift === 'PM') {
|
if (shift === 'PM') {
|
||||||
if (parseInt(hour) === 12) { return `${hour}:${minute}:${second}` } else { return `${parseInt(hour) + 12}:${minute}:${second}` }
|
if (parseInt(hour) === 12) {
|
||||||
|
return `${hour}:${minute}:${second}`
|
||||||
} else {
|
} else {
|
||||||
if (parseInt(hour) === 12) { return `00:${minute}:${second}` } else { return `${hour}:${minute}:${second}` }
|
return `${parseInt(hour) + 12}:${minute}:${second}`
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (parseInt(hour) === 12) {
|
||||||
|
return `00:${minute}:${second}`
|
||||||
|
} else {
|
||||||
|
return `${hour}:${minute}:${second}`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ export function hsvToRgb (hue, saturation, value) {
|
|||||||
|
|
||||||
const chroma = value * saturation
|
const chroma = value * saturation
|
||||||
const hueSection = hue / 60
|
const hueSection = hue / 60
|
||||||
const secondLargestComponent = chroma * (1 - Math.abs(hueSection % 2 - 1))
|
const secondLargestComponent = chroma * (1 - Math.abs((hueSection % 2) - 1))
|
||||||
const matchValue = value - chroma
|
const matchValue = value - chroma
|
||||||
|
|
||||||
return getRgbBySection(hueSection, chroma, matchValue, secondLargestComponent)
|
return getRgbBySection(hueSection, chroma, matchValue, secondLargestComponent)
|
||||||
@ -89,7 +89,12 @@ export function approximatelyEqualHsv (hsv1, hsv2) {
|
|||||||
return bHue && bSaturation && bValue
|
return bHue && bSaturation && bValue
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRgbBySection (hueSection, chroma, matchValue, secondLargestComponent) {
|
function getRgbBySection(
|
||||||
|
hueSection,
|
||||||
|
chroma,
|
||||||
|
matchValue,
|
||||||
|
secondLargestComponent
|
||||||
|
) {
|
||||||
function convertToInt(input) {
|
function convertToInt(input) {
|
||||||
return Math.round(255 * input)
|
return Math.round(255 * input)
|
||||||
}
|
}
|
||||||
|
@ -4,99 +4,110 @@
|
|||||||
const celsiusToFahrenheit = (celsius) => {
|
const celsiusToFahrenheit = (celsius) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
||||||
return Math.round(((celsius) * 9 / 5) + 32)
|
return Math.round((celsius * 9) / 5 + 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
const celsiusToKelvin = (celsius) => {
|
const celsiusToKelvin = (celsius) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
||||||
return Math.round((celsius) + 273.15)
|
return Math.round(celsius + 273.15)
|
||||||
}
|
}
|
||||||
|
|
||||||
const celsiusToRankine = (celsius) => {
|
const celsiusToRankine = (celsius) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
||||||
return Math.round(((celsius) * 9 / 5) + 491.67)
|
return Math.round((celsius * 9) / 5 + 491.67)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fahrenheitToCelsius = (fahrenheit) => {
|
const fahrenheitToCelsius = (fahrenheit) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
||||||
return Math.round(((fahrenheit) - 32) * 5 / 9)
|
return Math.round(((fahrenheit - 32) * 5) / 9)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fahrenheitToKelvin = (fahrenheit) => {
|
const fahrenheitToKelvin = (fahrenheit) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
||||||
return Math.round((((fahrenheit) - 32) * 5 / 9) + 273.15)
|
return Math.round(((fahrenheit - 32) * 5) / 9 + 273.15)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fahrenheitToRankine = (fahrenheit) => {
|
const fahrenheitToRankine = (fahrenheit) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
||||||
return Math.round((fahrenheit) + 459.67)
|
return Math.round(fahrenheit + 459.67)
|
||||||
}
|
}
|
||||||
|
|
||||||
const kelvinToCelsius = (kelvin) => {
|
const kelvinToCelsius = (kelvin) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
||||||
return Math.round((kelvin) - 273.15)
|
return Math.round(kelvin - 273.15)
|
||||||
}
|
}
|
||||||
|
|
||||||
const kelvinToFahrenheit = (kelvin) => {
|
const kelvinToFahrenheit = (kelvin) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
||||||
return Math.round((((kelvin) - 273.15) * 9 / 5) + 32)
|
return Math.round(((kelvin - 273.15) * 9) / 5 + 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
const kelvinToRankine = (kelvin) => {
|
const kelvinToRankine = (kelvin) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
||||||
return Math.round(((kelvin) * 9 / 5))
|
return Math.round((kelvin * 9) / 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
const rankineToCelsius = (rankine) => {
|
const rankineToCelsius = (rankine) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Celsius
|
||||||
return Math.round(((rankine) - 491.67) * 5 / 9)
|
return Math.round(((rankine - 491.67) * 5) / 9)
|
||||||
}
|
}
|
||||||
|
|
||||||
const rankineToFahrenheit = (rankine) => {
|
const rankineToFahrenheit = (rankine) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Fahrenheit
|
||||||
return Math.round((rankine) - 459.67)
|
return Math.round(rankine - 459.67)
|
||||||
}
|
}
|
||||||
|
|
||||||
const rankineToKelvin = (rankine) => {
|
const rankineToKelvin = (rankine) => {
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Rankine_scale
|
||||||
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
// Wikipedia reference: https://en.wikipedia.org/wiki/Kelvin
|
||||||
return Math.round(((rankine) * 5 / 9))
|
return Math.round((rankine * 5) / 9)
|
||||||
}
|
}
|
||||||
|
|
||||||
const reaumurToKelvin = (reaumur) => {
|
const reaumurToKelvin = (reaumur) => {
|
||||||
// Reference:- http://www.csgnetwork.com/temp2conv.html
|
// Reference:- http://www.csgnetwork.com/temp2conv.html
|
||||||
return Math.round(((reaumur) * 1.25 + 273.15))
|
return Math.round(reaumur * 1.25 + 273.15)
|
||||||
}
|
}
|
||||||
|
|
||||||
const reaumurToFahrenheit = (reaumur) => {
|
const reaumurToFahrenheit = (reaumur) => {
|
||||||
// Reference:- http://www.csgnetwork.com/temp2conv.html
|
// Reference:- http://www.csgnetwork.com/temp2conv.html
|
||||||
return Math.round(((reaumur) * 2.25 + 32))
|
return Math.round(reaumur * 2.25 + 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
const reaumurToCelsius = (reaumur) => {
|
const reaumurToCelsius = (reaumur) => {
|
||||||
// Reference:- http://www.csgnetwork.com/temp2conv.html
|
// Reference:- http://www.csgnetwork.com/temp2conv.html
|
||||||
return Math.round(((reaumur) * 1.25))
|
return Math.round(reaumur * 1.25)
|
||||||
}
|
}
|
||||||
|
|
||||||
const reaumurToRankine = (reaumur) => {
|
const reaumurToRankine = (reaumur) => {
|
||||||
// Reference:- http://www.csgnetwork.com/temp2conv.html
|
// Reference:- http://www.csgnetwork.com/temp2conv.html
|
||||||
return Math.round(((reaumur) * 2.25 + 32 + 459.67))
|
return Math.round(reaumur * 2.25 + 32 + 459.67)
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
celsiusToFahrenheit, celsiusToKelvin, celsiusToRankine,
|
celsiusToFahrenheit,
|
||||||
fahrenheitToCelsius, fahrenheitToKelvin, fahrenheitToRankine,
|
celsiusToKelvin,
|
||||||
kelvinToCelsius, kelvinToFahrenheit, kelvinToRankine,
|
celsiusToRankine,
|
||||||
rankineToCelsius, rankineToFahrenheit, rankineToKelvin,
|
fahrenheitToCelsius,
|
||||||
reaumurToCelsius, reaumurToFahrenheit, reaumurToKelvin, reaumurToRankine
|
fahrenheitToKelvin,
|
||||||
|
fahrenheitToRankine,
|
||||||
|
kelvinToCelsius,
|
||||||
|
kelvinToFahrenheit,
|
||||||
|
kelvinToRankine,
|
||||||
|
rankineToCelsius,
|
||||||
|
rankineToFahrenheit,
|
||||||
|
rankineToKelvin,
|
||||||
|
reaumurToCelsius,
|
||||||
|
reaumurToFahrenheit,
|
||||||
|
reaumurToKelvin,
|
||||||
|
reaumurToRankine
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
const titleCaseConversion = (inputString) => {
|
const titleCaseConversion = (inputString) => {
|
||||||
if (inputString === '') return ''
|
if (inputString === '') return ''
|
||||||
// Extract all space separated string.
|
// Extract all space separated string.
|
||||||
const stringCollections = inputString.split(' ').map(word => {
|
const stringCollections = inputString.split(' ').map((word) => {
|
||||||
let firstChar = ''
|
let firstChar = ''
|
||||||
// Get the [ASCII](https://en.wikipedia.org/wiki/ASCII) character code by the use charCodeAt method.
|
// Get the [ASCII](https://en.wikipedia.org/wiki/ASCII) character code by the use charCodeAt method.
|
||||||
const firstCharCode = word[0].charCodeAt()
|
const firstCharCode = word[0].charCodeAt()
|
||||||
@ -25,7 +25,10 @@ const titleCaseConversion = (inputString) => {
|
|||||||
// Else store the characters without any modification.
|
// Else store the characters without any modification.
|
||||||
firstChar += word[0]
|
firstChar += word[0]
|
||||||
}
|
}
|
||||||
const newWordChar = word.slice(1).split('').map(char => {
|
const newWordChar = word
|
||||||
|
.slice(1)
|
||||||
|
.split('')
|
||||||
|
.map((char) => {
|
||||||
// Get the ASCII character code by the use charCodeAt method.
|
// Get the ASCII character code by the use charCodeAt method.
|
||||||
const presentCharCode = char.charCodeAt()
|
const presentCharCode = char.charCodeAt()
|
||||||
// If the ASCII character code lies between 65 to 90, it means they are in the uppercase so convert it.
|
// If the ASCII character code lies between 65 to 90, it means they are in the uppercase so convert it.
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
const upperCaseConversion = (inputString) => {
|
const upperCaseConversion = (inputString) => {
|
||||||
// Take a string and split it into characters.
|
// Take a string and split it into characters.
|
||||||
const newString = inputString.split('').map(char => {
|
const newString = inputString.split('').map((char) => {
|
||||||
// Get a character code by the use charCodeAt method.
|
// Get a character code by the use charCodeAt method.
|
||||||
const presentCharCode = char.charCodeAt()
|
const presentCharCode = char.charCodeAt()
|
||||||
// If the character code lies between 97 to 122, it means they are in the lowercase so convert it.
|
// If the character code lies between 97 to 122, it means they are in the lowercase so convert it.
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import { convertArbitraryBase, convertArbitraryBaseBigIntVersion } from '../ArbitraryBase'
|
import {
|
||||||
|
convertArbitraryBase,
|
||||||
|
convertArbitraryBaseBigIntVersion
|
||||||
|
} from '../ArbitraryBase'
|
||||||
|
|
||||||
test('Check the answer of convertArbitraryBase(98, 0123456789, 01234567) is 142', () => {
|
test('Check the answer of convertArbitraryBase(98, 0123456789, 01234567) is 142', () => {
|
||||||
const res = convertArbitraryBase('98', '0123456789', '01234567')
|
const res = convertArbitraryBase('98', '0123456789', '01234567')
|
||||||
|
@ -14,6 +14,8 @@ describe('BinaryToHex', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('expects to return correct hexadecimal value, matching (num).toString(16)', () => {
|
it('expects to return correct hexadecimal value, matching (num).toString(16)', () => {
|
||||||
expect(binaryToHex('1111')).toBe(parseInt('1111', 2).toString(16).toUpperCase())
|
expect(binaryToHex('1111')).toBe(
|
||||||
|
parseInt('1111', 2).toString(16).toUpperCase()
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -20,14 +20,30 @@ describe('rgbToHsv', () => {
|
|||||||
// "approximatelyEqualHsv" needed because of small deviations due to rounding for the RGB-values
|
// "approximatelyEqualHsv" needed because of small deviations due to rounding for the RGB-values
|
||||||
it('should calculate the correct HSV values', () => {
|
it('should calculate the correct HSV values', () => {
|
||||||
expect(approximatelyEqualHsv(rgbToHsv(0, 0, 0), [0, 0, 0])).toEqual(true)
|
expect(approximatelyEqualHsv(rgbToHsv(0, 0, 0), [0, 0, 0])).toEqual(true)
|
||||||
expect(approximatelyEqualHsv(rgbToHsv(255, 255, 255), [0, 0, 1])).toEqual(true)
|
expect(approximatelyEqualHsv(rgbToHsv(255, 255, 255), [0, 0, 1])).toEqual(
|
||||||
|
true
|
||||||
|
)
|
||||||
expect(approximatelyEqualHsv(rgbToHsv(255, 0, 0), [0, 1, 1])).toEqual(true)
|
expect(approximatelyEqualHsv(rgbToHsv(255, 0, 0), [0, 1, 1])).toEqual(true)
|
||||||
expect(approximatelyEqualHsv(rgbToHsv(255, 255, 0), [60, 1, 1])).toEqual(true)
|
expect(approximatelyEqualHsv(rgbToHsv(255, 255, 0), [60, 1, 1])).toEqual(
|
||||||
expect(approximatelyEqualHsv(rgbToHsv(0, 255, 0), [120, 1, 1])).toEqual(true)
|
true
|
||||||
expect(approximatelyEqualHsv(rgbToHsv(0, 0, 255), [240, 1, 1])).toEqual(true)
|
)
|
||||||
expect(approximatelyEqualHsv(rgbToHsv(255, 0, 255), [300, 1, 1])).toEqual(true)
|
expect(approximatelyEqualHsv(rgbToHsv(0, 255, 0), [120, 1, 1])).toEqual(
|
||||||
expect(approximatelyEqualHsv(rgbToHsv(64, 128, 128), [180, 0.5, 0.5])).toEqual(true)
|
true
|
||||||
expect(approximatelyEqualHsv(rgbToHsv(193, 196, 224), [234, 0.14, 0.88])).toEqual(true)
|
)
|
||||||
expect(approximatelyEqualHsv(rgbToHsv(128, 32, 80), [330, 0.75, 0.5])).toEqual(true)
|
expect(approximatelyEqualHsv(rgbToHsv(0, 0, 255), [240, 1, 1])).toEqual(
|
||||||
|
true
|
||||||
|
)
|
||||||
|
expect(approximatelyEqualHsv(rgbToHsv(255, 0, 255), [300, 1, 1])).toEqual(
|
||||||
|
true
|
||||||
|
)
|
||||||
|
expect(
|
||||||
|
approximatelyEqualHsv(rgbToHsv(64, 128, 128), [180, 0.5, 0.5])
|
||||||
|
).toEqual(true)
|
||||||
|
expect(
|
||||||
|
approximatelyEqualHsv(rgbToHsv(193, 196, 224), [234, 0.14, 0.88])
|
||||||
|
).toEqual(true)
|
||||||
|
expect(
|
||||||
|
approximatelyEqualHsv(rgbToHsv(128, 32, 80), [330, 0.75, 0.5])
|
||||||
|
).toEqual(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import { titleCaseConversion } from '../TitleCaseConversion'
|
import { titleCaseConversion } from '../TitleCaseConversion'
|
||||||
|
|
||||||
describe(('Tests for the titleCaseConversion function'), () => {
|
describe('Tests for the titleCaseConversion function', () => {
|
||||||
it('should return an empty string when the input is an empty string', () => {
|
it('should return an empty string when the input is an empty string', () => {
|
||||||
expect(titleCaseConversion('')).toEqual('')
|
expect(titleCaseConversion('')).toEqual('')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return the input string when the input string is a title case string', () => {
|
it('should return the input string when the input string is a title case string', () => {
|
||||||
expect(titleCaseConversion('A Proper Title Case String')).toEqual('A Proper Title Case String')
|
expect(titleCaseConversion('A Proper Title Case String')).toEqual(
|
||||||
|
'A Proper Title Case String'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return a title case string when input is an all-uppercase string', () => {
|
it('should return a title case string when input is an all-uppercase string', () => {
|
||||||
@ -34,7 +36,9 @@ describe(('Tests for the titleCaseConversion function'), () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should return a title case string when input is an all-lowercase string with punctuation', () => {
|
it('should return a title case string when input is an all-lowercase string with punctuation', () => {
|
||||||
expect(titleCaseConversion('lower, case, input.')).toEqual('Lower, Case, Input.')
|
expect(titleCaseConversion('lower, case, input.')).toEqual(
|
||||||
|
'Lower, Case, Input.'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return a title case string when input is an mixed-case string', () => {
|
it('should return a title case string when input is an mixed-case string', () => {
|
||||||
@ -46,6 +50,8 @@ describe(('Tests for the titleCaseConversion function'), () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should return a title case string when input is an mixed-case string with punctuation', () => {
|
it('should return a title case string when input is an mixed-case string with punctuation', () => {
|
||||||
expect(titleCaseConversion('mixeD, CaSe, INPuT!')).toEqual('Mixed, Case, Input!')
|
expect(titleCaseConversion('mixeD, CaSe, INPuT!')).toEqual(
|
||||||
|
'Mixed, Case, Input!'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { upperCaseConversion } from '../UpperCaseConversion'
|
import { upperCaseConversion } from '../UpperCaseConversion'
|
||||||
|
|
||||||
describe(('Test the upperCaseConversion function'), () => {
|
describe('Test the upperCaseConversion function', () => {
|
||||||
it('should return an empty string when the input is an empty string', () => {
|
it('should return an empty string when the input is an empty string', () => {
|
||||||
expect(upperCaseConversion('')).toEqual('')
|
expect(upperCaseConversion('')).toEqual('')
|
||||||
})
|
})
|
||||||
@ -26,7 +26,9 @@ describe(('Test the upperCaseConversion function'), () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should return an all-uppercase string when input is an all-lowercase string with punctuation', () => {
|
it('should return an all-uppercase string when input is an all-lowercase string with punctuation', () => {
|
||||||
expect(upperCaseConversion('lower-case, input.')).toEqual('LOWER-CASE, INPUT.')
|
expect(upperCaseConversion('lower-case, input.')).toEqual(
|
||||||
|
'LOWER-CASE, INPUT.'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return an all-uppercase string when input is an mixed-case string', () => {
|
it('should return an all-uppercase string when input is an mixed-case string', () => {
|
||||||
@ -38,6 +40,8 @@ describe(('Test the upperCaseConversion function'), () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should return an all-uppercase string when input is an mixed-case string with punctuation', () => {
|
it('should return an all-uppercase string when input is an mixed-case string with punctuation', () => {
|
||||||
expect(upperCaseConversion('mixeD-CaSe INPuT!')).toEqual('MIXED-CASE INPUT!')
|
expect(upperCaseConversion('mixeD-CaSe INPuT!')).toEqual(
|
||||||
|
'MIXED-CASE INPUT!'
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
* [HexToBinary](Conversions/HexToBinary.js)
|
* [HexToBinary](Conversions/HexToBinary.js)
|
||||||
* [HexToDecimal](Conversions/HexToDecimal.js)
|
* [HexToDecimal](Conversions/HexToDecimal.js)
|
||||||
* [HexToRGB](Conversions/HexToRGB.js)
|
* [HexToRGB](Conversions/HexToRGB.js)
|
||||||
|
* [LengthConversion](Conversions/LengthConversion.js)
|
||||||
* [LitersToImperialGallons](Conversions/LitersToImperialGallons.js)
|
* [LitersToImperialGallons](Conversions/LitersToImperialGallons.js)
|
||||||
* [LitersToUSGallons](Conversions/LitersToUSGallons.js)
|
* [LitersToUSGallons](Conversions/LitersToUSGallons.js)
|
||||||
* [LowerCaseConversion](Conversions/LowerCaseConversion.js)
|
* [LowerCaseConversion](Conversions/LowerCaseConversion.js)
|
||||||
@ -233,6 +234,7 @@
|
|||||||
* [PowLogarithmic](Maths/PowLogarithmic.js)
|
* [PowLogarithmic](Maths/PowLogarithmic.js)
|
||||||
* [PrimeCheck](Maths/PrimeCheck.js)
|
* [PrimeCheck](Maths/PrimeCheck.js)
|
||||||
* [PrimeFactors](Maths/PrimeFactors.js)
|
* [PrimeFactors](Maths/PrimeFactors.js)
|
||||||
|
* [QuadraticRoots](Maths/QuadraticRoots.js)
|
||||||
* [RadianToDegree](Maths/RadianToDegree.js)
|
* [RadianToDegree](Maths/RadianToDegree.js)
|
||||||
* [ReverseNumber](Maths/ReverseNumber.js)
|
* [ReverseNumber](Maths/ReverseNumber.js)
|
||||||
* [ReversePolishNotation](Maths/ReversePolishNotation.js)
|
* [ReversePolishNotation](Maths/ReversePolishNotation.js)
|
||||||
@ -363,6 +365,7 @@
|
|||||||
* [HammingDistance](String/HammingDistance.js)
|
* [HammingDistance](String/HammingDistance.js)
|
||||||
* [IsPalindrome](String/IsPalindrome.js)
|
* [IsPalindrome](String/IsPalindrome.js)
|
||||||
* [KMPPatternSearching](String/KMPPatternSearching.js)
|
* [KMPPatternSearching](String/KMPPatternSearching.js)
|
||||||
|
* [LengthofLongestSubstringWithoutRepetition](String/LengthofLongestSubstringWithoutRepetition.js)
|
||||||
* [LevenshteinDistance](String/LevenshteinDistance.js)
|
* [LevenshteinDistance](String/LevenshteinDistance.js)
|
||||||
* [Lower](String/Lower.js)
|
* [Lower](String/Lower.js)
|
||||||
* [MaxCharacter](String/MaxCharacter.js)
|
* [MaxCharacter](String/MaxCharacter.js)
|
||||||
|
@ -9,19 +9,38 @@
|
|||||||
* @complexity: O(log(n)) (worst case)
|
* @complexity: O(log(n)) (worst case)
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
const findMaxPointIndex = (array, rangeStartIndex, rangeEndIndex, originalLength) => {
|
const findMaxPointIndex = (
|
||||||
|
array,
|
||||||
|
rangeStartIndex,
|
||||||
|
rangeEndIndex,
|
||||||
|
originalLength
|
||||||
|
) => {
|
||||||
// find index range middle point
|
// find index range middle point
|
||||||
const middleIndex = rangeStartIndex + parseInt((rangeEndIndex - rangeStartIndex) / 2)
|
const middleIndex =
|
||||||
|
rangeStartIndex + parseInt((rangeEndIndex - rangeStartIndex) / 2)
|
||||||
|
|
||||||
// handle array bounds
|
// handle array bounds
|
||||||
if ((middleIndex === 0 || array[middleIndex - 1] <= array[middleIndex]) &&
|
if (
|
||||||
(middleIndex === originalLength - 1 || array[middleIndex + 1] <= array[middleIndex])) {
|
(middleIndex === 0 || array[middleIndex - 1] <= array[middleIndex]) &&
|
||||||
|
(middleIndex === originalLength - 1 ||
|
||||||
|
array[middleIndex + 1] <= array[middleIndex])
|
||||||
|
) {
|
||||||
return middleIndex
|
return middleIndex
|
||||||
} else if (middleIndex > 0 && array[middleIndex - 1] > array[middleIndex]) {
|
} else if (middleIndex > 0 && array[middleIndex - 1] > array[middleIndex]) {
|
||||||
return findMaxPointIndex(array, rangeStartIndex, (middleIndex - 1), originalLength)
|
return findMaxPointIndex(
|
||||||
|
array,
|
||||||
|
rangeStartIndex,
|
||||||
|
middleIndex - 1,
|
||||||
|
originalLength
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
// regular local max
|
// regular local max
|
||||||
return findMaxPointIndex(array, (middleIndex + 1), rangeEndIndex, originalLength)
|
return findMaxPointIndex(
|
||||||
|
array,
|
||||||
|
middleIndex + 1,
|
||||||
|
rangeEndIndex,
|
||||||
|
originalLength
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,10 +33,13 @@ const CountLocalMaximumPoints = (array, startIndex, endIndex) => {
|
|||||||
|
|
||||||
// handle the two halves
|
// handle the two halves
|
||||||
const middleIndex = parseInt((startIndex + endIndex) / 2)
|
const middleIndex = parseInt((startIndex + endIndex) / 2)
|
||||||
return CountLocalMaximumPoints(array, startIndex, middleIndex) +
|
return (
|
||||||
|
CountLocalMaximumPoints(array, startIndex, middleIndex) +
|
||||||
CountLocalMaximumPoints(array, middleIndex + 1, endIndex)
|
CountLocalMaximumPoints(array, middleIndex + 1, endIndex)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const NumberOfLocalMaximumPoints = (A) => CountLocalMaximumPoints(A, 0, A.length - 1)
|
const NumberOfLocalMaximumPoints = (A) =>
|
||||||
|
CountLocalMaximumPoints(A, 0, A.length - 1)
|
||||||
|
|
||||||
export { NumberOfLocalMaximumPoints }
|
export { NumberOfLocalMaximumPoints }
|
||||||
|
@ -11,7 +11,8 @@
|
|||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function QuickSelect (items, kth) { // eslint-disable-line no-unused-vars
|
function QuickSelect(items, kth) {
|
||||||
|
// eslint-disable-line no-unused-vars
|
||||||
if (kth < 1 || kth > items.length) {
|
if (kth < 1 || kth > items.length) {
|
||||||
throw new RangeError('Index Out of Bound')
|
throw new RangeError('Index Out of Bound')
|
||||||
}
|
}
|
||||||
@ -58,7 +59,7 @@ function getRandomInt (min, max) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Swap(arr, x, y) {
|
function Swap(arr, x, y) {
|
||||||
[arr[x], arr[y]] = [arr[y], arr[x]]
|
;[arr[x], arr[y]] = [arr[y], arr[x]]
|
||||||
}
|
}
|
||||||
|
|
||||||
export { QuickSelect }
|
export { QuickSelect }
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { Reverse } from '../Reverse.js'
|
import { Reverse } from '../Reverse.js'
|
||||||
import each from 'jest-each'
|
|
||||||
|
|
||||||
describe('reverse elements in an array', () => {
|
describe('reverse elements in an array', () => {
|
||||||
each`
|
it.each([
|
||||||
array | expected
|
[[], []],
|
||||||
${[]} | ${[]}
|
[[1], [1]],
|
||||||
${[1]} | ${[1]}
|
[
|
||||||
${[1, 2, 3, 4]} | ${[4, 3, 2, 1]}
|
[1, 2, 3, 4],
|
||||||
`.test('returns $expected when given $array', ({ array, expected }) => {
|
[4, 3, 2, 1]
|
||||||
|
]
|
||||||
|
])('returns %j when given %j', (array, expected) => {
|
||||||
expect(Reverse(array)).toEqual(expected)
|
expect(Reverse(array)).toEqual(expected)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -8,7 +8,7 @@ class Graph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
containsVertex(vertex) {
|
containsVertex(vertex) {
|
||||||
return typeof (this.adjacencyMap[vertex]) !== 'undefined'
|
return typeof this.adjacencyMap[vertex] !== 'undefined'
|
||||||
}
|
}
|
||||||
|
|
||||||
addEdge(vertex1, vertex2) {
|
addEdge(vertex1, vertex2) {
|
||||||
@ -18,7 +18,7 @@ class Graph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printGraph (output = value => console.log(value)) {
|
printGraph(output = (value) => console.log(value)) {
|
||||||
const keys = Object.keys(this.adjacencyMap)
|
const keys = Object.keys(this.adjacencyMap)
|
||||||
for (const i of keys) {
|
for (const i of keys) {
|
||||||
const values = this.adjacencyMap[i]
|
const values = this.adjacencyMap[i]
|
||||||
@ -34,13 +34,14 @@ class Graph {
|
|||||||
* Prints the Breadth first traversal of the graph from source.
|
* Prints the Breadth first traversal of the graph from source.
|
||||||
* @param {number} source The source vertex to start BFS.
|
* @param {number} source The source vertex to start BFS.
|
||||||
*/
|
*/
|
||||||
bfs (source, output = value => console.log(value)) {
|
bfs(source, output = (value) => console.log(value)) {
|
||||||
const queue = [[source, 0]] // level of source is 0
|
const queue = [[source, 0]] // level of source is 0
|
||||||
const visited = new Set()
|
const visited = new Set()
|
||||||
|
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const [node, level] = queue.shift() // remove the front of the queue
|
const [node, level] = queue.shift() // remove the front of the queue
|
||||||
if (visited.has(node)) { // visited
|
if (visited.has(node)) {
|
||||||
|
// visited
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,8 +57,9 @@ class Graph {
|
|||||||
* Prints the Depth first traversal of the graph from source.
|
* Prints the Depth first traversal of the graph from source.
|
||||||
* @param {number} source The source vertex to start DFS.
|
* @param {number} source The source vertex to start DFS.
|
||||||
*/
|
*/
|
||||||
dfs (source, visited = new Set(), output = value => console.log(value)) {
|
dfs(source, visited = new Set(), output = (value) => console.log(value)) {
|
||||||
if (visited.has(source)) { // visited
|
if (visited.has(source)) {
|
||||||
|
// visited
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ class Graph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prints the vertex and adjacency list
|
// Prints the vertex and adjacency list
|
||||||
printGraph (output = value => console.log(value)) {
|
printGraph(output = (value) => console.log(value)) {
|
||||||
// get all the vertices
|
// get all the vertices
|
||||||
const getKeys = this.AdjList.keys()
|
const getKeys = this.AdjList.keys()
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ describe('Test Graph2', () => {
|
|||||||
graph.addEdge('C', 'F')
|
graph.addEdge('C', 'F')
|
||||||
|
|
||||||
it('Check adjacency lists', () => {
|
it('Check adjacency lists', () => {
|
||||||
const mockFn = jest.fn()
|
const mockFn = vi.fn()
|
||||||
graph.printGraph(mockFn)
|
graph.printGraph(mockFn)
|
||||||
|
|
||||||
// Expect one call per vertex
|
// Expect one call per vertex
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Priority Queue Helper functions
|
// Priority Queue Helper functions
|
||||||
const getParentPosition = position => Math.floor((position - 1) / 2)
|
const getParentPosition = (position) => Math.floor((position - 1) / 2)
|
||||||
const getChildrenPositions = position => [2 * position + 1, 2 * position + 2]
|
const getChildrenPositions = (position) => [2 * position + 1, 2 * position + 2]
|
||||||
|
|
||||||
class KeyPriorityQueue {
|
class KeyPriorityQueue {
|
||||||
// Priority Queue class using Minimum Binary Heap
|
// Priority Queue class using Minimum Binary Heap
|
||||||
@ -97,7 +97,8 @@ class KeyPriorityQueue {
|
|||||||
|
|
||||||
_getPriorityOrInfinite(position) {
|
_getPriorityOrInfinite(position) {
|
||||||
// Helper function, returns priority of the node, or Infinite if no node corresponds to this position
|
// Helper function, returns priority of the node, or Infinite if no node corresponds to this position
|
||||||
if (position >= 0 && position < this._heap.length) return this.priorities.get(this._heap[position])
|
if (position >= 0 && position < this._heap.length)
|
||||||
|
return this.priorities.get(this._heap[position])
|
||||||
else return Infinity
|
else return Infinity
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +138,7 @@ class KeyPriorityQueue {
|
|||||||
this._swap(child2Pos, currPos)
|
this._swap(child2Pos, currPos)
|
||||||
currPos = child2Pos
|
currPos = child2Pos
|
||||||
}
|
}
|
||||||
[child1Pos, child2Pos] = getChildrenPositions(currPos)
|
;[child1Pos, child2Pos] = getChildrenPositions(currPos)
|
||||||
child1Priority = this._getPriorityOrInfinite(child1Pos)
|
child1Priority = this._getPriorityOrInfinite(child1Pos)
|
||||||
child2Priority = this._getPriorityOrInfinite(child2Pos)
|
child2Priority = this._getPriorityOrInfinite(child2Pos)
|
||||||
currPriority = this._getPriorityOrInfinite(currPos)
|
currPriority = this._getPriorityOrInfinite(currPos)
|
||||||
@ -146,7 +147,10 @@ class KeyPriorityQueue {
|
|||||||
|
|
||||||
_swap(position1, position2) {
|
_swap(position1, position2) {
|
||||||
// Helper function to swap 2 nodes
|
// Helper function to swap 2 nodes
|
||||||
[this._heap[position1], this._heap[position2]] = [this._heap[position2], this._heap[position1]]
|
;[this._heap[position1], this._heap[position2]] = [
|
||||||
|
this._heap[position2],
|
||||||
|
this._heap[position1]
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,8 @@ class MinHeap {
|
|||||||
|
|
||||||
while (childOneIdx <= endIdx) {
|
while (childOneIdx <= endIdx) {
|
||||||
const childTwoIdx = childOneIdx + 1 <= endIdx ? childOneIdx + 1 : -1
|
const childTwoIdx = childOneIdx + 1 <= endIdx ? childOneIdx + 1 : -1
|
||||||
const swapIdx = childTwoIdx !== -1 && heap[childTwoIdx] < heap[childOneIdx]
|
const swapIdx =
|
||||||
|
childTwoIdx !== -1 && heap[childTwoIdx] < heap[childOneIdx]
|
||||||
? childTwoIdx
|
? childTwoIdx
|
||||||
: childOneIdx
|
: childOneIdx
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ class MinPriorityQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// prints the heap
|
// prints the heap
|
||||||
print (output = value => console.log(value)) {
|
print(output = (value) => console.log(value)) {
|
||||||
output(this.heap.slice(1))
|
output(this.heap.slice(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,10 @@ class MinPriorityQueue {
|
|||||||
const heapSort = []
|
const heapSort = []
|
||||||
while (this.size > 0) {
|
while (this.size > 0) {
|
||||||
// swap first element with last element
|
// swap first element with last element
|
||||||
[this.heap[1], this.heap[this.size]] = [this.heap[this.size], this.heap[1]]
|
;[this.heap[1], this.heap[this.size]] = [
|
||||||
|
this.heap[this.size],
|
||||||
|
this.heap[1]
|
||||||
|
]
|
||||||
heapSort.push(this.heap.pop())
|
heapSort.push(this.heap.pop())
|
||||||
this.size--
|
this.size--
|
||||||
this.sink()
|
this.sink()
|
||||||
@ -92,8 +95,7 @@ class MinPriorityQueue {
|
|||||||
this.heap[k] > this.heap[2 * k] ||
|
this.heap[k] > this.heap[2 * k] ||
|
||||||
this.heap[k] > this.heap[2 * k + 1]
|
this.heap[k] > this.heap[2 * k + 1]
|
||||||
) {
|
) {
|
||||||
minIndex =
|
minIndex = this.heap[2 * k] < this.heap[2 * k + 1] ? 2 * k : 2 * k + 1
|
||||||
this.heap[2 * k] < this.heap[2 * k + 1] ? 2 * k : 2 * k + 1
|
|
||||||
} else {
|
} else {
|
||||||
minIndex = k
|
minIndex = k
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,9 @@ describe('MinHeap', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should initialize a heap from an input array', () => {
|
it('should initialize a heap from an input array', () => {
|
||||||
expect(heap).toEqual({ 'heap': [1, 4, 2, 7, 16, 10, 39, 23, 9, 43, 85, 42, 51] }) // eslint-disable-line
|
expect(heap).toEqual({
|
||||||
|
heap: [1, 4, 2, 7, 16, 10, 39, 23, 9, 43, 85, 42, 51]
|
||||||
|
}) // eslint-disable-line
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should show the top value in the heap', () => {
|
it('should show the top value in the heap', () => {
|
||||||
@ -22,12 +24,14 @@ describe('MinHeap', () => {
|
|||||||
const minValue = heap.extractMin()
|
const minValue = heap.extractMin()
|
||||||
|
|
||||||
expect(minValue).toEqual(1)
|
expect(minValue).toEqual(1)
|
||||||
expect(heap).toEqual({ 'heap': [2, 4, 10, 7, 16, 42, 39, 23, 9, 43, 85, 51] }) // eslint-disable-line
|
expect(heap).toEqual({ heap: [2, 4, 10, 7, 16, 42, 39, 23, 9, 43, 85, 51] }) // eslint-disable-line
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should insert a new value and sort until it meets heap conditions', () => {
|
it('should insert a new value and sort until it meets heap conditions', () => {
|
||||||
heap.insert(15)
|
heap.insert(15)
|
||||||
|
|
||||||
expect(heap).toEqual({ 'heap': [2, 4, 10, 7, 16, 15, 39, 23, 9, 43, 85, 51, 42] }) // eslint-disable-line
|
expect(heap).toEqual({
|
||||||
|
heap: [2, 4, 10, 7, 16, 15, 39, 23, 9, 43, 85, 51, 42]
|
||||||
|
}) // eslint-disable-line
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -7,11 +7,11 @@ describe('MinPriorityQueue', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
queue = new MinPriorityQueue(capacity)
|
queue = new MinPriorityQueue(capacity)
|
||||||
values.forEach(v => queue.insert(v))
|
values.forEach((v) => queue.insert(v))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Check heap ordering', () => {
|
it('Check heap ordering', () => {
|
||||||
const mockFn = jest.fn()
|
const mockFn = vi.fn()
|
||||||
queue.print(mockFn)
|
queue.print(mockFn)
|
||||||
|
|
||||||
expect(mockFn.mock.calls.length).toBe(1) // Expect one call
|
expect(mockFn.mock.calls.length).toBe(1) // Expect one call
|
||||||
@ -24,7 +24,7 @@ describe('MinPriorityQueue', () => {
|
|||||||
|
|
||||||
it('heapSort() expected to reverse the heap ordering', () => {
|
it('heapSort() expected to reverse the heap ordering', () => {
|
||||||
queue.heapReverse()
|
queue.heapReverse()
|
||||||
const mockFn = jest.fn()
|
const mockFn = vi.fn()
|
||||||
queue.print(mockFn)
|
queue.print(mockFn)
|
||||||
|
|
||||||
expect(mockFn.mock.calls.length).toBe(1)
|
expect(mockFn.mock.calls.length).toBe(1)
|
||||||
|
@ -9,12 +9,16 @@ function detectCycle (head) {
|
|||||||
Given head, the head of a linked list, determine if the linked list has a cycle in it.
|
Given head, the head of a linked list, determine if the linked list has a cycle in it.
|
||||||
Link for the Problem: https://leetcode.com/problems/linked-list-cycle/
|
Link for the Problem: https://leetcode.com/problems/linked-list-cycle/
|
||||||
*/
|
*/
|
||||||
if (!head) { return false }
|
if (!head) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
let slow = head
|
let slow = head
|
||||||
let fast = head.next
|
let fast = head.next
|
||||||
while (fast && fast.next) {
|
while (fast && fast.next) {
|
||||||
if (fast === slow) { return true }
|
if (fast === slow) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
fast = fast.next.next
|
fast = fast.next.next
|
||||||
slow = slow.next
|
slow = slow.next
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,6 @@ class ReverseSinglyLinkedList {
|
|||||||
head = next
|
head = next
|
||||||
}
|
}
|
||||||
return prev
|
return prev
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
export { ReverseSinglyLinkedList }
|
export { ReverseSinglyLinkedList }
|
||||||
|
@ -42,7 +42,9 @@ class SinglyCircularLinkedList {
|
|||||||
|
|
||||||
// Add any data to the end of the linkedList
|
// Add any data to the end of the linkedList
|
||||||
add(data) {
|
add(data) {
|
||||||
if (!this.headNode) { return this.addAtFirst(data) }
|
if (!this.headNode) {
|
||||||
|
return this.addAtFirst(data)
|
||||||
|
}
|
||||||
const node = new Node(data)
|
const node = new Node(data)
|
||||||
// Getting the last node
|
// Getting the last node
|
||||||
const currentNode = this.getElementAt(this.length - 1)
|
const currentNode = this.getElementAt(this.length - 1)
|
||||||
@ -56,7 +58,8 @@ class SinglyCircularLinkedList {
|
|||||||
insertAt(index, data) {
|
insertAt(index, data) {
|
||||||
if (index === 0) return this.addAtFirst(data)
|
if (index === 0) return this.addAtFirst(data)
|
||||||
if (index === this.length) return this.add(data)
|
if (index === this.length) return this.add(data)
|
||||||
if (index < 0 || index > this.length) throw new RangeError(`Index is out of range max ${this.length}`)
|
if (index < 0 || index > this.length)
|
||||||
|
throw new RangeError(`Index is out of range max ${this.length}`)
|
||||||
const node = new Node(data)
|
const node = new Node(data)
|
||||||
const previousNode = this.getElementAt(index - 1)
|
const previousNode = this.getElementAt(index - 1)
|
||||||
node.next = previousNode.next
|
node.next = previousNode.next
|
||||||
@ -126,7 +129,7 @@ class SinglyCircularLinkedList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// logs the data
|
// logs the data
|
||||||
printData (output = value => console.log(value)) {
|
printData(output = (value) => console.log(value)) {
|
||||||
let { currentIndex, currentNode } = this.initiateNodeAndIndex()
|
let { currentIndex, currentNode } = this.initiateNodeAndIndex()
|
||||||
|
|
||||||
while (currentNode !== null && currentIndex < this.length) {
|
while (currentNode !== null && currentIndex < this.length) {
|
||||||
|
@ -299,7 +299,7 @@ class LinkedList {
|
|||||||
}
|
}
|
||||||
this.tailNode = this.headNode
|
this.tailNode = this.headNode
|
||||||
this.headNode = prev
|
this.headNode = prev
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Node, LinkedList }
|
export { Node, LinkedList }
|
||||||
|
@ -59,14 +59,17 @@ class CircularQueue {
|
|||||||
|
|
||||||
// Checks if max capacity of queue has been reached or not
|
// Checks if max capacity of queue has been reached or not
|
||||||
checkOverflow() {
|
checkOverflow() {
|
||||||
if ((this.front === 1 && this.rear === this.maxLength) || (this.front === this.rear + 1)) {
|
if (
|
||||||
|
(this.front === 1 && this.rear === this.maxLength) ||
|
||||||
|
this.front === this.rear + 1
|
||||||
|
) {
|
||||||
// CIRCULAR QUEUE OVERFLOW
|
// CIRCULAR QUEUE OVERFLOW
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints the entire array ('*' represents blank space)
|
// Prints the entire array ('*' represents blank space)
|
||||||
display (output = value => console.log(value)) {
|
display(output = (value) => console.log(value)) {
|
||||||
for (let index = 1; index < this.queue.length; index++) {
|
for (let index = 1; index < this.queue.length; index++) {
|
||||||
output(this.queue[index])
|
output(this.queue[index])
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ class Queue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// display elements of the inputstack
|
// display elements of the inputstack
|
||||||
listIn (output = value => console.log(value)) {
|
listIn(output = (value) => console.log(value)) {
|
||||||
let i = 0
|
let i = 0
|
||||||
while (i < this.inputStack.length) {
|
while (i < this.inputStack.length) {
|
||||||
output(this.inputStack[i])
|
output(this.inputStack[i])
|
||||||
@ -40,7 +40,7 @@ class Queue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// display element of the outputstack
|
// display element of the outputstack
|
||||||
listOut (output = value => console.log(value)) {
|
listOut(output = (value) => console.log(value)) {
|
||||||
let i = 0
|
let i = 0
|
||||||
while (i < this.outputStack.length) {
|
while (i < this.outputStack.length) {
|
||||||
output(this.outputStack[i])
|
output(this.outputStack[i])
|
||||||
|
@ -45,13 +45,13 @@ const Stack = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// To see all the elements in the stack
|
// To see all the elements in the stack
|
||||||
Stack.prototype.view = function (output = value => console.log(value)) {
|
Stack.prototype.view = function (output = (value) => console.log(value)) {
|
||||||
for (let i = 0; i < this.top; i++) {
|
for (let i = 0; i < this.top; i++) {
|
||||||
output(this.stack[i])
|
output(this.stack[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Stack
|
return Stack
|
||||||
}())
|
})()
|
||||||
|
|
||||||
export { Stack }
|
export { Stack }
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
* RETURN > 0 if a > b
|
* RETURN > 0 if a > b
|
||||||
* MUST RETURN 0 if a == b
|
* MUST RETURN 0 if a == b
|
||||||
*/
|
*/
|
||||||
let utils;
|
let utils
|
||||||
(function (_utils) {
|
;(function (_utils) {
|
||||||
function comparator() {
|
function comparator() {
|
||||||
return function (v1, v2) {
|
return function (v1, v2) {
|
||||||
if (v1 < v2) return -1
|
if (v1 < v2) return -1
|
||||||
@ -53,7 +53,9 @@ const AVLTree = (function () {
|
|||||||
|
|
||||||
// get height of a node
|
// get height of a node
|
||||||
const getHeight = function (node) {
|
const getHeight = function (node) {
|
||||||
if (node == null) { return 0 }
|
if (node == null) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
return node._height
|
return node._height
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,12 +66,15 @@ const AVLTree = (function () {
|
|||||||
|
|
||||||
// update height of a node based on children's heights
|
// update height of a node based on children's heights
|
||||||
const updateHeight = function (node) {
|
const updateHeight = function (node) {
|
||||||
if (node == null) { return }
|
if (node == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
node._height = Math.max(getHeight(node._left), getHeight(node._right)) + 1
|
node._height = Math.max(getHeight(node._left), getHeight(node._right)) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: To check if the balanceFactor is valid
|
// Helper: To check if the balanceFactor is valid
|
||||||
const isValidBalanceFactor = (balanceFactor) => [0, 1, -1].includes(balanceFactor)
|
const isValidBalanceFactor = (balanceFactor) =>
|
||||||
|
[0, 1, -1].includes(balanceFactor)
|
||||||
|
|
||||||
// rotations of AVL Tree
|
// rotations of AVL Tree
|
||||||
const leftRotate = function (node) {
|
const leftRotate = function (node) {
|
||||||
@ -140,13 +145,18 @@ const AVLTree = (function () {
|
|||||||
}
|
}
|
||||||
updateHeight(root)
|
updateHeight(root)
|
||||||
const balanceFactor = getHeightDifference(root)
|
const balanceFactor = getHeightDifference(root)
|
||||||
return isValidBalanceFactor(balanceFactor) ? root : insertBalance(root, val, balanceFactor, tree)
|
return isValidBalanceFactor(balanceFactor)
|
||||||
|
? root
|
||||||
|
: insertBalance(root, val, balanceFactor, tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete am element
|
// delete am element
|
||||||
const deleteElement = function (root, _val, tree) {
|
const deleteElement = function (root, _val, tree) {
|
||||||
if (root == null) { return root }
|
if (root == null) {
|
||||||
if (tree._comp(root._val, _val) === 0) { // key found case
|
return root
|
||||||
|
}
|
||||||
|
if (tree._comp(root._val, _val) === 0) {
|
||||||
|
// key found case
|
||||||
if (root._left === null && root._right === null) {
|
if (root._left === null && root._right === null) {
|
||||||
root = null
|
root = null
|
||||||
tree.size--
|
tree.size--
|
||||||
@ -177,7 +187,9 @@ const AVLTree = (function () {
|
|||||||
}
|
}
|
||||||
// search tree for a element
|
// search tree for a element
|
||||||
const searchAVLTree = function (root, val, tree) {
|
const searchAVLTree = function (root, val, tree) {
|
||||||
if (root == null) { return null }
|
if (root == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
if (tree._comp(root._val, val) === 0) {
|
if (tree._comp(root._val, val) === 0) {
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
@ -222,7 +234,7 @@ const AVLTree = (function () {
|
|||||||
return prevSize !== this.size
|
return prevSize !== this.size
|
||||||
}
|
}
|
||||||
return _avl
|
return _avl
|
||||||
}())
|
})()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Code for Testing the AVLTree
|
* A Code for Testing the AVLTree
|
||||||
|
@ -32,7 +32,7 @@ const Node = (function Node () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Visit a node
|
// Visit a node
|
||||||
Node.prototype.visit = function (output = value => console.log(value)) {
|
Node.prototype.visit = function (output = (value) => console.log(value)) {
|
||||||
// Recursively go left
|
// Recursively go left
|
||||||
if (this.left !== null) {
|
if (this.left !== null) {
|
||||||
this.left.visit()
|
this.left.visit()
|
||||||
@ -103,14 +103,14 @@ const Node = (function Node () {
|
|||||||
}
|
}
|
||||||
// returns the constructor
|
// returns the constructor
|
||||||
return Node
|
return Node
|
||||||
}())
|
})()
|
||||||
|
|
||||||
// class Tree
|
// class Tree
|
||||||
const Tree = (function () {
|
const Tree = (function () {
|
||||||
function Tree() {
|
function Tree() {
|
||||||
// Just store the root
|
// Just store the root
|
||||||
this.root = null
|
this.root = null
|
||||||
};
|
}
|
||||||
|
|
||||||
// Inorder traversal
|
// Inorder traversal
|
||||||
Tree.prototype.traverse = function () {
|
Tree.prototype.traverse = function () {
|
||||||
@ -149,6 +149,6 @@ const Tree = (function () {
|
|||||||
|
|
||||||
// returns the constructor
|
// returns the constructor
|
||||||
return Tree
|
return Tree
|
||||||
}())
|
})()
|
||||||
|
|
||||||
export { Tree }
|
export { Tree }
|
||||||
|
@ -18,7 +18,9 @@ function Trie () {
|
|||||||
Trie.findAllWords = function (root, word, output) {
|
Trie.findAllWords = function (root, word, output) {
|
||||||
if (root === null) return
|
if (root === null) return
|
||||||
if (root.count > 0) {
|
if (root.count > 0) {
|
||||||
if (typeof output === 'object') { output.push({ word, count: root.count }) }
|
if (typeof output === 'object') {
|
||||||
|
output.push({ word, count: root.count })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let key
|
let key
|
||||||
for (key in root.children) {
|
for (key in root.children) {
|
||||||
@ -38,7 +40,9 @@ Trie.prototype.insert = function (word) {
|
|||||||
const len = word.length
|
const len = word.length
|
||||||
let i
|
let i
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (node.children[word.charAt(i)] === undefined) { node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node) }
|
if (node.children[word.charAt(i)] === undefined) {
|
||||||
|
node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node)
|
||||||
|
}
|
||||||
node = node.children[word.charAt(i)]
|
node = node.children[word.charAt(i)]
|
||||||
}
|
}
|
||||||
node.count += 1
|
node.count += 1
|
||||||
@ -87,7 +91,11 @@ Trie.prototype.remove = function (word, count) {
|
|||||||
// if the object forms some other objects prefix we don't delete it
|
// if the object forms some other objects prefix we don't delete it
|
||||||
// For checking an empty object
|
// For checking an empty object
|
||||||
// https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object
|
// https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object
|
||||||
if (child.count <= 0 && (Object.keys(child.children).length && child.children.constructor === Object)) {
|
if (
|
||||||
|
child.count <= 0 &&
|
||||||
|
Object.keys(child.children).length &&
|
||||||
|
child.children.constructor === Object
|
||||||
|
) {
|
||||||
child.parent.children[child.key] = undefined
|
child.parent.children[child.key] = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,14 @@ describe('AVLTree Implementation: ', () => {
|
|||||||
const emptyTree = new AVLTree(collator.compare)
|
const emptyTree = new AVLTree(collator.compare)
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
demoData.forEach(item => {
|
demoData.forEach((item) => {
|
||||||
if (avlTree.add(item)) {
|
if (avlTree.add(item)) {
|
||||||
dataList.push(item)
|
dataList.push(item)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
avlStringTree._comp = collator.compare
|
avlStringTree._comp = collator.compare
|
||||||
stringData.forEach(item => avlStringTree.add(item))
|
stringData.forEach((item) => avlStringTree.add(item))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('delete and search from empty tree', () => {
|
it('delete and search from empty tree', () => {
|
||||||
@ -33,10 +33,10 @@ describe('AVLTree Implementation: ', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('search if inserted element is present', () => {
|
it('search if inserted element is present', () => {
|
||||||
demoData.forEach(data => {
|
demoData.forEach((data) => {
|
||||||
expect(avlTree.find(data)).toBeTruthy()
|
expect(avlTree.find(data)).toBeTruthy()
|
||||||
})
|
})
|
||||||
stringData.forEach(data => {
|
stringData.forEach((data) => {
|
||||||
expect(avlStringTree.find(data)).toBeTruthy()
|
expect(avlStringTree.find(data)).toBeTruthy()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -29,7 +29,10 @@ class Vector2 {
|
|||||||
* @returns Whether they are approximately equal or not.
|
* @returns Whether they are approximately equal or not.
|
||||||
*/
|
*/
|
||||||
equalsApproximately(vector, epsilon) {
|
equalsApproximately(vector, epsilon) {
|
||||||
return (Math.abs(this.x - vector.x) < epsilon && Math.abs(this.y - vector.y) < epsilon)
|
return (
|
||||||
|
Math.abs(this.x - vector.x) < epsilon &&
|
||||||
|
Math.abs(this.y - vector.y) < epsilon
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,52 +5,80 @@ describe('Vector2', () => {
|
|||||||
it('should compare equality correctly', () => {
|
it('should compare equality correctly', () => {
|
||||||
expect(new Vector2(1, 0).equalsExactly(new Vector2(1, 0))).toBe(true)
|
expect(new Vector2(1, 0).equalsExactly(new Vector2(1, 0))).toBe(true)
|
||||||
|
|
||||||
expect(new Vector2(1.23, 4.56).equalsExactly(new Vector2(0, 0))).toBe(false)
|
expect(new Vector2(1.23, 4.56).equalsExactly(new Vector2(0, 0))).toBe(
|
||||||
|
false
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#equalsApproximately', () => {
|
describe('#equalsApproximately', () => {
|
||||||
it('should compare equality (approximately) correctly', () => {
|
it('should compare equality (approximately) correctly', () => {
|
||||||
expect(new Vector2(1, 0).equalsApproximately(new Vector2(1, 0.0000001), 0.000001))
|
expect(
|
||||||
.toBe(true)
|
new Vector2(1, 0).equalsApproximately(
|
||||||
|
new Vector2(1, 0.0000001),
|
||||||
|
0.000001
|
||||||
|
)
|
||||||
|
).toBe(true)
|
||||||
|
|
||||||
expect(new Vector2(1.23, 4.56).equalsApproximately(new Vector2(1.24, 4.56), 0.000001))
|
expect(
|
||||||
.toBe(false)
|
new Vector2(1.23, 4.56).equalsApproximately(
|
||||||
|
new Vector2(1.24, 4.56),
|
||||||
|
0.000001
|
||||||
|
)
|
||||||
|
).toBe(false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#add', () => {
|
describe('#add', () => {
|
||||||
it('should add two vectors correctly', () => {
|
it('should add two vectors correctly', () => {
|
||||||
expect(new Vector2(1, 0).add(new Vector2(0, 1)).equalsApproximately(new Vector2(1, 1), 0.000001))
|
expect(
|
||||||
.toBe(true)
|
new Vector2(1, 0)
|
||||||
|
.add(new Vector2(0, 1))
|
||||||
|
.equalsApproximately(new Vector2(1, 1), 0.000001)
|
||||||
|
).toBe(true)
|
||||||
|
|
||||||
expect(new Vector2(-3.3, -9).add(new Vector2(-2.2, 3)).equalsApproximately(new Vector2(-5.5, -6), 0.000001))
|
expect(
|
||||||
.toBe(true)
|
new Vector2(-3.3, -9)
|
||||||
|
.add(new Vector2(-2.2, 3))
|
||||||
|
.equalsApproximately(new Vector2(-5.5, -6), 0.000001)
|
||||||
|
).toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#subtract', () => {
|
describe('#subtract', () => {
|
||||||
it('should subtract two vectors correctly', () => {
|
it('should subtract two vectors correctly', () => {
|
||||||
expect(new Vector2(1, 0).subtract(new Vector2(0, 1)).equalsApproximately(new Vector2(1, -1), 0.000001))
|
expect(
|
||||||
.toBe(true)
|
new Vector2(1, 0)
|
||||||
|
.subtract(new Vector2(0, 1))
|
||||||
|
.equalsApproximately(new Vector2(1, -1), 0.000001)
|
||||||
|
).toBe(true)
|
||||||
|
|
||||||
expect(new Vector2(234.5, 1.7).subtract(new Vector2(3.3, 2.7)).equalsApproximately(new Vector2(231.2, -1), 0.000001))
|
expect(
|
||||||
.toBe(true)
|
new Vector2(234.5, 1.7)
|
||||||
|
.subtract(new Vector2(3.3, 2.7))
|
||||||
|
.equalsApproximately(new Vector2(231.2, -1), 0.000001)
|
||||||
|
).toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#multiply', () => {
|
describe('#multiply', () => {
|
||||||
it('should multiply two vectors correctly', () => {
|
it('should multiply two vectors correctly', () => {
|
||||||
expect(new Vector2(1, 0).multiply(5).equalsApproximately(new Vector2(5, 0), 0.000001))
|
expect(
|
||||||
.toBe(true)
|
new Vector2(1, 0)
|
||||||
|
.multiply(5)
|
||||||
|
.equalsApproximately(new Vector2(5, 0), 0.000001)
|
||||||
|
).toBe(true)
|
||||||
|
|
||||||
expect(new Vector2(3.41, -7.12).multiply(-3.1).equalsApproximately(new Vector2(-10.571, 22.072), 0.000001))
|
expect(
|
||||||
.toBe(true)
|
new Vector2(3.41, -7.12)
|
||||||
|
.multiply(-3.1)
|
||||||
|
.equalsApproximately(new Vector2(-10.571, 22.072), 0.000001)
|
||||||
|
).toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#length', () => {
|
describe('#length', () => {
|
||||||
it('should calculate it\'s length correctly', () => {
|
it("should calculate it's length correctly", () => {
|
||||||
expect(new Vector2(1, 0).length()).toBe(1)
|
expect(new Vector2(1, 0).length()).toBe(1)
|
||||||
|
|
||||||
expect(new Vector2(-1, 1).length()).toBe(Math.sqrt(2))
|
expect(new Vector2(-1, 1).length()).toBe(Math.sqrt(2))
|
||||||
@ -59,11 +87,20 @@ describe('Vector2', () => {
|
|||||||
|
|
||||||
describe('#normalize', () => {
|
describe('#normalize', () => {
|
||||||
it('should normalize vectors correctly', () => {
|
it('should normalize vectors correctly', () => {
|
||||||
expect(new Vector2(1, 0).normalize().equalsApproximately(new Vector2(1, 0), 0.000001))
|
expect(
|
||||||
.toBe(true)
|
new Vector2(1, 0)
|
||||||
|
.normalize()
|
||||||
|
.equalsApproximately(new Vector2(1, 0), 0.000001)
|
||||||
|
).toBe(true)
|
||||||
|
|
||||||
expect(new Vector2(1, -1).normalize().equalsApproximately(new Vector2(Math.sqrt(2) / 2, -Math.sqrt(2) / 2), 0.000001))
|
expect(
|
||||||
.toBe(true)
|
new Vector2(1, -1)
|
||||||
|
.normalize()
|
||||||
|
.equalsApproximately(
|
||||||
|
new Vector2(Math.sqrt(2) / 2, -Math.sqrt(2) / 2),
|
||||||
|
0.000001
|
||||||
|
)
|
||||||
|
).toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -85,19 +122,29 @@ describe('Vector2', () => {
|
|||||||
|
|
||||||
describe('#rotate', () => {
|
describe('#rotate', () => {
|
||||||
it('should rotate a vector correctly', () => {
|
it('should rotate a vector correctly', () => {
|
||||||
expect(new Vector2(0, -1).rotate(Math.PI / 2).equalsApproximately(new Vector2(1, 0), 0.000001))
|
expect(
|
||||||
.toBe(true)
|
new Vector2(0, -1)
|
||||||
|
.rotate(Math.PI / 2)
|
||||||
|
.equalsApproximately(new Vector2(1, 0), 0.000001)
|
||||||
|
).toBe(true)
|
||||||
|
|
||||||
expect(new Vector2(1.23, -4.56).rotate(Math.PI).equalsApproximately(new Vector2(-1.23, 4.56), 0.000001))
|
expect(
|
||||||
.toBe(true)
|
new Vector2(1.23, -4.56)
|
||||||
|
.rotate(Math.PI)
|
||||||
|
.equalsApproximately(new Vector2(-1.23, 4.56), 0.000001)
|
||||||
|
).toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#angleBetween', () => {
|
describe('#angleBetween', () => {
|
||||||
it('should calculate the angle between two vectors correctly', () => {
|
it('should calculate the angle between two vectors correctly', () => {
|
||||||
expect(new Vector2(1, 0).angleBetween(new Vector2(0, 1))).toBe(Math.PI / 2)
|
expect(new Vector2(1, 0).angleBetween(new Vector2(0, 1))).toBe(
|
||||||
|
Math.PI / 2
|
||||||
|
)
|
||||||
|
|
||||||
expect(new Vector2(1, 0).angleBetween(new Vector2(1, -1))).toBe(-Math.PI / 4)
|
expect(new Vector2(1, 0).angleBetween(new Vector2(1, -1))).toBe(
|
||||||
|
-Math.PI / 4
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -15,7 +15,7 @@ space complexity - O(n*m)
|
|||||||
const minimumEditDistance = (word1, word2) => {
|
const minimumEditDistance = (word1, word2) => {
|
||||||
const n = word1.length
|
const n = word1.length
|
||||||
const m = word2.length
|
const m = word2.length
|
||||||
const dp = new Array(m + 1).fill(0).map(item => [])
|
const dp = new Array(m + 1).fill(0).map((item) => [])
|
||||||
|
|
||||||
/*
|
/*
|
||||||
fill dp matrix with default values -
|
fill dp matrix with default values -
|
||||||
|
@ -14,9 +14,10 @@ class Month {
|
|||||||
this.monthDaysLeap = [31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
this.monthDaysLeap = [31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||||
}
|
}
|
||||||
|
|
||||||
printCal (days, startDay, output = value => console.log(value)) {
|
printCal(days, startDay, output = (value) => console.log(value)) {
|
||||||
output('M T W Th F S Su')
|
output('M T W Th F S Su')
|
||||||
const dates = []; let i
|
const dates = []
|
||||||
|
let i
|
||||||
for (i = 1; i <= days; i++) {
|
for (i = 1; i <= days; i++) {
|
||||||
dates.push(i)
|
dates.push(i)
|
||||||
}
|
}
|
||||||
@ -25,9 +26,9 @@ class Month {
|
|||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
let row = ''
|
let row = ''
|
||||||
for (i = 0; (i < 7) && (dates.length !== 0); i++) {
|
for (i = 0; i < 7 && dates.length !== 0; i++) {
|
||||||
row += dates.shift()
|
row += dates.shift()
|
||||||
while ((row.length % 4) !== 0) {
|
while (row.length % 4 !== 0) {
|
||||||
row += ' '
|
row += ' '
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,7 +38,9 @@ class Month {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parseDate(date) {
|
parseDate(date) {
|
||||||
const dateAr = []; let block = ''; let i
|
const dateAr = []
|
||||||
|
let block = ''
|
||||||
|
let i
|
||||||
for (i = 0; i < date.length; i++) {
|
for (i = 0; i < date.length; i++) {
|
||||||
if (date[i] === '/') {
|
if (date[i] === '/') {
|
||||||
dateAr.push(parseInt(block))
|
dateAr.push(parseInt(block))
|
||||||
@ -68,23 +71,25 @@ class Month {
|
|||||||
getDayDiff(startDate, endDate) {
|
getDayDiff(startDate, endDate) {
|
||||||
if (this.isGreater(startDate, endDate) === null) {
|
if (this.isGreater(startDate, endDate) === null) {
|
||||||
return 0
|
return 0
|
||||||
} else if ((this.isGreater(startDate, endDate) === true)) {
|
} else if (this.isGreater(startDate, endDate) === true) {
|
||||||
const midDate = startDate
|
const midDate = startDate
|
||||||
startDate = endDate
|
startDate = endDate
|
||||||
endDate = midDate
|
endDate = midDate
|
||||||
}
|
}
|
||||||
let diff = 0
|
let diff = 0
|
||||||
while (startDate.year !== endDate.year) {
|
while (startDate.year !== endDate.year) {
|
||||||
diff += (isLeapYear(startDate.year)) ? 366 : 365
|
diff += isLeapYear(startDate.year) ? 366 : 365
|
||||||
startDate.year = startDate.year + 1
|
startDate.year = startDate.year + 1
|
||||||
}
|
}
|
||||||
while (startDate.month !== endDate.month) {
|
while (startDate.month !== endDate.month) {
|
||||||
if (startDate.month < endDate.month) {
|
if (startDate.month < endDate.month) {
|
||||||
if (isLeapYear(startDate.year)) diff += this.monthDaysLeap[startDate.month]
|
if (isLeapYear(startDate.year))
|
||||||
|
diff += this.monthDaysLeap[startDate.month]
|
||||||
else diff += this.monthDays[startDate.month]
|
else diff += this.monthDays[startDate.month]
|
||||||
startDate.month = startDate.month + 1
|
startDate.month = startDate.month + 1
|
||||||
} else {
|
} else {
|
||||||
if (isLeapYear(startDate.year)) diff -= this.monthDaysLeap[startDate.month - 1]
|
if (isLeapYear(startDate.year))
|
||||||
|
diff -= this.monthDaysLeap[startDate.month - 1]
|
||||||
else diff -= this.monthDays[startDate.month - 1]
|
else diff -= this.monthDays[startDate.month - 1]
|
||||||
startDate.month = startDate.month - 1
|
startDate.month = startDate.month - 1
|
||||||
}
|
}
|
||||||
@ -93,13 +98,17 @@ class Month {
|
|||||||
}
|
}
|
||||||
|
|
||||||
generateMonthCal(date) {
|
generateMonthCal(date) {
|
||||||
const Month = this.parseDate(date); let day = ''
|
const Month = this.parseDate(date)
|
||||||
|
let day = ''
|
||||||
let difference = this.getDayDiff(this.epoch, Month)
|
let difference = this.getDayDiff(this.epoch, Month)
|
||||||
difference = difference % 7
|
difference = difference % 7
|
||||||
let Month2 = this.parseDate(date)
|
let Month2 = this.parseDate(date)
|
||||||
day = (this.isGreater(Month2, this.epoch)) ? this.Days[difference] : this.BDays[difference]
|
day = this.isGreater(Month2, this.epoch)
|
||||||
|
? this.Days[difference]
|
||||||
|
: this.BDays[difference]
|
||||||
Month2 = this.parseDate(date)
|
Month2 = this.parseDate(date)
|
||||||
if (isLeapYear(Month2.year)) this.printCal(this.monthDaysLeap[Month2.month], day)
|
if (isLeapYear(Month2.year))
|
||||||
|
this.printCal(this.monthDaysLeap[Month2.month], day)
|
||||||
else this.printCal(this.monthDays[Month2.month], day)
|
else this.printCal(this.monthDays[Month2.month], day)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,12 @@ function calculateLevenshteinDp (x, y) {
|
|||||||
} else if (j === 0) {
|
} else if (j === 0) {
|
||||||
dp[i][j] = i
|
dp[i][j] = i
|
||||||
} else {
|
} else {
|
||||||
dp[i][j] = minimum(dp[i - 1][j - 1] + costOfSubstitution(x.charAt(i - 1), y.charAt(j - 1)), dp[i - 1][j] + 1, dp[i][j - 1] + 1)
|
dp[i][j] = minimum(
|
||||||
|
dp[i - 1][j - 1] +
|
||||||
|
costOfSubstitution(x.charAt(i - 1), y.charAt(j - 1)),
|
||||||
|
dp[i - 1][j] + 1,
|
||||||
|
dp[i][j - 1] + 1
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,8 @@ References:
|
|||||||
* @returns {number} Length of the longest common subsequence
|
* @returns {number} Length of the longest common subsequence
|
||||||
*/
|
*/
|
||||||
function longestCommonSubsequence(str1, str2) {
|
function longestCommonSubsequence(str1, str2) {
|
||||||
const memo = new Array(str1.length + 1).fill(null)
|
const memo = new Array(str1.length + 1)
|
||||||
|
.fill(null)
|
||||||
.map(() => new Array(str2.length + 1).fill(null))
|
.map(() => new Array(str2.length + 1).fill(null))
|
||||||
|
|
||||||
function recursive(end1, end2) {
|
function recursive(end1, end2) {
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
export const longestPalindromeSubsequence = function (s) {
|
export const longestPalindromeSubsequence = function (s) {
|
||||||
const n = s.length
|
const n = s.length
|
||||||
|
|
||||||
const dp = new Array(n).fill(0).map(item => new Array(n).fill(0).map(item => 0))
|
const dp = new Array(n)
|
||||||
|
.fill(0)
|
||||||
|
.map((item) => new Array(n).fill(0).map((item) => 0))
|
||||||
|
|
||||||
// fill predefined for single character
|
// fill predefined for single character
|
||||||
for (let i = 0; i < n; i++) {
|
for (let i = 0; i < n; i++) {
|
||||||
|
@ -20,7 +20,9 @@ const minCostPath = (matrix) => {
|
|||||||
for (let i = 1; i < n; i++) moves[i][0] = moves[i - 1][0] + matrix[i][0]
|
for (let i = 1; i < n; i++) moves[i][0] = moves[i - 1][0] + matrix[i][0]
|
||||||
|
|
||||||
for (let i = 1; i < n; i++) {
|
for (let i = 1; i < n; i++) {
|
||||||
for (let j = 1; j < m; j++) { moves[i][j] = Math.min(moves[i - 1][j], moves[i][j - 1]) + matrix[i][j] }
|
for (let j = 1; j < m; j++) {
|
||||||
|
moves[i][j] = Math.min(moves[i - 1][j], moves[i][j - 1]) + matrix[i][j]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return moves[n - 1][m - 1]
|
return moves[n - 1][m - 1]
|
||||||
|
@ -9,7 +9,9 @@ export function rodCut (prices, n) {
|
|||||||
|
|
||||||
for (let i = 1; i <= n; i++) {
|
for (let i = 1; i <= n; i++) {
|
||||||
let maxVal = Number.MIN_VALUE
|
let maxVal = Number.MIN_VALUE
|
||||||
for (let j = 0; j < i; j++) { maxVal = Math.max(maxVal, prices[j] + memo[i - j - 1]) }
|
for (let j = 0; j < i; j++) {
|
||||||
|
maxVal = Math.max(maxVal, prices[j] + memo[i - j - 1])
|
||||||
|
}
|
||||||
memo[i] = maxVal
|
memo[i] = maxVal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const isValid = (board, row, col, k) => {
|
const isValid = (board, row, col, k) => {
|
||||||
for (let i = 0; i < 9; i++) {
|
for (let i = 0; i < 9; i++) {
|
||||||
const m = 3 * Math.floor(row / 3) + Math.floor(i / 3)
|
const m = 3 * Math.floor(row / 3) + Math.floor(i / 3)
|
||||||
const n = 3 * Math.floor(col / 3) + i % 3
|
const n = 3 * Math.floor(col / 3) + (i % 3)
|
||||||
if (board[row][i] === k || board[i][col] === k || board[m][n] === k) {
|
if (board[row][i] === k || board[i][col] === k || board[m][n] === k) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,10 @@ const zeroOneKnapsack = (arr, n, cap, cache) => {
|
|||||||
return cache[n][cap]
|
return cache[n][cap]
|
||||||
}
|
}
|
||||||
if (arr[n - 1][0] <= cap) {
|
if (arr[n - 1][0] <= cap) {
|
||||||
cache[n][cap] = Math.max(arr[n - 1][1] + zeroOneKnapsack(arr, n - 1, cap - arr[n - 1][0], cache), zeroOneKnapsack(arr, n - 1, cap, cache))
|
cache[n][cap] = Math.max(
|
||||||
|
arr[n - 1][1] + zeroOneKnapsack(arr, n - 1, cap - arr[n - 1][0], cache),
|
||||||
|
zeroOneKnapsack(arr, n - 1, cap, cache)
|
||||||
|
)
|
||||||
return cache[n][cap]
|
return cache[n][cap]
|
||||||
} else {
|
} else {
|
||||||
cache[n][cap] = zeroOneKnapsack(arr, n - 1, cap, cache)
|
cache[n][cap] = zeroOneKnapsack(arr, n - 1, cap, cache)
|
||||||
@ -52,9 +55,7 @@ const example = () => {
|
|||||||
arr.push(input[j])
|
arr.push(input[j])
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
const newArr = arr.map(e =>
|
const newArr = arr.map((e) => e.trim().split(' ').map(Number))
|
||||||
e.trim().split(' ').map(Number)
|
|
||||||
)
|
|
||||||
const cache = []
|
const cache = []
|
||||||
for (let i = 0; i <= currlen; i++) {
|
for (let i = 0; i <= currlen; i++) {
|
||||||
const temp = []
|
const temp = []
|
||||||
|
@ -26,7 +26,11 @@ describe('LongestCommonSubsequence', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('expects to return the longest common subsequence, medium-length inputs', () => {
|
it('expects to return the longest common subsequence, medium-length inputs', () => {
|
||||||
expect(longestCommonSubsequence('bsbininm', 'jmjkbkjkv')).toEqual('b'.length)
|
expect(longestCommonSubsequence('bsbininm', 'jmjkbkjkv')).toEqual(
|
||||||
expect(longestCommonSubsequence('oxcpqrsvwf', 'shmtulqrypy')).toEqual('qr'.length)
|
'b'.length
|
||||||
|
)
|
||||||
|
expect(longestCommonSubsequence('oxcpqrsvwf', 'shmtulqrypy')).toEqual(
|
||||||
|
'qr'.length
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -47,7 +47,9 @@ describe('MaxProductOfThree, random arrays of size 3 to 5', () => {
|
|||||||
for (let i = 0; i < numberOfRandomTests; i++) {
|
for (let i = 0; i < numberOfRandomTests; i++) {
|
||||||
const arr = []
|
const arr = []
|
||||||
// Randomize the length of the array in the current test
|
// Randomize the length of the array in the current test
|
||||||
const length = Math.floor(Math.random() * (maxLength - minLength) + minLength)
|
const length = Math.floor(
|
||||||
|
Math.random() * (maxLength - minLength) + minLength
|
||||||
|
)
|
||||||
|
|
||||||
// Fill the array with random values in the specified range
|
// Fill the array with random values in the specified range
|
||||||
for (let j = 0; j < length + 1; j++) {
|
for (let j = 0; j < length + 1; j++) {
|
||||||
@ -58,13 +60,19 @@ describe('MaxProductOfThree, random arrays of size 3 to 5', () => {
|
|||||||
const expectedProduct = completeMaxThree(arr)
|
const expectedProduct = completeMaxThree(arr)
|
||||||
|
|
||||||
// Set up the expectation
|
// Set up the expectation
|
||||||
it('Expect the array ' + arr.toString() + ' to return the maximum three product of ' + expectedProduct, () => {
|
it(
|
||||||
|
'Expect the array ' +
|
||||||
|
arr.toString() +
|
||||||
|
' to return the maximum three product of ' +
|
||||||
|
expectedProduct,
|
||||||
|
() => {
|
||||||
// Calculate the max three product using the function being tested
|
// Calculate the max three product using the function being tested
|
||||||
const actualProduct = maxProductOfThree(arr)
|
const actualProduct = maxProductOfThree(arr)
|
||||||
|
|
||||||
// Was unable to use expect().toBe(), since it sometimes compared 0 to -0, and that would not pass
|
// Was unable to use expect().toBe(), since it sometimes compared 0 to -0, and that would not pass
|
||||||
// At the same time, standardjs forbid me from checking for === -0 to convert to 0
|
// At the same time, standardjs forbid me from checking for === -0 to convert to 0
|
||||||
expect(actualProduct === expectedProduct).toBeTruthy()
|
expect(actualProduct === expectedProduct).toBeTruthy()
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -18,6 +18,8 @@ describe('SieveOfEratosthenes', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('Primes till 70', () => {
|
it('Primes till 70', () => {
|
||||||
expect(sieveOfEratosthenes(70)).toEqual([2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67])
|
expect(sieveOfEratosthenes(70)).toEqual([
|
||||||
|
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67
|
||||||
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -3,13 +3,37 @@ import { uniquePaths2 } from '../UniquePaths2'
|
|||||||
describe('Unique Paths2', () => {
|
describe('Unique Paths2', () => {
|
||||||
// Should return number of ways, taken into account the obstacles
|
// Should return number of ways, taken into account the obstacles
|
||||||
test('There are obstacles in the way', () => {
|
test('There are obstacles in the way', () => {
|
||||||
expect(uniquePaths2([[0, 0, 0], [0, 1, 0], [0, 0, 0]])).toEqual(2)
|
expect(
|
||||||
expect(uniquePaths2([[0, 0, 0], [0, 1, 0], [0, 0, 0], [1, 0, 0]])).toEqual(3)
|
uniquePaths2([
|
||||||
|
[0, 0, 0],
|
||||||
|
[0, 1, 0],
|
||||||
|
[0, 0, 0]
|
||||||
|
])
|
||||||
|
).toEqual(2)
|
||||||
|
expect(
|
||||||
|
uniquePaths2([
|
||||||
|
[0, 0, 0],
|
||||||
|
[0, 1, 0],
|
||||||
|
[0, 0, 0],
|
||||||
|
[1, 0, 0]
|
||||||
|
])
|
||||||
|
).toEqual(3)
|
||||||
})
|
})
|
||||||
// Should return number of all possible ways to reach right-bottom corner
|
// Should return number of all possible ways to reach right-bottom corner
|
||||||
test('There are no obstacles in the way', () => {
|
test('There are no obstacles in the way', () => {
|
||||||
expect(uniquePaths2([[0, 0, 0], [0, 0, 0], [0, 0, 0]])).toEqual(6)
|
expect(
|
||||||
expect(uniquePaths2([[0, 0, 0], [0, 0, 0]])).toEqual(3)
|
uniquePaths2([
|
||||||
|
[0, 0, 0],
|
||||||
|
[0, 0, 0],
|
||||||
|
[0, 0, 0]
|
||||||
|
])
|
||||||
|
).toEqual(6)
|
||||||
|
expect(
|
||||||
|
uniquePaths2([
|
||||||
|
[0, 0, 0],
|
||||||
|
[0, 0, 0]
|
||||||
|
])
|
||||||
|
).toEqual(3)
|
||||||
})
|
})
|
||||||
// Should throw an exception b/c input data has wrong type
|
// Should throw an exception b/c input data has wrong type
|
||||||
test('There are wrong type of input data', () => {
|
test('There are wrong type of input data', () => {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user