Skip to content

Commit 3e4176e

Browse files
authored
Merge branch 'TheAlgorithms:master' into remove-Eratosthenes-intarray
2 parents e3ef5c3 + 85a55da commit 3e4176e

24 files changed

+892
-118
lines changed

.github/workflows/UploadCoverageReport.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ name: UploadCoverageReport
88
- master
99
pull_request:
1010

11+
env:
12+
REPORT_PATH: "coverage/coverage-final.json"
13+
1114
jobs:
1215
UploadCoverageReport:
1316
runs-on: ubuntu-latest
@@ -25,9 +28,18 @@ jobs:
2528
- name: Generate coverage report
2629
run: npm test -- --coverage
2730

28-
- name: Upload coverage to codecov
29-
uses: codecov/codecov-action@v3
31+
- name: Upload coverage to codecov (tokenless)
32+
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository
33+
uses: codecov/codecov-action@v4
34+
with:
35+
files: "${{ env.REPORT_PATH }}"
36+
fail_ci_if_error: true
37+
38+
- name: Upload coverage to codecov (with token)
39+
if: "! github.event.pull_request.head.repo.fork "
40+
uses: codecov/codecov-action@v4
3041
with:
31-
files: "coverage/coverage-final.json"
42+
token: ${{ secrets.CODECOV_TOKEN }}
43+
files: "${{ env.REPORT_PATH }}"
3244
fail_ci_if_error: true
3345
...

Backtracking/tests/RatInAMaze.test.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ describe('RatInAMaze', () => {
66

77
for (const value of values) {
88
// we deliberately want to check whether this constructor call fails or not
9-
// eslint-disable-next-line no-new
109
expect(() => {
1110
new RatInAMaze(value)
1211
}).toThrow()
@@ -15,7 +14,6 @@ describe('RatInAMaze', () => {
1514

1615
it('should fail for an empty array', () => {
1716
// we deliberately want to check whether this constructor call fails or not
18-
// eslint-disable-next-line no-new
1917
expect(() => {
2018
new RatInAMaze([])
2119
}).toThrow()
@@ -28,7 +26,6 @@ describe('RatInAMaze', () => {
2826
]
2927

3028
// we deliberately want to check whether this constructor call fails or not
31-
// eslint-disable-next-line no-new
3229
expect(() => {
3330
new RatInAMaze(array)
3431
}).toThrow()
@@ -39,7 +36,6 @@ describe('RatInAMaze', () => {
3936

4037
for (const value of values) {
4138
// we deliberately want to check whether this constructor call fails or not
42-
// eslint-disable-next-line no-new
4339
expect(() => {
4440
new RatInAMaze(value)
4541
}).toThrow()

Backtracking/tests/Sudoku.test.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ const solved = [
2727
describe('Sudoku', () => {
2828
it('should create a valid board successfully', () => {
2929
// we deliberately want to check whether this constructor call fails or not
30-
// eslint-disable-next-line no-new
3130
expect(() => {
3231
new Sudoku(data)
3332
}).not.toThrow()

Compression/RLE.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* RLE (Run Length Encoding) is a simple form of data compression.
3+
* The basic idea is to represent repeated successive characters as a single count and character.
4+
* For example, the string "AAAABBBCCDAA" would be encoded as "4A3B2C1D2A".
5+
*
6+
* @author - [ddaniel27](https://github.com/ddaniel27)
7+
*/
8+
9+
function Compress(str) {
10+
let compressed = ''
11+
let count = 1
12+
13+
for (let i = 0; i < str.length; i++) {
14+
if (str[i] !== str[i + 1]) {
15+
compressed += count + str[i]
16+
count = 1
17+
continue
18+
}
19+
20+
count++
21+
}
22+
23+
return compressed
24+
}
25+
26+
function Decompress(str) {
27+
let decompressed = ''
28+
let match = [...str.matchAll(/(\d+)(\D)/g)] // match all groups of digits followed by a non-digit character
29+
30+
match.forEach((item) => {
31+
let [count, char] = [item[1], item[2]]
32+
decompressed += char.repeat(count)
33+
})
34+
35+
return decompressed
36+
}
37+
38+
export { Compress, Decompress }

Compression/test/RLE.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Compress, Decompress } from '../RLE'
2+
3+
describe('Test RLE Compressor/Decompressor', () => {
4+
it('Test - 1, Pass long repetitive strings', () => {
5+
expect(Compress('AAAAAAAAAAAAAA')).toBe('14A')
6+
expect(Compress('AAABBQQQQQFG')).toBe('3A2B5Q1F1G')
7+
})
8+
9+
it('Test - 2, Pass compressed strings', () => {
10+
expect(Decompress('14A')).toBe('AAAAAAAAAAAAAA')
11+
expect(Decompress('3A2B5Q1F1G')).toBe('AAABBQQQQQFG')
12+
})
13+
})

Conversions/HexToDecimal.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
function hexToInt(hexNum) {
2+
if (!/^[0-9A-F]+$/.test(hexNum)) {
3+
throw new Error('Invalid hex string.')
4+
}
25
const numArr = hexNum.split('') // converts number to array
36
return numArr.map((item, index) => {
47
switch (item) {
@@ -29,4 +32,4 @@ function hexToDecimal(hexNum) {
2932
}, 0)
3033
}
3134

32-
export { hexToInt, hexToDecimal }
35+
export { hexToDecimal }

Conversions/test/HexToDecimal.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { hexToDecimal } from '../HexToDecimal'
2+
3+
describe('Testing HexToDecimal', () => {
4+
it.each([
5+
['0', 0],
6+
['1', 1],
7+
['A', 10],
8+
['B', 11],
9+
['C', 12],
10+
['D', 13],
11+
['E', 14],
12+
['F', 15],
13+
['10', 16],
14+
['859', 2137],
15+
['4D2', 1234],
16+
['81323ABD92', 554893491602]
17+
])('check with %s', (hexStr, expected) => {
18+
expect(hexToDecimal(hexStr)).toBe(expected)
19+
})
20+
21+
it.each(['a', '-1', 'G', ''])('throws for %s', (hexStr) => {
22+
expect(() => hexToDecimal(hexStr)).toThrowError()
23+
})
24+
})

DIRECTORY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
* [ROT13](Ciphers/ROT13.js)
3636
* [VigenereCipher](Ciphers/VigenereCipher.js)
3737
* [XORCipher](Ciphers/XORCipher.js)
38+
* **Compression**
39+
* [RLE](Compression/RLE.js)
3840
* **Conversions**
3941
* [ArbitraryBase](Conversions/ArbitraryBase.js)
4042
* [ArrayBufferToBase64](Conversions/ArrayBufferToBase64.js)
@@ -285,6 +287,7 @@
285287
* [Problem016](Project-Euler/Problem016.js)
286288
* [Problem017](Project-Euler/Problem017.js)
287289
* [Problem018](Project-Euler/Problem018.js)
290+
* [Problem019](Project-Euler/Problem019.js)
288291
* [Problem020](Project-Euler/Problem020.js)
289292
* [Problem021](Project-Euler/Problem021.js)
290293
* [Problem023](Project-Euler/Problem023.js)

Data-Structures/Array/QuickSelect.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
*/
1313

1414
function QuickSelect(items, kth) {
15-
// eslint-disable-line no-unused-vars
1615
if (kth < 1 || kth > items.length) {
1716
throw new RangeError('Index Out of Bound')
1817
}

Data-Structures/Queue/QueueUsing2Stacks.js

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,6 @@ class Queue {
2929
return top
3030
}
3131
}
32-
33-
// display elements of the inputstack
34-
listIn(output = (value) => console.log(value)) {
35-
let i = 0
36-
while (i < this.inputStack.length) {
37-
output(this.inputStack[i])
38-
i++
39-
}
40-
}
41-
42-
// display element of the outputstack
43-
listOut(output = (value) => console.log(value)) {
44-
let i = 0
45-
while (i < this.outputStack.length) {
46-
output(this.outputStack[i])
47-
i++
48-
}
49-
}
5032
}
5133

5234
export { Queue }

Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
/*
2-
Given an array of non-negative integers and a value sum,
2+
Given an array of positive integers and a value sum,
33
determine the total number of the subset with sum
44
equal to the given sum.
55
*/
66
/*
77
Given solution is O(n*sum) Time complexity and O(sum) Space complexity
88
*/
99
function NumberOfSubsetSum(array, sum) {
10+
if (sum < 0) {
11+
throw new Error('The sum must be non-negative.')
12+
}
13+
14+
if (!array.every((num) => num > 0)) {
15+
throw new Error('All of the inputs of the array must be positive.')
16+
}
1017
const dp = [] // create an dp array where dp[i] denote number of subset with sum equal to i
1118
for (let i = 1; i <= sum; i++) {
1219
dp[i] = 0
@@ -23,10 +30,4 @@ function NumberOfSubsetSum(array, sum) {
2330
return dp[sum]
2431
}
2532

26-
// example
27-
28-
// const array = [1, 1, 2, 2, 3, 1, 1]
29-
// const sum = 4
30-
// const result = NumberOfSubsetSum(array, sum)
31-
3233
export { NumberOfSubsetSum }
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { NumberOfSubsetSum } from '../NumberOfSubsetEqualToGivenSum'
2+
3+
describe('Testing NumberOfSubsetSum', () => {
4+
it.each([
5+
[[], 0, 1],
6+
[[], 1, 0],
7+
[[1], 2, 0],
8+
[[1, 2, 3, 4, 5], 0, 1],
9+
[[1, 1, 1, 1, 1], 5, 1],
10+
[[1, 1, 1, 1, 1], 4, 5],
11+
[[1, 2, 3, 3], 6, 3],
12+
[[10, 20, 30, 1], 31, 2],
13+
[[1, 1, 2, 2, 3, 1, 1], 4, 18]
14+
])('check with %j and %i', (arr, sum, expected) => {
15+
expect(NumberOfSubsetSum(arr, sum)).toBe(expected)
16+
})
17+
18+
it.each([
19+
[[1, 2], -1],
20+
[[0, 2], 2],
21+
[[1, -1], 0]
22+
])('throws for %j and %i', (arr, sum) => {
23+
expect(() => NumberOfSubsetSum(arr, sum)).toThrowError()
24+
})
25+
})

Maths/AverageMean.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ const mean = (nums) => {
1313
throw new TypeError('Invalid Input')
1414
}
1515

16-
// This loop sums all values in the 'nums' array using forEach loop
17-
const sum = nums.reduce((sum, cur) => sum + cur, 0)
18-
19-
// Divide sum by the length of the 'nums' array.
20-
return sum / nums.length
16+
return nums.reduce((sum, cur) => sum + cur, 0) / nums.length
2117
}
2218

2319
export { mean }

Maths/test/EulerMethod.manual-test.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ function plotLine(label, points, width, height) {
1515

1616
// Chart-class from chartjs
1717
const chart = new Chart(canvas, {
18-
// eslint-disable-line
1918
type: 'scatter',
2019
data: {
2120
datasets: [

Maths/test/FindMinIterator.test.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,12 @@ describe('FindMinIterator', () => {
2222
})
2323

2424
test('given empty generator then min is undefined', () => {
25-
const src = function* () {} // eslint-disable-line
25+
const src = function* () {}
2626
expect(FindMinIterator(src())).toBeUndefined()
2727
})
2828

2929
test('given generator then min is found', () => {
3030
const src = function* () {
31-
// eslint-disable-line
3231
yield 1
3332
yield -1
3433
yield 0
@@ -38,7 +37,6 @@ describe('FindMinIterator', () => {
3837

3938
test('given string generator then min string length is found', () => {
4039
const src = function* () {
41-
// eslint-disable-line
4240
yield 'abc'
4341
yield 'de'
4442
yield 'qwerty'

Project-Euler/Problem005.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ Smallest multiple
55
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
66
*/
77

8-
export const findSmallestMultiple = () => {
9-
const divisors = [
10-
20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2
11-
]
12-
let num = 21
8+
export const findSmallestMultiple = (maxDivisor) => {
9+
const divisors = Array.from({ length: maxDivisor }, (_, i) => i + 1)
10+
let num = maxDivisor + 1
1311
let result
1412

1513
while (!result) {

Project-Euler/Problem019.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Problem 19 - Counting Sundays
3+
*
4+
* @see {@link https://projecteuler.net/problem=19}
5+
*
6+
* You are given the following information, but you may prefer to do some research for yourself.
7+
* 1 Jan 1900 was a Monday.
8+
* Thirty days has September,
9+
* April, June and November.
10+
* All the rest have thirty-one,
11+
* Saving February alone,
12+
* Which has twenty-eight, rain or shine.
13+
* And on leap years, twenty-nine.
14+
* A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
15+
* How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
16+
*
17+
* @author ddaniel27
18+
*/
19+
import { isLeapYear } from '../Maths/LeapYear'
20+
21+
function problem19() {
22+
let sundaysCount = 0 // Count of Sundays
23+
let dayOfWeek = 2 // 1st Jan 1900 was a Monday, so 1st Jan 1901 was a Tuesday
24+
25+
for (let year = 1901; year <= 2000; year++) {
26+
for (let month = 1; month <= 12; month++) {
27+
if (dayOfWeek === 0) {
28+
// If it's a Sunday (0 is Sunday, 1 is Monday, ..., 6 is Saturday)
29+
sundaysCount++
30+
}
31+
32+
let daysInMonth = 31
33+
if (month === 4 || month === 6 || month === 9 || month === 11) {
34+
// April, June, September, November
35+
daysInMonth = 30
36+
} else if (month === 2) {
37+
// February
38+
daysInMonth = isLeapYear(year) ? 29 : 28
39+
}
40+
41+
dayOfWeek = (dayOfWeek + daysInMonth) % 7 // Calculate the day of the week
42+
}
43+
}
44+
45+
return sundaysCount
46+
}
47+
48+
export { problem19 }

Project-Euler/test/Problem005.test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { expect } from 'vitest'
2+
import { findSmallestMultiple } from '../Problem005.js'
3+
4+
describe.concurrent('Find smallest multiple', () => {
5+
test.each([
6+
[10, 2520],
7+
[15, 360360],
8+
[20, 232792560]
9+
])('max divisor -> %i, smallest multiple -> %i', (a, expected) => {
10+
expect(findSmallestMultiple(a)).toBe(expected)
11+
})
12+
})

0 commit comments

Comments
 (0)