From 652b89ebf43d9b1a01405fdfe31b7b65f22bd1b0 Mon Sep 17 00:00:00 2001 From: Khair Alanam Date: Fri, 24 Mar 2023 19:08:43 +0530 Subject: [PATCH 01/56] Add Remove Duplicates Problem --- L-I/0007 RemoveDuplicates/RemoveDuplicates.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 L-I/0007 RemoveDuplicates/RemoveDuplicates.js diff --git a/L-I/0007 RemoveDuplicates/RemoveDuplicates.js b/L-I/0007 RemoveDuplicates/RemoveDuplicates.js new file mode 100644 index 0000000..f0f09f2 --- /dev/null +++ b/L-I/0007 RemoveDuplicates/RemoveDuplicates.js @@ -0,0 +1,18 @@ +const RemoveDuplicates = (nums) => { + i = 1; + + size = nums.length; + + while (i < size) { + if (nums[i] === nums[i - 1]) { + nums.splice(i, 1); + size -= 1; + } else i += 1; + } + + return nums; +}; + +nums = [1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 8, 9]; + +console.log(RemoveDuplicates(nums)); From fe41be00b42147a27baded31161c7ec993ee3542 Mon Sep 17 00:00:00 2001 From: Khair Alanam Date: Fri, 24 Mar 2023 19:09:03 +0530 Subject: [PATCH 02/56] Add README for Remove Duplicates Problem --- L-I/0007 RemoveDuplicates/README.md | 60 +++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 L-I/0007 RemoveDuplicates/README.md diff --git a/L-I/0007 RemoveDuplicates/README.md b/L-I/0007 RemoveDuplicates/README.md new file mode 100644 index 0000000..c02ff34 --- /dev/null +++ b/L-I/0007 RemoveDuplicates/README.md @@ -0,0 +1,60 @@ +# Palindrome (L-I) + +## Problem + +- Write a function in JavaScript that takes a sorted array of integers as input and returns an array with unique elements + +- Example Inputs and Outputs: + +- Input: `[0, 0, 1, 1, 1, 2, 2, 3, 3, 4]` -> Output: `[ 0, 1, 2, 3, 4 ]` +- Input: `[1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 8, 9]` -> Output: `[ + 1, 2, 3, 4, + 6, 7, 8, 9 +]` + +## Solution + +```javascript +const RemoveDuplicates = (nums) => { + i = 1; + + size = nums.length; + + while (i < size) { + if (nums[i] === nums[i - 1]) { + nums.splice(i, 1); + size -= 1; + } else i += 1; + } + + return nums; +}; +``` + +## How it works + +- The function takes an array `nums` as input and returns `nums` with unique elements. + +- We initialise an index `i` to be `1` and `size` to be the length of `nums`. + +- We run a while loop whenever `i < size`. + +- if the current element at index `i` is equal to the previous element, then remove the current element from `nums` + +- If not, then increment `i` by `1`. + +- After the while loop terminates, we return the `nums` array. + +## References + +- [Leetcode](https://leetcode.com/problems/remove-duplicates-from-sorted-array/) + +## Problem Added By + +- [GitHub](https://www.github.com/khairalanam) +- [LinkedIn](https://www.linkedin.com/in/khair-alanam-b27b69221/) +- [Twitter](https://twitter.com/khair_alanam) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. From 5773c5de9dc1ff885cc68720523848de51f1b660 Mon Sep 17 00:00:00 2001 From: Khair Alanam Date: Sat, 25 Mar 2023 15:01:11 +0530 Subject: [PATCH 03/56] Add Bubble Sort Problem --- L-I/0008 BubbleSort/BubbleSort.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 L-I/0008 BubbleSort/BubbleSort.js diff --git a/L-I/0008 BubbleSort/BubbleSort.js b/L-I/0008 BubbleSort/BubbleSort.js new file mode 100644 index 0000000..de1bae0 --- /dev/null +++ b/L-I/0008 BubbleSort/BubbleSort.js @@ -0,0 +1,20 @@ +const BubbleSort = (arr) => { + for (let i = 0; i < arr.length - 1; i++) { + for (let j = 0; j < arr.length - i - 1; j++) { + if (arr[j] > arr[j + 1]) { + temp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = temp; + } + } + } +}; + +arr = [0, 4, 2, 3, 7, 3, 6, 2, 9, 10, 2, 6]; +arrOne = [45, 32, 12, 67, 86, 92, 29, 24, 53, 1, 6, 32, 56]; + +BubbleSort(arr); +BubbleSort(arrOne); + +console.log(arr); +console.log(arrOne); From 2bf811b268d49a85443619dcc1ce8cfa4b53cd14 Mon Sep 17 00:00:00 2001 From: Khair Alanam Date: Sat, 25 Mar 2023 15:01:32 +0530 Subject: [PATCH 04/56] Add README for Bubble Sort Problem --- L-I/0008 BubbleSort/README.md | 51 +++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 L-I/0008 BubbleSort/README.md diff --git a/L-I/0008 BubbleSort/README.md b/L-I/0008 BubbleSort/README.md new file mode 100644 index 0000000..989eb9c --- /dev/null +++ b/L-I/0008 BubbleSort/README.md @@ -0,0 +1,51 @@ +# 0008 BubbleSort ( L-I ) + +## Problem + +Implement a function that sorts an array in increasing order using bubble sort. + +## Testcases + +- Input: `[0, 4, 2, 3, 7, 3, 6, 2, 9, 10, 2, 6]`
+ Output: `[0, 2, 2, 2, 3, 3, 4, 6, 6, 7, 9, 10]` + +- Input: `[45, 32, 12, 67, 86, 92, 29, 24, 53, 1, 6, 32, 56]`
+ Output: `[1, 6, 12, 24, 29, 32, 32, 45, 53, 56, 67, 86, 92]` + +## Solution + +```javascript +const BubbleSort = (arr) => { + for (let i = 0; i < arr.length - 1; i++) { + for (let j = 0; j < arr.length - i - 1; j++) { + if (arr[j] > arr[j + 1]) { + temp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = temp; + } + } + } +}; +``` + +## How it works + +- The function takes an array of integers `arr` as an argument. +- The function runs a for loop in `i` until the second last element. This is due to the fact that on every iteration of the `i` loop, the last `i` elements are sorted. Therefore, running the `i` loop for the first element is unnecessary. +- The inner loop runs in `j` and will traverse `arr` from the start to the `n - i`th position since the last `i` elements are sorted. +- The function terminates with the sorted `arr`. +- The function will also work for those arrays that have duplicate elements. + +## References + +- [GeeksForGeeks](https://www.geeksforgeeks.org/bubble-sort/) + +## Problem Added By + +- [GitHub](https://www.github.com/khairalanam) +- [LinkedIn](https://www.linkedin.com/in/khair-alanam-b27b69221/) +- [Twitter](https://twitter.com/khair_alanam) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. From 19d9ba7cb88c900b99f0e148a713de0e28eccfc7 Mon Sep 17 00:00:00 2001 From: Khair Alanam Date: Sun, 26 Mar 2023 13:08:13 +0530 Subject: [PATCH 05/56] Add Valid Parentheses Problem --- L-B/0022 ValidParentheses/ValidParentheses.js | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 L-B/0022 ValidParentheses/ValidParentheses.js diff --git a/L-B/0022 ValidParentheses/ValidParentheses.js b/L-B/0022 ValidParentheses/ValidParentheses.js new file mode 100644 index 0000000..98e3334 --- /dev/null +++ b/L-B/0022 ValidParentheses/ValidParentheses.js @@ -0,0 +1,29 @@ +const ValidParentheses = (s) => { + var stack = []; + + obj = { + "(": ")", + "{": "}", + "[": "]", + }; + + for (let i of s) { + if (Object.keys(obj).includes(i)) { + stack.push(i); + } else if (stack && obj[stack[stack.length - 1]] == i) { + stack.pop(); + } else { + return false; + } + } + + return stack.length === 0 ? true : false; +}; + +s = "()"; +s1 = "()[]{}"; +s2 = "(]"; + +console.log(ValidParentheses(s)); +console.log(ValidParentheses(s1)); +console.log(ValidParentheses(s2)); From 4f7d780a50c56582852ac60807d2f2856adf2ab4 Mon Sep 17 00:00:00 2001 From: Khair Alanam Date: Sun, 26 Mar 2023 13:08:37 +0530 Subject: [PATCH 06/56] Add README for Valid Parentheses Problem --- L-B/0022 ValidParentheses/README.md | 72 +++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 L-B/0022 ValidParentheses/README.md diff --git a/L-B/0022 ValidParentheses/README.md b/L-B/0022 ValidParentheses/README.md new file mode 100644 index 0000000..d002cbf --- /dev/null +++ b/L-B/0022 ValidParentheses/README.md @@ -0,0 +1,72 @@ +# Valid Parentheses (L-B) + +## Problem + +Given a string `s` containing just the characters `'(', ')', '{', '}', '['` and `']'`, determine if the input string is valid. + +An input string is valid if: + +- Open brackets must be closed by the same type of brackets. +- Open brackets must be closed in the correct order. +- Every close bracket has a corresponding open bracket of the same type. + +## Testcases + +- Input: `"()"`
+ Output: `true` + +- Input: `"()[]{}"`
+ Output: `true` + +- Input: `"(]"`
+ Output: `false` + +## Solution + +```javascript +const ValidParentheses = (s) => { + var stack = []; + + obj = { + "(": ")", + "{": "}", + "[": "]", + }; + + for (let i of s) { + if (Object.keys(obj).includes(i)) { + stack.push(i); + } else if (stack && obj[stack[stack.length - 1]] == i) { + stack.pop(); + } else { + return false; + } + } + + return stack.length === 0 ? true : false; +}; +``` + +## How it works + +- We initialize a `stack` to keep track of the parentheses. +- We make an object `obj` which keeps the values for the corresponding opening and closing brackets. +- The function runs a for loop for the string `s`. +- If the current letter is part of the `obj`'s keys, then push the letter to the `stack`. +- Else if the stack is not empty and the top of the `stack` corresponds with the current letter, then pop an element out of the `stack`. +- Else, return `false` +- If the for loop terminates normally then return `true` if the stack is empty or else `false`. + +## References + +- [LeetCode](https://leetcode.com/problems/valid-parentheses/) + +## Problem Added By + +- [GitHub](https://www.github.com/khairalanam) +- [LinkedIn](https://www.linkedin.com/in/khair-alanam-b27b69221/) +- [Twitter](https://twitter.com/khair_alanam) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. From 18e00c91ac74df3ac0f5cebbe0d73338a748a7d1 Mon Sep 17 00:00:00 2001 From: Khair Alanam Date: Mon, 27 Mar 2023 19:23:30 +0530 Subject: [PATCH 07/56] Add Two Sum Problem --- L-I/0009 TwoSum/TwoSum.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 L-I/0009 TwoSum/TwoSum.js diff --git a/L-I/0009 TwoSum/TwoSum.js b/L-I/0009 TwoSum/TwoSum.js new file mode 100644 index 0000000..de7d57d --- /dev/null +++ b/L-I/0009 TwoSum/TwoSum.js @@ -0,0 +1,25 @@ +const TwoSum = (nums, target) => { + numToIndex = {}; + + for (let i = 0; i < nums.length; i++) { + if (target - nums[i] in numToIndex) + return [numToIndex[target - nums[i]], i]; + + numToIndex[nums[i]] = i; + } + + return []; +}; + +nums = [3, 2, 4]; +target = 6; + +nums1 = [2, 7, 11, 15]; +target1 = 9; + +nums2 = [3, 3]; +target2 = 6; + +console.log(TwoSum(nums, target)); +console.log(TwoSum(nums1, target1)); +console.log(TwoSum(nums2, target2)); From f3ac3504924564b4213e33334c8769178cd2f8da Mon Sep 17 00:00:00 2001 From: Khair Alanam Date: Mon, 27 Mar 2023 19:23:47 +0530 Subject: [PATCH 08/56] Add README for the Two Sum Problem --- L-I/0009 TwoSum/README.md | 56 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 L-I/0009 TwoSum/README.md diff --git a/L-I/0009 TwoSum/README.md b/L-I/0009 TwoSum/README.md new file mode 100644 index 0000000..59c1ed0 --- /dev/null +++ b/L-I/0009 TwoSum/README.md @@ -0,0 +1,56 @@ +# 0009 TwoSum ( L-I ) + +## Problem + +Given an array of integers `nums` and an integer `target`, return indices of the two numbers such that they add up to `target`. + +## Testcases + +- Input: `nums = [3, 2, 4], target = 6`
+ Output: `[1, 2]` + +- Input: `nums = [2, 7, 11, 15], target = 9`
+ Output: `[0, 1]` + +- Input: `nums = [3, 3], target = 6`
+ Output: `[0, 1]` + +## Solution + +```javascript +const TwoSum = (nums, target) => { + numToIndex = {}; + + for (let i = 0; i < nums.length; i++) { + if (target - nums[i] in numToIndex) + return [numToIndex[target - nums[i]], i]; + + numToIndex[nums[i]] = i; + } + + return []; +}; +``` + +## How it works + +- The functiont takes an array of integers `nums` and an integer `target`. +- We initialise an object `numToIndex` to push the element and its index as key-value pairs. +- The function runs a for loop for the length of `nums`. +- If the difference of `target` and the current element at `i`th index is present in the keys of `numToIndex`, then return the array that contains the element corresponding to the difference as well as the current element. +- If not present, then set the element at `i`th index to be equal to `i` for `numToIndex`. +- If the for loop terminates normally, then return an empty array. + +## References + +- [LeetCode](https://leetcode.com/problems/two-sum/) + +## Problem Added By + +- [GitHub](https://www.github.com/khairalanam) +- [LinkedIn](https://www.linkedin.com/in/khair-alanam-b27b69221/) +- [Twitter](https://twitter.com/khair_alanam) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. From 5dd3315d720f6f748d4fe2d386577ced9d45cdd9 Mon Sep 17 00:00:00 2001 From: Haris Date: Fri, 7 Apr 2023 21:02:48 +0500 Subject: [PATCH 09/56] Merge pull request from harisdev-netizen/haris PR for contributing --- L-A/0004 Candy ( L-A )/README.md | 68 ++++++++++++++++++++++++++++++++ L-A/0004 Candy ( L-A )/candy.js | 27 +++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 L-A/0004 Candy ( L-A )/README.md create mode 100644 L-A/0004 Candy ( L-A )/candy.js diff --git a/L-A/0004 Candy ( L-A )/README.md b/L-A/0004 Candy ( L-A )/README.md new file mode 100644 index 0000000..f7ec0fa --- /dev/null +++ b/L-A/0004 Candy ( L-A )/README.md @@ -0,0 +1,68 @@ +# 0004 Candy ( L-A ) + +## Problem + +There are n children standing in a line. Each child is assigned a rating value given in the integer array ratings. + +You are giving candies to these children subjected to the following requirements: +- Each child must have at least one candy. +- Children with a higher rating get more candies than their neighbors. + +Return the minimum number of candies you need to have to distribute the candies to the children. + +## Test Case + +```javascript +Input: ratings = [1,0,2] +Output: 5 +Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively. +``` + +## Solution + +```javascript +var candy = function(ratings) { + const candies = ratings.map(() => 1); + const len = ratings.length; + if (len <= 1) return len; + + for (let index = 1; index < len; index++) { + if (ratings[index] > ratings[index-1]) { + candies[index] = candies[index-1] + 1; + } + } + + let sum = candies[len-1]; + for (let index = len-2; index >= 0; index--) { + if (ratings[index] > ratings[index+1] && candies[index] <= candies[index+1]) { + candies[index] = candies[index+1] + 1; + } + sum += candies[index]; + } + + return sum; +}; +``` + +## How it works + +- Given an array of integers representing ratings of candy, the goal is to distribute minimum candies among children such that a child with a higher rating gets more candies than their neighbor with a lower rating. +- The code first initializes a new array called `candies` with the same length as the input `ratings` array, and fills it with ones. This means that initially, each child will receive at least one candy. +- Next, the code checks if the input `ratings` array has a length of 1 or less, in which case the function simply returns the length of the array. +- Then, the code loops through the input `ratings` array, starting from the second element, and compares each element to the previous element. If the current element has a higher rating than the previous element, the corresponding element in the `candies` array is updated to be one more than the previous element's value. This ensures that children with higher ratings receive more candies than their neighbors with lower ratings. +- After that, the code loops through the `candies` array again, this time starting from the second-to-last element and going backwards. For each element, the code checks if it has a higher rating than its next neighbor and if its current number of candies is less than or equal to its next neighbor's number of candies. If both conditions are true, the current element's number of candies is updated to be one more than its next neighbor's number of candies. This makes sure that the distribution of candies is optimal and the minimum number of candies are used. +- Finally, the code calculates the total number of candies distributed by summing up all the elements in the `candies` array and returns the sum. + +## References + +- [LeetCode](https://leetcode.com/problems/candy/) + +## Problem Added By + +- [Haris](https://github.com/harisdev-netizen) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. diff --git a/L-A/0004 Candy ( L-A )/candy.js b/L-A/0004 Candy ( L-A )/candy.js new file mode 100644 index 0000000..1e4fa15 --- /dev/null +++ b/L-A/0004 Candy ( L-A )/candy.js @@ -0,0 +1,27 @@ +function candy(ratings) { + const candies = new Array(ratings.length).fill(1); // initialize candies array with 1 for each child + let sum = candies.reduce((acc, val) => acc + val, 0); // sum up initial candies + + // update candies for increasing ratings from left to right + for (let i = 1; i < ratings.length; i++) { + if (ratings[i] > ratings[i - 1]) { + candies[i] = candies[i - 1] + 1; + sum += candies[i] - 1; // add the extra candies used to the sum + } + } + + // update candies for decreasing ratings from right to left + for (let i = ratings.length - 2; i >= 0; i--) { + if (ratings[i] > ratings[i + 1] && candies[i] <= candies[i + 1]) { + candies[i] = candies[i + 1] + 1; + sum += candies[i] - 1; // add the extra candies used to the sum + } + } + + return sum; +} + +// We can test the function with some sample inputs +console.log(candy([1,0,2])); +console.log(candy([1,2,2])); +console.log(candy([1,3,4,5,2])); \ No newline at end of file From 8878a7f83da63af438a2a5db732bb898cfbe43a1 Mon Sep 17 00:00:00 2001 From: Haris Date: Sat, 8 Apr 2023 03:23:21 +0500 Subject: [PATCH 10/56] "added 0005 Trapping Rain Water to L-A" --- .../README.md | 68 +++++++++++++++++++ .../trappingRainWater.js | 34 ++++++++++ 2 files changed, 102 insertions(+) create mode 100644 L-A/0005 Trapping Rain Water ( L-A )/README.md create mode 100644 L-A/0005 Trapping Rain Water ( L-A )/trappingRainWater.js diff --git a/L-A/0005 Trapping Rain Water ( L-A )/README.md b/L-A/0005 Trapping Rain Water ( L-A )/README.md new file mode 100644 index 0000000..1f07cfc --- /dev/null +++ b/L-A/0005 Trapping Rain Water ( L-A )/README.md @@ -0,0 +1,68 @@ +# 0005 Trapping Rain Water ( L-A ) + +## Problem + +Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining. + +## Example 1 + +``` +Input: height = [0,1,0,2,1,0,1,3,2,1,2,1] +Output: 6 +Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. +``` + +## Solution + +```javascript +const trap = function (height) { + let ans = 0; + const size = height.length; + let leftMax = height[0]; + let rightMax = height[size - 1]; + const leftArr = new Array(size); + leftArr[0] = height[0]; + const rightArr = new Array(size); + rightArr[size - 1] = height[size - 1]; + + for (let i = 1; i < size; i++) { + leftMax = Math.max(leftMax, height[i]); + leftArr[i] = leftMax; + } + + for (let k = size - 2; k >= 0; k--) { + rightMax = Math.max(rightMax, height[k]); + rightArr[k] = rightMax; + } + + for (let j = 0; j < size; j++) { + ans += Math.max(Math.min(leftArr[j], rightArr[j]) - height[j], 0); + } + + return ans; +}; + +``` + +## How it works + +- The function `trap` takes an array of integers `height` as input and returns an integer representing the amount of water that can be trapped. +- The function initializes the variables `ans`, `size`, `leftMax`, and `rightMax` to 0, the length of the `height` array, and the maximum heights to the left and right of the array, respectively. It also initializes two arrays leftArr and rightArr to store the maximum height to the left and right of each index, respectively. +- The function then loops through the `height` array from left to right and stores the maximum height to the left of each index in the `leftArr` array using the variable `leftMax`. +- The function loops through the `height` array from right to left and stores the maximum height to the right of each index in the `rightArr` array using the variable `rightMax`. +- The function loops through the `height` array again and calculates the amount of water that can be trapped at each index by taking the minimum of the maximum heights to the left and right of the index, subtracting the height at the index, and taking the maximum with 0 to avoid negative values. The calculated value is added to the `ans` variable. +- The function returns the final `ans` value. + +## References + +- [LeetCode](https://leetcode.com/problems/trapping-rain-water/) + +## Problem Added By + +- [Haris](https://github.com/harisdev-netizen) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. diff --git a/L-A/0005 Trapping Rain Water ( L-A )/trappingRainWater.js b/L-A/0005 Trapping Rain Water ( L-A )/trappingRainWater.js new file mode 100644 index 0000000..7ade059 --- /dev/null +++ b/L-A/0005 Trapping Rain Water ( L-A )/trappingRainWater.js @@ -0,0 +1,34 @@ +/** + * @param {number[]} height - Array of heights. + * @return {number} - Amount of water that can be trapped. + */ + +const trap = function (height) { + let ans = 0; + const size = height.length; + let leftMax = height[0]; + let rightMax = height[size - 1]; + const leftArr = new Array(size); + leftArr[0] = height[0]; + const rightArr = new Array(size); + rightArr[size - 1] = height[size - 1]; + + // Calculate the maximum height to the left of each index and store it in the leftArr. + for (let i = 1; i < size; i++) { + leftMax = Math.max(leftMax, height[i]); + leftArr[i] = leftMax; + } + + // Calculate the maximum height to the right of each index and store it in the rightArr. + for (let k = size - 2; k >= 0; k--) { + rightMax = Math.max(rightMax, height[k]); + rightArr[k] = rightMax; + } + + // Calculate the amount of water that can be trapped at each index and add it to the answer. + for (let j = 0; j < size; j++) { + ans += Math.max(Math.min(leftArr[j], rightArr[j]) - height[j], 0); + } + + return ans; +}; From 6d37427982260287d456b6e0a5c2e3eda569ede8 Mon Sep 17 00:00:00 2001 From: Haris Date: Sun, 9 Apr 2023 05:47:15 +0500 Subject: [PATCH 11/56] added 0006 Wild Card Matching (L-A) --- L-A/0006 Wild Card Matching ( L-A )/README.md | 68 +++++++++++++++++++ .../wildCardMatching.js | 32 +++++++++ 2 files changed, 100 insertions(+) create mode 100644 L-A/0006 Wild Card Matching ( L-A )/README.md create mode 100644 L-A/0006 Wild Card Matching ( L-A )/wildCardMatching.js diff --git a/L-A/0006 Wild Card Matching ( L-A )/README.md b/L-A/0006 Wild Card Matching ( L-A )/README.md new file mode 100644 index 0000000..9359c03 --- /dev/null +++ b/L-A/0006 Wild Card Matching ( L-A )/README.md @@ -0,0 +1,68 @@ +# 0005 Trapping Rain Water ( L-A ) + +## Problem + +Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining. + +## Example 1 + +``` +Input: s = "aa", p = "a" +Output: false +Explanation: "a" does not match the entire string "aa". +``` + +## Solution + +```javascript +function isMatch(s, p) { + const memo = {}; + return dp(0, 0, memo); + + function dp(i, j, memo) { + const key = `${i}-${j}`; + + if (memo.hasOwnProperty(key)) { + return memo[key]; + } + + if (j === p.length) { + return i === s.length; + } + + const firstMatch = i < s.length && (p[j] === s[i] || p[j] === "?"); + + if (p[j] === "*") { + memo[key] = + dp(i, j + 1, memo) || + (firstMatch && dp(i + 1, j, memo)); + } else { + memo[key] = firstMatch && dp(i + 1, j + 1, memo); + } + + return memo[key]; + } +} + +``` + +## How it works +- This solution uses dynamic programming with memoization to efficiently solve the problem. The `dp` function takes two indices (`i` and `j`) to represent the current positions in the string `s` and pattern `p`, respectively, as well as a memoization object (`memo`) to store previous results. +- The base cases for the recursion are when the pattern is empty (`j === p.length`) and the string is empty (`i === s.length`). In this case, the function returns `true` if the string is empty as well, and ``false` otherwise. +- If the current character in the pattern is a wildcard (`'*'`), there are two possibilities: either the wildcard matches 0 characters (in which case we move to the next character in the pattern by calling `dp(i, j + 1, memo)`), or the wildcard matches 1 or more characters (in which case we move to the next character in the string by calling `dp(i + 1, j, memo)` if there is a match at the current position). We use the `||` operator to combine these two possibilities, and memoize the result. +- If the current character in the pattern is not a wildcard, we check if there is a match at the current position (`firstMatch = i < s.length && (p[j] === s[i] || p[j] === '?')`). If there is a match, we move to the next character in both the string and the pattern by calling `dp(i + 1, j + 1, memo)`. We memoize the result and return it. +- At the end, we call the `dp` function with the initial indices (`0` and `0`) and the memoization object. The result of the function represents whether the string matches the pattern. + +## References + +- [LeetCode](https://leetcode.com/problems/wildcard-matching/) + +## Problem Added By + +- [Haris](https://github.com/harisdev-netizen) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. diff --git a/L-A/0006 Wild Card Matching ( L-A )/wildCardMatching.js b/L-A/0006 Wild Card Matching ( L-A )/wildCardMatching.js new file mode 100644 index 0000000..abd044b --- /dev/null +++ b/L-A/0006 Wild Card Matching ( L-A )/wildCardMatching.js @@ -0,0 +1,32 @@ +function isMatch(s, p) { + const memo = {}; // memoization object to store previous results + return dp(0, 0, memo); + + function dp(i, j, memo) { + const key = `${i}-${j}`; // key to store and retrieve memoization results + + if (memo.hasOwnProperty(key)) { + // check if result has already been computed + return memo[key]; + } + + if (j === p.length) { + // if pattern is empty, string must also be empty + return i === s.length; + } + + const firstMatch = i < s.length && (p[j] === s[i] || p[j] === "?"); + + if (p[j] === "*") { + // if current character is wildcard + memo[key] = + dp(i, j + 1, memo) || // match 0 characters + (firstMatch && dp(i + 1, j, memo)); // match 1 or more characters + } else { + // if current character is not a wildcard + memo[key] = firstMatch && dp(i + 1, j + 1, memo); // match current characters + } + + return memo[key]; + } +} From f18425f290f298922d9a5b7f0c6cefc84539e171 Mon Sep 17 00:00:00 2001 From: Haris Date: Tue, 11 Apr 2023 00:56:26 +0500 Subject: [PATCH 12/56] added 0007 Skyline Problem --- L-A/0007 The Skyline Problem/README.md | 91 +++++++++++++++++++++++ L-A/0007 The Skyline Problem/skyline.js | 97 +++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 L-A/0007 The Skyline Problem/README.md create mode 100644 L-A/0007 The Skyline Problem/skyline.js diff --git a/L-A/0007 The Skyline Problem/README.md b/L-A/0007 The Skyline Problem/README.md new file mode 100644 index 0000000..989e16d --- /dev/null +++ b/L-A/0007 The Skyline Problem/README.md @@ -0,0 +1,91 @@ +# 0005 Trapping Rain Water ( L-A ) + +## Problem + +A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Given the locations and heights of all the buildings, return the skyline formed by these buildings collectively. + +The geometric information of each building is given in the array `buildings` where `buildings[i] = [lefti, righti, heighti]`: + +- `lefti` is the x coordinate of the left edge of the ith building. +- `righti` is the x coordinate of the right edge of the ith building. +- `heighti` is the height of the ith building. + +You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0. + +## Example 1 + +``` +Input: buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]] +Output: [[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]] +Explanation: +Figure A shows the buildings of the input. +Figure B shows the skyline formed by those buildings. The red points in figure B represent the key points in the output list. +``` + +## Solution Pseudocode + +```javascript +Function getSkyline(buildings): + // base case + if (length(buildings) == 1): + return [(buildings[0].left, buildings[0].height), (buildings[0].right, 0)] + + // divide the buildings into two groups + mid = length(buildings) // 2 + left = getSkyline(buildings[:mid]) + right = getSkyline(buildings[mid:]) + + // merge the two groups + return merge(left, right) + +Function merge(left, right): + // initialize the pointers and the result array + i, j = 0, 0 + result = [] + left_height, right_height = 0, 0 + // merge the two lists + while (i < len(left) and j < len(right)): + if (left[i][0] < right[j][0]): + x = left[i][0] + left_height = left[i][1] + height = max(left_height, right_height) + result.append((x, height)) + i += 1 + else: + x = right[j][0] + right_height = right[j][1] + height = max(left_height, right_height) + result.append((x, height)) + j += 1 + // append the remaining points from left or right + while (i < len(left)): + result.append(left[i]) + i += 1 + while (j < len(right)): + result.append(right[j]) + j += 1 + + return result + +``` + +## How it works +- The `getSkyline` function is the main function that takes in a list of buildings as input and returns the skyline as a list of points. The function first checks if there is only one building in the list, in which case it returns two points representing the left and right boundaries of the building. +- If there are more than one building in the list, the function recursively divides the buildings into two groups using the midpoint, and calls itself on each group. The results from the two recursive calls are then merged using the `merge` function. +- The `merge` function takes in two lists of points representing the skylines of the left and right groups and merges them into a single list. The function initializes two pointers, `i` and `j`, to 0 and sets `left_height` and `right_height` to 0. The `result` array is used to store the merged skyline. +- The function then uses a while loop to iterate over the two input lists. At each iteration, it compares the x-coordinates of the points at the current positions of the two pointers. If the x-coordinate of the point in the left list is less than the x-coordinate of the point in the right list, it means that the left building is closer to the viewer, so the function uses the left building's height to update the `left_height` variable and calculates the maximum height between `left_height` and `right_height`. The function then appends a new point with the x-coordinate and maximum height to the `result` array, and increments the `i` pointer. +- If the x-coordinate of the point in the right list is less than or equal to the x-coordinate of the point in the left list, it means that the right building is closer to the viewer, so the function uses the right building's height to update the `right_height` variable + +## References + +- [LeetCode](https://leetcode.com/problems/the-skyline-problem/) + +## Problem Added By + +- [Haris](https://github.com/harisdev-netizen) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. diff --git a/L-A/0007 The Skyline Problem/skyline.js b/L-A/0007 The Skyline Problem/skyline.js new file mode 100644 index 0000000..71c2563 --- /dev/null +++ b/L-A/0007 The Skyline Problem/skyline.js @@ -0,0 +1,97 @@ +class Heap { + constructor(compareFunc) { + this.compare = compareFunc || ((a, b) => a - b); + this.elements = []; + } + + get size() { + return this.elements.length; + } + + get top() { + return this.elements[0]; + } + + push(element) { + this.elements.push(element); + this.heapifyUp(); + } + + pop() { + const top = this.elements[0]; + const bottom = this.elements.pop(); + if (this.elements.length > 0) { + this.elements[0] = bottom; + this.heapifyDown(); + } + return top; + } + + heapifyUp() { + let current = this.elements.length - 1; + while (current > 0) { + const parent = Math.floor((current - 1) / 2); + if (this.compare(this.elements[current], this.elements[parent]) < 0) { + [this.elements[current], this.elements[parent]] = [this.elements[parent], this.elements[current]]; + current = parent; + } else { + break; + } + } + } + + heapifyDown() { + let current = 0; + while (current < this.elements.length) { + let child = null; + const left = current * 2 + 1; + const right = current * 2 + 2; + if (left < this.elements.length && this.compare(this.elements[left], this.elements[current]) < 0) { + child = left; + } + if (right < this.elements.length && this.compare(this.elements[right], this.elements[current]) < 0 + && this.compare(this.elements[right], this.elements[left]) < 0) { + child = right; + } + if (child !== null) { + [this.elements[current], this.elements[child]] = [this.elements[child], this.elements[current]]; + current = child; + } else { + break; + } + } + } +} + +function getSkyline(buildings) { + const n = buildings.length; + const criticalPoints = new Heap((a, b) => a[0] !== b[0] ? a[0] - b[0] : b[1] - a[1]); + for (let i = 0; i < n; i++) { + const [left, right, height] = buildings[i]; + criticalPoints.push([left, -height, i]); + criticalPoints.push([right, height, i]); + } + const activeBuildings = new Heap((a, b) => b[1] - a[1]); + const skyline = [[0, 0]]; + while (criticalPoints.size > 0) { + const [x, h, i] = criticalPoints.top; + const isStart = h < 0; + const height = Math.abs(h); + if (isStart) { + activeBuildings.push([buildings[i][2], buildings[i][1]]); + } else { + activeBuildings.elements.forEach(([ah, ar], j) => { + if (j === i) { + activeBuildings.elements[j] = activeBuildings.elements[activeBuildings.size - 1]; + activeBuildings.elements.pop(); + activeBuildings.heapifyDown(); + return; + } + if (ar > buildings[i][0]) { + skyline.push([x, Math.min(height, ah)]); + if (ar > buildings[i][1]) { + activeBuildings.elements[j][1] = buildings[i][1]; + activeBuildings.heapifyDown(); + } + } + }); From d72e3fdce658ab158adc35e23e56e5a964cb6a82 Mon Sep 17 00:00:00 2001 From: Haris Date: Fri, 14 Apr 2023 00:10:28 +0500 Subject: [PATCH 13/56] added 0008 Longest Common Subsequence to ( L-A ) --- .../README.md | 83 +++++++++++++++++++ .../longestCommonSubsequence.js | 54 ++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 L-A/0008 Longest Common Subsequence ( L-A )/README.md create mode 100644 L-A/0008 Longest Common Subsequence ( L-A )/longestCommonSubsequence.js diff --git a/L-A/0008 Longest Common Subsequence ( L-A )/README.md b/L-A/0008 Longest Common Subsequence ( L-A )/README.md new file mode 100644 index 0000000..6f6eb46 --- /dev/null +++ b/L-A/0008 Longest Common Subsequence ( L-A )/README.md @@ -0,0 +1,83 @@ +# 0005 Longest Common Subsequence ( L-A ) + +## Problem + +Given two strings, find the length of their longest common subsequence (LCS). A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements. + +## Example 1 + +``` +Input: +str1 = "ABCDGH" +str2 = "AEDFHR" + +Output: +The longest common subsequence is "ADH" with a length of 3. + +Input: +str1 = "AGGTAB" +str2 = "GXTXAYB" + +Output: +The longest common subsequence is "GTAB" with a length of 4. +``` + +## Solution Pseudocode + +```javascript +function longestCommonSubsequence(str1, str2) { + const m = str1.length; + const n = str2.length; + + // Initialize a 2D array with 0 + const lcs = Array(m + 1) + .fill() + .map(() => Array(n + 1).fill(0)); + + // Fill the 2D array with LCS lengths + for (let i = 1; i <= m; i++) { + for (let j = 1; j <= n; j++) { + if (str1[i - 1] === str2[j - 1]) { + lcs[i][j] = lcs[i - 1][j - 1] + 1; + } else { + lcs[i][j] = Math.max(lcs[i - 1][j], lcs[i][j - 1]); + } + } + } + + // Return the length of LCS + return lcs[m][n]; +} + +// Example usage +const str1 = "ABCDGH"; +const str2 = "AEDFHR"; +const result = longestCommonSubsequence(str1, str2); +console.log(result); // Output: 3 + +// Another example +const str3 = "AGGTAB"; +const str4 = "GXTXAYB"; +const result2 = longestCommonSubsequence(str3, str4); +console.log(result2); // Output: 4 +``` + +## How it works + +- The code returns an object with two properties: `length`, which is the length of the longest common subsequence, and `sequence`, which is the actual subsequence itself. +- It also includes a section of code to trace back the 2D array and find the actual LCS string. +- The time complexity of this algorithm is O(mn), where m and n are the lengths of the input strings. + +## References + +- [Google](https://www.google.com/search?client=opera&q=Longest+Common+Subsequence&sourceid=opera&ie=UTF-8&oe=UTF-8) + +## Problem Added By + +- [Haris](https://github.com/harisdev-netizen) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. diff --git a/L-A/0008 Longest Common Subsequence ( L-A )/longestCommonSubsequence.js b/L-A/0008 Longest Common Subsequence ( L-A )/longestCommonSubsequence.js new file mode 100644 index 0000000..c06790d --- /dev/null +++ b/L-A/0008 Longest Common Subsequence ( L-A )/longestCommonSubsequence.js @@ -0,0 +1,54 @@ +function longestCommonSubsequence(str1, str2) { + const m = str1.length; + const n = str2.length; + + // Initialize a 2D array with 0 + const lcs = Array(m + 1) + .fill() + .map(() => Array(n + 1).fill(0)); + + // Fill the 2D array with LCS lengths + for (let i = 1; i <= m; i++) { + for (let j = 1; j <= n; j++) { + if (str1[i - 1] === str2[j - 1]) { + lcs[i][j] = lcs[i - 1][j - 1] + 1; + } else { + lcs[i][j] = Math.max(lcs[i - 1][j], lcs[i][j - 1]); + } + } + } + + // Find the LCS string by tracing back the 2D array + let i = m; + let j = n; + let lcsStr = ""; + + while (i > 0 && j > 0) { + if (str1[i - 1] === str2[j - 1]) { + lcsStr = str1[i - 1] + lcsStr; + i--; + j--; + } else if (lcs[i - 1][j] > lcs[i][j - 1]) { + i--; + } else { + j--; + } + } + + return { + length: lcs[m][n], + sequence: lcsStr, + }; +} + +// Example usage +const str1 = "ABCDGH"; +const str2 = "AEDFHR"; +const result = longestCommonSubsequence(str1, str2); +console.log(result); // Output: { length: 3, sequence: 'ADH' } + +// Another example +const str3 = "AGGTAB"; +const str4 = "GXTXAYB"; +const result2 = longestCommonSubsequence(str3, str4); +console.log(result2); // Output: { length: 4, sequence: 'GTAB' } From fd4537777520e8de8765522013ca2cc4ad64d449 Mon Sep 17 00:00:00 2001 From: Haris Date: Sun, 16 Apr 2023 00:18:55 +0500 Subject: [PATCH 14/56] Added 0009 Word Search II Problem + Made few changes to prev files --- L-A/0006 Wild Card Matching ( L-A )/README.md | 2 +- L-A/0007 The Skyline Problem/README.md | 2 +- .../README.md | 2 +- L-A/0009 Word Search II ( L-A )/README.md | 78 +++++++++++++++++++ L-A/0009 Word Search II ( L-A )/wordSearch.js | 38 +++++++++ 5 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 L-A/0009 Word Search II ( L-A )/README.md create mode 100644 L-A/0009 Word Search II ( L-A )/wordSearch.js diff --git a/L-A/0006 Wild Card Matching ( L-A )/README.md b/L-A/0006 Wild Card Matching ( L-A )/README.md index 9359c03..d788476 100644 --- a/L-A/0006 Wild Card Matching ( L-A )/README.md +++ b/L-A/0006 Wild Card Matching ( L-A )/README.md @@ -1,4 +1,4 @@ -# 0005 Trapping Rain Water ( L-A ) +# 0006 Wild Card Matching ( L-A ) ## Problem diff --git a/L-A/0007 The Skyline Problem/README.md b/L-A/0007 The Skyline Problem/README.md index 989e16d..f86fbcb 100644 --- a/L-A/0007 The Skyline Problem/README.md +++ b/L-A/0007 The Skyline Problem/README.md @@ -1,4 +1,4 @@ -# 0005 Trapping Rain Water ( L-A ) +# 0007 The Skyline Problem ( L-A ) ## Problem diff --git a/L-A/0008 Longest Common Subsequence ( L-A )/README.md b/L-A/0008 Longest Common Subsequence ( L-A )/README.md index 6f6eb46..5387f50 100644 --- a/L-A/0008 Longest Common Subsequence ( L-A )/README.md +++ b/L-A/0008 Longest Common Subsequence ( L-A )/README.md @@ -1,4 +1,4 @@ -# 0005 Longest Common Subsequence ( L-A ) +# 0008 Longest Common Subsequence ( L-A ) ## Problem diff --git a/L-A/0009 Word Search II ( L-A )/README.md b/L-A/0009 Word Search II ( L-A )/README.md new file mode 100644 index 0000000..d6625c9 --- /dev/null +++ b/L-A/0009 Word Search II ( L-A )/README.md @@ -0,0 +1,78 @@ +# 0009 Word Search II ( L-A ) + +## Problem + +Given two strings, find the length of their longest common subsequence (LCS). A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements. + +## Example 1 + +``` +Input: +str1 = "ABCDGH" +str2 = "AEDFHR" + +Output: +The longest common subsequence is "ADH" with a length of 3. + +Input: +str1 = "AGGTAB" +str2 = "GXTXAYB" + +Output: +The longest common subsequence is "GTAB" with a length of 4. +``` + +## Solution Pseudocode + +```javascript +function findWords(board, words): + result = [] + + function dfs(i, j, word, visited): + if i < 0 or j < 0 or i >= board.length or j >= board[0].length: + return + if visited[i][j]: + return + word += board[i][j] + + if words includes word: + result.push(word) + + visited[i][j] = true + + dfs(i+1, j, word, visited) + dfs(i-1, j, word, visited) + dfs(i, j+1, word, visited) + dfs(i, j-1, word, visited) + + visited[i][j] = false + + visited = new Array(board.length).fill(false).map(() => new Array(board[0].length).fill(false)) + + for i from 0 to board.length-1: + for j from 0 to board[0].length-1: + dfs(i, j, "", visited) + + return result +``` + +## How it works + +- We first define a `result` array to store the found words. Then, we define a `dfs` function that takes the current position on the board (`i` and `j`), the current word being built (`word`), and a `visited` array to keep track of visited positions. +- The function checks if the current position is out of bounds or has already been visited. If either of these conditions are true, the function returns. Otherwise, the function adds the current character to the word, and checks if the word is in the list of target words. If it is, it adds the word to the `result` array. +- The function then marks the current position as visited and performs a depth-first search on all adjacent positions. After the search is complete, the current position is marked as unvisited. +- Lastly, we create a `visited` array with the same dimensions as the board, and iterate through each position on the board, calling the `dfs` function with the initial parameters. The function returns the `result` array containing all the found words. + +## References + +- [LeetCode](https://leetcode.com/problems/word-search-ii/) + +## Problem Added By + +- [Haris](https://github.com/harisdev-netizen) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. diff --git a/L-A/0009 Word Search II ( L-A )/wordSearch.js b/L-A/0009 Word Search II ( L-A )/wordSearch.js new file mode 100644 index 0000000..527e8d7 --- /dev/null +++ b/L-A/0009 Word Search II ( L-A )/wordSearch.js @@ -0,0 +1,38 @@ +function findWords(board, words) { + const result = []; // array to store found words + + function dfs(i, j, word, visited) { + // depth-first search function + if (i < 0 || j < 0 || i >= board.length || j >= board[0].length) return; // check if position is out of bounds + if (visited[i][j]) return; // check if position has already been visited + word += board[i][j]; // add current character to current word + + if (words.includes(word)) { + // check if current word is a target word + result.push(word); // add word to result array + } + + visited[i][j] = true; // mark current position as visited + + // search adjacent positions recursively + dfs(i + 1, j, word, visited); + dfs(i - 1, j, word, visited); + dfs(i, j + 1, word, visited); + dfs(i, j - 1, word, visited); + + visited[i][j] = false; // mark current position as unvisited (backtrack) + } + + const visited = new Array(board.length) + .fill(false) + .map(() => new Array(board[0].length).fill(false)); // initialize visited array + + for (let i = 0; i < board.length; i++) { + // iterate over each position on the board + for (let j = 0; j < board[0].length; j++) { + dfs(i, j, "", visited); // perform depth-first search starting at current position + } + } + + return result; // return array of found words +} From 7a25c68c3a79164bd85727f152c58219c052807c Mon Sep 17 00:00:00 2001 From: Paternostro Date: Fri, 5 May 2023 19:29:11 -0300 Subject: [PATCH 15/56] Added Circular Arc Problem --- L-B/0023 CircularArc (L-B)/CircularArc.js | 6 +++++ L-B/0023 CircularArc (L-B)/README.md | 33 +++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 L-B/0023 CircularArc (L-B)/CircularArc.js create mode 100644 L-B/0023 CircularArc (L-B)/README.md diff --git a/L-B/0023 CircularArc (L-B)/CircularArc.js b/L-B/0023 CircularArc (L-B)/CircularArc.js new file mode 100644 index 0000000..a27022d --- /dev/null +++ b/L-B/0023 CircularArc (L-B)/CircularArc.js @@ -0,0 +1,6 @@ +function CircularArc(r, theta) { + let thetaRad = theta * (Math.PI / 180); + return thetaRad * r; +} + +CircularArc(10, 45); // Change these numbers \ No newline at end of file diff --git a/L-B/0023 CircularArc (L-B)/README.md b/L-B/0023 CircularArc (L-B)/README.md new file mode 100644 index 0000000..f8568f5 --- /dev/null +++ b/L-B/0023 CircularArc (L-B)/README.md @@ -0,0 +1,33 @@ +# CircularArc + +## Problem +Write a function that takes a radius 'r' and a angle 'theta' in DEGREES and returns the length of the circular arc. + +## Solution + +```javascript +function CircularArc(r, theta) { + let thetaRad = theta * (Math.PI / 180); + return thetaRad * r; +} +``` + +## How it works +- First we convert the angle from degrees to radians. +- Then we calculate the arc based on the angle in radians using the arc formula. + + +## References +- [Wikipedia](https://en.wikipedia.org/wiki/Circular_arc) +- [GoLinuxCloud](https://www.golinuxcloud.com/mathtoradians-javascript/) + +## Problem Added By +Same as reference, use your any social links +- [GitHub](https://github.com/paternostrox) +- [LinkedIn](https://www.linkedin.com/in/paternostrox) + + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. \ No newline at end of file From ecea3e52c96acf62d8b40d4de539aee83348395b Mon Sep 17 00:00:00 2001 From: Aneesh <90706436+007aneesh@users.noreply.github.com> Date: Thu, 11 May 2023 16:18:47 +0530 Subject: [PATCH 16/56] kadane_algo added in L-I (#51) --- L-I/0010 Kadanes_algorithm/README.md | 36 ++++++++++++++ .../kadane_algorithm.js | 49 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 L-I/0010 Kadanes_algorithm/README.md create mode 100644 L-I/0010 Kadanes_algorithm/kadane_algorithm.js diff --git a/L-I/0010 Kadanes_algorithm/README.md b/L-I/0010 Kadanes_algorithm/README.md new file mode 100644 index 0000000..dd9c6e5 --- /dev/null +++ b/L-I/0010 Kadanes_algorithm/README.md @@ -0,0 +1,36 @@ +Name : Aneesh +Github username : 007aneesh +Repository name : data-structures-and-algorithms +Problem : Kadane's algorithm in Javascript +Issue Number : #1182 +Problem statement : Given an integer array nums, find the subarray with the largest sum, and return its sum. + +Sample testcases: + +Testcase 1 --> + +Input: number of elements in array = 9 +nums = [-2,1,-3,4,-1,2,1,-5,4] +Output: 6 + +Testcase 2 --> +Input: number of elements in array +nums = [5,4,-1,7,8] +Output: 23 + +Time Complexity = O(n) +Space Complexity = O(n) + +Explanation: +This code asks the user to enter the number of elements in an array, +and then prompts them to enter each element of the array one at a time. +Once the array is complete, the code applies the Kadane's algorithm to +find the maximum sum of any subarray within the array, and then prints +the result to the console. + +Kadane's algorithm is a way of finding the maximum sum of a contiguous subarray within an array, +and it does so by keeping track of the maximum sum seen so far as it iterates through the array. +At each step, it adds the current element to a running sum, and if that sum becomes negative, +it resets the running sum to zero. If the running sum is ever greater than the maximum seen so far, +it updates the maximum. Finally, it returns the maximum sum. + diff --git a/L-I/0010 Kadanes_algorithm/kadane_algorithm.js b/L-I/0010 Kadanes_algorithm/kadane_algorithm.js new file mode 100644 index 0000000..24ba053 --- /dev/null +++ b/L-I/0010 Kadanes_algorithm/kadane_algorithm.js @@ -0,0 +1,49 @@ +// ----------------------------------------------------------------------------- code begins now! +const readline = require("readline"); + +function kadaneAlgorithm(arr) { + if (!arr) return 0; + let sum = 0; + let max = 0; + + for (let i = 0; i < arr.length; i++) { + max += arr[i]; + + if (max < 0) { + max = 0; + } + + if (sum < max) { + sum = max; + } + } + + return sum; +} + +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); + +let arr = []; + +rl.question("Enter number of elements in the array: ", function (n) { + let count = 0; + + function getArrayInput() { + if (count < n) { + rl.question("Enter element in array: ", function (input) { + arr.push(Number(input)); + count++; + getArrayInput(); + }); + } else { + let ans = kadaneAlgorithm(arr); + console.log(ans); + rl.close(); + } + } + + getArrayInput(); +}); From 7e5d18c168015639ea22ab555fc0f016f54dd440 Mon Sep 17 00:00:00 2001 From: DevvSakib Date: Thu, 5 Oct 2023 10:42:37 +0600 Subject: [PATCH 17/56] new problem added #52 --- L-B/0024 reverseGivenString/README.md | 35 +++++++++++++++++++ .../reverseGivenString.js | 13 +++++++ 2 files changed, 48 insertions(+) create mode 100644 L-B/0024 reverseGivenString/README.md create mode 100644 L-B/0024 reverseGivenString/reverseGivenString.js diff --git a/L-B/0024 reverseGivenString/README.md b/L-B/0024 reverseGivenString/README.md new file mode 100644 index 0000000..dab3bac --- /dev/null +++ b/L-B/0024 reverseGivenString/README.md @@ -0,0 +1,35 @@ +# Two-dimensional array(L-B) + +## Problem +Create a function that takes a string as input and returns the reversed version of the string without using the built-in reverse() method. + +## Solution + +```javascript +const revMyString = str => { + let revStr = ""; + const arrStr = str.split("") + for (let i = arrStr.length - 1; i >= 0; i--) revStr += arrStr[i] + return revStr; + +} +``` + +## How it works +- We split the string into an array of characters +- We loop through the array from the last index to the first index +- We add each character to the revStr variable +- We return the revStr variable + +## References +- [Wikipedia](https://en.wikipedia.org/wiki/Fizz_buzz) + +## Problem Added By +- [GitHub](https://www.github.com/devvsakib) + + + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. \ No newline at end of file diff --git a/L-B/0024 reverseGivenString/reverseGivenString.js b/L-B/0024 reverseGivenString/reverseGivenString.js new file mode 100644 index 0000000..84978eb --- /dev/null +++ b/L-B/0024 reverseGivenString/reverseGivenString.js @@ -0,0 +1,13 @@ +const revMyString = str => { + let revStr = ""; + + const arrStr = str.split("") + + for (let i = arrStr.length - 1; i >= 0; i--) revStr += arrStr[i] + + + return revStr; + +} + +console.log(revMyString("he")); \ No newline at end of file From 4f5958259d8eeb104e301bc2f8fd832d10e96315 Mon Sep 17 00:00:00 2001 From: DevvSakib Date: Thu, 5 Oct 2023 10:45:47 +0600 Subject: [PATCH 18/56] SECURITY.md --- SECURITY.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..034e848 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,21 @@ +# Security Policy + +## Supported Versions + +Use this section to tell people about which versions of your project are +currently being supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| 5.1.x | :white_check_mark: | +| 5.0.x | :x: | +| 4.0.x | :white_check_mark: | +| < 4.0 | :x: | + +## Reporting a Vulnerability + +Use this section to tell people how to report a vulnerability. + +Tell them where to go, how often they can expect to get an update on a +reported vulnerability, what to expect if the vulnerability is accepted or +declined, etc. From 45844e66b30e636e734980cde3f3790dc7e1edbd Mon Sep 17 00:00:00 2001 From: DevvSakib Date: Thu, 5 Oct 2023 10:46:25 +0600 Subject: [PATCH 19/56] coc added --- CODE_OF_CONDUCT.md | 128 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..18c9147 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. From 2a29d443434e0ecce592dbefab15d54ae0622c79 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:25:18 +0530 Subject: [PATCH 20/56] Created: README.md --- .../README.md | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 L-A/0010 Design Cancellable Function (L-A)/README.md diff --git a/L-A/0010 Design Cancellable Function (L-A)/README.md b/L-A/0010 Design Cancellable Function (L-A)/README.md new file mode 100644 index 0000000..fbcad22 --- /dev/null +++ b/L-A/0010 Design Cancellable Function (L-A)/README.md @@ -0,0 +1,74 @@ +# 2650. Design Cancellable Function +[LeetCode](https://leetcode.com/problems/design-cancellable-function/) + +Sometimes you have a long running task, and you may wish to cancel it before it completes. To help with this goal, write a function `cancellable` that accepts a generator object and returns an array of two values: a cancel function and a promise. +You may assume the generator function will only yield promises. It is your function's responsibility to pass the values resolved by the promise back to the generator. If the promise rejects, your function should throw that error back to the generator. +If the cancel callback is called before the generator is done, your function should throw an error back to the generator. That error should be the string `"Cancelled"` (Not an `Error` object). If the error was caught, the returned promise should resolve with the next value that was yielded or returned. Otherwise, the promise should reject with the thrown error. No more code should be executed. + +When the generator is done, the promise your function returned should resolve the value the generator returned. If, however, the generator throws an error, the returned promise should reject with the error. + +An example of how your code would be used: +```javascript +function* tasks() { + const val = yield new Promise(resolve => resolve(2 + 2)); + yield new Promise(resolve => setTimeout(resolve, 100)); + return val + 1; // calculation shouldn't be done. +} +const [cancel, promise] = cancellable(tasks()); +setTimeout(cancel, 50); +promise.catch(console.log); // logs "Cancelled" at t=50ms +``` +If instead `cancel()` was not called or was called after `t=100ms`, the promise would have resolved 5. + + +## Example 1: + +Input: +```javascript +generatorFunction = function*() { + return 42; +} +cancelledAt = 100 +``` +**Output:** {"resolved": 42} +**Explanation:** +```javascript +const generator = generatorFunction(); +const [cancel, promise] = cancellable(generator); +setTimeout(cancel, 100); +promise.then(console.log); // resolves 42 at t=0ms +``` +The generator immediately yields 42 and finishes. Because of that, the returned promise immediately resolves 42. Note that cancelling a finished generator does nothing. + +## Example 2: + +Input: +```javascript +generatorFunction = function*() { + const msg = yield new Promise(res => res("Hello")); + throw `Error: ${msg}`; +} +cancelledAt = null +``` +**Output:** {"rejected": "Error: Hello"} +**Explanation:** +A promise is yielded. The function handles this by waiting for it to resolve and then passes the resolved value back to the generator. Then an error is thrown which has the effect of causing the promise to reject with the same thrown error. + +## Example 3: + +Input: +```javascript +generatorFunction = function*() { + yield new Promise(res => setTimeout(res, 200)); + return "Success"; +} +cancelledAt = 100 +``` +**Output:** {"rejected": "Cancelled"} +**Explanation:** +While the function is waiting for the yielded promise to resolve, cancel() is called. This causes an error message to be sent back to the generator. Since this error is uncaught, the returned promise rejected with this error. + +## Constraints: + +`cancelledAt == null or 0 <= cancelledAt <= 1000` +`generatorFunction` returns a generator object From 71c98e4b3218631cf968e251a2328d7461562d4a Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:26:25 +0530 Subject: [PATCH 21/56] Created: Design Cancellable Function - Solution --- .../Design Cancellable Function.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 L-A/0010 Design Cancellable Function (L-A)/Design Cancellable Function.js diff --git a/L-A/0010 Design Cancellable Function (L-A)/Design Cancellable Function.js b/L-A/0010 Design Cancellable Function (L-A)/Design Cancellable Function.js new file mode 100644 index 0000000..bfe1952 --- /dev/null +++ b/L-A/0010 Design Cancellable Function (L-A)/Design Cancellable Function.js @@ -0,0 +1,22 @@ +const cancellable = (generator) => { + let cancel; + const cancelPromise = new Promise((_, reject) => { + cancel = () => reject("Cancelled"); + }); + // Every Promise rejection has to be caught. + cancelPromise.catch(() => {}); + + const promise = (async () => { + let next = generator.next(); + while (!next.done) { + try { + next = generator.next(await Promise.race([next.value, cancelPromise])); + } catch (e) { + next = generator.throw(e); + } + } + return next.value; + })(); + + return [cancel, promise]; +}; From dbe713265275b6eb41c7d311e0d5d0d0ad6526c3 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:27:27 +0530 Subject: [PATCH 22/56] Updated: README.md --- L-A/0010 Design Cancellable Function (L-A)/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/L-A/0010 Design Cancellable Function (L-A)/README.md b/L-A/0010 Design Cancellable Function (L-A)/README.md index fbcad22..ab63d50 100644 --- a/L-A/0010 Design Cancellable Function (L-A)/README.md +++ b/L-A/0010 Design Cancellable Function (L-A)/README.md @@ -30,7 +30,7 @@ generatorFunction = function*() { } cancelledAt = 100 ``` -**Output:** {"resolved": 42} +**Output:** `{"resolved": 42}`
**Explanation:** ```javascript const generator = generatorFunction(); @@ -50,7 +50,7 @@ generatorFunction = function*() { } cancelledAt = null ``` -**Output:** {"rejected": "Error: Hello"} +**Output:** `{"rejected": "Error: Hello"}`
**Explanation:** A promise is yielded. The function handles this by waiting for it to resolve and then passes the resolved value back to the generator. Then an error is thrown which has the effect of causing the promise to reject with the same thrown error. @@ -64,7 +64,7 @@ generatorFunction = function*() { } cancelledAt = 100 ``` -**Output:** {"rejected": "Cancelled"} +**Output:** `{"rejected": "Cancelled"}`
**Explanation:** While the function is waiting for the yielded promise to resolve, cancel() is called. This causes an error message to be sent back to the generator. Since this error is uncaught, the returned promise rejected with this error. From b6fd900e0f658b3b945f4ae4a2045c4c637a7ffd Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:28:20 +0530 Subject: [PATCH 23/56] Updated: README.md Corrected MarkDown Formatting --- L-A/0010 Design Cancellable Function (L-A)/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/L-A/0010 Design Cancellable Function (L-A)/README.md b/L-A/0010 Design Cancellable Function (L-A)/README.md index ab63d50..5d88b31 100644 --- a/L-A/0010 Design Cancellable Function (L-A)/README.md +++ b/L-A/0010 Design Cancellable Function (L-A)/README.md @@ -70,5 +70,5 @@ While the function is waiting for the yielded promise to resolve, cancel() is ca ## Constraints: -`cancelledAt == null or 0 <= cancelledAt <= 1000` +`cancelledAt == null or 0 <= cancelledAt <= 1000`
`generatorFunction` returns a generator object From c3e24970c1c601dd5ef2e43520090c5eb90cf7ba Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:34:13 +0530 Subject: [PATCH 24/56] Created: README.md for `Seven Boom!` --- L-B/0025 Seven Boom!/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 L-B/0025 Seven Boom!/README.md diff --git a/L-B/0025 Seven Boom!/README.md b/L-B/0025 Seven Boom!/README.md new file mode 100644 index 0000000..694f8f1 --- /dev/null +++ b/L-B/0025 Seven Boom!/README.md @@ -0,0 +1,17 @@ +# Seven Boom! +[Edabit Problem](https://edabit.com/challenge/6R6gReGTGwzpwuffD) + +Create a function that takes an array of numbers and return `"Boom!"` if the digit 7 appears in the array. Otherwise, return `"there is no 7 in the array"`. + +Examples: +```javascript +sevenBoom([1, 2, 3, 4, 5, 6, 7]) ➞ "Boom!" +// 7 contains the number seven. + +sevenBoom([8, 6, 33, 100]) ➞ "there is no 7 in the array" +// None of the items contain 7 within them. + +sevenBoom([2, 55, 60, 97, 86]) ➞ "Boom!" +// 97 contains the number seven. +``` + From 29ef0765644bef33802c17f1bd26082980ffd907 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:34:57 +0530 Subject: [PATCH 25/56] Created: Solution for SevenBoom! --- L-B/0025 Seven Boom!/SevenBoom.js | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 L-B/0025 Seven Boom!/SevenBoom.js diff --git a/L-B/0025 Seven Boom!/SevenBoom.js b/L-B/0025 Seven Boom!/SevenBoom.js new file mode 100644 index 0000000..efa2f28 --- /dev/null +++ b/L-B/0025 Seven Boom!/SevenBoom.js @@ -0,0 +1,8 @@ +function sevenBoom(arr) { + for (let i = 0; i < arr.length; i++) { + if (String(arr[i]).includes('7')) { + return 'Boom!'; + } + } + return 'there is no 7 in the array'; +} From f2f1ace1a63bf428390dba534e342800d042dc80 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:41:01 +0530 Subject: [PATCH 26/56] Created: README.md for The Fiscal Code --- L-A/0011 The Fiscal Code/README.md | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 L-A/0011 The Fiscal Code/README.md diff --git a/L-A/0011 The Fiscal Code/README.md b/L-A/0011 The Fiscal Code/README.md new file mode 100644 index 0000000..4d6b381 --- /dev/null +++ b/L-A/0011 The Fiscal Code/README.md @@ -0,0 +1,57 @@ +# The Fiscal Code +**[Edabit Solution](https://edabit.com/challenge/Pa2rHJ6KeRBTF28Pg)** + +Each person in Italy has an unique identifying ID code issued by the national tax office after the birth registration: the Fiscal Code ([Codice Fiscale](https://en.wikipedia.org/wiki/Italian_fiscal_code_card)). + +Given an object containing the personal data of a person (name, surname, gender and date of birth) return the 11 code characters as a string following these steps: + +-Generate 3 capital letters from the surname, if it has: + + - At least 3 consonants then the first three consonants are used. (Newman -> NWM). + - Less than 3 consonants then vowels will replace missing characters in the same order they appear (Fox -> FXO | Hope -> HPO). + - Less than three letters then "X" will take the third slot after the consonant and the vowel (Yu -> YUX). + +- Generate 3 capital letters from the name, if it has: + + - Exactly 3 consonants then consonants are used in the order they appear (Matt -> MTT). + - More than 3 consonants then first, third and fourth consonant are used (Samantha -> SNT | Thomas -> TMS). + - Less than 3 consonants then vowels will replace missing characters in the same order they appear (Bob -> BBO | Paula -> PLA). + - Less than three letters then "X" will take the the third slot after the consonant and the vowel (Al -> LAX). + +- Generate 2 numbers, 1 letter and 2 numbers from date of birth and gender: + + - Take the last two digits of the year of birth (1985 -> 85). + - Generate a letter corresponding to the month of birth (January -> A | December -> T) using the table for conversion included in the code. + - For males take the day of birth adding one zero at the start if is less than 10 (any 9th day -> 09 | any 20th day -> 20). + - For females take the day of birth and sum 40 to it (any 9th day -> 49 | any 20th day -> 60). + +### Examples: + +```javascipt +fiscalCode({ + name: "Matt", + surname: "Edabit", + gender: "M", + dob: "1/1/1900" +}) ➞ "DBTMTT00A01" + +fiscalCode({ + name: "Helen", + surname: "Yu", + gender: "F", + dob: "1/12/1950" +}) ➞ "YUXHLN50T41" + +fiscalCode({ + name: "Mickey", + surname: "Mouse", + gender: "M", + dob: "16/1/1928" +}) ➞ "MSOMKY28A16" +``` + +**Notes:** +- Code letters must be uppercase. +- Date of birth is given in D/M/YYYY format. +- The conversion table for months is already in the starting code. +- Y is not a vowel. From 5a2fd51ed02dd04751897b8455f0be686797052a Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:41:29 +0530 Subject: [PATCH 27/56] Updated README.md Formatting --- L-A/0011 The Fiscal Code/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/L-A/0011 The Fiscal Code/README.md b/L-A/0011 The Fiscal Code/README.md index 4d6b381..52f0dcc 100644 --- a/L-A/0011 The Fiscal Code/README.md +++ b/L-A/0011 The Fiscal Code/README.md @@ -5,7 +5,7 @@ Each person in Italy has an unique identifying ID code issued by the national ta Given an object containing the personal data of a person (name, surname, gender and date of birth) return the 11 code characters as a string following these steps: --Generate 3 capital letters from the surname, if it has: +- Generate 3 capital letters from the surname, if it has: - At least 3 consonants then the first three consonants are used. (Newman -> NWM). - Less than 3 consonants then vowels will replace missing characters in the same order they appear (Fox -> FXO | Hope -> HPO). From ec9cce24900e1d14d6c533cfa3ef9bd49cfa5a08 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:42:00 +0530 Subject: [PATCH 28/56] Updated: README.md Formatting --- L-A/0011 The Fiscal Code/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/L-A/0011 The Fiscal Code/README.md b/L-A/0011 The Fiscal Code/README.md index 52f0dcc..3465b45 100644 --- a/L-A/0011 The Fiscal Code/README.md +++ b/L-A/0011 The Fiscal Code/README.md @@ -1,5 +1,5 @@ # The Fiscal Code -**[Edabit Solution](https://edabit.com/challenge/Pa2rHJ6KeRBTF28Pg)** +**[Edabit Problem](https://edabit.com/challenge/Pa2rHJ6KeRBTF28Pg)** Each person in Italy has an unique identifying ID code issued by the national tax office after the birth registration: the Fiscal Code ([Codice Fiscale](https://en.wikipedia.org/wiki/Italian_fiscal_code_card)). From 8bff86ee5c15d43682c3eb8af946208bdc3876ed Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:43:28 +0530 Subject: [PATCH 29/56] Created: TheFiscalCode Solution --- L-A/0011 The Fiscal Code/TheFiscalCode.js | 79 +++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 L-A/0011 The Fiscal Code/TheFiscalCode.js diff --git a/L-A/0011 The Fiscal Code/TheFiscalCode.js b/L-A/0011 The Fiscal Code/TheFiscalCode.js new file mode 100644 index 0000000..f1f8a2d --- /dev/null +++ b/L-A/0011 The Fiscal Code/TheFiscalCode.js @@ -0,0 +1,79 @@ +function fiscalCode(data) { + const monthsConversion = { + '01': 'A', '02': 'B', '03': 'C', '04': 'D', '05': 'E', '06': 'H', + '07': 'L', '08': 'M', '09': 'P', '10': 'R', '11': 'S', '12': 'T' + }; + + // Helper function to generate code for names and surnames + function generateCode(name, isSurname) { + const vowels = 'AEIOU'; + let consonants = ''; + let code = ''; + + // Helper function to check if a character is a consonant + function isConsonant(char) { + return /[BCDFGHJKLMNPQRSTVWXYZ]/.test(char); + } + + for (let i = 0; i < name.length && consonants.length < 3; i++) { + const char = name[i].toUpperCase(); + if (isConsonant(char)) { + consonants += char; + } + } + + if (consonants.length < 3) { + for (let i = 0; i < name.length && consonants.length < 3; i++) { + const char = name[i].toUpperCase(); + if (vowels.includes(char)) { + consonants += char; + } + } + } + + if (consonants.length < 3) { + consonants += 'X'.repeat(3 - consonants.length); + } + + code = consonants; + + if (isSurname) { + code += 'XXX'; + } else { + code += name.length >= 3 ? name[0] + name[2] + name[3] : name + 'XX'; + } + + return code; + } + + const surnameCode = generateCode(data.surname, true); + const nameCode = generateCode(data.name, false); + + const year = data.dob.split('/')[2].slice(-2); + const month = monthsConversion[data.dob.split('/')[1]]; + const day = (data.gender === 'F' ? 40 + parseInt(data.dob.split('/')[0]) : parseInt(data.dob.split('/')[0])).toString().padStart(2, '0'); + + return `${surnameCode}${nameCode}${year}${month}${day}`; +} + +// Examples +console.log(fiscalCode({ + name: "Matt", + surname: "Edabit", + gender: "M", + dob: "1/1/1900" +})); // ➞ "DBTMTT00A01" + +console.log(fiscalCode({ + name: "Helen", + surname: "Yu", + gender: "F", + dob: "1/12/1950" +})); // ➞ "YUXHLN50T41" + +console.log(fiscalCode({ + name: "Mickey", + surname: "Mouse", + gender: "M", + dob: "16/1/1928" +})); // ➞ "MSOMKY28A16" From f9faeea358ceafdb0116df5fbc4d58df9b000d77 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:45:52 +0530 Subject: [PATCH 30/56] Created: README.md --- L-A/0012 SVG Path Data Parser/README.md | 54 +++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 L-A/0012 SVG Path Data Parser/README.md diff --git a/L-A/0012 SVG Path Data Parser/README.md b/L-A/0012 SVG Path Data Parser/README.md new file mode 100644 index 0000000..24c40f4 --- /dev/null +++ b/L-A/0012 SVG Path Data Parser/README.md @@ -0,0 +1,54 @@ +# SVG Path Data Parser +[Edabit Problem](https://edabit.com/challenge/ysMrKPGby3FXiYtQn) + +A `` element can usually be found inside an `` element and has an attribute **d** that represents the definition of the outline of a shape. + +A brief summary about this attribute: + +It contains commands (letters) and coordinates (numbers) +All instructions are expressed as one character (e.g., a moveto is expressed as an **M**). +Superfluous white space and separators such as commas can be eliminated (e.g., M 10 10 L 20 20 contains unnecessary spaces and could be expressed more compactly as `M10 10L20 20`). +The command letter can be eliminated on subsequent commands if the same command is used multiple times in a row (e.g., you can drop the second L in `M 10 20 L 20 10 L -10 -20` and use `M 10 20 L 20 10 -10 -20` instead). + +Your job is to build a parser that will convert this string in an array of commands, where each array element is an object with the `command` letter and an array of `parameters`. + +This summary is incomplete but should get you started, for more information please refer to the W3C specification found in the resources tab. + +## Examples + +```javascript +pathDataParser("") ➞ [] + +pathDataParser("M 0 0") ➞ [{command: 'M', parameters: [0, 0]}] + +pathDataParser("M 1 1.5 L 0 1.5 0 0.5 1 0.5 0.5 0 0 0.5 1 1.5 1 0.5 0 1.5" ➞ [ + {command: "M", parameters: [1, 1.5]}, + {command: "L", parameters: [0, 1.5, 0, 0.5, 1, 0.5, 0.5, 0, 0, 0.5, 1, 1.5, 1, 0.5, 0, 1.5]} +] + +pathDataParser("M 0,1 h 1 v -1 h 1 v 1 h 1 C 2,1 3,3 1.5,3 C 0,3 1,1 0,1 z" ➞ [ + {command: "M", parameters: [0, 1]}, + {command: "h", parameters: [1]}, + {command: "v", parameters: [-1]}, + {command: "h", parameters: [1]}, + {command: "v", parameters: [1]}, + {command: "h", parameters: [1]}, + {command: "C", parameters: [2, 1, 3, 3, 1.5, 3]}, + {command: "C", parameters: [0, 3, 1, 1, 0, 1]}, + {command: "z", parameters: []} +] +``` + +## Notes: + +- Return an empty array if no commands are found (example #1) +- The z (or Z) command is the only one without parameters, in this case return an empty array (see last command of example #4) +- The parameters array contains numbers, not strings, so you'll have to convert them +- Sometimes numbers can be very compressed to save space, let's look at some examples that might trip you up: + - Decimal numbers can start with a dot: .4 is the same as 0.4 + - If a negative number comes after another number, the space is optional: 0-4 is equal to 0 -4 + - Multiple decimal numbers in a row can be very tricky, remember that a number CAN NOT have more than 1 dot, so this: 1.2.34 is actually 2 different numbers: 1.2 and 0.34 +- Some examples have commas, some do not, some have multiline strings, some are a single line, remember to take into account all valid cases! Check out the tests tab to find out more. + +## By: arindal1 +***[GitHub](https://github.com/arindal1)*** From ea76ac441c6b4c50c01f37e287665c98da5bc4ff Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:47:28 +0530 Subject: [PATCH 31/56] Created: `SVGDataParser` Solution --- .../SVGDataParser.js | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 L-A/0012 SVG Path Data Parser/SVGDataParser.js diff --git a/L-A/0012 SVG Path Data Parser/SVGDataParser.js b/L-A/0012 SVG Path Data Parser/SVGDataParser.js new file mode 100644 index 0000000..931a790 --- /dev/null +++ b/L-A/0012 SVG Path Data Parser/SVGDataParser.js @@ -0,0 +1,40 @@ +function pathDataParser(data) { + const commands = []; + let currentCommand = null; + let currentParams = []; + let currentParam = ''; + + for (let i = 0; i < data.length; i++) { + const char = data[i]; + + if (char === ' ' || char === ',') { + if (currentParam !== '') { + currentParams.push(parseFloat(currentParam)); + currentParam = ''; + } + } else if (/[a-zA-Z]/.test(char)) { + if (currentCommand !== null) { + commands.push({ command: currentCommand, parameters: currentParams }); + currentParams = []; + } + currentCommand = char; + } else { + currentParam += char; + } + } + + if (currentCommand !== null) { + if (currentParam !== '') { + currentParams.push(parseFloat(currentParam)); + } + commands.push({ command: currentCommand, parameters: currentParams }); + } + + return commands; +} + +// Examples +console.log(pathDataParser("")); +console.log(pathDataParser("M 0 0")); +console.log(pathDataParser("M 1 1.5 L 0 1.5 0 0.5 1 0.5 0.5 0 0 0.5 1 1.5 1 0.5 0 1.5")); +console.log(pathDataParser("M 0,1 h 1 v -1 h 1 v 1 h 1 C 2,1 3,3 1.5,3 C 0,3 1,1 0,1 z")); From 782f3d04dfc7f50f8c7e7c6aa1ca0004ea2829ab Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:52:04 +0530 Subject: [PATCH 32/56] Created: **Caesar's Cipher/README.md** --- L-A/0013 Caesar's Cipher/README.md | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 L-A/0013 Caesar's Cipher/README.md diff --git a/L-A/0013 Caesar's Cipher/README.md b/L-A/0013 Caesar's Cipher/README.md new file mode 100644 index 0000000..20500cc --- /dev/null +++ b/L-A/0013 Caesar's Cipher/README.md @@ -0,0 +1,34 @@ +# Caesar's Cipher +[Edabit Problem](https://edabit.com/challenge/a33jdGXkaQRtK9ZTs) + +Julius Caesar protected his confidential information by encrypting it using a cipher. Caesar's cipher (check ***Resources*** tab for more info) shifts each letter by a number of letters. If the shift takes you past the end of the alphabet, just rotate back to the front of the alphabet. In the case of a rotation by *3, w, x, y* and *z* would map to *z, a, b* and *c*. + +Create a function that takes a string *s* (text to be encrypted) and an integer *k* (the rotation factor). It should return an encrypted string. + +## Example: +```javascript +caesarCipher("middle-Outz", 2) ➞ "okffng-Qwvb" + +// m -> o +// i -> k +// d -> f +// d -> f +// l -> n +// e -> g +// - - +// O -> Q +// u -> w +// t -> v +// z -> b + +caesarCipher("Always-Look-on-the-Bright-Side-of-Life", 5) +➞ "Fqbfdx-Qttp-ts-ymj-Gwnlmy-Xnij-tk-Qnkj" + +caesarCipher("A friend in need is a friend indeed", 20) +➞ "U zlcyhx ch hyyx cm u zlcyhx chxyyx" +``` + +### Notes: All test input will be a valid ASCII string. + +## By: arindal1 +***[GitHub](https://github.com/arindal1)*** From 9fd706efe731dd3b70f25075f06ea03068b1a5cc Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:52:44 +0530 Subject: [PATCH 33/56] Updated: `Caesar's Cipher/README.md` --- L-A/0013 Caesar's Cipher/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/L-A/0013 Caesar's Cipher/README.md b/L-A/0013 Caesar's Cipher/README.md index 20500cc..ef84879 100644 --- a/L-A/0013 Caesar's Cipher/README.md +++ b/L-A/0013 Caesar's Cipher/README.md @@ -1,5 +1,5 @@ # Caesar's Cipher -[Edabit Problem](https://edabit.com/challenge/a33jdGXkaQRtK9ZTs) +[Edabit Problem](https://edabit.com/challenge/a33jdGXkaQRtK9ZTs) Julius Caesar protected his confidential information by encrypting it using a cipher. Caesar's cipher (check ***Resources*** tab for more info) shifts each letter by a number of letters. If the shift takes you past the end of the alphabet, just rotate back to the front of the alphabet. In the case of a rotation by *3, w, x, y* and *z* would map to *z, a, b* and *c*. From 64b510c9b0d0c51dfb176c566d24569df646556f Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:54:23 +0530 Subject: [PATCH 34/56] Created: Solution for `Caesar's Cipher` --- L-A/0013 Caesar's Cipher/CaesarsCipher.js | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 L-A/0013 Caesar's Cipher/CaesarsCipher.js diff --git a/L-A/0013 Caesar's Cipher/CaesarsCipher.js b/L-A/0013 Caesar's Cipher/CaesarsCipher.js new file mode 100644 index 0000000..0c46e12 --- /dev/null +++ b/L-A/0013 Caesar's Cipher/CaesarsCipher.js @@ -0,0 +1,31 @@ +function caesarCipher(str, k) { + // Helper function to shift a single character by k positions + function shiftChar(char, k) { + const isUpperCase = /[A-Z]/.test(char); + const alphabetSize = 26; + + const baseCharCode = isUpperCase ? 'A'.charCodeAt(0) : 'a'.charCodeAt(0); + const shiftedCharCode = ((char.charCodeAt(0) - baseCharCode + k) % alphabetSize + alphabetSize) % alphabetSize + baseCharCode; + + return String.fromCharCode(shiftedCharCode); + } + + let result = ''; + + for (let i = 0; i < str.length; i++) { + const char = str[i]; + + if (/[A-Za-z]/.test(char)) { + result += shiftChar(char, k); + } else { + result += char; // Non-alphabetic characters remain unchanged + } + } + + return result; +} + +// Examples +console.log(caesarCipher("middle-Outz", 2)); // ➞ "okffng-Qwvb" +console.log(caesarCipher("Always-Look-on-the-Bright-Side-of-Life", 5)); // ➞ "Fqbfdx-Qttp-ts-ymj-Gwnlmy-Xnij-tk-Qnkj" +console.log(caesarCipher("A friend in need is a friend indeed", 20)); // ➞ "U zlcyhx ch hyyx cm u zlcyhx chxyyx" From ad6d187b208354cda350632517960f95b41f3880 Mon Sep 17 00:00:00 2001 From: Femil Savaliya Date: Thu, 5 Oct 2023 12:49:47 +0000 Subject: [PATCH 35/56] add three sum problem's solution --- L-I/0011 ThreeSum/README.md | 127 ++++++++++++++++++++++++++++++++++ L-I/0011 ThreeSum/threeSum.js | 58 ++++++++++++++++ 2 files changed, 185 insertions(+) create mode 100644 L-I/0011 ThreeSum/README.md create mode 100644 L-I/0011 ThreeSum/threeSum.js diff --git a/L-I/0011 ThreeSum/README.md b/L-I/0011 ThreeSum/README.md new file mode 100644 index 0000000..b4547d9 --- /dev/null +++ b/L-I/0011 ThreeSum/README.md @@ -0,0 +1,127 @@ +# 0011 ThreeSum ( L-I ) + +## Problem +Three Sum (3SUM) + +Given an array nums of n integers, are there elements  `a, b, c`   in nums such that   `a + b + c = target` ? Find all unique triplets in the array which gives the sum is equal to  `target`  . + + + +## Solution + +```javascript +// 1. Brute Force Solution +const threeSum_brute_Force = (nums, target) => { + let result = []; + for (let i = 0; i < nums.length; i++) { + for (let j = i + 1; j < nums.length; j++) { + for (let k = j + 1; k < nums.length; k++) { + if (nums[i] + nums[j] + nums[k] === target) { + result.push([nums[i], nums[j], nums[k]]); + } + } + } + } + return result; +} + +// 2. Using a hash table +const threeSum_hash_table = (nums, target) => { + let result = []; + const hash = {}; + for (let i = 0; i < nums.length; i++) { + for (let j = i + 1; j < nums.length; j++) { + const complement = target - (nums[i] + nums[j]); + if (complement in hash) { + result.push([nums[i], nums[j], complement]); + } else { + hash[nums[j]] = true; + } + } + } + + return result; +} + +// 3. Two Pointer Technique +const threeSum_two_pointer = (nums, target) => { + let result = []; + nums.sort((a, b) => a - b); + for (let i = 0; i < nums.length - 2; i++) { + if (i > 0 && nums[i] === nums[i - 1]) continue; + let left = i + 1; + let right = nums.length - 1; + while (left < right) { + const sum = nums[i] + nums[left] + nums[right]; + if (sum === target) { + result.push([nums[i], nums[left], nums[right]]); + while (left < right && nums[left] === nums[left + 1]) left++; + while (left < right && nums[right] === nums[right - 1]) right--; + left++; + right--; + } else if (sum < target) { + left++; + } else { + right--; + } + } + } + return result; +} +``` + +## How it works +### 1. Brute Force Steps + +1. Initialize an empty array result to store the unique triplets that sum to the target value. + +2. Use three nested loops to iterate through the elements of the nums array. The outermost loop (indexed by i) iterates from the first element to the second-to-last element. + +3. The second loop (indexed by j) iterates from the element after the i-th element to the second-to-last element. + +4. The innermost loop (indexed by k) iterates from the element after the j-th element to the last element of the nums array. + +5. Within the innermost loop, check if the sum of the elements at indices i, j, and k is equal to the target value. + +6. If the sum is equal to the target, create a triplet by selecting the elements at these indices (nums[i], nums[j], nums[k]) and push it into the result array. + +7. Continue iterating through the loops to find all such triplets. + +8. Finally, return the result array containing all unique triplets that sum to the target value. + +### 2. Hash Table Steps + +1. Initialize an empty array result to store the unique triplets. +2. Create an empty hash table hash to store the values encountered in the inner loop. +3. Use two nested loops to iterate through the nums array. +4. Calculate the complement by subtracting the sum of nums[i] and nums[j] from the target. +5. Check if the complement exists in the hash table. +6. If found, add [nums[i], nums[j], complement] to the result array. +7. If not found, store nums[j] in the hash table. +8. Return the result array containing all unique triplets that sum to the target value. + +### 3. Two Pointer Technique Steps + +1. Sort the nums array in ascending order. +2. Iterate through the sorted array with a loop, selecting an element nums[i] as the first element of a potential triplet. +3. Use two pointers, left and right, to search for a pair of elements that sum up to the complement of nums[i] (i.e., target - nums[i]). +4. If found, add [nums[i], nums[left], nums[right]] to the result array, and move both pointers while skipping duplicates. +5. Continue the iteration until all unique triplets that sum to the target are found. +6. Return the result array containing all unique triplets. + + +## References +- [Wikipedia](https://en.wikipedia.org/wiki/3SUM) +- [Leetcode](https://leetcode.com/problems/3sum/) + + +## Problem Added By +- [PortFolio](https://femil-savaliya.netlify.app) +- [GitHub](https://www.github.com/Femil32) +- [LinkedIn](https://www.linkedin.com/in/femil-savaliya) + + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. \ No newline at end of file diff --git a/L-I/0011 ThreeSum/threeSum.js b/L-I/0011 ThreeSum/threeSum.js new file mode 100644 index 0000000..17cdb52 --- /dev/null +++ b/L-I/0011 ThreeSum/threeSum.js @@ -0,0 +1,58 @@ +// 1. Brute Force Solution +const threeSum_brute_Force = (nums, target) => { + let result = []; + for (let i = 0; i < nums.length; i++) { + for (let j = i + 1; j < nums.length; j++) { + for (let k = j + 1; k < nums.length; k++) { + if (nums[i] + nums[j] + nums[k] === target) { + result.push([nums[i], nums[j], nums[k]]); + } + } + } + } + return result; +} + +// 2. Using a hash table +const threeSum_hash_table = (nums, target) => { + let result = []; + const hash = {}; + for (let i = 0; i < nums.length; i++) { + for (let j = i + 1; j < nums.length; j++) { + const complement = target - (nums[i] + nums[j]); + if (complement in hash) { + result.push([nums[i], nums[j], complement]); + } else { + hash[nums[j]] = true; + } + } + } + + return result; +} + +// 3. Two Pointer Technique +const threeSum_two_pointer = (nums, target) => { + let result = []; + nums.sort((a, b) => a - b); + for (let i = 0; i < nums.length - 2; i++) { + if (i > 0 && nums[i] === nums[i - 1]) continue; + let left = i + 1; + let right = nums.length - 1; + while (left < right) { + const sum = nums[i] + nums[left] + nums[right]; + if (sum === target) { + result.push([nums[i], nums[left], nums[right]]); + while (left < right && nums[left] === nums[left + 1]) left++; + while (left < right && nums[right] === nums[right - 1]) right--; + left++; + right--; + } else if (sum < target) { + left++; + } else { + right--; + } + } + } + return result; +} \ No newline at end of file From 5dc98c26473f99dd09287ac809b1421502268367 Mon Sep 17 00:00:00 2001 From: Femil Savaliya Date: Thu, 5 Oct 2023 12:51:32 +0000 Subject: [PATCH 36/56] Initial commit From 432e7a35857545d65603f3cc0ce15f38964748e3 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:25:41 +0530 Subject: [PATCH 37/56] Create 0014 Memoize II --- L-A/0014 Memoize II | 1 + 1 file changed, 1 insertion(+) create mode 100644 L-A/0014 Memoize II diff --git a/L-A/0014 Memoize II b/L-A/0014 Memoize II new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/L-A/0014 Memoize II @@ -0,0 +1 @@ + From 3ffe7a9b43cce0127bd338770dbd306f43ff3ecd Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:32:25 +0530 Subject: [PATCH 38/56] Delete L-A/0014 Memoize II --- L-A/0014 Memoize II | 1 - 1 file changed, 1 deletion(-) delete mode 100644 L-A/0014 Memoize II diff --git a/L-A/0014 Memoize II b/L-A/0014 Memoize II deleted file mode 100644 index 8b13789..0000000 --- a/L-A/0014 Memoize II +++ /dev/null @@ -1 +0,0 @@ - From 6dcd124f2c4aa709bb1bded581891931d366dafc Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:36:12 +0530 Subject: [PATCH 39/56] Create README.md --- L-A/0014 Memoize II/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 L-A/0014 Memoize II/README.md diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/L-A/0014 Memoize II/README.md @@ -0,0 +1 @@ + From c440ce5f001edd9433d177fe13de7725ce033086 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:36:48 +0530 Subject: [PATCH 40/56] Create MemoizeII.js --- L-A/0014 Memoize II/MemoizeII.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 L-A/0014 Memoize II/MemoizeII.js diff --git a/L-A/0014 Memoize II/MemoizeII.js b/L-A/0014 Memoize II/MemoizeII.js new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/L-A/0014 Memoize II/MemoizeII.js @@ -0,0 +1 @@ + From 66972cee8fa3cf067cb2099ed0dfbf70c8ceefdb Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:37:27 +0530 Subject: [PATCH 41/56] Update README.md --- L-A/0014 Memoize II/README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index 8b13789..d6ca538 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -1 +1,26 @@ +# Memoize II +[LeetCode Problem]https://leetcode.com/problems/memoize-ii/ +Given a function fn, return a memoized version of that function. + +A memoized function is a function that will never be called twice with the same inputs. Instead it will return a cached value. + +fn can be any function and there are no constraints on what type of values it accepts. Inputs are considered identical if they are === to each other. + +## Example 1: +```javascript +Input: +getInputs = () => [[2,2],[2,2],[1,2]] +fn = function (a, b) { return a + b; } +Output: [{"val":4,"calls":1},{"val":4,"calls":1},{"val":3,"calls":2}] +Explanation: +const inputs = getInputs(); +const memoized = memoize(fn); +for (const arr of inputs) { + memoized(...arr); +} + +For the inputs of (2, 2): 2 + 2 = 4, and it required a call to fn(). +For the inputs of (2, 2): 2 + 2 = 4, but those inputs were seen before so no call to fn() was required. +For the inputs of (1, 2): 1 + 2 = 3, and it required another call to fn() for a total of 2. +``` From b4033142c23793b51b04d9e638f1bc74a7f0b65e Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:39:34 +0530 Subject: [PATCH 42/56] Update README.md --- L-A/0014 Memoize II/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index d6ca538..96174d6 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -24,3 +24,25 @@ For the inputs of (2, 2): 2 + 2 = 4, and it required a call to fn(). For the inputs of (2, 2): 2 + 2 = 4, but those inputs were seen before so no call to fn() was required. For the inputs of (1, 2): 1 + 2 = 3, and it required another call to fn() for a total of 2. ``` + +## Example 2: +```javascript +Input: +getInputs = () => [[{},{}],[{},{}],[{},{}]] +fn = function (a, b) { return ({...a, ...b}); } +Output: [{"val":{},"calls":1},{"val":{},"calls":2},{"val":{},"calls":3}] +Explanation: +Merging two empty objects will always result in an empty object. It may seem like there should only be 1 call to fn() because of cache-hits, however none of those objects are === to each other. +``` + + +## Example 3: +```javascript +Input: +getInputs = () => { const o = {}; return [[o,o],[o,o],[o,o]]; } +fn = function (a, b) { return ({...a, ...b}); } +Output: [{"val":{},"calls":1},{"val":{},"calls":1},{"val":{},"calls":1}] +Explanation: +Merging two empty objects will always result in an empty object. The 2nd and 3rd third function calls result in a cache-hit. This is because every object passed in is identical. +``` + From 3192dce42138eff151d04e56f32241837d88efc3 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:40:40 +0530 Subject: [PATCH 43/56] Update README.md --- L-A/0014 Memoize II/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index 96174d6..c5b0de5 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -46,3 +46,9 @@ Explanation: Merging two empty objects will always result in an empty object. The 2nd and 3rd third function calls result in a cache-hit. This is because every object passed in is identical. ``` +### Constraints: +```javascript +1 <= inputs.length <= 105 +0 <= inputs.flat().length <= 105 +inputs[i][j] != NaN +``` From 5604e6ba203972c7e5cd4f028ee8ec9bce528aa8 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Fri, 6 Oct 2023 00:10:27 +0530 Subject: [PATCH 44/56] Update README.md --- L-A/0014 Memoize II/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index c5b0de5..5f57e92 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -52,3 +52,18 @@ Merging two empty objects will always result in an empty object. The 2nd and 3rd 0 <= inputs.flat().length <= 105 inputs[i][j] != NaN ``` + +## Approach: +Map is perfect for storing single argument. Each consecutive argument must have cache based on previous argument, which will form a tree like structure, like this: +```javascript +fn(1,3,4) // { 1: { 3: { 4: {}}}}; +fn(1,4,3) // { 1: { 3: { 4: {}}, 4: { 3: {}}}}; +``` +The only problem, is how do we store our result. It's been never stated, that memoized function will be called with the same amount of arguments every time. We need a way to store our result anywhere on the path and also make sure that it will never be misteaken with argument. Here is example. +```javascript +fn(1,3) // { 1: { 3: 4}}; +-> 4 +fn(1) // { 1: { 3: 4}}; +-> { 3: 4 } // returning cache branch as result +``` +There are different aproaches to overcome this. But since every Symbol() call is guaranteed to return a unique Symbol we can use it to store actual result with guarantee, that it will never match any argument. From 0ab66011c21ccb39c03cfa531ce164020849de11 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Fri, 6 Oct 2023 00:21:58 +0530 Subject: [PATCH 45/56] Update MemoizeII.js --- L-A/0014 Memoize II/MemoizeII.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/L-A/0014 Memoize II/MemoizeII.js b/L-A/0014 Memoize II/MemoizeII.js index 8b13789..3d7f3c8 100644 --- a/L-A/0014 Memoize II/MemoizeII.js +++ b/L-A/0014 Memoize II/MemoizeII.js @@ -1 +1,26 @@ +const RES = Symbol("result"); + +/** + * @param {Function} fn + */ +function memoize(fn) { + const globalCache = new Map(); + + return (...params) => { + let currentCache = globalCache; + for(const param of params) { + if (!currentCache.has(param)) { + currentCache.set(param, new Map()); + } + currentCache = currentCache.get(param); + } + + if (currentCache.has(RES)) return currentCache.get(RES); + + const result = fn(...params); + + currentCache.set(RES, result); + return result; + } +} From 08f1ca8ad71488c17072cab1d9fa14da7af9e6af Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Fri, 6 Oct 2023 00:23:56 +0530 Subject: [PATCH 46/56] Update README.md --- L-A/0014 Memoize II/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index 5f57e92..40aa91a 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -67,3 +67,7 @@ fn(1) // { 1: { 3: 4}}; -> { 3: 4 } // returning cache branch as result ``` There are different aproaches to overcome this. But since every Symbol() call is guaranteed to return a unique Symbol we can use it to store actual result with guarantee, that it will never match any argument. + +## Problem Added By + +-[deveshidwivedi](https://github.com/deveshidwivedi) From 5394024c2759ce916b20e3fcdc2c4a038cfdf8b7 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Fri, 6 Oct 2023 00:24:24 +0530 Subject: [PATCH 47/56] Update README.md --- L-A/0014 Memoize II/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index 40aa91a..e46913d 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -70,4 +70,4 @@ There are different aproaches to overcome this. But since every Symbol() call is ## Problem Added By --[deveshidwivedi](https://github.com/deveshidwivedi) +- [deveshidwivedi](https://github.com/deveshidwivedi) From 457427281727b74bc00ef629542d6aa18bd33ba6 Mon Sep 17 00:00:00 2001 From: DevvSakib Date: Fri, 6 Oct 2023 10:41:59 +0600 Subject: [PATCH 48/56] Update README.md --- L-A/0014 Memoize II/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index e46913d..5e046c3 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -71,3 +71,10 @@ There are different aproaches to overcome this. But since every Symbol() call is ## Problem Added By - [deveshidwivedi](https://github.com/deveshidwivedi) + + + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. From 51947b2ba91ec4550d41257615ee65fad4fbcbfe Mon Sep 17 00:00:00 2001 From: himanshukoshti Date: Fri, 6 Oct 2023 22:54:51 +0530 Subject: [PATCH 49/56] longest valid parentheses --- .../LongestValidParentheses.js | 8 +++ L-A/0015 Longest Valid Parentheses/README.md | 60 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 L-A/0015 Longest Valid Parentheses/LongestValidParentheses.js create mode 100644 L-A/0015 Longest Valid Parentheses/README.md diff --git a/L-A/0015 Longest Valid Parentheses/LongestValidParentheses.js b/L-A/0015 Longest Valid Parentheses/LongestValidParentheses.js new file mode 100644 index 0000000..b19384a --- /dev/null +++ b/L-A/0015 Longest Valid Parentheses/LongestValidParentheses.js @@ -0,0 +1,8 @@ +var longestValidParentheses = function(S) { + let stack = [-1], ans = 0 + for (let i = 0; i < S.length; i++) + if (S[i] === '(') stack.push(i) + else if (stack.length === 1) stack[0] = i + else stack.pop(), ans = Math.max(ans, i - stack[stack.length-1]) + return ans +}; \ No newline at end of file diff --git a/L-A/0015 Longest Valid Parentheses/README.md b/L-A/0015 Longest Valid Parentheses/README.md new file mode 100644 index 0000000..60a6ddb --- /dev/null +++ b/L-A/0015 Longest Valid Parentheses/README.md @@ -0,0 +1,60 @@ +# Longest Valid Parentheses +[LeetCode Problem]https://leetcode.com/problems/longest-valid-parentheses/description/ + +Given a string containing just the characters '(' and ')', return the length of the longest valid (well-formed) parentheses substring. + +## Example 1 +``` +Input: s = "(()" +Output: 2 +Explanation: The longest valid parentheses substring is "()". +``` + +## Example 2: +``` +Input: s = ")()())" +Output: 4 +Explanation: The longest valid parentheses substring is "()()". +``` + +## Example 3: +``` +Input: s = "" +Output: 0 +``` + +### Constraints: +```javascript +0 <= s.length <= 3 * 104 +s[i] is '(', or ')' +``` + +## Approach: +One of the key things to realize about valid parentheses strings is that they're entirely self-satisfied, meaning that while you can have one substring that is entirely inside another, you can't have two substrings that only partially overlap. + +This means that we can use a greedy O(N) time complexity solution to this problem without the need for any kind of backtracking. In fact, we should be able to use a very standard stack-based valid parentheses string algorithm with just three very minor modifications. + +In a stadard valid parentheses string algorithm, we iterate through the string (S) and push the index (i) of any '(' to our stack. Whenever we find a ')', we match it with the last entry on the stack and pop said entry off. We know the string is not valid if we find a ')' while there are no '(' indexes in the stack with which to match it, and also if we have leftover '(' in the stack when we reach the end of S. + +For this problem, we will need to add in a step that updates our answer (ans) when we close a parentheses pair. Since we stored the index of the '(' in our stack, we can easily find the difference between the ')' at i and the last entry in the stack, which should be the length of the valid substring which was just closed. + +But here we run into a problem, because consecutive valid substrings can be grouped into a larger valid substring (ie, '()()' = 4). So instead of counting from the last stack entry, we should actually count from the second to last entry, to include any other valid closed substrings since the most recent '(' that will still remain after we pop the just-matched last stack entry off. + +This, of course, brings us to the second and third changes. Since we're checking the second to last stack entry, what happens in the case of '()()' when you close the second valid substring yet there's only the one stack entry left at the time? + +To avoid this issue, we can just wrap the entire string in another imaginary set of parentheses by starting with stack = [-1], indicating that there's an imaginary '(' just before the beginning of the string at i = 0. + +The other issue is that we will want to continue even if the string up to i becomes invalid due to a ')' appearing when the stack is "empty", or in this case has only our imaginary index left. In that case, we can just effectively restart our stack by updating our imaginary '(' index (stack[0] = i) and continue on. + +Then, once we reach the end of S, we can just return ans. + +## Problem Added By + +- [himanshukoshti](https://github.com/himanshukoshti) + + + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. From ab7436a7360925649dff8b878494caa2761969ac Mon Sep 17 00:00:00 2001 From: Tipchan Songtheng Date: Sat, 7 Oct 2023 18:35:51 +0530 Subject: [PATCH 50/56] Add DNA_Matching problem to (L-I). --- L-I/0011 DNA_Matching/DNA_Matching.js | 22 ++++++++ L-I/0011 DNA_Matching/README.md | 78 +++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 L-I/0011 DNA_Matching/DNA_Matching.js create mode 100644 L-I/0011 DNA_Matching/README.md diff --git a/L-I/0011 DNA_Matching/DNA_Matching.js b/L-I/0011 DNA_Matching/DNA_Matching.js new file mode 100644 index 0000000..9c511b3 --- /dev/null +++ b/L-I/0011 DNA_Matching/DNA_Matching.js @@ -0,0 +1,22 @@ +function dnaMatch(dna1, dna2) { + // Check if the lengths of the two DNA sequences are different + if (dna1.length !== dna2.length) { + return false; // Different lengths, not a match + } + + // Iterate through each character of the DNA sequences + for (let i = 0; i < dna1.length; i++) { + // Compare characters at the current position + if (dna1[i] !== dna2[i]) { + return false; // Characters don't match, not a match + } + } + + // If we reach this point, all characters match, so it's a match + return true; +} + +// Test cases +console.log(dnaMatch("ACGT", "ACGT")); // true +console.log(dnaMatch("ACGT", "ACTG")); // false +console.log(dnaMatch("AACT", "AACC")); // false diff --git a/L-I/0011 DNA_Matching/README.md b/L-I/0011 DNA_Matching/README.md new file mode 100644 index 0000000..c125365 --- /dev/null +++ b/L-I/0011 DNA_Matching/README.md @@ -0,0 +1,78 @@ +# 0011 DNA_Matching ( L-I ) + +## Problem + +You are given two DNA sequences as strings, representing the genetic code of two individuals. Each DNA sequence consists of a series of characters, where each character can be one of four options: 'A' (adenine), 'C' (cytosine), 'G' (guanine), or 'T' (thymine). + +Write a JavaScript function called dnaMatch that takes these two DNA sequences as input and returns true if they are a match and false otherwise. Two DNA sequences are considered a match if they have the same characters in the same order. + +**Example** + +``` +If the input DNA sequences are "ACGT" and "ACGT", the function should return true because they are an exact match. +If the input DNA sequences are "ACGT" and "ACTG", the function should return false because the order of characters is different. +If the input DNA sequences are "AACT" and "AACC", the function should return true because some characters do not match. +``` + +**Here's an example of how the function should work:** + +```javascript +console.log(dnaMatch("ACGT", "ACGT")); // true +console.log(dnaMatch("ACGT", "ACTG")); // false +console.log(dnaMatch("AACT", "AACC")); // false +``` + +## Solutions + +```javascript +function dnaMatch(dna1, dna2) { + // Check if the lengths of the two DNA sequences are different + if (dna1.length !== dna2.length) { + return false; // Different lengths, not a match + } + + // Iterate through each character of the DNA sequences + for (let i = 0; i < dna1.length; i++) { + // Compare characters at the current position + if (dna1[i] !== dna2[i]) { + return false; // Characters don't match, not a match + } + } + + // If we reach this point, all characters match, so it's a match + return true; +} + +// Test cases +console.log(dnaMatch("ACGT", "ACGT")); // true +console.log(dnaMatch("ACGT", "ACTG")); // false +console.log(dnaMatch("AACT", "AACC")); // false +``` + +## How it works + +1. The `dnaMatch` function takes two input arguments: `dna1` and `dna2`, which are the two DNA sequences we want to compare. + +2. First, it checks if the lengths of `dna1` and `dna2` are different using the `if (dna1.length !== dna2.length)` conditional statement. If they have different lengths, the function immediately returns `false` because sequences of different lengths cannot be a match. + +3. If the lengths are the same, the function proceeds to compare the characters of the two DNA sequences. + +4. It enters a `for` loop that iterates through the characters of the sequences. The loop is controlled by the variable `i`, which starts at 0 and goes up to `dna1.length - 1`. This loop allows us to compare characters at the same position in both sequences. + +5. Inside the loop, the code compares the characters at the current position `i` using the conditional statement `if (dna1[i] !== dna2[i])`. If the characters at position `i` are not the same in both sequences, the function immediately returns `false` because it found a mismatch. + +6. If the loop completes without finding any mismatches, meaning it has compared all characters in both sequences, the function returns `true`. This indicates that the two DNA sequences are identical and, therefore, a match. + +## References + +- [ChatGPT](https://chat.openai.com/) + +## Problem Added By + +- [Tipchan](https://github.com/tsongtheng) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. From 77433078943ba5ef5c12fad3a2f1dcf40859762a Mon Sep 17 00:00:00 2001 From: Tipchan Songtheng Date: Sat, 7 Oct 2023 21:57:05 +0530 Subject: [PATCH 51/56] Add Largest Prime Palindrome to (L-A). --- .../LargestPrimePalindrome.js | 39 +++++++++ L-A/0015 Largest Prime Palindrome/README.md | 81 +++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 L-A/0015 Largest Prime Palindrome/LargestPrimePalindrome.js create mode 100644 L-A/0015 Largest Prime Palindrome/README.md diff --git a/L-A/0015 Largest Prime Palindrome/LargestPrimePalindrome.js b/L-A/0015 Largest Prime Palindrome/LargestPrimePalindrome.js new file mode 100644 index 0000000..e7e2df6 --- /dev/null +++ b/L-A/0015 Largest Prime Palindrome/LargestPrimePalindrome.js @@ -0,0 +1,39 @@ +function isPrime(num) { + if (num <= 1) { + return false; + } + if (num <= 3) { + return true; + } + if (num % 2 === 0 || num % 3 === 0) { + return false; + } + let i = 5; + while (i * i <= num) { + if (num % i === 0 || num % (i + 2) === 0) { + return false; + } + i += 6; + } + return true; +} + +function isPalindrome(num) { + const numStr = num.toString(); + const reversedStr = numStr.split("").reverse().join(""); + return numStr === reversedStr; +} + +function largestPrimePalindrome(n) { + for (let i = n; i >= 2; i--) { + if (isPrime(i) && isPalindrome(i)) { + return i; + } + } + return null; // No prime palindrome found in the range +} + +// Test cases +console.log(largestPrimePalindrome(100)); // 7 +console.log(largestPrimePalindrome(50)); // 7 +console.log(largestPrimePalindrome(10)); // 7 diff --git a/L-A/0015 Largest Prime Palindrome/README.md b/L-A/0015 Largest Prime Palindrome/README.md new file mode 100644 index 0000000..3617356 --- /dev/null +++ b/L-A/0015 Largest Prime Palindrome/README.md @@ -0,0 +1,81 @@ +# 0015 Largest Prime Palindrome ( L-A ) + +## Problem + +Write a JavaScript function called largestPrimePalindrome that takes an integer **n** as input and returns the largest prime palindrome that is less than or equal to **n**. A prime palindrome is a number that is both prime and reads the same forward and backward. + +**Example** + +``` +If the input n is 100, the function should return 7 because the largest prime palindrome less than or equal to 100 is 7. + +If the input n is 50, the function should return 7 because 7 is the largest prime palindrome less than or equal to 50. + +If the input n is 10, the function should return 7 because 7 is the largest prime palindrome less than or equal to 10. +``` + +## Solutions + +```javascript +function isPrime(num) { + if (num <= 1) { + return false; + } + if (num <= 3) { + return true; + } + if (num % 2 === 0 || num % 3 === 0) { + return false; + } + let i = 5; + while (i * i <= num) { + if (num % i === 0 || num % (i + 2) === 0) { + return false; + } + i += 6; + } + return true; +} + +function isPalindrome(num) { + const numStr = num.toString(); + const reversedStr = numStr.split("").reverse().join(""); + return numStr === reversedStr; +} + +function largestPrimePalindrome(n) { + for (let i = n; i >= 2; i--) { + if (isPrime(i) && isPalindrome(i)) { + return i; + } + } + return null; // No prime palindrome found in the range +} + +// Test cases +console.log(largestPrimePalindrome(100)); // 7 +console.log(largestPrimePalindrome(50)); // 7 +console.log(largestPrimePalindrome(10)); // 7 +``` + +## How it works + +1. The isPrime function checks whether a given number is prime using a primality test that efficiently eliminates multiples of 2 and 3 and then checks for divisibility by numbers of the form 6k ± 1. + +2. The isPalindrome function checks whether a given number is a palindrome by converting it to a string, reversing the string, and comparing it to the original string. + +3. The largestPrimePalindrome function starts from the given number n and counts down to 2, checking each number in reverse order. It uses the isPrime and isPalindrome functions to find the largest prime palindrome in the given range. + +## References + +- [ChatGPT](https://chat.openai.com/) + +## Problem Added By + +- [Tipchan](https://github.com/tsongtheng) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. From e076482c12437c4dea1226c116b443a770a149a8 Mon Sep 17 00:00:00 2001 From: Tipchan Songtheng Date: Sat, 7 Oct 2023 22:12:32 +0530 Subject: [PATCH 52/56] Add Calculate Tip to (L-B). --- L-B/0026 Calculate Tip/CalculateTip.js | 9 +++++ L-B/0026 Calculate Tip/README.md | 56 ++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 L-B/0026 Calculate Tip/CalculateTip.js create mode 100644 L-B/0026 Calculate Tip/README.md diff --git a/L-B/0026 Calculate Tip/CalculateTip.js b/L-B/0026 Calculate Tip/CalculateTip.js new file mode 100644 index 0000000..1443820 --- /dev/null +++ b/L-B/0026 Calculate Tip/CalculateTip.js @@ -0,0 +1,9 @@ +function calculateTip(totalCost, tipPercentage) { + // Calculate the tip amount by multiplying totalCost by tipPercentage divided by 100 + const tipAmount = (totalCost * tipPercentage) / 100; + return tipAmount; +} + +// Test cases +console.log(calculateTip(50, 15)); // 7.5 +console.log(calculateTip(75, 20)); // 15 diff --git a/L-B/0026 Calculate Tip/README.md b/L-B/0026 Calculate Tip/README.md new file mode 100644 index 0000000..45af127 --- /dev/null +++ b/L-B/0026 Calculate Tip/README.md @@ -0,0 +1,56 @@ +# 0026 Calculate Tip ( L-B ) + +## Problem + +You are at a restaurant, and you want to calculate the tip for your meal. Write a JavaScript function called **calculateTip** that takes two inputs: the total cost of the meal and the tip percentage.Your function should calculate the tip amount and return it. + +**Example** + +``` +If the total cost is $50 and the tip percentage is 15%, the function should return $7.5 because 15% of $50 is $7.5. + +If the total cost is $75 and the tip percentage is 20%, the function should return $15 because 20% of $75 is $15. +``` + +- **_You can assume that the tip percentage is provided as a whole number (e.g., 15 for 15%) and that the total cost is a positive number._** + +**Here's an example of how the function should work:** + +```javascript +console.log(calculateTip(50, 15)); // 7.5 +console.log(calculateTip(75, 20)); // 15 +``` + +## Solutions + +```javascript +function calculateTip(totalCost, tipPercentage) { + // Calculate the tip amount by multiplying totalCost by tipPercentage divided by 100 + const tipAmount = (totalCost * tipPercentage) / 100; + return tipAmount; +} + +// Test cases +console.log(calculateTip(50, 15)); // 7.5 +console.log(calculateTip(75, 20)); // 15 +``` + +## How it works + +1. We define a function calculateTip that takes two parameters: totalCost (the total cost of the meal) and tipPercentage (the percentage of the tip to be calculated). + +2. Inside the function, we calculate the tip amount by multiplying totalCost by tipPercentage divided by 100. This is because tip percentages are usually provided as whole numbers (e.g., 15 for 15%). + +## References + +- [ChatGPT](https://chat.openai.com/) + +## Problem Added By + +- [Tipchan](https://github.com/tsongtheng) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. From 9362b781e9cbf84a431ec05562437c2d1f3558d4 Mon Sep 17 00:00:00 2001 From: aladin002dz Date: Tue, 10 Oct 2023 14:24:30 +0100 Subject: [PATCH 53/56] get extension from a file name --- L-B/0026 FileExtension/FileExtension.js | 17 ++++++++ L-B/0026 FileExtension/FileExtension.test.js | 40 +++++++++++++++++++ L-B/0026 FileExtension/README.md | 41 ++++++++++++++++++++ L-B/0026 FileExtension/jest.config.json | 1 + 4 files changed, 99 insertions(+) create mode 100644 L-B/0026 FileExtension/FileExtension.js create mode 100644 L-B/0026 FileExtension/FileExtension.test.js create mode 100644 L-B/0026 FileExtension/README.md create mode 100644 L-B/0026 FileExtension/jest.config.json diff --git a/L-B/0026 FileExtension/FileExtension.js b/L-B/0026 FileExtension/FileExtension.js new file mode 100644 index 0000000..6987c7f --- /dev/null +++ b/L-B/0026 FileExtension/FileExtension.js @@ -0,0 +1,17 @@ +function extractFileExtension(fileName) { + // Split the file name into an array of strings at the dot character. + const splitFileName = fileName.split('.'); + + // Check if the split file name array has more than one element. + if (splitFileName.length > 1) { + // Get the last element in the array, which is the file extension. + const fileExtension = splitFileName.pop(); + + // Return the file extension. + return fileExtension; + } + // The file name does not have an extension, so return an empty string. + return ''; +} + +module.exports = extractFileExtension; diff --git a/L-B/0026 FileExtension/FileExtension.test.js b/L-B/0026 FileExtension/FileExtension.test.js new file mode 100644 index 0000000..86bdb7f --- /dev/null +++ b/L-B/0026 FileExtension/FileExtension.test.js @@ -0,0 +1,40 @@ + +const extractFileExtension = require('./FileExtension') + +describe('extractFileExtension', () => { + it('should return the file extension when given a valid file name', () => { + expect(extractFileExtension('example.txt')).toBe('txt'); + expect(extractFileExtension('document.docx')).toBe('docx'); + expect(extractFileExtension('image.jpg')).toBe('jpg'); + }); + + it('should return an empty string when given a file name without an extension', () => { + expect(extractFileExtension('README')).toBe(''); + expect(extractFileExtension('LICENSE')).toBe(''); + }); + + it('should return an empty string when given an empty string', () => { + expect(extractFileExtension('')).toBe(''); + }); +}); + +/* +test output: + PASS ./FileExtension.test.js + extractFileExtension + √ should return the file extension when given a valid file name (4 ms) + √ should return an empty string when given a file name without an extension (1 ms) + √ should return an empty string when given an empty string + +Test Suites: 1 passed, 1 total +Tests: 3 passed, 3 total +Snapshots: 0 total +Time: 0.958 s, estimated 1 s +Ran all test suites. +*/ + +/* +Testing with Jest global installation: +> npm install -g jest +> jest +*/ diff --git a/L-B/0026 FileExtension/README.md b/L-B/0026 FileExtension/README.md new file mode 100644 index 0000000..a84b3fc --- /dev/null +++ b/L-B/0026 FileExtension/README.md @@ -0,0 +1,41 @@ +# Get the file extension + +## Problem + +Write a function that takes a string and returns the file extension, which is the string after the last dot (.) in the string. If there is no dot in the string, return undefined. + +## Solution + +```javascript +function extractFileExtension(fileName) { + // Split the file name into an array of strings at the dot character. + const splitFileName = fileName.split("."); + + // Get the last element in the array, which is the file extension. + const fileExtension = splitFileName.pop(); + + // Return the file extension. + return fileExtension; +} +``` + +## How it works + +- The `extractFileExtension` function takes a string as an argument. +- The `split` method is used to split the string into an array of strings at the dot character. +- The `pop` method is used to get the last element in the array, which is the file extension. +- The file extension is returned. + +## References + +- [String.prototype.split()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split) + +## Problem Added By + +- [GitHub](https://github.com/aladin002dz) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. diff --git a/L-B/0026 FileExtension/jest.config.json b/L-B/0026 FileExtension/jest.config.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/L-B/0026 FileExtension/jest.config.json @@ -0,0 +1 @@ +{} \ No newline at end of file From 16e30ac3a712e24088044002ecc97ee809b524fd Mon Sep 17 00:00:00 2001 From: aladin002dz Date: Tue, 10 Oct 2023 14:29:56 +0100 Subject: [PATCH 54/56] FileExtension readme update --- L-B/0026 FileExtension/README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/L-B/0026 FileExtension/README.md b/L-B/0026 FileExtension/README.md index a84b3fc..d69f24a 100644 --- a/L-B/0026 FileExtension/README.md +++ b/L-B/0026 FileExtension/README.md @@ -2,7 +2,7 @@ ## Problem -Write a function that takes a string and returns the file extension, which is the string after the last dot (.) in the string. If there is no dot in the string, return undefined. +Write a function that takes a string and returns the file extension, which is the string after the last dot (.) in the string. If there is no dot in the string, return empty string. ## Solution @@ -11,11 +11,16 @@ function extractFileExtension(fileName) { // Split the file name into an array of strings at the dot character. const splitFileName = fileName.split("."); - // Get the last element in the array, which is the file extension. - const fileExtension = splitFileName.pop(); + // Check if the split file name array has more than one element. + if (splitFileName.length > 1) { + // Get the last element in the array, which is the file extension. + const fileExtension = splitFileName.pop(); - // Return the file extension. - return fileExtension; + // Return the file extension. + return fileExtension; + } + // The file name does not have an extension, so return an empty string. + return ""; } ``` From 595b53fa1dea5672e7edf1f1c69e5eb1ee3e1b01 Mon Sep 17 00:00:00 2001 From: rimsha-shoukat Date: Tue, 23 Dec 2025 20:13:50 +0500 Subject: [PATCH 55/56] remove duplicates from array/string --- L-B/0027 Remove duplicates/README.md | 62 +++++++++++++++++++ .../removeDuplicates.js | 18 ++++++ 2 files changed, 80 insertions(+) create mode 100644 L-B/0027 Remove duplicates/README.md create mode 100644 L-B/0027 Remove duplicates/removeDuplicates.js diff --git a/L-B/0027 Remove duplicates/README.md b/L-B/0027 Remove duplicates/README.md new file mode 100644 index 0000000..5e79830 --- /dev/null +++ b/L-B/0027 Remove duplicates/README.md @@ -0,0 +1,62 @@ +# 0027 removeDuplicates ( L-B ) + +## Problem +Write a function that removes duplicate values from the given input. +- If the input is an array, return a new array with unique values. +- If the input is a string, return a new string with duplicate characters removed. +- The original order must be preserved. + +## Solution +```js +function removeDuplicates(input) { + let unique = []; + for (let i = 0; i < input.length; i++) { + if (!unique.includes(input[i])) { + unique.push(input[i]); + } + } + if(typeof(input) === "string"){ + unique = unique.toString().replace(/,/g, ''); + } + console.log(unique); + return unique; +} +``` + +## Test Cases +```js +removeDuplicates([2, 4, 8, 4, 2, 6, 9, 2, 6, 8, 10]); +// Output: [2, 4, 8, 6, 9, 10] + +removeDuplicates([1, 1, 1, 4, 0, 6, -2, 2, 6, 7, 10]); +// Output: [1, 4, 0, 6, -2, 2, 7, 10] + +removeDuplicates("zoom"); +// Output: "zom" + +removeDuplicates("hello world"); +// Output: "helo wrd" +``` + +## How it works +- Create an empty array called unique +- Loop through each character or element in the input +- Check if the current value already exists in unique +- If it does not exist, we add it to unique +- After the loop: +- If the input is a string, we convert the array into a string +- Remove commas using replace +- Finally, return the result + +## References +- [MDN – Array.prototype.includes()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes) +- [MDN – typeof operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) + + +## Problem Added By +- [GitHub](https://github.com/rimsha-shoukat) + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. diff --git a/L-B/0027 Remove duplicates/removeDuplicates.js b/L-B/0027 Remove duplicates/removeDuplicates.js new file mode 100644 index 0000000..29f6dba --- /dev/null +++ b/L-B/0027 Remove duplicates/removeDuplicates.js @@ -0,0 +1,18 @@ +function removeDuplicates(input) { + let unique = []; + for (let i = 0; i < input.length; i++) { + if (!unique.includes(input[i])) { + unique.push(input[i]); + } + } + if(typeof(input) === "string"){ + unique = unique.toString().replace(/,/g, ''); + } + console.log(unique); + return unique; +} + +removeDuplicates([2, 4, 8, 4, 2, 6, 9, 2, 6, 8, 10]); +removeDuplicates([1, 1, 1, 4, 0, 6, -2, 2, 6, 7, 10]); +removeDuplicates("zoom"); +removeDuplicates("hello world"); \ No newline at end of file From 8799e77949cc48fc3a63382581b2f55d9ae9b387 Mon Sep 17 00:00:00 2001 From: rimsha-shoukat Date: Tue, 23 Dec 2025 20:16:39 +0500 Subject: [PATCH 56/56] length conveter --- L-I/0012 Length converter/README.md | 79 ++++++++++++++++++++ L-I/0012 Length converter/lengthConverter.js | 29 +++++++ 2 files changed, 108 insertions(+) create mode 100644 L-I/0012 Length converter/README.md create mode 100644 L-I/0012 Length converter/lengthConverter.js diff --git a/L-I/0012 Length converter/README.md b/L-I/0012 Length converter/README.md new file mode 100644 index 0000000..82560ba --- /dev/null +++ b/L-I/0012 Length converter/README.md @@ -0,0 +1,79 @@ +# 0012 lengthConverter ( L-I ) + +## Problem +Create a function that converts a given length value from one unit to another. +The function should: +- Accept a numeric length +- Accept a fromUnit and toUnit +- Support common metric and imperial units +- Return the converted value rounded to 5 decimal places +- Throw an error if an invalid unit is provided + +## Supported Units +- meters +- kilometers +- centimeters +- millimeters +- inches +- feet +- yards +- miles + +## Solution +```js +function lengthConverter(length, fromUnit, toUnit) { + const units = { + "meters": 1, + "kilometers": 1000, + "centimeters": 0.01, + "millimeters": 0.001, + "inches": 0.0254, + "feet": 0.3048, + "yards": 0.9144, + "miles": 1609.34 + }; + + if (!units[fromUnit] || !units[toUnit]) { + throw new Error("Invalid unit"); + } + const meters = length * units[fromUnit]; + console.log((meters / units[toUnit]).toFixed(3)); + return (meters / units[toUnit]).toFixed(3); +} +``` + +## Test Cases +```js +removeDuplicates([2, 4, 8, 4, 2, 6, 9, 2, 6, 8, 10]); +// Output: [2, 4, 8, 6, 9, 10] + +removeDuplicates([1, 1, 1, 4, 0, 6, -2, 2, 6, 7, 10]); +// Output: [1, 4, 0, 6, -2, 2, 7, 10] + +removeDuplicates("zoom"); +// Output: "zom" + +removeDuplicates("hello world"); +// Output: "helo wrd" +``` + +## How it works +- Define a units object where each unit is mapped to its value in meters +- Validate both fromUnit and toUnit +- The input length is first converted into meters +- Then we convert meters into the target unit +- The result is rounded to 5 decimal places using toFixed(5) +- Finally, the converted value is returned + +## References +- [Wikipedia – Unit conversion](https://en.wikipedia.org/wiki/Unit_conversion) +- [MDN – JavaScript Objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects) + + +## Problem Added By +- [GitHub](https://github.com/rimsha-shoukat) + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. \ No newline at end of file diff --git a/L-I/0012 Length converter/lengthConverter.js b/L-I/0012 Length converter/lengthConverter.js new file mode 100644 index 0000000..d6a78f1 --- /dev/null +++ b/L-I/0012 Length converter/lengthConverter.js @@ -0,0 +1,29 @@ +function lengthConverter(length, fromUnit, toUnit) { + const units = { + "meters": 1, + "kilometers": 1000, + "centimeters": 0.01, + "millimeters": 0.001, + "inches": 0.0254, + "feet": 0.3048, + "yards": 0.9144, + "miles": 1609.34 + }; + + if (!units[fromUnit] || !units[toUnit]) { + throw new Error("Invalid unit"); + } + + const meters = length * units[fromUnit]; + console.log((meters / units[toUnit]).toFixed(2)); + return (meters / units[toUnit]).toFixed(2); +} + +lengthConverter(100, "meters", "kilometers"); +lengthConverter(5, "miles", "feet"); +lengthConverter(12, "inches", "centimeters"); +lengthConverter(2500, "centimeters", "meters"); +lengthConverter(3, "kilometers", "miles"); +lengthConverter(10, "feet", "yards"); +lengthConverter(5000, "millimeters", "meters"); +lengthConverter(2, "yards", "inches"); \ No newline at end of file