mirror of
https://github.com/TheAlgorithms/JavaScript.git
synced 2025-07-19 18:13:44 +08:00
feat: Test running overhaul, switch to Prettier & reformat everything (#1407)
* chore: Switch to Node 20 + Vitest * chore: migrate to vitest mock functions * chore: code style (switch to prettier) * test: re-enable long-running test Seems the switch to Node 20 and Vitest has vastly improved the code's and / or the test's runtime! see #1193 * chore: code style * chore: fix failing tests * Updated Documentation in README.md * Update contribution guidelines to state usage of Prettier * fix: set prettier printWidth back to 80 * chore: apply updated code style automatically * fix: set prettier line endings to lf again * chore: apply updated code style automatically --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Lars Müller <34514239+appgurueu@users.noreply.github.com>
This commit is contained in:
@ -22,14 +22,14 @@
|
||||
*/
|
||||
|
||||
class Combinations {
|
||||
constructor (n, k) {
|
||||
constructor(n, k) {
|
||||
this.n = n
|
||||
this.k = k
|
||||
this.current = [] // will be used for storing current combination
|
||||
this.combinations = []
|
||||
}
|
||||
|
||||
findCombinations (high = this.n, total = this.k, low = 1) {
|
||||
findCombinations(high = this.n, total = this.k, low = 1) {
|
||||
if (total === 0) {
|
||||
this.combinations.push([...this.current])
|
||||
return this.combinations
|
||||
|
@ -10,14 +10,14 @@
|
||||
*/
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
const permutations = arr => {
|
||||
const permutations = (arr) => {
|
||||
const P = []
|
||||
const permute = (arr, low, high) => {
|
||||
if (low === high) {
|
||||
|
@ -1,12 +1,12 @@
|
||||
// Wikipedia: https://en.wikipedia.org/wiki/Knight%27s_tour
|
||||
|
||||
class OpenKnightTour {
|
||||
constructor (size) {
|
||||
constructor(size) {
|
||||
this.board = new Array(size).fill(0).map(() => new Array(size).fill(0))
|
||||
this.size = size
|
||||
}
|
||||
|
||||
getMoves ([i, j]) {
|
||||
getMoves([i, j]) {
|
||||
// helper function to get the valid moves of the knight from the current position
|
||||
const moves = [
|
||||
[i + 2, j - 1],
|
||||
@ -19,15 +19,17 @@ class OpenKnightTour {
|
||||
[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
|
||||
return !this.board.map(row => row.includes(0)).includes(true)
|
||||
return !this.board.map((row) => row.includes(0)).includes(true)
|
||||
}
|
||||
|
||||
solve () {
|
||||
solve() {
|
||||
// function to find the solution for the given board
|
||||
for (let i = 0; i < this.size; i++) {
|
||||
for (let j = 0; j < this.size; j++) {
|
||||
@ -37,7 +39,7 @@ class OpenKnightTour {
|
||||
return false
|
||||
}
|
||||
|
||||
solveHelper ([i, j], curr) {
|
||||
solveHelper([i, j], curr) {
|
||||
// helper function for the main computation
|
||||
if (this.isComplete()) return true
|
||||
|
||||
@ -52,7 +54,7 @@ class OpenKnightTour {
|
||||
return false
|
||||
}
|
||||
|
||||
printBoard (output = value => console.log(value)) {
|
||||
printBoard(output = (value) => console.log(value)) {
|
||||
// utility function to display the board
|
||||
for (const row of this.board) {
|
||||
let string = ''
|
||||
|
@ -1,5 +1,5 @@
|
||||
class NQueens {
|
||||
constructor (size) {
|
||||
constructor(size) {
|
||||
if (size < 0) {
|
||||
throw RangeError('Invalid board size')
|
||||
}
|
||||
@ -8,7 +8,7 @@ class NQueens {
|
||||
this.solutionCount = 0
|
||||
}
|
||||
|
||||
isValid ([row, col]) {
|
||||
isValid([row, col]) {
|
||||
// function to check if the placement of the queen in the given location is valid
|
||||
|
||||
// checking the left of the current row
|
||||
@ -29,15 +29,15 @@ class NQueens {
|
||||
return true
|
||||
}
|
||||
|
||||
placeQueen (row, col) {
|
||||
placeQueen(row, col) {
|
||||
this.board[row][col] = 'Q'
|
||||
}
|
||||
|
||||
removeQueen (row, col) {
|
||||
removeQueen(row, col) {
|
||||
this.board[row][col] = '.'
|
||||
}
|
||||
|
||||
solve (col = 0) {
|
||||
solve(col = 0) {
|
||||
if (col >= this.size) {
|
||||
this.solutionCount++
|
||||
return true
|
||||
@ -54,7 +54,7 @@ class NQueens {
|
||||
return false
|
||||
}
|
||||
|
||||
printBoard (output = value => console.log(value)) {
|
||||
printBoard(output = (value) => console.log(value)) {
|
||||
if (!output._isMockFunction) {
|
||||
output('\n')
|
||||
}
|
||||
|
@ -21,19 +21,23 @@
|
||||
* @param grid The grid to check.
|
||||
* @throws TypeError When the given grid is invalid.
|
||||
*/
|
||||
function validateGrid (grid) {
|
||||
if (!Array.isArray(grid) || grid.length === 0) throw new TypeError('Grid must be a non-empty array')
|
||||
function validateGrid(grid) {
|
||||
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')
|
||||
|
||||
const allCellsHaveValidValues = grid.every(row => {
|
||||
return row.every(cell => cell === 0 || cell === 1)
|
||||
const allCellsHaveValidValues = grid.every((row) => {
|
||||
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) {
|
||||
const n = grid.length
|
||||
return x >= 0 && x < n && y >= 0 && y < n && grid[y][x] === 1
|
||||
}
|
||||
@ -48,7 +52,7 @@ function isSafe (grid, x, y) {
|
||||
* @param path The path we took to get from the source cell to the current location.
|
||||
* @returns {string|boolean} Either the path to the target cell or false.
|
||||
*/
|
||||
function getPathPart (grid, x, y, solution, path) {
|
||||
function getPathPart(grid, x, y, solution, path) {
|
||||
const n = grid.length
|
||||
|
||||
// are we there yet?
|
||||
@ -89,7 +93,7 @@ function getPathPart (grid, x, y, solution, path) {
|
||||
return false
|
||||
}
|
||||
|
||||
function getPath (grid) {
|
||||
function getPath(grid) {
|
||||
// grid dimensions
|
||||
const n = grid.length
|
||||
|
||||
@ -108,7 +112,7 @@ function getPath (grid) {
|
||||
* Creates an instance of the "rat in a maze" based on a given grid (maze).
|
||||
*/
|
||||
export class RatInAMaze {
|
||||
constructor (grid) {
|
||||
constructor(grid) {
|
||||
// first, let's do some error checking on the input
|
||||
validateGrid(grid)
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
class Sudoku {
|
||||
// Sudoku Class to hold the board and related functions
|
||||
constructor (board) {
|
||||
constructor(board) {
|
||||
this.board = board
|
||||
}
|
||||
|
||||
findEmptyCell () {
|
||||
findEmptyCell() {
|
||||
// Find a empty cell in the board (returns [-1, -1] if all cells are filled)
|
||||
for (let i = 0; i < 9; i++) {
|
||||
for (let j = 0; j < 9; j++) {
|
||||
@ -14,7 +14,7 @@ class Sudoku {
|
||||
return [-1, -1]
|
||||
}
|
||||
|
||||
check ([y, x], value) {
|
||||
check([y, x], value) {
|
||||
// checks if the value to be added in the board is an acceptable value for the cell
|
||||
|
||||
// checking through the row
|
||||
@ -29,8 +29,8 @@ class Sudoku {
|
||||
// checking through the 3x3 block of the cell
|
||||
const secRow = Math.floor(y / 3)
|
||||
const secCol = Math.floor(x / 3)
|
||||
for (let i = (secRow * 3); i < ((secRow * 3) + 3); i++) {
|
||||
for (let j = (secCol * 3); j < ((secCol * 3) + 3); j++) {
|
||||
for (let i = secRow * 3; i < secRow * 3 + 3; i++) {
|
||||
for (let j = secCol * 3; j < secCol * 3 + 3; j++) {
|
||||
if (y !== i && x !== j && this.board[i][j] === value) return false
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,7 @@ class Sudoku {
|
||||
return true
|
||||
}
|
||||
|
||||
solve () {
|
||||
solve() {
|
||||
const [y, x] = this.findEmptyCell()
|
||||
|
||||
// checking if the board is complete
|
||||
@ -56,20 +56,23 @@ class Sudoku {
|
||||
return false
|
||||
}
|
||||
|
||||
getSection (row, [start, end]) {
|
||||
getSection(row, [start, end]) {
|
||||
return this.board[row].slice(start, end)
|
||||
}
|
||||
|
||||
printBoard (output = (...v) => console.log(...v)) {
|
||||
printBoard(output = (...v) => console.log(...v)) {
|
||||
// helper function to display board
|
||||
for (let i = 0; i < 9; i++) {
|
||||
if (i % 3 === 0 && i !== 0) {
|
||||
output('- - - - - - - - - - - -')
|
||||
}
|
||||
output(
|
||||
...this.getSection(i, [0, 3]), ' | ',
|
||||
...this.getSection(i, [3, 6]), ' | ',
|
||||
...this.getSection(i, [6, 9]))
|
||||
...this.getSection(i, [0, 3]),
|
||||
' | ',
|
||||
...this.getSection(i, [3, 6]),
|
||||
' | ',
|
||||
...this.getSection(i, [6, 9])
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,22 @@ import { Combinations } from '../AllCombinationsOfSizeK'
|
||||
describe('AllCombinationsOfSizeK', () => {
|
||||
it('should return 3x2 matrix solution for n = 3 and k = 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', () => {
|
||||
const test2 = new Combinations(4, 2)
|
||||
expect(test2.findCombinations()).toEqual([[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]])
|
||||
expect(test2.findCombinations()).toEqual([
|
||||
[1, 2],
|
||||
[1, 3],
|
||||
[1, 4],
|
||||
[2, 3],
|
||||
[2, 4],
|
||||
[3, 4]
|
||||
])
|
||||
})
|
||||
})
|
||||
|
@ -1,5 +1,11 @@
|
||||
import { generateParentheses } from '../generateParentheses'
|
||||
|
||||
test('generate all valid parentheses of input 3', () => {
|
||||
expect(generateParentheses(3)).toStrictEqual(['((()))', '(()())', '(())()', '()(())', '()()()'])
|
||||
expect(generateParentheses(3)).toStrictEqual([
|
||||
'((()))',
|
||||
'(()())',
|
||||
'(())()',
|
||||
'()(())',
|
||||
'()()()'
|
||||
])
|
||||
})
|
||||
|
@ -14,6 +14,8 @@ describe('NQueens', () => {
|
||||
})
|
||||
|
||||
it('should throw RangeError for negative size board', () => {
|
||||
expect(() => { return new NQueens(-1) }).toThrow(RangeError)
|
||||
expect(() => {
|
||||
return new NQueens(-1)
|
||||
}).toThrow(RangeError)
|
||||
})
|
||||
})
|
||||
|
@ -7,14 +7,18 @@ describe('RatInAMaze', () => {
|
||||
for (const value of values) {
|
||||
// we deliberately want to check whether this constructor call fails or not
|
||||
// eslint-disable-next-line no-new
|
||||
expect(() => { new RatInAMaze(value) }).toThrow()
|
||||
expect(() => {
|
||||
new RatInAMaze(value)
|
||||
}).toThrow()
|
||||
}
|
||||
})
|
||||
|
||||
it('should fail for an empty array', () => {
|
||||
// we deliberately want to check whether this constructor call fails or not
|
||||
// eslint-disable-next-line no-new
|
||||
expect(() => { new RatInAMaze([]) }).toThrow()
|
||||
expect(() => {
|
||||
new RatInAMaze([])
|
||||
}).toThrow()
|
||||
})
|
||||
|
||||
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
|
||||
// eslint-disable-next-line no-new
|
||||
expect(() => { new RatInAMaze(array) }).toThrow()
|
||||
expect(() => {
|
||||
new RatInAMaze(array)
|
||||
}).toThrow()
|
||||
})
|
||||
|
||||
it('should fail for arrays containing invalid values', () => {
|
||||
@ -34,7 +40,9 @@ describe('RatInAMaze', () => {
|
||||
for (const value of values) {
|
||||
// we deliberately want to check whether this constructor call fails or not
|
||||
// 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', () => {
|
||||
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.path).toBe('RDDR')
|
||||
})
|
||||
|
||||
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.path).toBe('')
|
||||
})
|
||||
|
@ -28,7 +28,9 @@ describe('Sudoku', () => {
|
||||
it('should create a valid board successfully', () => {
|
||||
// we deliberately want to check whether this constructor call fails or not
|
||||
// eslint-disable-next-line no-new
|
||||
expect(() => { new Sudoku(data) }).not.toThrow()
|
||||
expect(() => {
|
||||
new Sudoku(data)
|
||||
}).not.toThrow()
|
||||
})
|
||||
|
||||
it('should find an empty cell', () => {
|
||||
|
Reference in New Issue
Block a user