Skip to content

[pull] master from TheAlgorithms:master #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Keep GitHub Actions up to date with Dependabot...
# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
2 changes: 1 addition & 1 deletion .github/workflows/Ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: npm

- name: 📦 Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/UpdateDirectory.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: npm

- name: 📦 Install dependencies
Expand Down
20 changes: 16 additions & 4 deletions .github/workflows/UploadCoverageReport.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ name: UploadCoverageReport
- master
pull_request:

env:
REPORT_PATH: "coverage/coverage-final.json"

jobs:
UploadCoverageReport:
runs-on: ubuntu-latest
Expand All @@ -16,7 +19,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: npm

- name: Install dependencies
Expand All @@ -25,9 +28,18 @@ jobs:
- name: Generate coverage report
run: npm test -- --coverage

- name: Upload coverage to codecov
uses: codecov/codecov-action@v3
- name: Upload coverage to codecov (tokenless)
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository
uses: codecov/codecov-action@v4
with:
files: "${{ env.REPORT_PATH }}"
fail_ci_if_error: true

- name: Upload coverage to codecov (with token)
if: "! github.event.pull_request.head.repo.fork "
uses: codecov/codecov-action@v4
with:
files: "coverage/coverage-final.json"
token: ${{ secrets.CODECOV_TOKEN }}
files: "${{ env.REPORT_PATH }}"
fail_ci_if_error: true
...
4 changes: 0 additions & 4 deletions Backtracking/tests/RatInAMaze.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ describe('RatInAMaze', () => {

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

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

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

for (const value of values) {
// we deliberately want to check whether this constructor call fails or not
// eslint-disable-next-line no-new
expect(() => {
new RatInAMaze(value)
}).toThrow()
Expand Down
1 change: 0 additions & 1 deletion Backtracking/tests/Sudoku.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ const solved = [
describe('Sudoku', () => {
it('should create a valid board successfully', () => {
// we deliberately want to check whether this constructor call fails or not
// eslint-disable-next-line no-new
expect(() => {
new Sudoku(data)
}).not.toThrow()
Expand Down
38 changes: 38 additions & 0 deletions Compression/RLE.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* RLE (Run Length Encoding) is a simple form of data compression.
* The basic idea is to represent repeated successive characters as a single count and character.
* For example, the string "AAAABBBCCDAA" would be encoded as "4A3B2C1D2A".
*
* @author - [ddaniel27](https://github.com/ddaniel27)
*/

function Compress(str) {
let compressed = ''
let count = 1

for (let i = 0; i < str.length; i++) {
if (str[i] !== str[i + 1]) {
compressed += count + str[i]
count = 1
continue
}

count++
}

return compressed
}

function Decompress(str) {
let decompressed = ''
let match = [...str.matchAll(/(\d+)(\D)/g)] // match all groups of digits followed by a non-digit character

match.forEach((item) => {
let [count, char] = [item[1], item[2]]
decompressed += char.repeat(count)
})

return decompressed
}

export { Compress, Decompress }
13 changes: 13 additions & 0 deletions Compression/test/RLE.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Compress, Decompress } from '../RLE'

describe('Test RLE Compressor/Decompressor', () => {
it('Test - 1, Pass long repetitive strings', () => {
expect(Compress('AAAAAAAAAAAAAA')).toBe('14A')
expect(Compress('AAABBQQQQQFG')).toBe('3A2B5Q1F1G')
})

it('Test - 2, Pass compressed strings', () => {
expect(Decompress('14A')).toBe('AAAAAAAAAAAAAA')
expect(Decompress('3A2B5Q1F1G')).toBe('AAABBQQQQQFG')
})
})
5 changes: 4 additions & 1 deletion Conversions/HexToDecimal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
function hexToInt(hexNum) {
if (!/^[0-9A-F]+$/.test(hexNum)) {
throw new Error('Invalid hex string.')
}
const numArr = hexNum.split('') // converts number to array
return numArr.map((item, index) => {
switch (item) {
Expand Down Expand Up @@ -29,4 +32,4 @@ function hexToDecimal(hexNum) {
}, 0)
}

export { hexToInt, hexToDecimal }
export { hexToDecimal }
24 changes: 24 additions & 0 deletions Conversions/test/HexToDecimal.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { hexToDecimal } from '../HexToDecimal'

describe('Testing HexToDecimal', () => {
it.each([
['0', 0],
['1', 1],
['A', 10],
['B', 11],
['C', 12],
['D', 13],
['E', 14],
['F', 15],
['10', 16],
['859', 2137],
['4D2', 1234],
['81323ABD92', 554893491602]
])('check with %s', (hexStr, expected) => {
expect(hexToDecimal(hexStr)).toBe(expected)
})

it.each(['a', '-1', 'G', ''])('throws for %s', (hexStr) => {
expect(() => hexToDecimal(hexStr)).toThrowError()
})
})
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@
* **Timing-Functions**
* [GetMonthDays](Timing-Functions/GetMonthDays.js)
* [IntervalTimer](Timing-Functions/IntervalTimer.js)
* [ParseDate](Timing-Functions/ParseDate.js)
* **Trees**
* [BreadthFirstTreeTraversal](Trees/BreadthFirstTreeTraversal.js)
* [DepthFirstSearch](Trees/DepthFirstSearch.js)
Expand Down
1 change: 0 additions & 1 deletion Data-Structures/Array/QuickSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
*/

function QuickSelect(items, kth) {
// eslint-disable-line no-unused-vars
if (kth < 1 || kth > items.length) {
throw new RangeError('Index Out of Bound')
}
Expand Down
18 changes: 0 additions & 18 deletions Data-Structures/Queue/QueueUsing2Stacks.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,6 @@ class Queue {
return top
}
}

// display elements of the inputstack
listIn(output = (value) => console.log(value)) {
let i = 0
while (i < this.inputStack.length) {
output(this.inputStack[i])
i++
}
}

// display element of the outputstack
listOut(output = (value) => console.log(value)) {
let i = 0
while (i < this.outputStack.length) {
output(this.outputStack[i])
i++
}
}
}

export { Queue }
3 changes: 3 additions & 0 deletions Dynamic-Programming/LongestIncreasingSubsequence.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
// Return the length of the Longest Increasing Subsequence, given array x
function longestIncreasingSubsequence(x) {
const length = x.length
if (length == 0) {
return 0
}
const dp = Array(length).fill(1)

let res = 1
Expand Down
15 changes: 8 additions & 7 deletions Dynamic-Programming/NumberOfSubsetEqualToGivenSum.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
/*
Given an array of non-negative integers and a value sum,
Given an array of positive integers and a value sum,
determine the total number of the subset with sum
equal to the given sum.
*/
/*
Given solution is O(n*sum) Time complexity and O(sum) Space complexity
*/
function NumberOfSubsetSum(array, sum) {
if (sum < 0) {
throw new Error('The sum must be non-negative.')
}

if (!array.every((num) => num > 0)) {
throw new Error('All of the inputs of the array must be positive.')
}
const dp = [] // create an dp array where dp[i] denote number of subset with sum equal to i
for (let i = 1; i <= sum; i++) {
dp[i] = 0
Expand All @@ -23,10 +30,4 @@ function NumberOfSubsetSum(array, sum) {
return dp[sum]
}

// example

// const array = [1, 1, 2, 2, 3, 1, 1]
// const sum = 4
// const result = NumberOfSubsetSum(array, sum)

export { NumberOfSubsetSum }
24 changes: 24 additions & 0 deletions Dynamic-Programming/tests/LongestIncreasingSubsequence.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { longestIncreasingSubsequence } from '../LongestIncreasingSubsequence'

describe('Testing longestIncreasingSubsequence', () => {
it.each([
[[], 0],
[[1], 1],
[[2, 2], 1],
[[3, 3, 3], 1],
[[4, 4, 4, 4], 1],
[[1, 2], 2],
[[1, 2, 2, 2, 2], 2],
[[1, 0, 2], 2],
[[1, 10, 2, 30], 3],
[[5, 8, 3, 7, 9, 1], 3],
[[10, 9, 2, 5, 3, 7, 101, 18], 4],
[[10, 10, 9, 9, 2, 2, 5, 5, 3, 3, 7, 7, 101, 101, 18, 18], 4],
[[0, 1, 0, 3, 2, 3], 4],
[[1, 1, 2, 2, 2], 2],
[[1, 1, 2, 2, 2, 3, 3, 3, 3], 3],
[[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15], 6]
])('check with %j', (input, expected) => {
expect(longestIncreasingSubsequence(input)).toBe(expected)
})
})
25 changes: 25 additions & 0 deletions Dynamic-Programming/tests/NumberOfSubsetEqualToGivenSum.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { NumberOfSubsetSum } from '../NumberOfSubsetEqualToGivenSum'

describe('Testing NumberOfSubsetSum', () => {
it.each([
[[], 0, 1],
[[], 1, 0],
[[1], 2, 0],
[[1, 2, 3, 4, 5], 0, 1],
[[1, 1, 1, 1, 1], 5, 1],
[[1, 1, 1, 1, 1], 4, 5],
[[1, 2, 3, 3], 6, 3],
[[10, 20, 30, 1], 31, 2],
[[1, 1, 2, 2, 3, 1, 1], 4, 18]
])('check with %j and %i', (arr, sum, expected) => {
expect(NumberOfSubsetSum(arr, sum)).toBe(expected)
})

it.each([
[[1, 2], -1],
[[0, 2], 2],
[[1, -1], 0]
])('throws for %j and %i', (arr, sum) => {
expect(() => NumberOfSubsetSum(arr, sum)).toThrowError()
})
})
1 change: 0 additions & 1 deletion Maths/test/EulerMethod.manual-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ function plotLine(label, points, width, height) {

// Chart-class from chartjs
const chart = new Chart(canvas, {
// eslint-disable-line
type: 'scatter',
data: {
datasets: [
Expand Down
4 changes: 1 addition & 3 deletions Maths/test/FindMinIterator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ describe('FindMinIterator', () => {
})

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

test('given generator then min is found', () => {
const src = function* () {
// eslint-disable-line
yield 1
yield -1
yield 0
Expand All @@ -38,7 +37,6 @@ describe('FindMinIterator', () => {

test('given string generator then min string length is found', () => {
const src = function* () {
// eslint-disable-line
yield 'abc'
yield 'de'
yield 'qwerty'
Expand Down
Loading
Loading