30-days-of-javascript 2.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/30-days-of-javaScript.txt +1 -0
- package/AffineCipher.js +105 -0
- package/AverageMedian.js +22 -0
- package/Base64ToArrayBuffer.js +48 -0
- package/BinaryExponentiationRecursive.js +20 -0
- package/BinarySearch.js +33 -0
- package/BreadthFirstSearch.js +37 -0
- package/Circle.js +19 -0
- package/Cone.js +30 -0
- package/CreatePermutations.js +38 -0
- package/DecimalToHex.js +28 -0
- package/DecimalToRoman.js +52 -0
- package/Density.js +11 -0
- package/DutchNationalFlagSort.js +33 -0
- package/ExponentialFunction.js +25 -0
- package/FibonacciNumberRecursive.js +16 -0
- package/FisherYatesShuffle.js +18 -0
- package/FloydWarshall.js +47 -0
- package/Haversine.js +44 -0
- package/HexToRGB.js +17 -0
- package/MD5.js +205 -0
- package/Minesweeper.js +38 -0
- package/NumberOfIslands.js +81 -0
- package/PatternMatching.js +33 -0
- package/Problem012.js +64 -0
- package/QuadraticRoots.js +37 -0
- package/QuickSelect.js +65 -0
- package/README.md +1 -0
- package/RadixSort.js +43 -0
- package/RomanToDecimal.js +34 -0
- package/SquareRootLogarithmic.js +41 -0
- package/SwapSort.js +31 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +41 -0
- package/dist/index.mjs +12 -0
- package/package.json +31 -0
package/MD5.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
// Module that replicates the MD5 Cryptographic Hash
|
|
2
|
+
// function in Javascript.
|
|
3
|
+
|
|
4
|
+
// main variables
|
|
5
|
+
const S = [
|
|
6
|
+
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5,
|
|
7
|
+
9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11,
|
|
8
|
+
16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15,
|
|
9
|
+
21
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
const K = [
|
|
13
|
+
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,
|
|
14
|
+
0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
|
15
|
+
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,
|
|
16
|
+
0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
|
17
|
+
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
|
|
18
|
+
0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
|
19
|
+
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
|
|
20
|
+
0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
|
21
|
+
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
|
|
22
|
+
0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
|
23
|
+
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Separates an array into equal sized chunks
|
|
28
|
+
*
|
|
29
|
+
* @param {Array|string} array - array or string to separate into chunks
|
|
30
|
+
* @param {number} size - number of elements wanted in each chunk
|
|
31
|
+
* @return {Array} - array of original array split into chunks
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* chunkify("this is a test", 2)
|
|
35
|
+
*/
|
|
36
|
+
function chunkify(array, size) {
|
|
37
|
+
const chunks = []
|
|
38
|
+
for (let i = 0; i < array.length; i += size) {
|
|
39
|
+
chunks.push(array.slice(i, i + size))
|
|
40
|
+
}
|
|
41
|
+
return chunks
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Rotates the bits to the left
|
|
46
|
+
*
|
|
47
|
+
* @param {number} bits - 32 bit number
|
|
48
|
+
* @param {number} turns - number of rotations to make
|
|
49
|
+
* @return {number} - number after bits rotation
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* rotateLeft(0b1011, 3); // 0b1011000
|
|
53
|
+
*/
|
|
54
|
+
function rotateLeft(bits, turns) {
|
|
55
|
+
return (bits << turns) | (bits >>> (32 - turns))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Converts Uint8Array to Uint32Array
|
|
60
|
+
*
|
|
61
|
+
* @param {Uint8Array} u8Array Uint8Array to convert
|
|
62
|
+
* @returns {Uint32Array} - Required Uint32Array
|
|
63
|
+
*/
|
|
64
|
+
function u8ToU32(u8Array) {
|
|
65
|
+
const uint32Array = new Uint32Array(u8Array.length / 4)
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < u8Array.length; i += 4) {
|
|
68
|
+
uint32Array[i / 4] =
|
|
69
|
+
(u8Array[i] |
|
|
70
|
+
(u8Array[i + 1] << 8) |
|
|
71
|
+
(u8Array[i + 2] << 16) |
|
|
72
|
+
(u8Array[i + 3] << 24)) >>>
|
|
73
|
+
0
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return uint32Array
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Converts Uint32Array to Uint8Array
|
|
81
|
+
*
|
|
82
|
+
* @param {Uint32Array} u32Array Uint32Array to convert
|
|
83
|
+
* @returns {Uint8Array} - Required Uint8Array
|
|
84
|
+
*/
|
|
85
|
+
function u32ToU8(u32Array) {
|
|
86
|
+
const uint8Array = new Uint8Array(u32Array.length * 4)
|
|
87
|
+
|
|
88
|
+
for (let i = 0; i < u32Array.length; i++) {
|
|
89
|
+
uint8Array[i * 4] = u32Array[i] & 0xff
|
|
90
|
+
uint8Array[i * 4 + 1] = (u32Array[i] >> 8) & 0xff
|
|
91
|
+
uint8Array[i * 4 + 2] = (u32Array[i] >> 16) & 0xff
|
|
92
|
+
uint8Array[i * 4 + 3] = (u32Array[i] >> 24) & 0xff
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return uint8Array
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Adds padding to the end of the given array
|
|
100
|
+
*
|
|
101
|
+
* @param {Uint8Array} u8Array Array to pad
|
|
102
|
+
* @param {number} size Resulting size of the array
|
|
103
|
+
*/
|
|
104
|
+
function padEnd(u8Array, size) {
|
|
105
|
+
const result = new Uint8Array(size)
|
|
106
|
+
result.set(u8Array)
|
|
107
|
+
result.fill(0, u8Array.length)
|
|
108
|
+
|
|
109
|
+
return result
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Pre-processes message to feed the algorithm loop
|
|
114
|
+
*
|
|
115
|
+
* @param {Uint8Array} message - message to pre-process
|
|
116
|
+
* @return {Uint32Array} - processed message
|
|
117
|
+
*/
|
|
118
|
+
function preProcess(message) {
|
|
119
|
+
// Extend message by adding '0'
|
|
120
|
+
//
|
|
121
|
+
// message.length + 1 is for adding '1' bit
|
|
122
|
+
// 56 - (length % 64) is for padding with '0's
|
|
123
|
+
// 8 is for appending 64 bit message length
|
|
124
|
+
let m = padEnd(
|
|
125
|
+
message,
|
|
126
|
+
message.length + 1 + (56 - ((message.length + 1) % 64)) + 8
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
// Add '1' bit at the end of the message
|
|
130
|
+
m[message.length] = 1 << 7
|
|
131
|
+
|
|
132
|
+
// convert message to 32 bit uint array
|
|
133
|
+
m = u8ToU32(m)
|
|
134
|
+
|
|
135
|
+
// Append the length of the message to the end
|
|
136
|
+
// (ml / 0x100000000) | 0 is equivalent to (ml >> 32) & 0xffffffff) in other languages
|
|
137
|
+
let ml = message.length * 8
|
|
138
|
+
m[m.length - 2] = ml & 0xffffffff
|
|
139
|
+
m[m.length - 1] = (ml / 0x100000000) | 0
|
|
140
|
+
|
|
141
|
+
return m
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Hashes message using MD5 Cryptographic Hash Function
|
|
146
|
+
*
|
|
147
|
+
* @see
|
|
148
|
+
* For more info: https://en.wikipedia.org/wiki/MD5
|
|
149
|
+
*
|
|
150
|
+
* @param {Uint8Array} message - message to hash
|
|
151
|
+
* @return {Uint8Array} - message digest (hash value)
|
|
152
|
+
*/
|
|
153
|
+
function MD5(message) {
|
|
154
|
+
// Initialize variables:
|
|
155
|
+
let [a0, b0, c0, d0] = [
|
|
156
|
+
0x67452301 >>> 0,
|
|
157
|
+
0xefcdab89 >>> 0,
|
|
158
|
+
0x98badcfe >>> 0,
|
|
159
|
+
0x10325476 >>> 0
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
// pre-process message and split into 512 bit chunks
|
|
163
|
+
const words = Array.from(preProcess(message))
|
|
164
|
+
const chunks = chunkify(words, 16)
|
|
165
|
+
|
|
166
|
+
chunks.forEach(function (chunk, _) {
|
|
167
|
+
// initialize variables for this chunk
|
|
168
|
+
let [A, B, C, D] = [a0, b0, c0, d0]
|
|
169
|
+
|
|
170
|
+
for (let i = 0; i < 64; i++) {
|
|
171
|
+
let [F, g] = [0, 0]
|
|
172
|
+
|
|
173
|
+
if (i <= 15) {
|
|
174
|
+
F = (B & C) | (~B & D)
|
|
175
|
+
g = i
|
|
176
|
+
} else if (i <= 31) {
|
|
177
|
+
F = (D & B) | (~D & C)
|
|
178
|
+
g = (5 * i + 1) % 16
|
|
179
|
+
} else if (i <= 47) {
|
|
180
|
+
F = B ^ C ^ D
|
|
181
|
+
g = (3 * i + 5) % 16
|
|
182
|
+
} else {
|
|
183
|
+
F = C ^ (B | ~D)
|
|
184
|
+
g = (7 * i) % 16
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
F = (F + A + K[i] + chunk[g]) >>> 0
|
|
188
|
+
A = D
|
|
189
|
+
D = C
|
|
190
|
+
C = B
|
|
191
|
+
B = ((B + rotateLeft(F, S[i])) & 0xffffffff) >>> 0
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// add values for this chunk to main hash variables (unsigned)
|
|
195
|
+
a0 = (a0 + A) >>> 0
|
|
196
|
+
b0 = (b0 + B) >>> 0
|
|
197
|
+
c0 = (c0 + C) >>> 0
|
|
198
|
+
d0 = (d0 + D) >>> 0
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
return u32ToU8([a0, b0, c0, d0])
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// export MD5 function
|
|
205
|
+
export { MD5 }
|
package/Minesweeper.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Author: IcarusTheFly (https://github.com/IcarusTheFly)
|
|
3
|
+
* Minesweeper explanation can be found in: https://en.wikipedia.org/wiki/Minesweeper_(video_game)
|
|
4
|
+
* This function will take a rectangular matrix filled with boolean values - the value for a cell
|
|
5
|
+
* with a mine will be true, otherwise it will be false.
|
|
6
|
+
* As a result it will return a rectangular matrix where each cell will have an integer that
|
|
7
|
+
* counts all the mines in the adjacent cells
|
|
8
|
+
* Two cells should share at least one corner to be considered adjacent
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @function minesweeper
|
|
13
|
+
* @description It counts the amount of mines surrounding every cell and returns a formatted matrix
|
|
14
|
+
* @param {boolean[][]} matrix
|
|
15
|
+
* @returns {number[][]} Matrix of numbers with the amount of mines surrounding each cell
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export const minesweeper = (matrix) => {
|
|
19
|
+
const arrResult = []
|
|
20
|
+
for (let x = 0; x < matrix.length; x++) {
|
|
21
|
+
const arrLine = []
|
|
22
|
+
for (let y = 0; y < matrix[x].length; y++) {
|
|
23
|
+
let minesInCell = 0
|
|
24
|
+
for (let xi = x - 1; xi <= x + 1; xi++) {
|
|
25
|
+
if (matrix[xi] !== undefined) {
|
|
26
|
+
for (let yi = y - 1; yi <= y + 1; yi++) {
|
|
27
|
+
if ((xi !== x || yi !== y) && matrix[xi][yi] === true) {
|
|
28
|
+
minesInCell++
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
arrLine.push(minesInCell)
|
|
34
|
+
}
|
|
35
|
+
arrResult.push(arrLine)
|
|
36
|
+
}
|
|
37
|
+
return arrResult
|
|
38
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* Number of Islands
|
|
2
|
+
https://dev.to/rattanakchea/amazons-interview-question-count-island-21h6
|
|
3
|
+
Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
|
|
4
|
+
|
|
5
|
+
a two dimensional grid map
|
|
6
|
+
each element is going to represent a piece of land
|
|
7
|
+
1 is land,
|
|
8
|
+
0 is water
|
|
9
|
+
output a number which is the number of islands
|
|
10
|
+
|
|
11
|
+
Example 1:
|
|
12
|
+
Input:
|
|
13
|
+
11110
|
|
14
|
+
11010
|
|
15
|
+
11000
|
|
16
|
+
00000
|
|
17
|
+
|
|
18
|
+
Output: 1
|
|
19
|
+
|
|
20
|
+
Example 2:
|
|
21
|
+
Input:
|
|
22
|
+
11000
|
|
23
|
+
11000
|
|
24
|
+
00100
|
|
25
|
+
00011
|
|
26
|
+
|
|
27
|
+
Output: 3
|
|
28
|
+
|
|
29
|
+
I: two dimensional array
|
|
30
|
+
O: a single integer; total number of islands
|
|
31
|
+
|
|
32
|
+
Pseudocode:
|
|
33
|
+
OUTER FUNCTION
|
|
34
|
+
set count to 0
|
|
35
|
+
|
|
36
|
+
INNER FUNCTION - flood (col, row)
|
|
37
|
+
if the tile is water
|
|
38
|
+
return
|
|
39
|
+
make tile water(flood tile)
|
|
40
|
+
invoke flood on the neighbor coordinates
|
|
41
|
+
|
|
42
|
+
iterate over the matrix (col, row)
|
|
43
|
+
if the current element is a 1
|
|
44
|
+
increment count
|
|
45
|
+
invoke flood (coordinates for col and row)
|
|
46
|
+
|
|
47
|
+
Return the count
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
const islands = (matrixGrid) => {
|
|
51
|
+
const matrix = matrixGrid
|
|
52
|
+
let counter = 0
|
|
53
|
+
|
|
54
|
+
const flood = (row, col) => {
|
|
55
|
+
if (row < 0 || col < 0) return // Off the map above or left
|
|
56
|
+
if (row >= matrix.length || col >= matrix[row].length) return // Off the map below or right
|
|
57
|
+
|
|
58
|
+
const tile = matrix[row][col]
|
|
59
|
+
if (tile !== '1') return
|
|
60
|
+
|
|
61
|
+
matrix[row][col] = '0'
|
|
62
|
+
|
|
63
|
+
flood(row + 1, col) // Down
|
|
64
|
+
flood(row - 1, col) // Up
|
|
65
|
+
flood(row, col + 1) // Right
|
|
66
|
+
flood(row, col - 1) // Left
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
for (let row = 0; row < matrix.length; row += 1) {
|
|
70
|
+
for (let col = 0; col < matrix[row].length; col += 1) {
|
|
71
|
+
const current = matrix[row][col]
|
|
72
|
+
if (current === '1') {
|
|
73
|
+
flood(row, col)
|
|
74
|
+
counter += 1
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return counter
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export { islands }
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Pattern matching is case insensitive as
|
|
3
|
+
the inputs are converted to lower case before the
|
|
4
|
+
algorithm is run.
|
|
5
|
+
|
|
6
|
+
The algorithm will run through the entire text and
|
|
7
|
+
return the starting index if the given pattern is
|
|
8
|
+
available in the text
|
|
9
|
+
*/
|
|
10
|
+
const checkIfPatternExists = (text, pattern) => {
|
|
11
|
+
if (typeof text !== 'string' || typeof pattern !== 'string') {
|
|
12
|
+
throw new TypeError('Given input is not a string')
|
|
13
|
+
}
|
|
14
|
+
const textLength = text.length // Store the length of the text in a variable
|
|
15
|
+
const patternLength = pattern.length // Store the length of the pattern in a variable
|
|
16
|
+
|
|
17
|
+
// Iterate through the text until the textlength - patternlength index
|
|
18
|
+
for (let i = 0; i <= textLength - patternLength; i++) {
|
|
19
|
+
// For each character in the text check if the subsequent character
|
|
20
|
+
// are matching the given pattern; if not break from the condition
|
|
21
|
+
for (let j = 0; j < textLength; j++) {
|
|
22
|
+
if (text[i + j] !== pattern[j]) break
|
|
23
|
+
|
|
24
|
+
// For each iteration of j check if the value of
|
|
25
|
+
// j + 1 is equal to the length of the pattern
|
|
26
|
+
if (j + 1 === patternLength) {
|
|
27
|
+
return `Given pattern is found at index ${i}`
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { checkIfPatternExists }
|
package/Problem012.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Problem 12 - Highly divisible triangular number
|
|
3
|
+
*
|
|
4
|
+
* https://projecteuler.net/problem=11
|
|
5
|
+
*
|
|
6
|
+
* The sequence of triangle numbers is generated by adding the natural numbers.
|
|
7
|
+
* So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28.
|
|
8
|
+
*
|
|
9
|
+
* The first ten terms would be: 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
|
|
10
|
+
* Let us list the factors of the first seven triangle numbers:
|
|
11
|
+
*
|
|
12
|
+
* 1: 1
|
|
13
|
+
* 3: 1,3
|
|
14
|
+
* 6: 1,2,3,6
|
|
15
|
+
* 10: 1,2,5,10
|
|
16
|
+
* 15: 1,3,5,15
|
|
17
|
+
* 21: 1,3,7,21
|
|
18
|
+
* 28: 1,2,4,7,14,28
|
|
19
|
+
*
|
|
20
|
+
* We can see that 28 is the first triangle number to have over five divisors.
|
|
21
|
+
*
|
|
22
|
+
* What is the value of the first triangle number to have over five hundred divisors?
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Gets number of divisors of a given number
|
|
27
|
+
* @params num The number whose divisors to find
|
|
28
|
+
*/
|
|
29
|
+
const getNumOfDivisors = (num) => {
|
|
30
|
+
// initialize numberOfDivisors
|
|
31
|
+
let numberOfDivisors = 0
|
|
32
|
+
|
|
33
|
+
// if one divisor less than sqrt(num) exists
|
|
34
|
+
// then another divisor greater than sqrt(n) exists and its value is num/i
|
|
35
|
+
const sqrtNum = Math.sqrt(num)
|
|
36
|
+
for (let i = 0; i <= sqrtNum; i++) {
|
|
37
|
+
// check if i divides num
|
|
38
|
+
if (num % i === 0) {
|
|
39
|
+
if (i === sqrtNum) {
|
|
40
|
+
// if both divisors are equal, i.e., num is perfect square, then only 1 divisor
|
|
41
|
+
numberOfDivisors++
|
|
42
|
+
} else {
|
|
43
|
+
// 2 divisors, one of them is less than sqrt(n), other greater than sqrt(n)
|
|
44
|
+
numberOfDivisors += 2
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return numberOfDivisors
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Loops till first triangular number with 500 divisors is found
|
|
53
|
+
*/
|
|
54
|
+
const firstTriangularWith500Divisors = () => {
|
|
55
|
+
let triangularNum
|
|
56
|
+
// loop forever until numOfDivisors becomes greater than or equal to 500
|
|
57
|
+
for (let n = 1; ; n++) {
|
|
58
|
+
// nth triangular number is (1/2)*n*(n+1) by Arithmetic Progression
|
|
59
|
+
triangularNum = (1 / 2) * n * (n + 1)
|
|
60
|
+
if (getNumOfDivisors(triangularNum) >= 500) return triangularNum
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { firstTriangularWith500Divisors }
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @see https://www.cuemath.com/algebra/roots-of-quadratic-equation/
|
|
3
|
+
* @author Dibya Debayan Dash
|
|
4
|
+
* Calculates the roots of a quadratic equation of the form ax^2 + bx + c = 0.
|
|
5
|
+
*
|
|
6
|
+
* @param {number} a - Coefficient of x^2.
|
|
7
|
+
* @param {number} b - Coefficient of x.
|
|
8
|
+
* @param {number} c - Constant term.
|
|
9
|
+
* @returns {number[]} - An array containing the roots if they are real,
|
|
10
|
+
* or an empty array indicating no real roots.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // Find the roots of the quadratic equation: 2x^2 - 4x + 2 = 0
|
|
14
|
+
* const roots = quadraticRoots(2, -4, 2);
|
|
15
|
+
* // Expected output: [1]
|
|
16
|
+
*/
|
|
17
|
+
const quadraticRoots = (a, b, c) => {
|
|
18
|
+
// Calculate the discriminant
|
|
19
|
+
const discriminant = b * b - 4 * a * c
|
|
20
|
+
|
|
21
|
+
// Check if roots are real
|
|
22
|
+
if (discriminant < 0) {
|
|
23
|
+
return []
|
|
24
|
+
} else if (discriminant === 0) {
|
|
25
|
+
// One real root
|
|
26
|
+
return [-b / (2 * a)]
|
|
27
|
+
} else {
|
|
28
|
+
// Two real roots
|
|
29
|
+
const sqrtDiscriminant = Math.sqrt(discriminant)
|
|
30
|
+
return [
|
|
31
|
+
(-b + sqrtDiscriminant) / (2 * a),
|
|
32
|
+
(-b - sqrtDiscriminant) / (2 * a)
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { quadraticRoots }
|
package/QuickSelect.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [QuickSelect](https://www.geeksforgeeks.org/quickselect-algorithm/) is an algorithm to find the kth smallest number
|
|
3
|
+
*
|
|
4
|
+
* Notes:
|
|
5
|
+
* -QuickSelect is related to QuickSort, thus has optimal best and average
|
|
6
|
+
* -case (O(n)) but unlikely poor worst case (O(n^2))
|
|
7
|
+
* -This implementation uses randomly selected pivots for better performance
|
|
8
|
+
*
|
|
9
|
+
* @complexity: O(n) (on average )
|
|
10
|
+
* @complexity: O(n^2) (worst case)
|
|
11
|
+
* @flow
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
function QuickSelect(items, kth) {
|
|
15
|
+
// eslint-disable-line no-unused-vars
|
|
16
|
+
if (kth < 1 || kth > items.length) {
|
|
17
|
+
throw new RangeError('Index Out of Bound')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return RandomizedSelect(items, 0, items.length - 1, kth)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function RandomizedSelect(items, left, right, i) {
|
|
24
|
+
if (left === right) return items[left]
|
|
25
|
+
|
|
26
|
+
const pivotIndex = RandomizedPartition(items, left, right)
|
|
27
|
+
const k = pivotIndex - left + 1
|
|
28
|
+
|
|
29
|
+
if (i === k) return items[pivotIndex]
|
|
30
|
+
if (i < k) return RandomizedSelect(items, left, pivotIndex - 1, i)
|
|
31
|
+
|
|
32
|
+
return RandomizedSelect(items, pivotIndex + 1, right, i - k)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function RandomizedPartition(items, left, right) {
|
|
36
|
+
const rand = getRandomInt(left, right)
|
|
37
|
+
Swap(items, rand, right)
|
|
38
|
+
return Partition(items, left, right)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function Partition(items, left, right) {
|
|
42
|
+
const x = items[right]
|
|
43
|
+
let pivotIndex = left - 1
|
|
44
|
+
|
|
45
|
+
for (let j = left; j < right; j++) {
|
|
46
|
+
if (items[j] <= x) {
|
|
47
|
+
pivotIndex++
|
|
48
|
+
Swap(items, pivotIndex, j)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Swap(items, pivotIndex + 1, right)
|
|
53
|
+
|
|
54
|
+
return pivotIndex + 1
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getRandomInt(min, max) {
|
|
58
|
+
return Math.floor(Math.random() * (max - min + 1)) + min
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function Swap(arr, x, y) {
|
|
62
|
+
;[arr[x], arr[y]] = [arr[y], arr[x]]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { QuickSelect }
|
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
A 30DaysOfJavaScript challenge is a guide for both beginners and advanced JavaScript developers
|
package/RadixSort.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Radix sorts an integer array without comparing the integers.
|
|
3
|
+
* It groups the integers by their digits which share the same
|
|
4
|
+
* significant position.
|
|
5
|
+
* For more information see: https://en.wikipedia.org/wiki/Radix_sort
|
|
6
|
+
*/
|
|
7
|
+
export function radixSort(items, RADIX) {
|
|
8
|
+
// default radix is then because we usually count to base 10
|
|
9
|
+
if (RADIX === undefined || RADIX < 1) {
|
|
10
|
+
RADIX = 10
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let maxLength = false
|
|
14
|
+
let placement = 1
|
|
15
|
+
|
|
16
|
+
while (!maxLength) {
|
|
17
|
+
maxLength = true
|
|
18
|
+
const buckets = []
|
|
19
|
+
|
|
20
|
+
for (let i = 0; i < RADIX; i++) {
|
|
21
|
+
buckets.push([])
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
for (let j = 0; j < items.length; j++) {
|
|
25
|
+
const tmp = items[j] / placement
|
|
26
|
+
buckets[Math.floor(tmp % RADIX)].push(items[j])
|
|
27
|
+
if (maxLength && tmp > 0) {
|
|
28
|
+
maxLength = false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let a = 0
|
|
33
|
+
for (let b = 0; b < RADIX; b++) {
|
|
34
|
+
const buck = buckets[b]
|
|
35
|
+
for (let k = 0; k < buck.length; k++) {
|
|
36
|
+
items[a] = buck[k]
|
|
37
|
+
a++
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
placement *= RADIX
|
|
41
|
+
}
|
|
42
|
+
return items
|
|
43
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const values = {
|
|
2
|
+
I: 1,
|
|
3
|
+
V: 5,
|
|
4
|
+
X: 10,
|
|
5
|
+
L: 50,
|
|
6
|
+
C: 100,
|
|
7
|
+
D: 500,
|
|
8
|
+
M: 1000
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function romanToDecimal(romanNumber) {
|
|
12
|
+
let prev = ' '
|
|
13
|
+
|
|
14
|
+
let sum = 0
|
|
15
|
+
|
|
16
|
+
let newPrev = 0
|
|
17
|
+
for (let i = romanNumber.length - 1; i >= 0; i--) {
|
|
18
|
+
const c = romanNumber.charAt(i)
|
|
19
|
+
|
|
20
|
+
if (prev !== ' ') {
|
|
21
|
+
newPrev = values[prev] > newPrev ? values[prev] : newPrev
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const currentNum = values[c]
|
|
25
|
+
if (currentNum >= newPrev) {
|
|
26
|
+
sum += currentNum
|
|
27
|
+
} else {
|
|
28
|
+
sum -= currentNum
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
prev = c
|
|
32
|
+
}
|
|
33
|
+
return sum
|
|
34
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @function squareRootLogarithmic
|
|
3
|
+
* @description
|
|
4
|
+
* Return the square root of 'num' rounded down
|
|
5
|
+
* to the nearest integer.
|
|
6
|
+
* More info: https://leetcode.com/problems/sqrtx/
|
|
7
|
+
* @param {Number} num Number whose square of root is to be found
|
|
8
|
+
* @returns {Number} Square root
|
|
9
|
+
* @see [BinarySearch](https://en.wikipedia.org/wiki/Binary_search_algorithm)
|
|
10
|
+
* @example
|
|
11
|
+
* const num1 = 4
|
|
12
|
+
* logarithmicSquareRoot(num1) // ====> 2
|
|
13
|
+
* @example
|
|
14
|
+
* const num2 = 8
|
|
15
|
+
* logarithmicSquareRoot(num1) // ====> 2
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
const squareRootLogarithmic = (num) => {
|
|
19
|
+
if (typeof num !== 'number') {
|
|
20
|
+
throw new Error('Input data must be numbers')
|
|
21
|
+
}
|
|
22
|
+
let answer = 0
|
|
23
|
+
let sqrt = 0
|
|
24
|
+
let edge = num
|
|
25
|
+
|
|
26
|
+
while (sqrt <= edge) {
|
|
27
|
+
const mid = Math.trunc((sqrt + edge) / 2)
|
|
28
|
+
if (mid * mid === num) {
|
|
29
|
+
return mid
|
|
30
|
+
} else if (mid * mid < num) {
|
|
31
|
+
sqrt = mid + 1
|
|
32
|
+
answer = mid
|
|
33
|
+
} else {
|
|
34
|
+
edge = mid - 1
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return answer
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { squareRootLogarithmic }
|
package/SwapSort.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @function SwapSort
|
|
3
|
+
* @description Swap Sort is an algorithm to find the number of swaps required to sort an array.
|
|
4
|
+
Time complexity of Swap Sort Algorithm is O(nlogn).
|
|
5
|
+
Auxiliary Space required for Swap Sort Algorithm is O(n).
|
|
6
|
+
* @param {Integer[]} items - Array of integers
|
|
7
|
+
* @return {Integer} - Number of swaps required to sort the array.
|
|
8
|
+
* @see [SwapSort](https://www.geeksforgeeks.org/minimum-number-swaps-required-sort-array/)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export function minSwapsToSort(items) {
|
|
12
|
+
const sortedArray = items.slice()
|
|
13
|
+
sortedArray.sort()
|
|
14
|
+
const indexMap = {}
|
|
15
|
+
for (let i = 0; i < items.length; i++) {
|
|
16
|
+
indexMap[items[i]] = i
|
|
17
|
+
}
|
|
18
|
+
let swaps = 0
|
|
19
|
+
for (let i = 0; i < items.length; i++) {
|
|
20
|
+
if (items[i] !== sortedArray[i]) {
|
|
21
|
+
const temp = items[i]
|
|
22
|
+
items[i] = items[indexMap[sortedArray[i]]]
|
|
23
|
+
items[indexMap[sortedArray[i]]] = temp
|
|
24
|
+
|
|
25
|
+
indexMap[temp] = indexMap[sortedArray[i]]
|
|
26
|
+
indexMap[sortedArray[i]] = i
|
|
27
|
+
swaps++
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return swaps
|
|
31
|
+
}
|
package/dist/index.d.mts
ADDED