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

@ -9,19 +9,38 @@
* @complexity: O(log(n)) (worst case)
* @flow
*/
const findMaxPointIndex = (array, rangeStartIndex, rangeEndIndex, originalLength) => {
const findMaxPointIndex = (
array,
rangeStartIndex,
rangeEndIndex,
originalLength
) => {
// find index range middle point
const middleIndex = rangeStartIndex + parseInt((rangeEndIndex - rangeStartIndex) / 2)
const middleIndex =
rangeStartIndex + parseInt((rangeEndIndex - rangeStartIndex) / 2)
// handle array bounds
if ((middleIndex === 0 || array[middleIndex - 1] <= array[middleIndex]) &&
(middleIndex === originalLength - 1 || array[middleIndex + 1] <= array[middleIndex])) {
if (
(middleIndex === 0 || array[middleIndex - 1] <= array[middleIndex]) &&
(middleIndex === originalLength - 1 ||
array[middleIndex + 1] <= array[middleIndex])
) {
return 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 {
// 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
const middleIndex = parseInt((startIndex + endIndex) / 2)
return CountLocalMaximumPoints(array, startIndex, middleIndex) +
return (
CountLocalMaximumPoints(array, startIndex, middleIndex) +
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 }

View File

@ -11,7 +11,8 @@
* @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) {
throw new RangeError('Index Out of Bound')
}
@ -19,7 +20,7 @@ function QuickSelect (items, kth) { // eslint-disable-line no-unused-vars
return RandomizedSelect(items, 0, items.length - 1, kth)
}
function RandomizedSelect (items, left, right, i) {
function RandomizedSelect(items, left, right, i) {
if (left === right) return items[left]
const pivotIndex = RandomizedPartition(items, left, right)
@ -31,13 +32,13 @@ function RandomizedSelect (items, left, right, i) {
return RandomizedSelect(items, pivotIndex + 1, right, i - k)
}
function RandomizedPartition (items, left, right) {
function RandomizedPartition(items, left, right) {
const rand = getRandomInt(left, right)
Swap(items, rand, right)
return Partition(items, left, right)
}
function Partition (items, left, right) {
function Partition(items, left, right) {
const x = items[right]
let pivotIndex = left - 1
@ -53,12 +54,12 @@ function Partition (items, left, right) {
return pivotIndex + 1
}
function getRandomInt (min, max) {
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
function Swap (arr, x, y) {
[arr[x], arr[y]] = [arr[y], arr[x]]
function Swap(arr, x, y) {
;[arr[x], arr[y]] = [arr[y], arr[x]]
}
export { QuickSelect }

View File

@ -1,13 +1,14 @@
import { Reverse } from '../Reverse.js'
import each from 'jest-each'
describe('reverse elements in an array', () => {
each`
array | expected
${[]} | ${[]}
${[1]} | ${[1]}
${[1, 2, 3, 4]} | ${[4, 3, 2, 1]}
`.test('returns $expected when given $array', ({ array, expected }) => {
expect(Reverse(array)).toEqual(expected)
})
it.each([
[[], []],
[[1], [1]],
[
[1, 2, 3, 4],
[4, 3, 2, 1]
]
])('returns %j when given %j', (array, expected) => {
expect(Reverse(array)).toEqual(expected)
})
})

View File

@ -1,24 +1,24 @@
class Graph {
constructor () {
constructor() {
this.adjacencyMap = {}
}
addVertex (vertex) {
addVertex(vertex) {
this.adjacencyMap[vertex] = []
}
containsVertex (vertex) {
return typeof (this.adjacencyMap[vertex]) !== 'undefined'
containsVertex(vertex) {
return typeof this.adjacencyMap[vertex] !== 'undefined'
}
addEdge (vertex1, vertex2) {
addEdge(vertex1, vertex2) {
if (this.containsVertex(vertex1) && this.containsVertex(vertex2)) {
this.adjacencyMap[vertex1].push(vertex2)
this.adjacencyMap[vertex2].push(vertex1)
}
}
printGraph (output = value => console.log(value)) {
printGraph(output = (value) => console.log(value)) {
const keys = Object.keys(this.adjacencyMap)
for (const i of keys) {
const values = this.adjacencyMap[i]
@ -34,13 +34,14 @@ class Graph {
* Prints the Breadth first traversal of the graph from source.
* @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 visited = new Set()
while (queue.length) {
const [node, level] = queue.shift() // remove the front of the queue
if (visited.has(node)) { // visited
if (visited.has(node)) {
// visited
continue
}
@ -56,8 +57,9 @@ class Graph {
* Prints the Depth first traversal of the graph from source.
* @param {number} source The source vertex to start DFS.
*/
dfs (source, visited = new Set(), output = value => console.log(value)) {
if (visited.has(source)) { // visited
dfs(source, visited = new Set(), output = (value) => console.log(value)) {
if (visited.has(source)) {
// visited
return
}

View File

@ -2,7 +2,7 @@
class Graph {
// defining vertex array and
// adjacent list
constructor (noOfVertices) {
constructor(noOfVertices) {
this.noOfVertices = noOfVertices
this.AdjList = new Map()
}
@ -17,7 +17,7 @@ class Graph {
// dfs(v)
// add vertex to the graph
addVertex (v) {
addVertex(v) {
// initialize the adjacent list with a
// null array
@ -25,7 +25,7 @@ class Graph {
}
// add edge to the graph
addEdge (v, w) {
addEdge(v, w) {
// get the list for vertex v and put the
// vertex w denoting edge between v and w
this.AdjList.get(v).push(w)
@ -36,7 +36,7 @@ class Graph {
}
// Prints the vertex and adjacency list
printGraph (output = value => console.log(value)) {
printGraph(output = (value) => console.log(value)) {
// get all the vertices
const getKeys = this.AdjList.keys()

View File

@ -1,18 +1,18 @@
class Graph {
constructor () {
constructor() {
this.adjacencyObject = {}
}
addVertex (vertex) {
addVertex(vertex) {
if (!this.adjacencyObject[vertex]) this.adjacencyObject[vertex] = []
}
addEdge (vertex1, vertex2) {
addEdge(vertex1, vertex2) {
this.adjacencyObject[vertex1].push(vertex2)
this.adjacencyObject[vertex2].push(vertex1)
}
removeEdge (vertex1, vertex2) {
removeEdge(vertex1, vertex2) {
this.adjacencyObject[vertex1] = this.adjacencyObject[vertex1].filter(
(v) => v !== vertex2
)
@ -21,7 +21,7 @@ class Graph {
)
}
removeVertex (vertex) {
removeVertex(vertex) {
while (this.adjacencyObject[vertex].length) {
const adjacentVertex = this.adjacencyObject[vertex].pop()
this.removeEdge(vertex, adjacentVertex)
@ -31,14 +31,14 @@ class Graph {
/**
* Return DFS (Depth First Search) List Using Recursive Method
*/
DFS (start) {
DFS(start) {
if (!start) return null
const result = []
const visited = {}
const adjacencyObject = this.adjacencyObject
function dfs (vertex) {
function dfs(vertex) {
if (!vertex) return null
visited[vertex] = true
result.push(vertex)
@ -56,7 +56,7 @@ class Graph {
/**
* Return DFS(Depth First Search) List Using Iteration
*/
DFSIterative (start) {
DFSIterative(start) {
if (!start) return null
const stack = [start]
@ -80,7 +80,7 @@ class Graph {
return result
}
BFS (start) {
BFS(start) {
if (!start) return null
const queue = [start]

View File

@ -18,7 +18,7 @@ describe('Test Graph2', () => {
graph.addEdge('C', 'F')
it('Check adjacency lists', () => {
const mockFn = jest.fn()
const mockFn = vi.fn()
graph.printGraph(mockFn)
// Expect one call per vertex

View File

@ -19,12 +19,12 @@
*/
// Priority Queue Helper functions
const getParentPosition = position => Math.floor((position - 1) / 2)
const getChildrenPositions = position => [2 * position + 1, 2 * position + 2]
const getParentPosition = (position) => Math.floor((position - 1) / 2)
const getChildrenPositions = (position) => [2 * position + 1, 2 * position + 2]
class KeyPriorityQueue {
// Priority Queue class using Minimum Binary Heap
constructor () {
constructor() {
this._heap = []
this.priorities = new Map()
}
@ -33,7 +33,7 @@ class KeyPriorityQueue {
* Checks if the heap is empty
* @returns boolean
*/
isEmpty () {
isEmpty() {
return this._heap.length === 0
}
@ -42,7 +42,7 @@ class KeyPriorityQueue {
* @param {*} key
* @param {number} priority
*/
push (key, priority) {
push(key, priority) {
this._heap.push(key)
this.priorities.set(key, priority)
this._shiftUp(this._heap.length - 1)
@ -52,7 +52,7 @@ class KeyPriorityQueue {
* Removes the element with least priority
* @returns the key of the element with least priority
*/
pop () {
pop() {
this._swap(0, this._heap.length - 1)
const key = this._heap.pop()
this.priorities.delete(key)
@ -65,7 +65,7 @@ class KeyPriorityQueue {
* @param {*} key
* @returns boolean
*/
contains (key) {
contains(key) {
return this.priorities.has(key)
}
@ -75,7 +75,7 @@ class KeyPriorityQueue {
* @param {*} key the element to change
* @param {number} priority new priority of the element
*/
update (key, priority) {
update(key, priority) {
const currPos = this._heap.indexOf(key)
// if the key does not exist yet, add it
if (currPos === -1) return this.push(key, priority)
@ -95,13 +95,14 @@ class KeyPriorityQueue {
}
}
_getPriorityOrInfinite (position) {
_getPriorityOrInfinite(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
}
_shiftUp (position) {
_shiftUp(position) {
// Helper function to shift up a node to proper position (equivalent to bubbleUp)
let currPos = position
let parentPos = getParentPosition(currPos)
@ -117,7 +118,7 @@ class KeyPriorityQueue {
}
}
_shiftDown (position) {
_shiftDown(position) {
// Helper function to shift down a node to proper position (equivalent to bubbleDown)
let currPos = position
let [child1Pos, child2Pos] = getChildrenPositions(currPos)
@ -137,16 +138,19 @@ class KeyPriorityQueue {
this._swap(child2Pos, currPos)
currPos = child2Pos
}
[child1Pos, child2Pos] = getChildrenPositions(currPos)
;[child1Pos, child2Pos] = getChildrenPositions(currPos)
child1Priority = this._getPriorityOrInfinite(child1Pos)
child2Priority = this._getPriorityOrInfinite(child2Pos)
currPriority = this._getPriorityOrInfinite(currPos)
}
}
_swap (position1, position2) {
_swap(position1, position2) {
// 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

@ -4,25 +4,25 @@
*/
class BinaryHeap {
constructor () {
constructor() {
this.heap = []
}
insert (value) {
insert(value) {
this.heap.push(value)
this.heapify()
}
size () {
size() {
return this.heap.length
}
empty () {
empty() {
return this.size() === 0
}
// using iterative approach to reorder the heap after insertion
heapify () {
heapify() {
let index = this.size() - 1
while (index > 0) {
@ -38,7 +38,7 @@ class BinaryHeap {
}
// Extracting the maximum element from the Heap
extractMax () {
extractMax() {
const max = this.heap[0]
const tmp = this.heap.pop()
if (!this.empty()) {
@ -49,7 +49,7 @@ class BinaryHeap {
}
// To restore the balance of the heap after extraction.
sinkDown (index) {
sinkDown(index) {
const left = 2 * index + 1
const right = 2 * index + 2
let largest = index

View File

@ -19,15 +19,15 @@
*/
class MinHeap {
constructor (array) {
constructor(array) {
this.heap = this.initializeHeap(array)
}
/**
* startingParent represents the parent of the last index (=== array.length-1)
* and iterates towards 0 with all index values below sorted to meet heap conditions
*/
initializeHeap (array) {
*/
initializeHeap(array) {
const startingParent = Math.floor((array.length - 2) / 2)
for (let currIdx = startingParent; currIdx >= 0; currIdx--) {
@ -52,15 +52,16 @@ class MinHeap {
* update currIdx and recalculate the new childOneIdx to check heap conditions again.
*
* if there is no swap, it means the children indices and the parent index satisfy heap conditions and can exit the function.
*/
sinkDown (currIdx, endIdx, heap) {
*/
sinkDown(currIdx, endIdx, heap) {
let childOneIdx = currIdx * 2 + 1
while (childOneIdx <= endIdx) {
const childTwoIdx = childOneIdx + 1 <= endIdx ? childOneIdx + 1 : -1
const swapIdx = childTwoIdx !== -1 && heap[childTwoIdx] < heap[childOneIdx]
? childTwoIdx
: childOneIdx
const swapIdx =
childTwoIdx !== -1 && heap[childTwoIdx] < heap[childOneIdx]
? childTwoIdx
: childOneIdx
if (heap[swapIdx] < heap[currIdx]) {
this.swap(currIdx, swapIdx, heap)
@ -79,8 +80,8 @@ class MinHeap {
* update currIdx and recalculate the new parentIdx to check heap condition again.
*
* iteration does not end while a valid currIdx has a value smaller than its parentIdx's value
*/
bubbleUp (currIdx) {
*/
bubbleUp(currIdx) {
let parentIdx = Math.floor((currIdx - 1) / 2)
while (currIdx > 0 && this.heap[currIdx] < this.heap[parentIdx]) {
@ -90,7 +91,7 @@ class MinHeap {
}
}
peek () {
peek() {
return this.heap[0]
}
@ -101,8 +102,8 @@ class MinHeap {
* the resulting min heap value now resides at heap[heap.length-1] which is popped and later returned.
*
* the remaining values in the heap are re-sorted
*/
extractMin () {
*/
extractMin() {
this.swap(0, this.heap.length - 1, this.heap)
const min = this.heap.pop()
this.sinkDown(0, this.heap.length - 1, this.heap)
@ -110,13 +111,13 @@ class MinHeap {
}
// a new value is pushed to the end of the heap and sorted up
insert (value) {
insert(value) {
this.heap.push(value)
this.bubbleUp(this.heap.length - 1)
}
// index-swapping helper method
swap (idx1, idx2, heap) {
swap(idx1, idx2, heap) {
const temp = heap[idx1]
heap[idx1] = heap[idx2]
heap[idx2] = temp

View File

@ -1,18 +1,18 @@
/* Minimum Priority Queue
* It is a part of heap data structure
* A heap is a specific tree based data structure
* in which all the nodes of tree are in a specific order.
* that is the children are arranged in some
* respect of their parents, can either be greater
* or less than the parent. This makes it a min priority queue
* or max priority queue.
*/
* It is a part of heap data structure
* A heap is a specific tree based data structure
* in which all the nodes of tree are in a specific order.
* that is the children are arranged in some
* respect of their parents, can either be greater
* or less than the parent. This makes it a min priority queue
* or max priority queue.
*/
// Functions: insert, delete, peek, isEmpty, print, heapSort, sink
class MinPriorityQueue {
// calls the constructor and initializes the capacity
constructor (c) {
constructor(c) {
this.heap = []
this.capacity = c
this.size = 0
@ -20,7 +20,7 @@ class MinPriorityQueue {
// inserts the key at the end and rearranges it
// so that the binary heap is in appropriate order
insert (key) {
insert(key) {
if (this.isFull()) return
this.heap[this.size + 1] = key
let k = this.size + 1
@ -36,33 +36,36 @@ class MinPriorityQueue {
}
// returns the highest priority value
peek () {
peek() {
return this.heap[1]
}
// returns boolean value whether the heap is empty or not
isEmpty () {
isEmpty() {
return this.size === 0
}
// returns boolean value whether the heap is full or not
isFull () {
isFull() {
return this.size === this.capacity
}
// prints the heap
print (output = value => console.log(value)) {
print(output = (value) => console.log(value)) {
output(this.heap.slice(1))
}
// heap reverse can be done by performing swapping the first
// element with the last, removing the last element to
// new array and calling sink function.
heapReverse () {
heapReverse() {
const heapSort = []
while (this.size > 0) {
// 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())
this.size--
this.sink()
@ -74,7 +77,7 @@ class MinPriorityQueue {
}
// this function reorders the heap after every delete function
sink () {
sink() {
let k = 1
while (2 * k <= this.size || 2 * k + 1 <= this.size) {
let minIndex
@ -92,8 +95,7 @@ class MinPriorityQueue {
this.heap[k] > this.heap[2 * k] ||
this.heap[k] > this.heap[2 * k + 1]
) {
minIndex =
this.heap[2 * k] < this.heap[2 * k + 1] ? 2 * k : 2 * k + 1
minIndex = this.heap[2 * k] < this.heap[2 * k + 1] ? 2 * k : 2 * k + 1
} else {
minIndex = k
}
@ -107,7 +109,7 @@ class MinPriorityQueue {
// deletes the highest priority value from the heap. The last
// element goes to ahead to first position and reorder heap
delete () {
delete() {
// checks empty and one element array conditions
if (this.isEmpty()) return
if (this.size === 1) {

View File

@ -9,7 +9,9 @@ describe('MinHeap', () => {
})
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', () => {
@ -22,12 +24,14 @@ describe('MinHeap', () => {
const minValue = heap.extractMin()
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', () => {
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(() => {
queue = new MinPriorityQueue(capacity)
values.forEach(v => queue.insert(v))
values.forEach((v) => queue.insert(v))
})
it('Check heap ordering', () => {
const mockFn = jest.fn()
const mockFn = vi.fn()
queue.print(mockFn)
expect(mockFn.mock.calls.length).toBe(1) // Expect one call
@ -24,7 +24,7 @@ describe('MinPriorityQueue', () => {
it('heapSort() expected to reverse the heap ordering', () => {
queue.heapReverse()
const mockFn = jest.fn()
const mockFn = vi.fn()
queue.print(mockFn)
expect(mockFn.mock.calls.length).toBe(1)

View File

@ -14,11 +14,11 @@ Link for the Problem: https://leetcode.com/problems/add-two-numbers/
*/
class AddTwoNumbers {
constructor () {
constructor() {
this.dummyNode = new Node(0)
}
solution (firstList, secondList) {
solution(firstList, secondList) {
let firstRunner = firstList
let secondRunner = secondList
let tail = this.dummyNode
@ -44,7 +44,7 @@ class AddTwoNumbers {
return this.dummyNode.next
}
solutionToArray () {
solutionToArray() {
const list = []
let currentNode = this.dummyNode.next
while (currentNode) {

View File

@ -3,18 +3,22 @@
* https://en.wikipedia.org/wiki/Cycle_detection
*/
function detectCycle (head) {
function detectCycle(head) {
/*
Problem Statement:
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/
*/
if (!head) { return false }
if (!head) {
return false
}
let slow = head
let fast = head.next
while (fast && fast.next) {
if (fast === slow) { return true }
if (fast === slow) {
return true
}
fast = fast.next.next
slow = slow.next
}

View File

@ -1,5 +1,5 @@
class Node {
constructor (element) {
constructor(element) {
this.element = element
this.next = null
this.prev = null
@ -7,14 +7,14 @@ class Node {
}
class DoubleLinkedList {
constructor () {
constructor() {
this.length = 0
this.head = null
this.tail = null
}
// Add new element
append (element) {
append(element) {
const node = new Node(element)
if (!this.head) {
@ -30,7 +30,7 @@ class DoubleLinkedList {
}
// Add element
insert (position, element) {
insert(position, element) {
// Check of out-of-bound values
if (position >= 0 && position <= this.length) {
const node = new Node(element)
@ -74,7 +74,7 @@ class DoubleLinkedList {
}
// Remove element at any position
removeAt (position) {
removeAt(position) {
// look for out-of-bounds value
if (position > -1 && position < this.length) {
let current = this.head
@ -114,7 +114,7 @@ class DoubleLinkedList {
}
// Get the indexOf item
indexOf (elm) {
indexOf(elm) {
let current = this.head
let index = -1
@ -133,27 +133,27 @@ class DoubleLinkedList {
}
// Find the item in the list
isPresent (elm) {
isPresent(elm) {
return this.indexOf(elm) !== -1
}
// Delete an item from the list
delete (elm) {
delete(elm) {
return this.removeAt(this.indexOf(elm))
}
// Delete first item from the list
deleteHead () {
deleteHead() {
this.removeAt(0)
}
// Delete last item from the list
deleteTail () {
deleteTail() {
this.removeAt(this.length - 1)
}
// Print item of the string
toString () {
toString() {
let current = this.head
let string = ''
@ -166,7 +166,7 @@ class DoubleLinkedList {
}
// Convert list to array
toArray () {
toArray() {
const arr = []
let current = this.head
@ -179,31 +179,31 @@ class DoubleLinkedList {
}
// Check if list is empty
isEmpty () {
isEmpty() {
return this.length === 0
}
// Get the size of the list
size () {
size() {
return this.length
}
// Get the this.head
getHead () {
getHead() {
return this.head
}
// Get the this.tail
getTail () {
getTail() {
return this.tail
}
// Method to iterate over the LinkedList
iterator () {
iterator() {
let currentNode = this.getHead()
if (currentNode === null) return -1
const iterate = function * () {
const iterate = function* () {
while (currentNode) {
yield currentNode.element
currentNode = currentNode.next
@ -214,7 +214,7 @@ class DoubleLinkedList {
// Method to log the LinkedList, for debugging
// it' a circular structure, so can't use stringify to debug the whole structure
log () {
log() {
let currentNode = this.getHead()
while (currentNode) {
console.log(currentNode.element)

View File

@ -1,7 +1,7 @@
/** A LinkedList based solution to reverse a number
Problem Statement: Given a number such that each of its digit is stored in a singly linked list. Reverse the linked list and return the head of the linked list Link for the Problem: https://leetcode.com/problems/reverse-linked-list/ */
class ReverseSinglyLinkedList {
solution (head) {
solution(head) {
let prev = null
let next = null
while (head) {
@ -11,6 +11,6 @@ class ReverseSinglyLinkedList {
head = next
}
return prev
};
}
}
export { ReverseSinglyLinkedList }

View File

@ -2,7 +2,7 @@
import { Node } from './SinglyLinkedList.js'
class SinglyCircularLinkedList {
constructor () {
constructor() {
this.headNode = null
this.length = 0
}
@ -15,12 +15,12 @@ class SinglyCircularLinkedList {
isEmpty = () => this.length === 0
// initiate the node and index
initiateNodeAndIndex () {
initiateNodeAndIndex() {
return { currentNode: this.headNode, currentIndex: 0 }
}
// get the data specific to an index
getElementAt (index) {
getElementAt(index) {
if (this.length !== 0 && index >= 0 && index <= this.length) {
let { currentNode } = this.initiateNodeAndIndex()
for (let i = 0; i < index && currentNode !== null; i++) {
@ -32,7 +32,7 @@ class SinglyCircularLinkedList {
}
// Add the element in the first position
addAtFirst (data) {
addAtFirst(data) {
const node = new Node(data)
node.next = this.headNode
this.headNode = node
@ -41,8 +41,10 @@ class SinglyCircularLinkedList {
}
// Add any data to the end of the linkedList
add (data) {
if (!this.headNode) { return this.addAtFirst(data) }
add(data) {
if (!this.headNode) {
return this.addAtFirst(data)
}
const node = new Node(data)
// Getting the last node
const currentNode = this.getElementAt(this.length - 1)
@ -53,10 +55,11 @@ class SinglyCircularLinkedList {
}
// insert data at a specific position
insertAt (index, data) {
insertAt(index, data) {
if (index === 0) return this.addAtFirst(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 previousNode = this.getElementAt(index - 1)
node.next = previousNode.next
@ -66,7 +69,7 @@ class SinglyCircularLinkedList {
}
// find the first index of the data
indexOf (data) {
indexOf(data) {
let { currentNode } = this.initiateNodeAndIndex()
// initializing currentIndex as -1
let currentIndex = -1
@ -81,7 +84,7 @@ class SinglyCircularLinkedList {
}
// remove the data from the end of the list
remove () {
remove() {
if (this.isEmpty()) return null
const secondLastNode = this.getElementAt(this.length - 2)
const removedNode = secondLastNode.next
@ -91,7 +94,7 @@ class SinglyCircularLinkedList {
}
// remove the data from the first of the list
removeFirst () {
removeFirst() {
if (this.isEmpty()) return null
const removedNode = this.headNode
if (this.length === 1) {
@ -106,7 +109,7 @@ class SinglyCircularLinkedList {
}
// remove the data from the index
removeAt (index) {
removeAt(index) {
if (this.isEmpty()) return null
if (index === 0) return this.removeFirst()
if (index === this.length) return this.remove()
@ -119,14 +122,14 @@ class SinglyCircularLinkedList {
}
// remove if the data is present
removeData (data) {
removeData(data) {
if (this.isEmpty()) return null
const index = this.indexOf(data)
return this.removeAt(index)
}
// logs the data
printData (output = value => console.log(value)) {
printData(output = (value) => console.log(value)) {
let { currentIndex, currentNode } = this.initiateNodeAndIndex()
while (currentNode !== null && currentIndex < this.length) {
@ -137,7 +140,7 @@ class SinglyCircularLinkedList {
}
// get the data from the linkedList
get () {
get() {
let { currentIndex, currentNode } = this.initiateNodeAndIndex()
const list = []
while (currentNode !== null && currentIndex < this.length) {
@ -148,7 +151,7 @@ class SinglyCircularLinkedList {
return list
}
clear () {
clear() {
this.headNode = null
this.length = 0
}

View File

@ -9,14 +9,14 @@
// Methods - size, head, addLast, addFirst, addAt, removeFirst, removeLast, remove, removeAt, indexOf, isEmpty, elementAt, findMiddle, get, clean, rotateListRight
class Node {
constructor (data) {
constructor(data) {
this.data = data
this.next = null
}
}
class LinkedList {
constructor (listOfValues) {
constructor(listOfValues) {
this.headNode = null
this.tailNode = null
this.length = 0
@ -29,32 +29,32 @@ class LinkedList {
}
// initiates the currentNode and currentIndex and return as an object
initiateNodeAndIndex () {
initiateNodeAndIndex() {
return { currentNode: this.headNode, currentIndex: 0 }
}
// Returns length
size () {
size() {
return this.length
}
// Returns the head
head () {
head() {
return this.headNode?.data ?? null
}
// Returns the tail
tail () {
tail() {
return this.tailNode?.data ?? null
}
// Return if the list is empty
isEmpty () {
isEmpty() {
return this.length === 0
}
// add a node at last it to linklist
addLast (element) {
addLast(element) {
// Check if its the first element
if (this.headNode === null) {
return this.addFirst(element)
@ -68,7 +68,7 @@ class LinkedList {
}
// add a node at first it to linklist
addFirst (element) {
addFirst(element) {
const node = new Node(element)
// Check if its the first element
if (this.headNode === null) {
@ -82,7 +82,7 @@ class LinkedList {
}
// remove the first from the linklist
removeFirst () {
removeFirst() {
// Check if head is null
if (this.headNode === null) {
return null
@ -99,7 +99,7 @@ class LinkedList {
}
// remove the last from the linklist
removeLast () {
removeLast() {
if (this.isEmpty()) return null
// Check if there is only one element
if (this.length === 1) {
@ -118,7 +118,7 @@ class LinkedList {
}
// Removes the node with the value as param
remove (element) {
remove(element) {
if (this.isEmpty()) return null
let { currentNode } = this.initiateNodeAndIndex()
let removedNode = null
@ -144,7 +144,7 @@ class LinkedList {
}
// Returns the index of the element passed as param otherwise -1
indexOf (element) {
indexOf(element) {
if (this.isEmpty()) return -1
let { currentNode, currentIndex } = this.initiateNodeAndIndex()
while (currentNode) {
@ -158,7 +158,7 @@ class LinkedList {
}
// Returns the element at an index
elementAt (index) {
elementAt(index) {
if (index >= this.length || index < 0) {
throw new RangeError('Out of Range index')
}
@ -171,7 +171,7 @@ class LinkedList {
}
// Adds the element at specified index
addAt (index, element) {
addAt(index, element) {
// Check if index is out of bounds of list
if (index > this.length || index < 0) {
throw new RangeError('Out of Range index')
@ -196,7 +196,7 @@ class LinkedList {
}
// Removes the node at specified index
removeAt (index) {
removeAt(index) {
// Check if index is present in list
if (index < 0 || index >= this.length) {
throw new RangeError('Out of Range index')
@ -216,7 +216,7 @@ class LinkedList {
}
// Returns a reference to middle node of linked list
findMiddle () {
findMiddle() {
// If there are two middle nodes, return the second middle node.
let fast = this.headNode
let slow = this.headNode
@ -229,14 +229,14 @@ class LinkedList {
}
// make the linkedList Empty
clean () {
clean() {
this.headNode = null
this.tailNode = null
this.length = 0
}
// Method to get the LinkedList
get () {
get() {
const list = []
let { currentNode } = this.initiateNodeAndIndex()
while (currentNode) {
@ -247,7 +247,7 @@ class LinkedList {
}
// Method for Rotating a List to the right by k places
rotateListRight (k) {
rotateListRight(k) {
if (!this.headNode) return
let current = this.headNode
let tail = this.tailNode
@ -268,11 +268,11 @@ class LinkedList {
}
// Method to iterate over the LinkedList
iterator () {
iterator() {
let { currentNode } = this.initiateNodeAndIndex()
if (currentNode === null) return -1
const iterate = function * () {
const iterate = function* () {
while (currentNode) {
yield currentNode.data
currentNode = currentNode.next
@ -282,12 +282,12 @@ class LinkedList {
}
// Method to log the LinkedList
log () {
log() {
console.log(JSON.stringify(this.headNode, null, 2))
}
// Method to reverse the LinkedList
reverse () {
reverse() {
let head = this.headNode
let prev = null
let next = null
@ -299,7 +299,7 @@ class LinkedList {
}
this.tailNode = this.headNode
this.headNode = prev
};
}
}
export { Node, LinkedList }

View File

@ -1,147 +1,147 @@
import { SinglyCircularLinkedList } from '../SinglyCircularLinkedList'
describe('SinglyCircularLinkedList', () => {
let list
beforeEach(() => {
list = new SinglyCircularLinkedList()
})
it('Check get', () => {
expect(list.get()).toEqual([])
expect(list.add(1)).toEqual(1)
expect(list.get()).toEqual([1])
expect(list.add(5)).toEqual(2)
expect(list.get()).toEqual([1, 5])
})
it('Check size', () => {
expect(list.size()).toEqual(0)
expect(list.add(1)).toEqual(1)
expect(list.add(1)).toEqual(2)
expect(list.size()).toEqual(2)
})
it('Check head', () => {
expect(list.head()).toEqual(null)
expect(list.add(1)).toEqual(1)
expect(list.head()).toEqual(1)
expect(list.add(1)).toEqual(2)
expect(list.head()).toEqual(1)
expect(list.addAtFirst(100)).toEqual(3)
expect(list.head()).toEqual(100)
expect(list.insertAt(0, 500)).toEqual(4)
expect(list.head()).toEqual(500)
list.clear()
expect(list.head()).toEqual(null)
})
it('Check isEmpty', () => {
expect(list.isEmpty()).toEqual(true)
expect(list.add(1)).toEqual(1)
expect(list.add(1)).toEqual(2)
expect(list.isEmpty()).toEqual(false)
})
it('Check getElementAt', () => {
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.getElementAt(1).data).toEqual(200)
expect(list.getElementAt(3).data).toEqual(500)
})
it('Check addAtFirst', () => {
list.add(1)
list.add(5)
list.add(7)
list.add(9)
list.add(0)
expect(list.get()).toEqual([1, 5, 7, 9, 0])
list.addAtFirst(100)
expect(list.get()).toEqual([100, 1, 5, 7, 9, 0])
})
it('Check add', () => {
list.add(1)
list.add(5)
list.add(7)
list.add(9)
list.add(0)
expect(list.get()).toEqual([1, 5, 7, 9, 0])
list.add(100)
expect(list.get()).toEqual([1, 5, 7, 9, 0, 100])
})
it('Check insertAt', () => {
expect(list.insertAt(0, 100)).toEqual(1)
expect(list.get()).toEqual([100])
expect(list.insertAt(0, 200)).toEqual(2)
expect(list.get()).toEqual([200, 100])
expect(list.insertAt(2, 300)).toEqual(3)
expect(list.get()).toEqual([200, 100, 300])
})
it('Checks indexOf', () => {
expect(list.indexOf(200)).toEqual(-1)
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.indexOf(200)).toEqual(1)
})
it('Check remove', () => {
expect(list.remove()).toEqual(null)
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.get()).toEqual([100, 200, 300, 500, 900])
const removedData = list.remove()
expect(removedData).toEqual(900)
expect(list.get()).toEqual([100, 200, 300, 500])
})
it('Check removeFirst', () => {
expect(list.removeFirst()).toEqual(null)
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.get()).toEqual([100, 200, 300, 500, 900])
const removedData = list.removeFirst()
expect(removedData).toEqual(100)
expect(list.get()).toEqual([200, 300, 500, 900])
})
it('Check removeAt', () => {
expect(list.removeAt(1)).toEqual(null)
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.get()).toEqual([100, 200, 300, 500, 900])
const removedData = list.removeAt(2)
expect(removedData).toEqual(300)
expect(list.get()).toEqual([100, 200, 500, 900])
})
it('Check removeData', () => {
expect(list.removeData(100)).toEqual(null)
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.get()).toEqual([100, 200, 300, 500, 900])
const removedData = list.removeData(200)
expect(removedData).toEqual(200)
expect(list.get()).toEqual([100, 300, 500, 900])
})
})
import { SinglyCircularLinkedList } from '../SinglyCircularLinkedList'
describe('SinglyCircularLinkedList', () => {
let list
beforeEach(() => {
list = new SinglyCircularLinkedList()
})
it('Check get', () => {
expect(list.get()).toEqual([])
expect(list.add(1)).toEqual(1)
expect(list.get()).toEqual([1])
expect(list.add(5)).toEqual(2)
expect(list.get()).toEqual([1, 5])
})
it('Check size', () => {
expect(list.size()).toEqual(0)
expect(list.add(1)).toEqual(1)
expect(list.add(1)).toEqual(2)
expect(list.size()).toEqual(2)
})
it('Check head', () => {
expect(list.head()).toEqual(null)
expect(list.add(1)).toEqual(1)
expect(list.head()).toEqual(1)
expect(list.add(1)).toEqual(2)
expect(list.head()).toEqual(1)
expect(list.addAtFirst(100)).toEqual(3)
expect(list.head()).toEqual(100)
expect(list.insertAt(0, 500)).toEqual(4)
expect(list.head()).toEqual(500)
list.clear()
expect(list.head()).toEqual(null)
})
it('Check isEmpty', () => {
expect(list.isEmpty()).toEqual(true)
expect(list.add(1)).toEqual(1)
expect(list.add(1)).toEqual(2)
expect(list.isEmpty()).toEqual(false)
})
it('Check getElementAt', () => {
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.getElementAt(1).data).toEqual(200)
expect(list.getElementAt(3).data).toEqual(500)
})
it('Check addAtFirst', () => {
list.add(1)
list.add(5)
list.add(7)
list.add(9)
list.add(0)
expect(list.get()).toEqual([1, 5, 7, 9, 0])
list.addAtFirst(100)
expect(list.get()).toEqual([100, 1, 5, 7, 9, 0])
})
it('Check add', () => {
list.add(1)
list.add(5)
list.add(7)
list.add(9)
list.add(0)
expect(list.get()).toEqual([1, 5, 7, 9, 0])
list.add(100)
expect(list.get()).toEqual([1, 5, 7, 9, 0, 100])
})
it('Check insertAt', () => {
expect(list.insertAt(0, 100)).toEqual(1)
expect(list.get()).toEqual([100])
expect(list.insertAt(0, 200)).toEqual(2)
expect(list.get()).toEqual([200, 100])
expect(list.insertAt(2, 300)).toEqual(3)
expect(list.get()).toEqual([200, 100, 300])
})
it('Checks indexOf', () => {
expect(list.indexOf(200)).toEqual(-1)
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.indexOf(200)).toEqual(1)
})
it('Check remove', () => {
expect(list.remove()).toEqual(null)
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.get()).toEqual([100, 200, 300, 500, 900])
const removedData = list.remove()
expect(removedData).toEqual(900)
expect(list.get()).toEqual([100, 200, 300, 500])
})
it('Check removeFirst', () => {
expect(list.removeFirst()).toEqual(null)
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.get()).toEqual([100, 200, 300, 500, 900])
const removedData = list.removeFirst()
expect(removedData).toEqual(100)
expect(list.get()).toEqual([200, 300, 500, 900])
})
it('Check removeAt', () => {
expect(list.removeAt(1)).toEqual(null)
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.get()).toEqual([100, 200, 300, 500, 900])
const removedData = list.removeAt(2)
expect(removedData).toEqual(300)
expect(list.get()).toEqual([100, 200, 500, 900])
})
it('Check removeData', () => {
expect(list.removeData(100)).toEqual(null)
list.add(100)
list.add(200)
list.add(300)
list.add(500)
list.add(900)
expect(list.get()).toEqual([100, 200, 300, 500, 900])
const removedData = list.removeData(200)
expect(removedData).toEqual(200)
expect(list.get()).toEqual([100, 300, 500, 900])
})
})

View File

@ -4,7 +4,7 @@
// Doesnt use dynamic memory so No memory leaks
class CircularQueue {
constructor (maxLength) {
constructor(maxLength) {
this.queue = []
this.front = 0
this.rear = 0
@ -12,7 +12,7 @@ class CircularQueue {
}
// ADD ELEMENTS TO QUEUE
enqueue (value) {
enqueue(value) {
if (this.checkOverflow()) return
if (this.checkEmpty()) {
this.front += 1
@ -26,7 +26,7 @@ class CircularQueue {
}
// REMOVES ELEMENTS
dequeue () {
dequeue() {
if (this.checkEmpty()) {
// UNDERFLOW
return
@ -44,13 +44,13 @@ class CircularQueue {
}
// checks if the queue is empty or not
checkEmpty () {
checkEmpty() {
if (this.front === 0 && this.rear === 0) {
return true
}
}
checkSingleelement () {
checkSingleelement() {
if (this.front === this.rear && this.rear !== 0) {
this.front = this.rear = 0
return true
@ -58,27 +58,30 @@ class CircularQueue {
}
// Checks if max capacity of queue has been reached or not
checkOverflow () {
if ((this.front === 1 && this.rear === this.maxLength) || (this.front === this.rear + 1)) {
checkOverflow() {
if (
(this.front === 1 && this.rear === this.maxLength) ||
this.front === this.rear + 1
) {
// CIRCULAR QUEUE OVERFLOW
return true
}
}
// 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++) {
output(this.queue[index])
}
}
// Displays the length of queue
length () {
length() {
return this.queue.length - 1
}
// Display the top most value of queue
peek () {
peek() {
return this.queue[this.front]
}
}

View File

@ -1,15 +1,15 @@
/* Queue
* A Queue is a data structure that allows you to add an element to the end of
* a list and remove the item at the front. A queue follows a FIFO (First In First Out)
* system, where the first item to enter the queue is the first to be removed,
* All these operation complexities are O(1).
* This implementation following the linked list structure.
*/
* A Queue is a data structure that allows you to add an element to the end of
* a list and remove the item at the front. A queue follows a FIFO (First In First Out)
* system, where the first item to enter the queue is the first to be removed,
* All these operation complexities are O(1).
* This implementation following the linked list structure.
*/
class Queue {
#size
constructor () {
constructor() {
this.head = null
this.tail = null
this.#size = 0
@ -17,7 +17,7 @@ class Queue {
return Object.seal(this)
}
get length () {
get length() {
return this.#size
}
@ -26,7 +26,7 @@ class Queue {
* @param {*} data
* @returns {number} - The current size of queue
*/
enqueue (data) {
enqueue(data) {
const node = { data, next: null }
if (!this.head && !this.tail) {
@ -44,7 +44,7 @@ class Queue {
* @description - Removes the value at the front of the queue
* @returns {*} - The first data of the queue
*/
dequeue () {
dequeue() {
if (this.isEmpty()) {
throw new Error('Queue is Empty')
}
@ -66,7 +66,7 @@ class Queue {
* @description - Return the item at the front of the queue
* @returns {*}
*/
peekFirst () {
peekFirst() {
if (this.isEmpty()) {
throw new Error('Queue is Empty')
}
@ -78,7 +78,7 @@ class Queue {
* @description - Return the item at the tail of the queue
* @returns {*}
*/
peekLast () {
peekLast() {
if (this.isEmpty()) {
throw new Error('Queue is Empty')
}
@ -90,7 +90,7 @@ class Queue {
* @description - Return the array of Queue
* @returns {Array<*>}
*/
toArray () {
toArray() {
const array = []
let node = this.head
@ -103,10 +103,10 @@ class Queue {
}
/**
* @description - Return is queue empty or not
* @returns {boolean}
*/
isEmpty () {
* @description - Return is queue empty or not
* @returns {boolean}
*/
isEmpty() {
return this.length === 0
}
}

View File

@ -2,17 +2,17 @@
// contribution made by hamza chabchoub for a university project
class Queue {
constructor () {
constructor() {
this.inputStack = []
this.outputStack = []
}
// Push item into the inputstack
enqueue (item) {
enqueue(item) {
this.inputStack.push(item)
}
dequeue () {
dequeue() {
// push all items to outputstack
this.outputStack = []
while (this.inputStack.length > 0) {
@ -31,7 +31,7 @@ class Queue {
}
// display elements of the inputstack
listIn (output = value => console.log(value)) {
listIn(output = (value) => console.log(value)) {
let i = 0
while (i < this.inputStack.length) {
output(this.inputStack[i])
@ -40,7 +40,7 @@ class Queue {
}
// display element of the outputstack
listOut (output = value => console.log(value)) {
listOut(output = (value) => console.log(value)) {
let i = 0
while (i < this.outputStack.length) {
output(this.outputStack[i])

View File

@ -1,15 +1,15 @@
/* Stack!!
* A stack is exactly what it sounds like. An element gets added to the top of
* the stack and only the element on the top may be removed. This is an example
* of an array implementation of a Stack. So an element can only be added/removed
* from the end of the array.
*/
* A stack is exactly what it sounds like. An element gets added to the top of
* the stack and only the element on the top may be removed. This is an example
* of an array implementation of a Stack. So an element can only be added/removed
* from the end of the array.
*/
// Functions: push, pop, peek, view, length
// Creates a stack constructor
const Stack = (function () {
function Stack () {
function Stack() {
// The top of the Stack
this.top = 0
// The array representation of the stack
@ -45,13 +45,13 @@ const Stack = (function () {
}
// 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++) {
output(this.stack[i])
}
}
return Stack
}())
})()
export { Stack }

View File

@ -10,19 +10,19 @@
// Class declaration
class Stack {
constructor () {
constructor() {
this.stack = []
this.top = 0
}
// Adds a value to the end of the Stack
push (newValue) {
push(newValue) {
this.stack.push(newValue)
this.top += 1
}
// Returns and removes the last element of the Stack
pop () {
pop() {
if (this.top !== 0) {
this.top -= 1
return this.stack.pop()
@ -31,17 +31,17 @@ class Stack {
}
// Returns the number of elements in the Stack
get length () {
get length() {
return this.top
}
// Returns true if stack is empty, false otherwise
get isEmpty () {
get isEmpty() {
return this.top === 0
}
// Returns the last element without removing it
get last () {
get last() {
if (this.top !== 0) {
return this.stack[this.stack.length - 1]
}
@ -49,7 +49,7 @@ class Stack {
}
// Checks if an object is the instance os the Stack class
static isStack (el) {
static isStack(el) {
return el instanceof Stack
}
}

View File

@ -13,9 +13,9 @@
* RETURN > 0 if a > b
* MUST RETURN 0 if a == b
*/
let utils;
(function (_utils) {
function comparator () {
let utils
;(function (_utils) {
function comparator() {
return function (v1, v2) {
if (v1 < v2) return -1
if (v2 < v1) return 1
@ -32,7 +32,7 @@ let utils;
* If no argument is sent it uses utils.comparator
*/
const AVLTree = (function () {
function _avl (comp) {
function _avl(comp) {
/** @public comparator function */
this._comp = undefined
this._comp = comp !== undefined ? comp : utils.comparator()
@ -53,7 +53,9 @@ const AVLTree = (function () {
// get height of a node
const getHeight = function (node) {
if (node == null) { return 0 }
if (node == null) {
return 0
}
return node._height
}
@ -64,12 +66,15 @@ const AVLTree = (function () {
// update height of a node based on children's heights
const updateHeight = function (node) {
if (node == null) { return }
if (node == null) {
return
}
node._height = Math.max(getHeight(node._left), getHeight(node._right)) + 1
}
// 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
const leftRotate = function (node) {
@ -140,13 +145,18 @@ const AVLTree = (function () {
}
updateHeight(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
const deleteElement = function (root, _val, tree) {
if (root == null) { return root }
if (tree._comp(root._val, _val) === 0) { // key found case
if (root == null) {
return root
}
if (tree._comp(root._val, _val) === 0) {
// key found case
if (root._left === null && root._right === null) {
root = null
tree.size--
@ -177,7 +187,9 @@ const AVLTree = (function () {
}
// search tree for a element
const searchAVLTree = function (root, val, tree) {
if (root == null) { return null }
if (root == null) {
return null
}
if (tree._comp(root._val, val) === 0) {
return root
}
@ -222,7 +234,7 @@ const AVLTree = (function () {
return prevSize !== this.size
}
return _avl
}())
})()
/**
* A Code for Testing the AVLTree

View File

@ -1,19 +1,19 @@
/* Binary Search Tree!!
*
* Nodes that will go on the Binary Tree.
* They consist of the data in them, the node to the left, the node
* to the right, and the parent from which they came from.
*
* A binary tree is a data structure in which an element
* has two successors(children). The left child is usually
* smaller than the parent, and the right child is usually
* bigger.
*/
*
* Nodes that will go on the Binary Tree.
* They consist of the data in them, the node to the left, the node
* to the right, and the parent from which they came from.
*
* A binary tree is a data structure in which an element
* has two successors(children). The left child is usually
* smaller than the parent, and the right child is usually
* bigger.
*/
// class Node
const Node = (function Node () {
const Node = (function Node() {
// Node in the tree
function Node (val) {
function Node(val) {
this.value = val
this.left = null
this.right = null
@ -32,7 +32,7 @@ const Node = (function 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
if (this.left !== null) {
this.left.visit()
@ -103,14 +103,14 @@ const Node = (function Node () {
}
// returns the constructor
return Node
}())
})()
// class Tree
const Tree = (function () {
function Tree () {
function Tree() {
// Just store the root
this.root = null
};
}
// Inorder traversal
Tree.prototype.traverse = function () {
@ -149,6 +149,6 @@ const Tree = (function () {
// returns the constructor
return Tree
}())
})()
export { Tree }

View File

@ -13,7 +13,7 @@
class SegmentTree {
size
tree
constructor (arr) {
constructor(arr) {
// we define tree like this
// tree[1] : root node of tree
// tree[i] : i'th node
@ -28,7 +28,7 @@ class SegmentTree {
}
// function to build the tree
build (arr) {
build(arr) {
const { size, tree } = this
// insert leaf nodes in tree
// leaf nodes will start from index N
@ -45,7 +45,7 @@ class SegmentTree {
}
}
update (index, value) {
update(index, value) {
const { size, tree } = this
// only update values in the parents of the given node being changed.
@ -65,7 +65,7 @@ class SegmentTree {
}
// interval [L,R) with left index(L) included and right (R) excluded.
query (left, right) {
query(left, right) {
const { size, tree } = this
// cause R is excluded, increase right for convenient
right++

View File

@ -1,4 +1,4 @@
const TrieNode = function TrieNode (key, parent) {
const TrieNode = function TrieNode(key, parent) {
this.key = key
this.count = 0
this.children = Object.create(null)
@ -9,7 +9,7 @@ const TrieNode = function TrieNode (key, parent) {
}
}
function Trie () {
function Trie() {
// create only root with null key and parent
this.root = new TrieNode(null, null)
}
@ -18,7 +18,9 @@ function Trie () {
Trie.findAllWords = function (root, word, output) {
if (root === null) return
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
for (key in root.children) {
@ -38,7 +40,9 @@ Trie.prototype.insert = function (word) {
const len = word.length
let 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.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
// For checking an empty 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
}
}

View File

@ -12,14 +12,14 @@ describe('AVLTree Implementation: ', () => {
const emptyTree = new AVLTree(collator.compare)
beforeAll(() => {
demoData.forEach(item => {
demoData.forEach((item) => {
if (avlTree.add(item)) {
dataList.push(item)
}
})
avlStringTree._comp = collator.compare
stringData.forEach(item => avlStringTree.add(item))
stringData.forEach((item) => avlStringTree.add(item))
})
it('delete and search from empty tree', () => {
@ -33,10 +33,10 @@ describe('AVLTree Implementation: ', () => {
})
it('search if inserted element is present', () => {
demoData.forEach(data => {
demoData.forEach((data) => {
expect(avlTree.find(data)).toBeTruthy()
})
stringData.forEach(data => {
stringData.forEach((data) => {
expect(avlStringTree.find(data)).toBeTruthy()
})
})

View File

@ -6,7 +6,7 @@
*/
class Vector2 {
constructor (x, y) {
constructor(x, y) {
this.x = x
this.y = y
}
@ -17,7 +17,7 @@ class Vector2 {
* @param vector The vector to compare to.
* @returns Whether they are exactly equal or not.
*/
equalsExactly (vector) {
equalsExactly(vector) {
return this.x === vector.x && this.y === vector.y
}
@ -28,8 +28,11 @@ class Vector2 {
* @param epsilon The allowed discrepancy for the x-values and the y-values.
* @returns Whether they are approximately equal or not.
*/
equalsApproximately (vector, epsilon) {
return (Math.abs(this.x - vector.x) < epsilon && Math.abs(this.y - vector.y) < epsilon)
equalsApproximately(vector, epsilon) {
return (
Math.abs(this.x - vector.x) < epsilon &&
Math.abs(this.y - vector.y) < epsilon
)
}
/**
@ -37,7 +40,7 @@ class Vector2 {
*
* @returns The length of the vector.
*/
length () {
length() {
return Math.sqrt(this.x * this.x + this.y * this.y)
}
@ -46,7 +49,7 @@ class Vector2 {
*
* @returns The normalized vector.
*/
normalize () {
normalize() {
const length = this.length()
if (length === 0) {
throw new Error('Cannot normalize vectors of length 0')
@ -60,7 +63,7 @@ class Vector2 {
* @param vector The vector to be added.
* @returns The sum-vector.
*/
add (vector) {
add(vector) {
const x = this.x + vector.x
const y = this.y + vector.y
return new Vector2(x, y)
@ -72,7 +75,7 @@ class Vector2 {
* @param vector The vector to be subtracted.
* @returns The difference-vector.
*/
subtract (vector) {
subtract(vector) {
const x = this.x - vector.x
const y = this.y - vector.y
return new Vector2(x, y)
@ -84,7 +87,7 @@ class Vector2 {
* @param scalar The factor by which to multiply the vector.
* @returns The scaled vector.
*/
multiply (scalar) {
multiply(scalar) {
const x = this.x * scalar
const y = this.y * scalar
return new Vector2(x, y)
@ -96,7 +99,7 @@ class Vector2 {
* @param vector The vector to which to calculate the distance.
* @returns The distance.
*/
distance (vector) {
distance(vector) {
const difference = vector.subtract(this)
return difference.length()
}
@ -107,7 +110,7 @@ class Vector2 {
* @param vector The vector used for the multiplication.
* @returns The resulting dot product.
*/
dotProduct (vector) {
dotProduct(vector) {
return this.x * vector.x + this.y * vector.y
}
@ -117,7 +120,7 @@ class Vector2 {
* @param angleInRadians The angle in radians by which to rotate the vector.
* @returns The rotated vector.
*/
rotate (angleInRadians) {
rotate(angleInRadians) {
const ca = Math.cos(angleInRadians)
const sa = Math.sin(angleInRadians)
const x = ca * this.x - sa * this.y
@ -131,7 +134,7 @@ class Vector2 {
* @param vector The 2nd vector for the measurement.
* @returns The angle in radians.
*/
angleBetween (vector) {
angleBetween(vector) {
return Math.atan2(vector.y, vector.x) - Math.atan2(this.y, this.x)
}
}

View File

@ -5,52 +5,80 @@ describe('Vector2', () => {
it('should compare equality correctly', () => {
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', () => {
it('should compare equality (approximately) correctly', () => {
expect(new Vector2(1, 0).equalsApproximately(new Vector2(1, 0.0000001), 0.000001))
.toBe(true)
expect(
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))
.toBe(false)
expect(
new Vector2(1.23, 4.56).equalsApproximately(
new Vector2(1.24, 4.56),
0.000001
)
).toBe(false)
})
})
describe('#add', () => {
it('should add two vectors correctly', () => {
expect(new Vector2(1, 0).add(new Vector2(0, 1)).equalsApproximately(new Vector2(1, 1), 0.000001))
.toBe(true)
expect(
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))
.toBe(true)
expect(
new Vector2(-3.3, -9)
.add(new Vector2(-2.2, 3))
.equalsApproximately(new Vector2(-5.5, -6), 0.000001)
).toBe(true)
})
})
describe('#subtract', () => {
it('should subtract two vectors correctly', () => {
expect(new Vector2(1, 0).subtract(new Vector2(0, 1)).equalsApproximately(new Vector2(1, -1), 0.000001))
.toBe(true)
expect(
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))
.toBe(true)
expect(
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', () => {
it('should multiply two vectors correctly', () => {
expect(new Vector2(1, 0).multiply(5).equalsApproximately(new Vector2(5, 0), 0.000001))
.toBe(true)
expect(
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))
.toBe(true)
expect(
new Vector2(3.41, -7.12)
.multiply(-3.1)
.equalsApproximately(new Vector2(-10.571, 22.072), 0.000001)
).toBe(true)
})
})
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, 1).length()).toBe(Math.sqrt(2))
@ -59,11 +87,20 @@ describe('Vector2', () => {
describe('#normalize', () => {
it('should normalize vectors correctly', () => {
expect(new Vector2(1, 0).normalize().equalsApproximately(new Vector2(1, 0), 0.000001))
.toBe(true)
expect(
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))
.toBe(true)
expect(
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', () => {
it('should rotate a vector correctly', () => {
expect(new Vector2(0, -1).rotate(Math.PI / 2).equalsApproximately(new Vector2(1, 0), 0.000001))
.toBe(true)
expect(
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))
.toBe(true)
expect(
new Vector2(1.23, -4.56)
.rotate(Math.PI)
.equalsApproximately(new Vector2(-1.23, 4.56), 0.000001)
).toBe(true)
})
})
describe('#angleBetween', () => {
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
)
})
})
})