chore: convert functions to an ES2015 classes (#1656)

* chore: convert functions to an ES2015 classes

* remove unnecessary functions
This commit is contained in:
Hasan Al-Kaf
2024-04-13 20:51:54 +03:00
committed by GitHub
parent 314144fae6
commit 6fe21d21e9
8 changed files with 392 additions and 386 deletions

View File

@ -24,8 +24,8 @@ const RailwayTimeConversion = (timeString) => {
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] = [ const [second, shift] = [
secondWithShift.substr(0, 2), secondWithShift.substring(0, 2),
secondWithShift.substr(2) secondWithShift.substring(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') {

View File

@ -7,11 +7,9 @@
const Reverse = (arr) => { const Reverse = (arr) => {
// limit specifies the amount of Reverse actions // limit specifies the amount of Reverse actions
for (let i = 0, j = arr.length - 1; i < arr.length / 2; i++, j--) { for (let i = 0, j = arr.length - 1; i < arr.length / 2; i++, j--)
const temp = arr[i] [arr[i], arr[j]] = [arr[j], arr[i]]
arr[i] = arr[j]
arr[j] = temp
}
return arr return arr
} }
export { Reverse } export { Reverse }

View File

@ -8,8 +8,8 @@
// Functions: push, pop, peek, view, length // Functions: push, pop, peek, view, length
// Creates a stack constructor // Creates a stack constructor
const Stack = (function () { class Stack {
function Stack() { constructor() {
// The top of the Stack // The top of the Stack
this.top = 0 this.top = 0
// The array representation of the stack // The array representation of the stack
@ -17,13 +17,13 @@ const Stack = (function () {
} }
// Adds a value onto the end of the stack // Adds a value onto the end of the stack
Stack.prototype.push = function (value) { push(value) {
this.stack[this.top] = value this.stack[this.top] = value
this.top++ this.top++
} }
// Removes and returns the value at the end of the stack // Removes and returns the value at the end of the stack
Stack.prototype.pop = function () { pop() {
if (this.top === 0) { if (this.top === 0) {
return 'Stack is Empty' return 'Stack is Empty'
} }
@ -35,23 +35,21 @@ const Stack = (function () {
} }
// Returns the size of the stack // Returns the size of the stack
Stack.prototype.size = function () { size() {
return this.top return this.top
} }
// Returns the value at the end of the stack // Returns the value at the end of the stack
Stack.prototype.peek = function () { peek() {
return this.stack[this.top - 1] return this.stack[this.top - 1]
} }
// 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)) { view(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
})()
export { Stack } export { Stack }

View File

@ -31,8 +31,8 @@ let utils
* @argument comp - A function used by AVL Tree For Comparison * @argument comp - A function used by AVL Tree For Comparison
* If no argument is sent it uses utils.comparator * If no argument is sent it uses utils.comparator
*/ */
const AVLTree = (function () { class AVLTree {
function _avl(comp) { constructor(comp) {
/** @public comparator function */ /** @public comparator function */
this._comp = undefined this._comp = undefined
this._comp = comp !== undefined ? comp : utils.comparator() this._comp = comp !== undefined ? comp : utils.comparator()
@ -43,162 +43,6 @@ const AVLTree = (function () {
this.size = 0 this.size = 0
} }
// creates new Node Object
const Node = function (val) {
this._val = val
this._left = null
this._right = null
this._height = 1
}
// get height of a node
const getHeight = function (node) {
if (node == null) {
return 0
}
return node._height
}
// height difference or balance factor of a node
const getHeightDifference = function (node) {
return node == null ? 0 : getHeight(node._left) - getHeight(node._right)
}
// update height of a node based on children's heights
const updateHeight = function (node) {
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)
// rotations of AVL Tree
const leftRotate = function (node) {
const temp = node._right
node._right = temp._left
temp._left = node
updateHeight(node)
updateHeight(temp)
return temp
}
const rightRotate = function (node) {
const temp = node._left
node._left = temp._right
temp._right = node
updateHeight(node)
updateHeight(temp)
return temp
}
// check if tree is balanced else balance it for insertion
const insertBalance = function (node, _val, balanceFactor, tree) {
if (balanceFactor > 1 && tree._comp(_val, node._left._val) < 0) {
return rightRotate(node) // Left Left Case
}
if (balanceFactor < 1 && tree._comp(_val, node._right._val) > 0) {
return leftRotate(node) // Right Right Case
}
if (balanceFactor > 1 && tree._comp(_val, node._left._val) > 0) {
node._left = leftRotate(node._left) // Left Right Case
return rightRotate(node)
}
node._right = rightRotate(node._right)
return leftRotate(node)
}
// check if tree is balanced after deletion
const delBalance = function (node) {
const balanceFactor1 = getHeightDifference(node)
if (isValidBalanceFactor(balanceFactor1)) {
return node
}
if (balanceFactor1 > 1) {
if (getHeightDifference(node._left) >= 0) {
return rightRotate(node) // Left Left
}
node._left = leftRotate(node._left)
return rightRotate(node) // Left Right
}
if (getHeightDifference(node._right) > 0) {
node._right = rightRotate(node._right)
return leftRotate(node) // Right Left
}
return leftRotate(node) // Right Right
}
// implement avl tree insertion
const insert = function (root, val, tree) {
if (root == null) {
tree.size++
return new Node(val)
}
if (tree._comp(root._val, val) < 0) {
root._right = insert(root._right, val, tree)
} else if (tree._comp(root._val, val) > 0) {
root._left = insert(root._left, val, tree)
} else {
return root
}
updateHeight(root)
const balanceFactor = getHeightDifference(root)
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._left === null && root._right === null) {
root = null
tree.size--
} else if (root._left === null) {
root = root._right
tree.size--
} else if (root._right === null) {
root = root._left
tree.size--
} else {
let temp = root._right
while (temp._left != null) {
temp = temp._left
}
root._val = temp._val
root._right = deleteElement(root._right, temp._val, tree)
}
} else {
if (tree._comp(root._val, _val) < 0) {
root._right = deleteElement(root._right, _val, tree)
} else {
root._left = deleteElement(root._left, _val, tree)
}
}
updateHeight(root)
root = delBalance(root)
return root
}
// search tree for a element
const searchAVLTree = function (root, val, tree) {
if (root == null) {
return null
}
if (tree._comp(root._val, val) === 0) {
return root
}
if (tree._comp(root._val, val) < 0) {
return searchAVLTree(root._right, val, tree)
}
return searchAVLTree(root._left, val, tree)
}
/* Public Functions */ /* Public Functions */
/** /**
* For Adding Elements to AVL Tree * For Adding Elements to AVL Tree
@ -207,20 +51,22 @@ const AVLTree = (function () {
* if a element exists it return false * if a element exists it return false
* @returns {Boolean} element added or not * @returns {Boolean} element added or not
*/ */
_avl.prototype.add = function (_val) { add(_val) {
const prevSize = this.size const prevSize = this.size
this.root = insert(this.root, _val, this) this.root = insert(this.root, _val, this)
return this.size !== prevSize return this.size !== prevSize
} }
/** /**
* TO check is a particular element exists or not * TO check is a particular element exists or not
* @param {any} _val * @param {any} _val
* @returns {Boolean} exists or not * @returns {Boolean} exists or not
*/ */
_avl.prototype.find = function (_val) { find(_val) {
const temp = searchAVLTree(this.root, _val, this) const temp = searchAVLTree(this.root, _val, this)
return temp != null return temp != null
} }
/** /**
* *
* @param {any} _val * @param {any} _val
@ -228,13 +74,170 @@ const AVLTree = (function () {
* in that case it return false * in that case it return false
* @returns {Boolean} if element was found and deleted * @returns {Boolean} if element was found and deleted
*/ */
_avl.prototype.remove = function (_val) { remove(_val) {
const prevSize = this.size const prevSize = this.size
this.root = deleteElement(this.root, _val, this) this.root = deleteElement(this.root, _val, this)
return prevSize !== this.size return prevSize !== this.size
} }
return _avl }
})()
// creates new Node Object
class Node {
constructor(val) {
this._val = val
this._left = null
this._right = null
this._height = 1
}
}
// get height of a node
const getHeight = function (node) {
if (node == null) {
return 0
}
return node._height
}
// height difference or balance factor of a node
const getHeightDifference = function (node) {
return node == null ? 0 : getHeight(node._left) - getHeight(node._right)
}
// update height of a node based on children's heights
const updateHeight = function (node) {
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)
// rotations of AVL Tree
const leftRotate = function (node) {
const temp = node._right
node._right = temp._left
temp._left = node
updateHeight(node)
updateHeight(temp)
return temp
}
const rightRotate = function (node) {
const temp = node._left
node._left = temp._right
temp._right = node
updateHeight(node)
updateHeight(temp)
return temp
}
// check if tree is balanced else balance it for insertion
const insertBalance = function (node, _val, balanceFactor, tree) {
if (balanceFactor > 1 && tree._comp(_val, node._left._val) < 0) {
return rightRotate(node) // Left Left Case
}
if (balanceFactor < 1 && tree._comp(_val, node._right._val) > 0) {
return leftRotate(node) // Right Right Case
}
if (balanceFactor > 1 && tree._comp(_val, node._left._val) > 0) {
node._left = leftRotate(node._left) // Left Right Case
return rightRotate(node)
}
node._right = rightRotate(node._right)
return leftRotate(node)
}
// check if tree is balanced after deletion
const delBalance = function (node) {
const balanceFactor1 = getHeightDifference(node)
if (isValidBalanceFactor(balanceFactor1)) {
return node
}
if (balanceFactor1 > 1) {
if (getHeightDifference(node._left) >= 0) {
return rightRotate(node) // Left Left
}
node._left = leftRotate(node._left)
return rightRotate(node) // Left Right
}
if (getHeightDifference(node._right) > 0) {
node._right = rightRotate(node._right)
return leftRotate(node) // Right Left
}
return leftRotate(node) // Right Right
}
// implement avl tree insertion
const insert = function (root, val, tree) {
if (root == null) {
tree.size++
return new Node(val)
}
if (tree._comp(root._val, val) < 0) {
root._right = insert(root._right, val, tree)
} else if (tree._comp(root._val, val) > 0) {
root._left = insert(root._left, val, tree)
} else {
return root
}
updateHeight(root)
const balanceFactor = getHeightDifference(root)
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._left === null && root._right === null) {
root = null
tree.size--
} else if (root._left === null) {
root = root._right
tree.size--
} else if (root._right === null) {
root = root._left
tree.size--
} else {
let temp = root._right
while (temp._left != null) {
temp = temp._left
}
root._val = temp._val
root._right = deleteElement(root._right, temp._val, tree)
}
} else {
if (tree._comp(root._val, _val) < 0) {
root._right = deleteElement(root._right, _val, tree)
} else {
root._left = deleteElement(root._left, _val, tree)
}
}
updateHeight(root)
root = delBalance(root)
return root
}
// search tree for a element
const searchAVLTree = function (root, val, tree) {
if (root == null) {
return null
}
if (tree._comp(root._val, val) === 0) {
return root
}
if (tree._comp(root._val, val) < 0) {
return searchAVLTree(root._right, val, tree)
}
return searchAVLTree(root._left, val, tree)
}
/** /**
* A Code for Testing the AVLTree * A Code for Testing the AVLTree

View File

@ -13,77 +13,79 @@
// class Node // class Node
const Node = (function Node() { const Node = (function Node() {
// Node in the tree // Node in the tree
function Node(val) { class Node {
this.value = val constructor(val) {
this.left = null this.value = val
this.right = null this.left = null
} this.right = null
// Search the tree for a value
Node.prototype.search = function (val) {
if (this.value === val) {
return this
} else if (val < this.value && this.left !== null) {
return this.left.search(val)
} else if (val > this.value && this.right !== null) {
return this.right.search(val)
} }
return null
}
// Visit a node // Search the tree for a value
Node.prototype.visit = function (output = (value) => console.log(value)) { search(val) {
// Recursively go left if (this.value === val) {
if (this.left !== null) { return this
this.left.visit() } else if (val < this.value && this.left !== null) {
} return this.left.search(val)
// Print out value } else if (val > this.value && this.right !== null) {
output(this.value) return this.right.search(val)
// Recursively go right
if (this.right !== null) {
this.right.visit()
}
}
// Add a node
Node.prototype.addNode = function (n) {
if (n.value < this.value) {
if (this.left === null) {
this.left = n
} else {
this.left.addNode(n)
} }
} else if (n.value > this.value) { return null
if (this.right === null) { }
this.right = n
} else { // Visit a node
this.right.addNode(n) visit(output = (value) => console.log(value)) {
// Recursively go left
if (this.left !== null) {
this.left.visit()
}
// Print out value
output(this.value)
// Recursively go right
if (this.right !== null) {
this.right.visit()
} }
} }
}
// remove a node // Add a node
Node.prototype.removeNode = function (val) { addNode(n) {
if (val === this.value) { if (n.value < this.value) {
if (!this.left && !this.right) { if (this.left === null) {
return null this.left = n
} else {
if (this.left) {
const leftMax = maxVal(this.left)
this.value = leftMax
this.left = this.left.removeNode(leftMax)
} else { } else {
const rightMin = minVal(this.right) this.left.addNode(n)
this.value = rightMin }
this.right = this.right.removeNode(rightMin) } else if (n.value > this.value) {
if (this.right === null) {
this.right = n
} else {
this.right.addNode(n)
} }
} }
} else if (val < this.value) {
this.left = this.left && this.left.removeNode(val)
} else if (val > this.value) {
this.right = this.right && this.right.removeNode(val)
} }
return this
// remove a node
removeNode(val) {
if (val === this.value) {
if (!this.left && !this.right) {
return null
} else {
if (this.left) {
const leftMax = maxVal(this.left)
this.value = leftMax
this.left = this.left.removeNode(leftMax)
} else {
const rightMin = minVal(this.right)
this.value = rightMin
this.right = this.right.removeNode(rightMin)
}
}
} else if (val < this.value) {
this.left = this.left && this.left.removeNode(val)
} else if (val > this.value) {
this.right = this.right && this.right.removeNode(val)
}
return this
}
} }
// find maximum value in the tree // find maximum value in the tree
@ -107,44 +109,46 @@ const Node = (function Node() {
// class Tree // class Tree
const Tree = (function () { const Tree = (function () {
function Tree() { class Tree {
// Just store the root constructor() {
this.root = null // Just store the root
} this.root = null
// Inorder traversal
Tree.prototype.traverse = function () {
if (!this.root) {
// No nodes are there in the tree till now
return
} }
this.root.visit()
}
// Start by searching the root // Inorder traversal
Tree.prototype.search = function (val) { traverse() {
const found = this.root.search(val) if (!this.root) {
if (found !== null) { // No nodes are there in the tree till now
return found.value return
}
this.root.visit()
} }
// not found
return null
}
// Add a new value to the tree // Start by searching the root
Tree.prototype.addValue = function (val) { search(val) {
const n = new Node(val) const found = this.root.search(val)
if (this.root === null) { if (found !== null) {
this.root = n return found.value
} else { }
this.root.addNode(n) // not found
return null
} }
}
// remove a value from the tree // Add a new value to the tree
Tree.prototype.removeValue = function (val) { addValue(val) {
// remove something if root exists const n = new Node(val)
this.root = this.root && this.root.removeNode(val) if (this.root === null) {
this.root = n
} else {
this.root.addNode(n)
}
}
// remove a value from the tree
removeValue(val) {
// remove something if root exists
this.root = this.root && this.root.removeNode(val)
}
} }
// returns the constructor // returns the constructor

View File

@ -1,129 +1,132 @@
const TrieNode = function TrieNode(key, parent) { class TrieNode {
this.key = key constructor(key, parent) {
this.count = 0 this.key = key
this.children = Object.create(null) this.count = 0
if (parent === undefined) { this.children = Object.create(null)
this.parent = null if (parent === undefined) {
} else { this.parent = null
this.parent = parent } else {
} this.parent = parent
}
function Trie() {
// create only root with null key and parent
this.root = new TrieNode(null, null)
}
// Recursively finds the occurrence of all words in a given node
Trie.findAllWords = function (root, word, output) {
if (root === null) return
if (root.count > 0) {
if (typeof output === 'object') {
output.push({ word, count: root.count })
} }
} }
let key
for (key in root.children) {
word += key
this.findAllWords(root.children[key], word, output)
word = word.slice(0, -1)
}
} }
Trie.prototype.insert = function (word) { class Trie {
if (typeof word !== 'string') return constructor() {
if (word === '') { // create only root with null key and parent
this.root.count += 1 this.root = new TrieNode(null, null)
return
} }
let node = this.root
const len = word.length // Recursively finds the occurrence of all words in a given node
let i static findAllWords(root, word, output) {
for (i = 0; i < len; i++) { if (root === null) return
if (node.children[word.charAt(i)] === undefined) { if (root.count > 0) {
node.children[word.charAt(i)] = new TrieNode(word.charAt(i), node) if (typeof output === 'object') {
output.push({ word, count: root.count })
}
}
let key
for (key in root.children) {
word += key
this.findAllWords(root.children[key], word, output)
word = word.slice(0, -1)
} }
node = node.children[word.charAt(i)]
}
node.count += 1
}
Trie.prototype.findPrefix = function (word) {
if (typeof word !== 'string') return null
let node = this.root
const len = word.length
let i
// After end of this loop node will be at desired prefix
for (i = 0; i < len; i++) {
if (node.children[word.charAt(i)] === undefined) return null // No such prefix exists
node = node.children[word.charAt(i)]
}
return node
}
Trie.prototype.remove = function (word, count) {
if (typeof word !== 'string') return
if (typeof count !== 'number') count = 1
else if (count <= 0) return
// for empty string just delete count of root
if (word === '') {
if (this.root.count >= count) this.root.count -= count
else this.root.count = 0
return
} }
let child = this.root insert(word) {
const len = word.length if (typeof word !== 'string') return
let i, key if (word === '') {
// child: node which is to be deleted this.root.count += 1
for (i = 0; i < len; i++) { return
key = word.charAt(i) }
if (child.children[key] === undefined) return let node = this.root
child = child.children[key] 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)
}
node = node.children[word.charAt(i)]
}
node.count += 1
} }
// Delete no of occurrences specified findPrefix(word) {
if (child.count >= count) child.count -= count if (typeof word !== 'string') return null
else child.count = 0 let node = this.root
const len = word.length
// If some occurrences are left we don't delete it or else let i
// if the object forms some other objects prefix we don't delete it // After end of this loop node will be at desired prefix
// For checking an empty object for (i = 0; i < len; i++) {
// https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object if (node.children[word.charAt(i)] === undefined) return null // No such prefix exists
if ( node = node.children[word.charAt(i)]
child.count <= 0 && }
Object.keys(child.children).length && return node
child.children.constructor === Object
) {
child.parent.children[child.key] = undefined
} }
}
Trie.prototype.findAllWords = function (prefix) { remove(word, count) {
const output = [] if (typeof word !== 'string') return
// find the node with provided prefix if (typeof count !== 'number') count = 1
const node = this.findPrefix(prefix) else if (count <= 0) return
// No such prefix exists
if (node === null) return output
Trie.findAllWords(node, prefix, output)
return output
}
Trie.prototype.contains = function (word) { // for empty string just delete count of root
// find the node with given prefix if (word === '') {
const node = this.findPrefix(word) if (this.root.count >= count) this.root.count -= count
// No such word exists else this.root.count = 0
return
}
return node !== null && node.count !== 0 let child = this.root
} const len = word.length
let i, key
// child: node which is to be deleted
for (i = 0; i < len; i++) {
key = word.charAt(i)
if (child.children[key] === undefined) return
child = child.children[key]
}
Trie.prototype.findOccurrences = function (word) { // Delete no of occurrences specified
// find the node with given prefix if (child.count >= count) child.count -= count
const node = this.findPrefix(word) else child.count = 0
// No such word exists
if (node === null) return 0 // If some occurrences are left we don't delete it or else
return node.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
) {
child.parent.children[child.key] = undefined
}
}
findAllWords(prefix) {
const output = []
// find the node with provided prefix
const node = this.findPrefix(prefix)
// No such prefix exists
if (node === null) return output
Trie.findAllWords(node, prefix, output)
return output
}
contains(word) {
// find the node with given prefix
const node = this.findPrefix(word)
// No such word exists
return node !== null && node.count !== 0
}
findOccurrences(word) {
// find the node with given prefix
const node = this.findPrefix(word)
// No such word exists
if (node === null) return 0
return node.count
}
} }
export { Trie } export { Trie }

View File

@ -4,7 +4,7 @@ determine the total number of the subset with sum
equal to the given sum. equal to the given sum.
*/ */
/* /*
Given solution is O(n*sum) Time complexity and O(sum) Space complexity Given solution is O(n*sum) Time complexity and O(sum) Space complexity
*/ */
function NumberOfSubsetSum(array, sum) { function NumberOfSubsetSum(array, sum) {
const dp = [] // create an dp array where dp[i] denote number of subset with sum equal to i const dp = [] // create an dp array where dp[i] denote number of subset with sum equal to i

View File

@ -1,6 +1,6 @@
// https://projecteuler.net/problem=4 // https://projecteuler.net/problem=4
/* A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99. /* A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers. Find the largest palindrome made from the product of two 3-digit numbers.
*/ */
export const largestPalindromic = (digits) => { export const largestPalindromic = (digits) => {
let i let i