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:
Roland Hummel
2023-10-03 23:08:19 +02:00
committed by GitHub
parent 0ca18c2b2c
commit 86d333ee94
392 changed files with 5849 additions and 16622 deletions

View File

@ -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

View File

@ -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)

View File

@ -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: |

View File

@ -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
View File

@ -0,0 +1,2 @@
.github
DIRECTORY.md

View File

@ -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) {

View File

@ -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 = ''

View File

@ -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')
} }

View File

@ -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) {

View File

@ -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])
)
} }
} }
} }

View File

@ -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]
])
}) })
}) })

View File

@ -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([
'((()))',
'(()())',
'(())()',
'()(())',
'()()()'
])
}) })

View File

@ -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)
}) })
}) })

View File

@ -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('')
}) })

View File

@ -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', () => {

View File

@ -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 }

View File

@ -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).

View File

@ -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

View File

@ -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)
} }

View File

@ -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,

View File

@ -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))

View File

@ -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], [])
)
} }

View File

@ -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

View File

@ -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

View File

@ -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]
])
}) })
}) })

View File

@ -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])
}) })
}) })
}) })

View File

@ -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)
} }
/** /**

View File

@ -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

View File

@ -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 }

View File

@ -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 {

View File

@ -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

View File

@ -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)
) )
} }

View File

@ -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')
}) })
}) })

View File

@ -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', () => {

View File

@ -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'
)
}) })
}) })

View File

@ -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 = []

View File

@ -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
} }

View File

@ -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

View File

@ -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
} }

View File

@ -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) => {

View File

@ -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

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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

View File

@ -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

View File

@ -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)
} }

View File

@ -33,6 +33,4 @@ const lengthConversion = (length, fromUnit, toUnit) => {
return convertedLength return convertedLength
} }
export { export { lengthConversion }
lengthConversion
}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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)}`
} }

View File

@ -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}`
}
} }
} }

View File

@ -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)
} }

View File

@ -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
} }

View File

@ -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.

View File

@ -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.

View File

@ -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')

View File

@ -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()
)
}) })
}) })

View File

@ -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)
}) })
}) })

View File

@ -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!'
)
}) })
}) })

View File

@ -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!'
)
}) })
}) })

View File

@ -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)

View File

@ -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
)
} }
} }

View File

@ -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 }

View File

@ -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 }

View File

@ -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)
}) })
}) })

View File

@ -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
} }

View File

@ -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()

View File

@ -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

View File

@ -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]
]
} }
} }

View File

@ -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

View File

@ -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
} }

View File

@ -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
}) })
}) })

View File

@ -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)

View File

@ -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
} }

View File

@ -11,6 +11,6 @@ class ReverseSinglyLinkedList {
head = next head = next
} }
return prev return prev
}; }
} }
export { ReverseSinglyLinkedList } export { ReverseSinglyLinkedList }

View File

@ -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) {

View File

@ -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 }

View File

@ -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])
} }

View File

@ -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])

View File

@ -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 }

View File

@ -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

View File

@ -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 }

View File

@ -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
} }
} }

View File

@ -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()
}) })
}) })

View File

@ -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
)
} }
/** /**

View File

@ -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
)
}) })
}) })
}) })

View File

@ -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 -

View File

@ -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)
} }
} }

View File

@ -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
)
} }
} }
} }

View File

@ -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) {

View File

@ -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++) {

View File

@ -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]

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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 = []

View File

@ -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
)
}) })
}) })

View File

@ -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()
}) }
)
} }
}) })

View File

@ -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
])
}) })
}) })

View File

@ -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