diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40b878d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..cd17a1f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,84 @@ +# Contributing Guidelines + +This documentation contains a set of guidelines to help you during the contribution process. +We are happy to welcome all the contributions from anyone willing to improve this repository in any way possible. Thank you for helping out and remember, **no contribution is too small.** + +# How can you help?🤝 +- Add Website Resources +- Add Code Snippets +- Enhancements in the exisiting code-snippets or Notes +- More ideas are welcomed! + +# Submitting Contributions👩‍💻👨‍💻 +Below you will find the process and workflow used to review and merge your changes. +## Step 0 : Find an issue +- Take a look at the Existing Issues or create your **own** Issues! +- Wait for the Issue to be assigned to you after which you can start working on it. +- Note : Every change in this project should/must have an associated issue. + + +## Step 1 : Fork the Project +- Fork this Repository. This will create a Local Copy of this Repository on your Github Profile. Keep a reference to the original project in `upstream` remote. +``` +$ git clone https://github.com// +$ cd +$ git remote add upstream https://github.com// +``` + +- If you have already forked the project, update your copy before working. +``` +$ git remote update +$ git checkout +$ git rebase upstream/ +``` +## Step 2 : Branch +Create a new branch. Use its name to identify the issue your addressing. +``` +# It will create a new branch with name Branch_Name and switch to that branch +$ git checkout -b branch_name +``` +## Step 3 : Work on the issue assigned +- Work on the issue(s) assigned to you. +- Add all the files/folders needed. +- After you've made changes or made your contribution to the project add changes to the branch you've just created by: +``` +# To add all new files to branch Branch_Name +$ git add . + +# To add only a few files to Branch_Name +$ git add +``` +- If not assigned, you can submit a PR solving the issue if no one else is working on that. + +## Step 4 : Commit +- To commit give a descriptive message for the convenience of reviewer by: +``` +# This message get associated with all files you have changed +$ git commit -m "message" +``` +- **NOTE**: A PR should have only one commit. Multiple commits should be squashed. + +## Step 5 : Work Remotely +- Now you are ready to your work to the remote repository. +- When your work is ready and complies with the project conventions, upload your changes to your fork: + +``` +# To push your work to your remote repository +$ git push -u origin Branch_Name +``` + + +## Step 6 : Pull Request +- Go to your repository in browser and click on compare and pull requests. Then add a title and description to your pull request that explains your contribution. + + +- Voila! Your Pull Request has been submitted and will be reviewed and merged.🥳 + +## Need more help?🤔 +You can refer to the following articles on basics of Git and Github and also contact the Project Mentors, in case you are stuck: +- [Forking a Repo](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) +- [Cloning a Repo](https://help.github.com/en/desktop/contributing-to-projects/creating-an-issue-or-pull-request) +- [How to create a Pull Request](https://opensource.com/article/19/7/create-pull-request-github) +- [Getting started with Git and GitHub](https://towardsdatascience.com/getting-started-with-git-and-github-6fcd0f2d4ac6) +- [Learn GitHub from Scratch](https://lab.github.com/githubtraining/introduction-to-github) + diff --git a/DSA/Arrays/BubbleSort.js b/DSA/Arrays/BubbleSort.js new file mode 100644 index 0000000..c37a9d6 --- /dev/null +++ b/DSA/Arrays/BubbleSort.js @@ -0,0 +1,24 @@ +// Bubble sort Implementation using Javascript + + function bblSort(arr){ + + // loop through array + for(var i = 0; i < arr.length; i++){ + + for(var j = 0; j < ( arr.length - i -1 ); j++){ + + if(arr[j] > arr[j+1]){ + + var temp = arr[j] + arr[j] = arr[j + 1] + arr[j+1] = temp + } + } + } + console.log(arr); +} + +var arr = [234, 43, 55, 63, 5, 6, 235, 547]; + +// call the function +bblSort(arr); \ No newline at end of file diff --git a/DSA/Arrays/BubbleSortM2.js b/DSA/Arrays/BubbleSortM2.js new file mode 100644 index 0000000..1ee0d53 --- /dev/null +++ b/DSA/Arrays/BubbleSortM2.js @@ -0,0 +1,24 @@ +function bubbleSort(arr) { + const n = arr.length; + let swapped; + + do { + swapped = false; + + for (let i = 0; i < n - 1; i++) { + if (arr[i] > arr[i + 1]) { + // Swap elements arr[i] and arr[i+1] + let temp = arr[i]; + arr[i] = arr[i + 1]; + arr[i + 1] = temp; + swapped = true; + } + } + } while (swapped); + + return arr; +} + +const arr = [234, 43, 55, 63, 5, 6, 235, 547]; +const sortedArray = bubbleSort(arr); +console.log(sortedArray); diff --git a/DSA/Arrays/BucketSort.js b/DSA/Arrays/BucketSort.js new file mode 100644 index 0000000..b5e491f --- /dev/null +++ b/DSA/Arrays/BucketSort.js @@ -0,0 +1,77 @@ +// Define the input array +const arr = [5, 3, 1, 2, 4, 7, 6]; + +// Define the bucketSort function +const bucketSort = (arr) => { + // Check if the input array is empty + if (arr.length === 0) { + return arr; // Return the empty array + } + + // Initialize variables for minValue, maxValue, and bucket size + let i, + minValue = arr[0], + maxValue = arr[0], + bucketSize = 5; + + // Find the minimum and maximum values in the input array + arr.forEach(function (currentVal) { + if (currentVal < minValue) { + minValue = currentVal; + } else if (currentVal > maxValue) { + maxValue = currentVal; + } + }); + + // Calculate the number of buckets needed based on the range of values + let bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1; + + // Create an array to hold all the buckets + let allBuckets = new Array(bucketCount); + + // Initialize each bucket as an empty array + for (i = 0; i < allBuckets.length; i++) { + allBuckets[i] = []; + } + + // Distribute values from the input array into the appropriate buckets + arr.forEach(function (currentVal) { + allBuckets[Math.floor((currentVal - minValue) / bucketSize)].push( + currentVal + ); + }); + + // Clear the input array to prepare for sorting + arr.length = 0; + + // Sort each bucket using insertion sort and merge them back into the input array + allBuckets.forEach(function (bucket) { + insertion(bucket); + bucket.forEach(function (element) { + arr.push(element); + }); + }); + + // Return the sorted array + return arr; +}; + +// Define the insertion sort function +const insertion = (arr) => { + let length = arr.length; + let i, j; + + // Iterate through the elements in the bucket and perform insertion sort + for (i = 1; i < length; i++) { + let temp = arr[i]; + for (j = i - 1; j >= 0 && arr[j] > temp; j--) { + arr[j + 1] = arr[j]; + } + arr[j + 1] = temp; + } + + return arr; // Return the sorted bucket +}; + +// Call the bucketSort function and print the sorted array +console.log(bucketSort(arr)); diff --git a/DSA/Arrays/Heapsort in DSA b/DSA/Arrays/Heapsort in DSA new file mode 100644 index 0000000..0398788 --- /dev/null +++ b/DSA/Arrays/Heapsort in DSA @@ -0,0 +1,35 @@ +function heapSort(arr) { + buildMaxHeap(arr); + for (let i = arr.length - 1; i > 0; i--) { + [arr[0], arr[i]] = [arr[i], arr[0]]; + maxHeapify(arr, 0, i); + } +} +function buildMaxHeap(arr) { + const n = arr.length; + for (let i = Math.floor(n / 2) - 1; i >= 0; i--) { + maxHeapify(arr, i, n); + } +} +function maxHeapify(arr, i, heapSize) { + const leftChild = 2 * i + 1; + const rightChild = 2 * i + 2; + let largest = i; + + if (leftChild < heapSize && arr[leftChild] > arr[largest]) { + largest = leftChild; + } + + if (rightChild < heapSize && arr[rightChild] > arr[largest]) { + largest = rightChild; + } + + if (largest !== i) { + [arr[i], arr[largest]] = [arr[largest], arr[i]]; // Swap arr[i] and arr[largest] + maxHeapify(arr, largest, heapSize); + } +} +const arr = [12, 11, 13, 5, 6, 7]; +heapSort(arr); + +console.log("Sorted array:", arr); diff --git a/DSA/Arrays/Insertionsort.js b/DSA/Arrays/Insertionsort.js new file mode 100644 index 0000000..6fdfe9d --- /dev/null +++ b/DSA/Arrays/Insertionsort.js @@ -0,0 +1,12 @@ +function insertionSort(arr) { + for (let i = 1; i < arr.length; i++) { + let currentValue = arr[i] + let j + for (j = i - 1; j >= 0 && arr[j] > currentValue; j--) { + arr[j + 1] = arr[j] + } + arr[j + 1] = currentValue + } + return arr +} +console.log(insertionSort([2, 1, 3, 7, 5])) // [1, 2, 3, 5, 7] \ No newline at end of file diff --git a/DSA/Arrays/KadanesAlgo.js b/DSA/Arrays/KadanesAlgo.js new file mode 100644 index 0000000..8f1f962 --- /dev/null +++ b/DSA/Arrays/KadanesAlgo.js @@ -0,0 +1,31 @@ + +function maxSubarraySum(arr, n) { + let maxi = Number.MIN_SAFE_INTEGER; // maximum sum + let sum = 0; + + for (let i = 0; i < n; i++) { + sum += arr[i]; + + if (sum > maxi) { + maxi = sum; + } + + // If sum < 0: discard the sum calculated + if (sum < 0) { + sum = 0; + } + } + + // To consider the sum of the empty subarray + // uncomment the following check: + + //if (maxi < 0) maxi = 0; + + return maxi; +} + +const arr = [-2, 1, -3, 4, -1, 2, 1, -5, 4]; +const n = arr.length; +const maxSum = maxSubarraySum(arr, n); +console.log("The maximum subarray sum is: " + maxSum); + diff --git a/DSA/Arrays/Maximumsubarray.js b/DSA/Arrays/Maximumsubarray.js new file mode 100644 index 0000000..f3a7a8b --- /dev/null +++ b/DSA/Arrays/Maximumsubarray.js @@ -0,0 +1,18 @@ +const maxSubArray = (nums) => { + // initiate two variable, maxSum for total max, sum for current max + let maxSum = -Infinity + let currentSum = 0 + // iterate through the nums, store sub-problems result + for(let i = 0; i < nums.length; i++){ + //cumulating answers to the top + + //compare currentSum add current number + //with current number and store the maximum value + currentSum = Math.max(nums[i], currentSum + nums[i]) + + //compare maxSum with currentSum and store the greater value + maxSum = Math.max(currentSum, maxSum) + + } + return maxSum +} \ No newline at end of file diff --git a/DSA/Arrays/RadixSort.js b/DSA/Arrays/RadixSort.js new file mode 100644 index 0000000..e4f1b5b --- /dev/null +++ b/DSA/Arrays/RadixSort.js @@ -0,0 +1,43 @@ +const arr = [121, 432, 564, 23, 1, 45, 788]; +const countingSort = (arr, size, place) => { + + let output = new Array(size + 1).fill(0); + let max = Math.max(...arr); + + let freq = new Array(max + 1).fill(0); + + + for (let i = 0; i < size; i++){ + const num = Math.floor(arr[i] / place) % 10; + freq[num]++; + } + + + for (let i = 1; i < 10; i++){ + freq[i] += freq[i - 1]; + } + + + for (let i = size - 1; i >= 0; i--) { + const num = Math.floor(arr[i] / place) % 10; + output[freq[num] - 1] = arr[i]; + freq[num]--; + } + + + for (let i = 0; i < size; i++){ + arr[i] = output[i]; + } +} + +const radixSort = (arr, size = arr.length) => { + + let max = Math.max(...arr); + + + for(let i = 1; parseInt(max / i) > 0; i *= 10){ + countingSort(arr, size, i); + } +} +radixSort(arr); +console.log(arr); \ No newline at end of file diff --git a/DSA/Arrays/SelectionSort.js b/DSA/Arrays/SelectionSort.js new file mode 100644 index 0000000..b1809bf --- /dev/null +++ b/DSA/Arrays/SelectionSort.js @@ -0,0 +1,17 @@ +function selectionSort(arr) { + for (let i = 0; i < arr.length - 1; i++) { + let min_index = i; + for (let j = i + 1; j < arr.length; j++) { + if (arr[j] < arr[min_index]) { // Changed the comparison to sort in ascending order + min_index = j; + } + } + let temp = arr[min_index]; + arr[min_index] = arr[i]; + arr[i] = temp; + } + return arr; +} + +let arr = [4, 12, 10, 15, 2]; +console.log(selectionSort(arr)); // Output: [2, 4, 10, 12, 15] diff --git a/DSA/Arrays/SpecialArrayWithXElementsGreaterThanEqualToX.js b/DSA/Arrays/SpecialArrayWithXElementsGreaterThanEqualToX.js new file mode 100644 index 0000000..7f83952 --- /dev/null +++ b/DSA/Arrays/SpecialArrayWithXElementsGreaterThanEqualToX.js @@ -0,0 +1,29 @@ +/** + * @param {number[]} nums + * @return {number} + */ +var specialArray = function(nums) { + for (let i = 0; i <= nums.length; i++) { + let count = 0; + for (let j = 0; j < nums.length; j++) { + if (nums[j] >= i) { + count++; + } + } + if (count === i) { + return i; + } + } + return -1; +}; + +// Define an additional function to find the maximum value in the array. +function findMaxValue(nums) { + return Math.max(...nums); +} + +// Export the specialArray function and the findMaxValue function. +module.exports = { + specialArray, + findMaxValue +}; diff --git a/DSA/BFS/waterJug.js b/DSA/BFS/waterJug.js new file mode 100644 index 0000000..6d887d0 --- /dev/null +++ b/DSA/BFS/waterJug.js @@ -0,0 +1,135 @@ +// Defining constants. +const ACTION_FILL_X = -1 +const ACTION_FILL_Y = -2 +const ACTION_EMPTY_X = -3 +const ACTION_EMPTY_Y = -4 +const ACTION_POUR_FILL_X = -5 +const ACTION_POUR_FILL_Y = -6 +const ACTION_POUR_EMPTY_X = -7 +const ACTION_POUR_EMPTY_Y = -8 + +function getChildren(node, m, n) { + const results = []; + const {x, y} = node.state; + if (x < m) + results.push({ + x: m, + y, + action: ACTION_FILL_X + }); + if (y < n) + results.push({ + x, + y: n, + action: ACTION_FILL_Y + }); + if (x > 0) + results.push({ + x: 0, + y, + action: ACTION_EMPTY_X + }); + if (y > 0) + results.push({ + x, + y: 0, + action: ACTION_EMPTY_Y + }); + if (x + y >= m && y > 0) + results.push({ + x: m, + y: x + y - m, + action: ACTION_POUR_FILL_X + }); + if (x + y >= n && x > 0) + results.push({ + x: x + y - n, + y: n, + action: ACTION_POUR_FILL_Y + }); + if (x + y <= m && y >= 0) + results.push({ + x: x + y, + y: 0, + action: ACTION_POUR_EMPTY_Y + }); + if (x + y <= n && x >= 0) + results.push({ + x: 0, + y: x + y, + action: ACTION_POUR_EMPTY_X + }); + return results; +} + +function solve(m, n, d) { + // The final state to achieve. + const goal = { x: d, y: 0 }; + // Starting from the topmost row of the matrix. + // Initiating the first state and node + const initialState = { + x: 0, + y: 0 + }; + const initialNode = { + state: initialState, + parent: null, + action: null, + }; + // For BFS, we use a Queue data type, FIFO. + let frontier = [initialNode]; + + while (frontier.length != 0) { + // Getting the first node in the frontier. + const node = frontier[0]; + frontier = frontier.slice(1); + // Checking if the node represents an element in the last row. + // If so, then add it to the goal state list and continue. + if (node.state.x == goal.x) { + printSolution(node); + break; + } + + // If it is not the goal state, we can get certain actions we can perform. + // Get all available actions the current node have. + const children = getChildren(node, m, n); + + for (let j = 0; j < children.length; j++) { + const result = children[j]; + const childState = { + x: result.x, + y: result.y, + }; + const child = { + state: childState, + parent: node, + action: result.action, + }; + // Add this node to the frontier. + frontier.push(child); + } + } +} + +function printSolution(node) { + const nodes = []; + while (node.parent != null) { + nodes.push(node); + node = node.parent; + } + nodes.push(node); + nodes.reverse(); + let answer = "{"; + for (let i = 0; i < nodes.length; i++) { + answer += `(${nodes[i].state.x}, ${nodes[i].state.y})`; + if (i !== nodes.length - 1) + answer += ', '; + } + answer += "}"; + console.log(answer); +} + +(() => { + const [m, n, d] = [4, 3, 2]; + solve(m, n, d); +})(); \ No newline at end of file diff --git a/DSA/BinarySearch/FindFirstAndLastPositionInASortedArray.js b/DSA/BinarySearch/FindFirstAndLastPositionInASortedArray.js new file mode 100644 index 0000000..86cd1f3 --- /dev/null +++ b/DSA/BinarySearch/FindFirstAndLastPositionInASortedArray.js @@ -0,0 +1,41 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ + var searchRange = function(arr, target) { + let firstPosition = -1; + let lastPosition = -1; + + let start = 0; + let end = arr.length - 1; + let mid; + + while(start <= end){ + mid = end - parseInt((end - start)/2) + if(arr[mid] === target){ + firstPosition = mid; + end = mid - 1 + }else if (arr[mid] < target){ + start = mid + 1 + }else{ + end = mid - 1 + } + } + start = 0; + end = arr.length - 1; + + while(start <= end){ + mid = end - parseInt((end - start)/2) + if(arr[mid] === target){ + lastPosition = mid; + start = mid + 1 + }else if (arr[mid] < target){ + start = mid + 1 + }else{ + end = mid - 1 + } + } + return [firstPosition, lastPosition] + +}; \ No newline at end of file diff --git a/DSA/BinarySearch/FindTheElementGivenPosition in linklist b/DSA/BinarySearch/FindTheElementGivenPosition in linklist new file mode 100644 index 0000000..a558266 --- /dev/null +++ b/DSA/BinarySearch/FindTheElementGivenPosition in linklist @@ -0,0 +1,60 @@ +class Node { + constructor(data) { + this.data = data; + this.next = null; + } +} + +class LinkedList { + constructor() { + this.head = null; + } + + append(data) { + const newNode = new Node(data); + + if (!this.head) { + this.head = newNode; + } else { + let current = this.head; + while (current.next) { + current = current.next; + } + current.next = newNode; + } + } + + findNodeAtPosition(position) { + if (position < 0 || !this.head) { + return null; // Position is out of bounds or the list is empty + } + + let current = this.head; + let index = 0; + + while (current) { + if (index === position) { + return current; + } + current = current.next; + index++; + } + + return null; + } +} +const linkedList = new LinkedList(); +linkedList.append(10); +linkedList.append(20); +linkedList.append(30); +linkedList.append(40); +linkedList.append(50); + +const positionToFind = 4; +const node = linkedList.findNodeAtPosition(positionToFind); + +if (node) { + console.log(`Node at position ${positionToFind} contains data: ${node.data}`); +} else { + console.log(`Node at position ${positionToFind} not found.`); +} diff --git a/DSA/BinarySearch/Sqrtx.js b/DSA/BinarySearch/Sqrtx.js new file mode 100644 index 0000000..891b069 --- /dev/null +++ b/DSA/BinarySearch/Sqrtx.js @@ -0,0 +1,26 @@ +/** + * @param {number} x + * @return {number} + */ + +// function to calculate square root of a number using binary search + var mySqrt = function(x) { + let start = 1; + let end = x; + let mid; + let res = 0 + + while(start <= end){ + mid = end - parseInt((end - start)/2) + console.log(mid) + if(mid*mid <= x){ + res = mid; + start = mid + 1 + }else{ + end = mid - 1; + } + } + return res + + +}; \ No newline at end of file diff --git a/DSA/BinarySearch/findElementInRotatedSortedArray.js b/DSA/BinarySearch/findElementInRotatedSortedArray.js new file mode 100644 index 0000000..4ff4e5c --- /dev/null +++ b/DSA/BinarySearch/findElementInRotatedSortedArray.js @@ -0,0 +1,57 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ + var search = function(nums, target) { + function binarySearch(arr, start, end, target){ + let mid; + while(start <= end){ + mid = end - parseInt((end - start)/2) + if(arr[mid] === target){ + return mid; + }else if(arr[mid] < target){ + start = mid + 1 + }else{ + end = mid - 1 + } + } + return -1 + } + function findMin(arr){ + let start = 0; + let end = arr.length-1 + let N = arr.length; + let res = -1; + + while(start <= end){ + if(arr[start] <= arr[end]){ + return start; + } + mid = end - parseInt((end-start)/2) + if(arr[mid] <= arr[(mid+1) % N] && arr[mid] <= arr[(mid+ N -1)%N]) { + res = mid; + break; + } + if(arr[mid] >= arr[start]){ + start = mid + 1 + } else if (arr[mid] <= arr[end]){ + end = mid - 1 + } + } + return res + } + + let minimumIndex = findMin(nums); + + + let res1 = binarySearch(nums, minimumIndex, nums.length, target); + let res2 = binarySearch(nums, 0, minimumIndex - 1, target); + + if(res1 !== -1){ + return res1; + } + return res2 +}; + +// cool stuff \ No newline at end of file diff --git a/DSA/BinarySearch/firstBadVersion.js b/DSA/BinarySearch/firstBadVersion.js new file mode 100644 index 0000000..175b8d5 --- /dev/null +++ b/DSA/BinarySearch/firstBadVersion.js @@ -0,0 +1,36 @@ +/** + * Definition for isBadVersion() + * + * @param {integer} version number + * @return {boolean} whether the version is bad + * isBadVersion = function(version) { + * ... + * }; + */ + +/** + * @param {function} isBadVersion() + * @return {function} + */ + var solution = function(isBadVersion) { + /** + * @param {integer} n Total versions + * @return {integer} The first bad version + */ + return function(n) { + let start = 1; + let end = n; + let mid; + let res = -1; + while(start <= end){ + mid = end - parseInt((end - start)/2) + if(isBadVersion(mid)){ + res = mid; + end = mid - 1; + }else{ + start = mid + 1; + } + } + return res + }; +}; \ No newline at end of file diff --git a/DSA/BinarySearch/guessNumber.js b/DSA/BinarySearch/guessNumber.js new file mode 100644 index 0000000..7bb6ddd --- /dev/null +++ b/DSA/BinarySearch/guessNumber.js @@ -0,0 +1,29 @@ +/** + * Forward declaration of guess API. + * @param {number} num your guess + * @return -1 if num is lower than the guess number + * 1 if num is higher than the guess number + * otherwise return 0 + * var guess = function(num) {} + */ + +/** + * @param {number} n + * @return {number} + */ + var guessNumber = function(n) { + let start = 1; + let end = n; + let mid; + + while(start <= end){ + mid = end - parseInt((end - start)/2) + if(guess(mid) === 0){ + return mid + }else if(guess(mid) === -1){ + end = mid - 1; + }else{ + start = mid + 1 + } + } +}; \ No newline at end of file diff --git a/DSA/BinarySearch/minimumDifferenceElementInSortedArray.js b/DSA/BinarySearch/minimumDifferenceElementInSortedArray.js new file mode 100644 index 0000000..b5448f5 --- /dev/null +++ b/DSA/BinarySearch/minimumDifferenceElementInSortedArray.js @@ -0,0 +1,17 @@ +function minimumDifference(arr, target){ + let start = 0; + let end = arr.length - 1; + let mid; + while(start <= end){ + mid = end - parseInt((end-start)/2) + if(arr[mid] === target){ + return arr[mid]; + } + else if(arr[mid] < target){ + start = mid + 1 + }else{ + end = mid - 1 + } + } + return Math.min(Math.abs(arr[start] - target), Math.abs(arr[end] - target)) +} \ No newline at end of file diff --git a/DSA/BinarySearch/searchInsertPosition.js b/DSA/BinarySearch/searchInsertPosition.js new file mode 100644 index 0000000..64a68d1 --- /dev/null +++ b/DSA/BinarySearch/searchInsertPosition.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ + var searchInsert = function(nums, target) { + let start = 0; + let end = nums.length - 1; + let mid; + let res = nums.length; + while(start <= end){ + mid = end - parseInt((end - start)/2) + if(nums[mid] === target){ + return mid + }else if(nums[mid] > target){ + res = mid; + end = mid - 1; + }else{ + start = mid + 1; + } + } + return res; + +}; \ No newline at end of file diff --git a/DSA/DFS/BinaryTreePaths.js b/DSA/DFS/BinaryTreePaths.js new file mode 100644 index 0000000..a99c1c0 --- /dev/null +++ b/DSA/DFS/BinaryTreePaths.js @@ -0,0 +1,18 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +var binaryTreePaths = function(root) { + let allAr = []; + getPath(root); + function getPath(node,arr=[]){ + (!node.left && !node.right) &&allAr.push([...arr, node.val]); + node.left && getPath(node.left, [...arr,node.val]); + node.right && getPath(node.right, [...arr,node.val]); + } + return allAr.map((a)=>a.join('->')); +}; diff --git a/DSA/DFS/Diameter of Binary Tree b/DSA/DFS/Diameter of Binary Tree new file mode 100644 index 0000000..6ee879c --- /dev/null +++ b/DSA/DFS/Diameter of Binary Tree @@ -0,0 +1,24 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +var diameterOfBinaryTree = function(root) { + let result = 0; + helper(root); + return result + + function helper(root){ + if(!root)return 0; + + let left = helper(root.left); + let right = helper(root.right); + + result = Math.max(left + right , result); + + return 1 + Math.max(left, right) + } +}; diff --git a/DSA/DFS/Find Mode in Binary Search Tree.js b/DSA/DFS/Find Mode in Binary Search Tree.js new file mode 100644 index 0000000..1f77f2c --- /dev/null +++ b/DSA/DFS/Find Mode in Binary Search Tree.js @@ -0,0 +1,28 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +var findMode = function(r) { + const map = new Map() + const maxMap = new Map() + let max = -Infinity + + function dfs(root){ + if(!root) return + map.set(root.val, (map.get(root.val) || 0) + 1) + if(map.get(root.val) >= max){ + max = map.get(root.val) + if(!maxMap.get(max)) maxMap.set(max, new Set()) + maxMap.get(max).add(root.val) + } + dfs(root.left) + dfs(root.right) + } + + dfs(r) + return [...maxMap.get(max)] +}; diff --git a/DSA/DFS/InvertBinaryTree.js b/DSA/DFS/InvertBinaryTree.js new file mode 100644 index 0000000..6491180 --- /dev/null +++ b/DSA/DFS/InvertBinaryTree.js @@ -0,0 +1,16 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ + +var invertTree = function(root) { + if(!root) { + return null; + } + [root.left, root.right] = [invertTree(root.right), invertTree(root.left)]; + return root; +}; diff --git a/DSA/DFS/KthSmallestElementInABST.js b/DSA/DFS/KthSmallestElementInABST.js new file mode 100644 index 0000000..6179420 --- /dev/null +++ b/DSA/DFS/KthSmallestElementInABST.js @@ -0,0 +1,21 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +var kthSmallest = function(root, k) { + let arrayOfElements = [] + + function dfs(node) { + if(!node) return; + + dfs(node.left); + arrayOfElements.push(node.val); + dfs(node.right); + } + dfs(root); + return arrayOfElements[k - 1]; +}; diff --git a/DSA/DFS/LowestCommonAncestorOfABinarySearchTree.js b/DSA/DFS/LowestCommonAncestorOfABinarySearchTree.js new file mode 100644 index 0000000..a9320f7 --- /dev/null +++ b/DSA/DFS/LowestCommonAncestorOfABinarySearchTree.js @@ -0,0 +1,37 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +var lowestCommonAncestor = function(root, p, q) { + +let ansNode = null +if(p.val == root.val || q.val == root.val){ + return root +} +function traverse(node){ + if((p.val < node.val && q.val > node.val) || (p.val > node.val && q.val < node.val)){ + ansNode = node + return + } + else if(p.val == node.val || q.val == node.val){ + ansNode = node + return + } + if(node.left) + traverse(node.left) + if(node.right) + traverse(node.right) +} + +if((p.val < root.val && q.val > root.val) || (p.val > root.val && q.val < root.val)) + return root +else if(p.val > root.val && q.val > root.val) + traverse(root.right) +else if(p.val < root.val && q.val < root.val) + traverse(root.left) + +return ansNode +}; diff --git a/DSA/DFS/SameTree.js b/DSA/DFS/SameTree.js new file mode 100644 index 0000000..936e6ad --- /dev/null +++ b/DSA/DFS/SameTree.js @@ -0,0 +1,20 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +var isSameTree = function(p, q) { + return is_tree_equal(p, q); + function is_tree_equal(tree1, tree2){ + if (tree1 === null && tree2 === null) return true; + if (tree1 === null || tree2 === null) return false; + if (tree1.val !== tree2.val) return false; + + const is_left_tree_equal = is_tree_equal(tree1.left, tree2.left) + const is_right_tree_equal = is_tree_equal(tree1.right, tree2.right) + return is_left_tree_equal && is_right_tree_equal + } +}; diff --git a/DSA/DFS/SymmetricTree.js b/DSA/DFS/SymmetricTree.js new file mode 100644 index 0000000..fb7a863 --- /dev/null +++ b/DSA/DFS/SymmetricTree.js @@ -0,0 +1,29 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +var isSymmetric = function(root) { +if(!root.left && !root.right) + return true +if((root.left && !root.right) || (!root.left && root.right)) + return false +let ans = true +function traverse(nodeL,nodeR){ + if(nodeL.val != nodeR.val) + ans = false + if(nodeL.left && nodeR.right) + traverse(nodeL.left,nodeR.right) + else if((!nodeL.left && nodeR.right) || (nodeL.left && !nodeR.right)) + ans = false + if(nodeL.right && nodeR.left) + traverse(nodeL.right, nodeR.left) + else if((!nodeL.right && nodeR.left) || (nodeL.right && !nodeR.left)) + ans = false +} +traverse(root.left,root.right) +return ans +}; diff --git a/DSA/DFS/lowest-common-ancestor-of-a-binary-tree.js b/DSA/DFS/lowest-common-ancestor-of-a-binary-tree.js new file mode 100644 index 0000000..4c99d9d --- /dev/null +++ b/DSA/DFS/lowest-common-ancestor-of-a-binary-tree.js @@ -0,0 +1,24 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +var lowestCommonAncestor = function(root, p, q) { + if(!root) { + return null; + } + const left = lowestCommonAncestor(root.left, p, q), + right = lowestCommonAncestor(root.right, p, q); + if((left && right) || root.val === p.val || root.val === q.val) { + return root; + } + else if(left) { + return left; + } + else if(right) { + return right; + } + return null; +}; diff --git a/DSA/DFS/maximumSumDownAMatrix.js b/DSA/DFS/maximumSumDownAMatrix.js new file mode 100644 index 0000000..eb1ce15 --- /dev/null +++ b/DSA/DFS/maximumSumDownAMatrix.js @@ -0,0 +1,146 @@ +/* + * This is a simple Depth-First Search Algorithm. + * + * You are provided with a square matrix with integer values. + * The task is to find the maximum sum using the integers in the matrix, + * starting from the first row and ending in the last row, such that you + * can only move diagonally left or diagonally right. + * + * If you have a 4x4 matrix: + * 1 7 3 6 + * 1 2 9 4 + * 9 8 5 7 + * 4 5 2 1 + * + * The path that you will have to find is: + * 7 + * 9 + * 8 + * 4 + * + * 7 + 9 + 8 + 4 = 28. + */ + + +// Defining constants. +const ACTION_RIGHT = 100; +const ACTION_LEFT = -100; + +function getChildren(x, y, n) { + const results = []; + // Checking if the values aren't at the left edge of the matrix + if (x != n - 1 && y != 0) { + results.push({ + x: x + 1, + y: y - 1, + action: ACTION_LEFT, + }); + } + // Checking if the values aren't at the right edge of the matrix + if (x != n - 1 && y != n - 1) { + results.push({ + x: x + 1, + y: y + 1, + action: ACTION_RIGHT, + }); + } + return results; +} + +function solve(matrix) { + // The list of nodes that are in the bottom of the matrix. + const goalList = []; + // Starting from the topmost row of the matrix. + for (let i = 0; i < matrix.length; i++) { + // Initiating the first state and node + const initialState = { + sum: matrix[0][i], + x: 0, + y: i, + }; + const initialNode = { + state: initialState, + parent: null, + action: null, + }; + // For DFS, we use a Stack data type, LIFO. + let frontier = [initialNode]; + + while (frontier.length != 0) { + // Getting the last node in the frontier. + const node = frontier.pop(); + // Checking if the node represents an element in the last row. + // If so, then add it to the goal state list and continue. + if (node.state.x == matrix.length - 1) { + goalList.push(node); + continue; + } + + // If it is not the goal state, we can get certain actions we can perform. + // Get all available actions the current node have. + const children = getChildren(node.state.x, node.state.y, matrix.length); + + for (let j = 0; j < children.length; j++) { + const result = children[j]; + // Record the cummulative sum and initialise a child state. + const newSum = node.state.sum + matrix[result.x][result.y]; + const childState = { + sum: newSum, + x: result.x, + y: result.y, + }; + const child = { + state: childState, + parent: node, + action: result.action, + }; + // Add this state to the frontier. + frontier.push(child); + } + } + } + + // After collecting all the goal states, sort them in decreasing order. + goalList.sort((n1, n2) => n2.state.sum - n1.state.sum); + // The first element with the sum will be the answer. + return goalList[0].state.sum; +} + +function printMatrix(matrix) { + for (let i = 0; i < matrix.length; i++) { + let s = ""; + for (let j = 0; j < matrix[i].length; j++) { + s += `${matrix[i][j]}\t`; + } + console.log(`\n${s}`); + } +} + +(() => { + // Initial driver code. + const matrix = [ + [5, 10, 75, 20, 76], + [4, 5, 8, 50, 32], + [80, 42, 0, 3, 4], + [82, 73, 7, 58, 45], + [45, 24, 13, 86, 0], + ]; + printMatrix(matrix); + const answer = solve(matrix); + console.log(answer); +})(); + +/* + * Explanation: + * + * State: it's the attributes that is required related to the problem. + * Action: it's the constant that defines how different nodes are connected. + * Node: it contains the current state, the action taken to reach that state, and the parent node. + * Frontier: A Stack which contains all the nodes and to be used while searching. + * + * We start with the inital node in the frontier and start a loop. + * We pop out the last node and check if it is the goal state and perform some action. + * If it is not a goal state, we will get all available actions that node currently have and iterate through them. + * Using the actions, we will create successive states and add them to the frontier. + * This process will continue till the frontier is empty. Hence, we can perform some final code to get the answer. + */ \ No newline at end of file diff --git a/DSA/DFS/minimum-distance-between-bst-nodes.js b/DSA/DFS/minimum-distance-between-bst-nodes.js new file mode 100644 index 0000000..a931a50 --- /dev/null +++ b/DSA/DFS/minimum-distance-between-bst-nodes.js @@ -0,0 +1,26 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +var minDiffInBST = function(root) { + let min = Number.MAX_VALUE +let arr = [] +function traverse(node){ + if(node.left) + traverse(node.left) + arr.push(node.val) + if(node.right) + traverse(node.right) +} +traverse(root) +for(let i = arr.length - 1 ; i > 0 ; i--){ + if(arr[i] - arr[i-1] < min){ + min = arr[i] - arr[i-1] + } +} +return min +}; diff --git a/DSA/DFS/validateBinaryTree.js b/DSA/DFS/validateBinaryTree.js new file mode 100644 index 0000000..60f49ea --- /dev/null +++ b/DSA/DFS/validateBinaryTree.js @@ -0,0 +1,17 @@ +var isValidBST = function (root) { + + + function helper(node, min, max) { + if (!node) return true; + + if (node.val <= min || node.val >= max) return false; + + let left = helper(node.left, min, node.val); + let right = helper(node.right, node.val, max) + + return left && right + + } + + return helper(root, -Infinity, Infinity) +}; \ No newline at end of file diff --git a/DSA/Graphs/DijkstraAlgorithm.js b/DSA/Graphs/DijkstraAlgorithm.js new file mode 100644 index 0000000..534c848 --- /dev/null +++ b/DSA/Graphs/DijkstraAlgorithm.js @@ -0,0 +1,73 @@ +const graphInfo = { + source: {A: 4, B: 1}, + A: {C: 3, D: 5}, + B: {A: 7, D: 2}, + C: {D: 4, destination: 3}, + D: {destination: 2}, + destination: {} + }; + + // primary function + const dijkstra = (graph) => { + + // shortest distance to each vertex + const distance = Object.assign( + {destination: Infinity}, graph.source); + + // display path + const parentArray = {destination: null}; + for (let child in graph.source) { + parentArray[child] = 'source'; + } + + // track vertexs that are marked + const marked = []; + + let vertex = minimumDistancevertex(distance, marked); + + while (vertex) { + let cost = distance[vertex]; + let children = graph[vertex]; + for (let n in children) { + let latestDistance = cost + children[n]; + if (!distance[n]) { + distance[n] = latestDistance; + parentArray[n] = vertex; + } + if (distance[n] > latestDistance) { + distance[n] = latestDistance; + parentArray[n] = vertex; + } + } + marked.push(vertex); + vertex = minimumDistancevertex(distance, marked); + } + + let shortestPath = ['destination']; + let parent = parentArray.destination; + while (parent) { + shortestPath.push(parent); + parent = parentArray[parent]; + } + shortestPath.reverse(); + + const result = { + distance: distance.destination, + path: shortestPath + }; + + return result; + }; + + const minimumDistancevertex = (distance, marked) => { + return Object.keys(distance).reduce((lowest, vertex) => { + if (lowest === null || distance[vertex] < distance[lowest]) { + if (!marked.includes(vertex)) { + lowest = vertex; + } + } + return lowest; + }, null); + }; + + console.log(dijkstra(graphInfo)); \ No newline at end of file diff --git a/DSA/Graphs/Kruskal Algorithm b/DSA/Graphs/Kruskal Algorithm new file mode 100644 index 0000000..8080866 --- /dev/null +++ b/DSA/Graphs/Kruskal Algorithm @@ -0,0 +1,43 @@ +class UnionFind { + constructor(elements) { + // Number of disconnected components + this.count = elements.length; + + // Keep Track of connected components + this.parent = {}; + + // Initialize the data structure such that all + // elements have themselves as parents + elements.forEach(e => (this.parent[e] = e)); + } + + union(a, b) { + let rootA = this.find(a); + let rootB = this.find(b); + + // Roots are same so these are already connected. + if (rootA === rootB) return; + + // Always make the element with smaller root the parent. + if (rootA < rootB) { + if (this.parent[b] != b) this.union(this.parent[b], a); + this.parent[b] = this.parent[a]; + } else { + if (this.parent[a] != a) this.union(this.parent[a], b); + this.parent[a] = this.parent[b]; + } + } + + // Returns final parent of a node + find(a) { + while (this.parent[a] !== a) { + a = this.parent[a]; + } + return a; + } + + // Checks connectivity of the 2 nodes + connected(a, b) { + return this.find(a) === this.find(b); + } +} diff --git a/DSA/Graphs/Maze.js b/DSA/Graphs/Maze.js new file mode 100644 index 0000000..d33ef15 --- /dev/null +++ b/DSA/Graphs/Maze.js @@ -0,0 +1,209 @@ +const maze = [ + ['S', 0, 1, 0, 1], + [0, 1, 0, 0, 0], + [0, 0, 1, 1, 0], + [1, 0, 0, 0, 'E'], +]; + + +function solveMazeDFS(maze) { + const rows = maze.length; + const cols = maze[0].length; + + function dfs(x, y) { + if (x < 0 || x >= rows || y < 0 || y >= cols || maze[x][y] === 1) { + return false; + } + + if (maze[x][y] === 'E') { + return true; // Reached the end of the maze + } + + maze[x][y] = 1; // Mark as visited + + // Explore in all four directions (up, down, left, right) + if (dfs(x + 1, y) || dfs(x - 1, y) || dfs(x, y + 1) || dfs(x, y - 1)) { + return true; + } + + maze[x][y] = 0; // Mark as unvisited if no path was found + return false; + } + + // Find the start point + let startX, startY; + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (maze[i][j] === 'S') { + startX = i; + startY = j; + break; + } + } + } + + // Call DFS from the start point + if (dfs(startX, startY)) { + return "Maze is solvable."; + } else { + return "Maze has no solution."; + } +} + +console.log(solveMazeDFS(maze)); + + + + +function solveMazeBFS(maze) { + const rows = maze.length; + const cols = maze[0].length; + const queue = []; + + // Find the start point + let startX, startY; + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (maze[i][j] === 'S') { + startX = i; + startY = j; + break; + } + } + } + + // Define possible moves (up, down, left, right) + const moves = [[1, 0], [-1, 0], [0, 1], [0, -1]]; + + queue.push([startX, startY]); + + while (queue.length > 0) { + const [x, y] = queue.shift(); + + if (maze[x][y] === 'E') { + return "Maze is solvable."; + } + + maze[x][y] = 1; // Mark as visited + + for (const [dx, dy] of moves) { + const newX = x + dx; + const newY = y + dy; + + if (newX >= 0 && newX < rows && newY >= 0 && newY < cols && maze[newX][newY] === 0) { + queue.push([newX, newY]); + } + } + } + + return "Maze has no solution."; +} + +console.log(solveMazeBFS(maze)); + + +class PriorityQueue { + constructor() { + this.elements = []; + } + + enqueue(element, priority) { + this.elements.push({ element, priority }); + this.elements.sort((a, b) => a.priority - b.priority); + } + + dequeue() { + return this.elements.shift().element; + } + + isEmpty() { + return this.elements.length === 0; + } +} + +function heuristic(x1, y1, x2, y2) { + // A simple heuristic function (Manhattan distance) + return Math.abs(x1 - x2) + Math.abs(y1 - y2); +} + +function solveMazeAStar(maze) { + const rows = maze.length; + const cols = maze[0].length; + + // Find the start and end points + let startX, startY, endX, endY; + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (maze[i][j] === 'S') { + startX = i; + startY = j; + } else if (maze[i][j] === 'E') { + endX = i; + endY = j; + } + } + } + + const openSet = new PriorityQueue(); + openSet.enqueue({ x: startX, y: startY, cost: 0 }, 0); + + const cameFrom = {}; + const gScore = {}; + + gScore[`${startX}-${startY}`] = 0; + + while (!openSet.isEmpty()) { + const current = openSet.dequeue(); + const { x, y } = current; + + if (x === endX && y === endY) { + // Reconstruct the path + const path = []; + let currentNode = { x: endX, y: endY }; + while (currentNode) { + path.unshift(currentNode); + currentNode = cameFrom[`${currentNode.x}-${currentNode.y}`]; + } + return path; + } + + for (const [dx, dy] of [[1, 0], [-1, 0], [0, 1], [0, -1]]) { + const newX = x + dx; + const newY = y + dy; + + if ( + newX >= 0 && + newX < rows && + newY >= 0 && + newY < cols && + maze[newX][newY] !== 1 + ) { + const tentativeGScore = gScore[`${x}-${y}`] + 1; + + if ( + !gScore[`${newX}-${newY}`] || + tentativeGScore < gScore[`${newX}-${newY}`] + ) { + cameFrom[`${newX}-${newY}`] = { x, y }; + gScore[`${newX}-${newY}`] = tentativeGScore; + const fScore = + tentativeGScore + heuristic(newX, newY, endX, endY); + openSet.enqueue({ x: newX, y: newY, cost: fScore }, fScore); + } + } + } + } + + return "Maze has no solution."; +} + +const path = solveMazeAStar(maze); + +if (path !== "Maze has no solution.") { + console.log("Path found:"); + path.forEach((cell, index) => { + console.log(`Step ${index + 1}: (${cell.x}, ${cell.y})`); + }); +} else { + console.log("Maze has no solution."); +} diff --git a/DSA/Graphs/Prim'sAlgorithm.js b/DSA/Graphs/Prim'sAlgorithm.js new file mode 100644 index 0000000..0201e0c --- /dev/null +++ b/DSA/Graphs/Prim'sAlgorithm.js @@ -0,0 +1,53 @@ +primsMST() { + // Initialize graph that'll contain the MST + const MST = new Graph(); + if (this.nodes.length === 0) { + return MST; + } + + + // Select first node as starting node + let s = this.nodes[0]; + + + // Create a Priority Queue and explored set + let edgeQueue = new PriorityQueue(this.nodes.length * this.nodes.length); + let explored = new Set(); + explored.add(s); + MST.addNode(s); + + + // Add all edges from this starting node to the PQ taking weights as priority + this.edges[s].forEach(edge => { + edgeQueue.enqueue([s, edge.node], edge.weight); + }); + + + // Take the smallest edge and add that to the new graph + let currentMinEdge = edgeQueue.dequeue(); + while (!edgeQueue.isEmpty()) { + + + // Continue removing edges till we get an edge with an unexplored node + while (!edgeQueue.isEmpty() && explored.has(currentMinEdge.data[1])) { + currentMinEdge = edgeQueue.dequeue(); + } + let nextNode = currentMinEdge.data[1]; + + + // Check again as queue might get empty without giving back unexplored element + if (!explored.has(nextNode)) { + MST.addNode(nextNode); + MST.addEdge(currentMinEdge.data[0], nextNode, currentMinEdge.priority); + // Again add all edges to the PQ + this.edges[nextNode].forEach(edge => { + edgeQueue.enqueue([nextNode, edge.node], edge.weight); + }); + + + // Mark this node as explored explored.add(nextNode); + s = nextNode; + } + } + return MST; +} diff --git a/DSA/Graphs/Travelling Salesman Problem/AntColonyOptimization.js b/DSA/Graphs/Travelling Salesman Problem/AntColonyOptimization.js new file mode 100644 index 0000000..3096252 --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/AntColonyOptimization.js @@ -0,0 +1,101 @@ +function antColonyOptimizationTSP(cities, distances, numAnts, maxIterations, pheromoneEvaporationRate, alpha, beta) { + const numCities = cities.length; + const initialPheromoneLevel = 1 / (numCities * numCities); + let pheromoneMatrix = Array.from({ length: numCities }, () => + Array(numCities).fill(initialPheromoneLevel) + ); + let bestOrder; + let bestDistance = Infinity; + + for (let iteration = 0; iteration < maxIterations; iteration++) { + const antPaths = []; + for (let ant = 0; ant < numAnts; ant++) { + const path = constructAntPath(pheromoneMatrix, distances, alpha, beta); + antPaths.push(path); + const pathDistance = calculateTotalDistance(path, distances); + if (pathDistance < bestDistance) { + bestOrder = path; + bestDistance = pathDistance; + } + } + + updatePheromoneMatrix(pheromoneMatrix, antPaths, pheromoneEvaporationRate); + } + + return { order: bestOrder, distance: bestDistance }; +} + +function constructAntPath(pheromoneMatrix, distances, alpha, beta) { + const numCities = pheromoneMatrix.length; + const startCity = Math.floor(Math.random() * numCities); + let currentCity = startCity; + const path = [startCity]; + const unvisitedCities = new Set([...Array(numCities).keys()].filter((i) => i !== startCity)); + + while (unvisitedCities.size > 0) { + const nextCity = chooseNextCity(currentCity, unvisitedCities, pheromoneMatrix, distances, alpha, beta); + path.push(nextCity); + unvisitedCities.delete(nextCity); + currentCity = nextCity; + } + + return path; +} + +function chooseNextCity(currentCity, unvisitedCities, pheromoneMatrix, distances, alpha, beta) { + const pheromoneLevels = []; + const totalProbability = [...unvisitedCities].reduce((sum, city) => { + const pheromone = pheromoneMatrix[currentCity][city]; + const distance = distances[currentCity][city]; + const probability = Math.pow(pheromone, alpha) * Math.pow(1 / distance, beta); + pheromoneLevels.push(probability); + return sum + probability; + }, 0); + + const randomValue = Math.random() * totalProbability; + let accumulatedProbability = 0; + + for (let i = 0; i < pheromoneLevels.length; i++) { + accumulatedProbability += pheromoneLevels[i]; + if (accumulatedProbability >= randomValue) { + return [...unvisitedCities][i]; + } + } + + return [...unvisitedCities][0]; // Fallback in case of numerical instability +} + +function updatePheromoneMatrix(pheromoneMatrix, antPaths, pheromoneEvaporationRate) { + const numCities = pheromoneMatrix.length; + + // Evaporate pheromone + for (let i = 0; i < numCities; i++) { + for (let j = 0; j < numCities; j++) { + pheromoneMatrix[i][j] *= (1 - pheromoneEvaporationRate); + } + } + + // Deposit pheromone based on ant paths + for (const path of antPaths) { + const pathDistance = calculateTotalDistance(path, distances); + for (let i = 0; i < path.length - 1; i++) { + const fromCity = path[i]; + const toCity = path[i + 1]; + pheromoneMatrix[fromCity][toCity] += 1 / pathDistance; + pheromoneMatrix[toCity][fromCity] += 1 / pathDistance; + } + } +} + +// Test case +const cities = ["A", "B", "C", "D"]; +const distances = [ + [0, 10, 15, 20], + [10, 0, 35, 25], + [15, 35, 0, 30], + [20, 25, 30, 0], +]; + +const result = antColonyOptimizationTSP(cities, distances, 10, 100, 0.5, 1.0, 2.0); +console.log("Ant Colony Optimization Order:", result.order.map((idx) => cities[idx]).join(" -> ")); +console.log("Ant Colony Optimization Distance:", result.distance); diff --git a/DSA/Graphs/Travelling Salesman Problem/BranchAndBound.js b/DSA/Graphs/Travelling Salesman Problem/BranchAndBound.js new file mode 100644 index 0000000..68e764e --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/BranchAndBound.js @@ -0,0 +1,50 @@ +function tspBranchAndBound(cities, distances) { + const n = cities.length; + const visited = new Array(n).fill(false); + visited[0] = true; + const initialPath = [0]; + const { order, distance } = branchAndBoundHelper(0, initialPath, 0, Infinity); + + function branchAndBoundHelper(currentCity, path, currentDistance, bestDistance) { + if (path.length === n) { + return { order: path, distance: currentDistance + distances[currentCity][0] }; + } + + let minDistance = bestDistance; + let minOrder = []; + + for (let nextCity = 0; nextCity < n; nextCity++) { + if (!visited[nextCity]) { + visited[nextCity] = true; + const newPath = [...path, nextCity]; + const newDistance = currentDistance + distances[currentCity][nextCity]; + + if (newDistance < minDistance) { + const result = branchAndBoundHelper(nextCity, newPath, newDistance, minDistance); + if (result.distance < minDistance) { + minDistance = result.distance; + minOrder = result.order; + } + } + + visited[nextCity] = false; + } + } + + return { order: minOrder, distance: minDistance }; + } + + return { order, distance }; +} + +// Test case +const cities = ["A", "B", "C"]; +const distances = [ + [0, 10, 15], + [10, 0, 20], + [15, 20, 0], +]; + +const result = tspBranchAndBound(cities, distances); +console.log("Branch and Bound Optimal Order:", result.order.map((idx) => cities[idx]).join(" -> ")); +console.log("Branch and Bound Optimal Distance:", result.distance); diff --git a/DSA/Graphs/Travelling Salesman Problem/BruteForce.js b/DSA/Graphs/Travelling Salesman Problem/BruteForce.js new file mode 100644 index 0000000..fdba98c --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/BruteForce.js @@ -0,0 +1,45 @@ +function permute(arr) { + if (arr.length === 0) return [[]]; + const [first, ...rest] = arr; + const permutationsWithoutFirst = permute(rest); + return permutationsWithoutFirst.flatMap((perm) => + perm.map((_, idx) => [...perm.slice(0, idx), first, ...perm.slice(idx)]) + ); +} + +function calculateTotalDistance(order, distances) { + let totalDistance = 0; + for (let i = 0; i < order.length - 1; i++) { + totalDistance += distances[order[i]][order[i + 1]]; + } + return totalDistance; +} + +function bruteForceTSP(cities, distances) { + const cityIndices = Array.from({ length: cities.length }, (_, i) => i); + const permutations = permute(cityIndices); + let minDistance = Infinity; + let bestOrder = []; + + for (const perm of permutations) { + const distance = calculateTotalDistance(perm, distances); + if (distance < minDistance) { + minDistance = distance; + bestOrder = perm; + } + } + + return { order: bestOrder, distance: minDistance }; +} + +// Test case +const cities = ["A", "B", "C"]; +const distances = [ + [0, 10, 15], + [10, 0, 20], + [15, 20, 0], +]; + +const result = bruteForceTSP(cities, distances); +console.log("Optimal Order:", result.order.map((idx) => cities[idx]).join(" -> ")); +console.log("Optimal Distance:", result.distance); \ No newline at end of file diff --git a/DSA/Graphs/Travelling Salesman Problem/ChristofidesAlgorithm.js b/DSA/Graphs/Travelling Salesman Problem/ChristofidesAlgorithm.js new file mode 100644 index 0000000..1ea53c3 --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/ChristofidesAlgorithm.js @@ -0,0 +1,127 @@ +function minimumSpanningTree(graph) { + const numVertices = graph.length; + const parent = new Array(numVertices).fill(-1); + const key = new Array(numVertices).fill(Infinity); + const inMST = new Array(numVertices).fill(false); + + key[0] = 0; + + for (let count = 0; count < numVertices - 1; count++) { + const u = minKey(key, inMST); + inMST[u] = true; + + for (let v = 0; v < numVertices; v++) { + if (graph[u][v] && !inMST[v] && graph[u][v] < key[v]) { + parent[v] = u; + key[v] = graph[u][v]; + } + } + } + + return parent; +} + +function minKey(key, inMST) { + const numVertices = key.length; + let min = Infinity; + let minIndex = -1; + + for (let v = 0; v < numVertices; v++) { + if (!inMST[v] && key[v] < min) { + min = key[v]; + minIndex = v; + } + } + + return minIndex; +} + +function minimumWeightPerfectMatching(graph, parent) { + const numVertices = graph.length; + const edges = []; + + for (let i = 1; i < numVertices; i++) { + edges.push([i, parent[i]]); + } + + const matching = []; + + const visited = new Array(numVertices).fill(false); + + for (const [u, v] of edges) { + if (!visited[u] && !visited[v]) { + matching.push([u, v]); + visited[u] = visited[v] = true; + } + } + + return matching; +} + +function eulerianTour(graph, startVertex) { + const tour = []; + const stack = [startVertex]; + while (stack.length) { + const currentVertex = stack.pop(); + tour.push(currentVertex); + for (let i = graph[currentVertex].length - 1; i >= 0; i--) { + if (graph[currentVertex][i] !== 0) { + stack.push(i); + graph[currentVertex][i] = graph[i][currentVertex] = 0; // Remove edge to avoid revisiting + } + } + } + return tour; +} + +function christofidesTSP(cities, distances) { + const numCities = cities.length; + const minimumSpanningTreeGraph = minimumSpanningTree(distances); + const matching = minimumWeightPerfectMatching(distances, minimumSpanningTreeGraph); + const graph = Array(numCities).fill(null).map(() => Array(numCities).fill(0)); + + for (const [u, v] of matching) { + graph[u][v] = graph[v][u] = distances[u][v]; + } + + for (let i = 0; i < numCities; i++) { + for (let j = 0; j < numCities; j++) { + if (minimumSpanningTreeGraph[i] !== j) { + graph[i][j] = distances[i][j]; + } + } + } + + const eulerianTourPath = eulerianTour(graph, 0); + const visited = new Set(); + const hamiltonianTour = []; + + for (const vertex of eulerianTourPath) { + if (!visited.has(vertex)) { + hamiltonianTour.push(vertex); + visited.add(vertex); + } + } + + hamiltonianTour.push(hamiltonianTour[0]); + + let totalDistance = 0; + for (let i = 0; i < hamiltonianTour.length - 1; i++) { + totalDistance += distances[hamiltonianTour[i]][hamiltonianTour[i + 1]]; + } + + return { order: hamiltonianTour, distance: totalDistance }; +} + +// Test case +const cities = ["A", "B", "C", "D"]; +const distances = [ + [0, 10, 15, 20], + [10, 0, 35, 25], + [15, 35, 0, 30], + [20, 25, 30, 0], +]; + +const result = christofidesTSP(cities, distances); +console.log("Christofides Algorithm Order:", result.order.map((idx) => cities[idx]).join(" -> ")); +console.log("Christofides Algorithm Distance:", result.distance); diff --git a/DSA/Graphs/Travelling Salesman Problem/DynamicProgramingBitmask.js b/DSA/Graphs/Travelling Salesman Problem/DynamicProgramingBitmask.js new file mode 100644 index 0000000..60d237a --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/DynamicProgramingBitmask.js @@ -0,0 +1,40 @@ +function tspDynamicProgrammingBitmask(cities, distances) { + const n = cities.length; + const memo = new Array(n).fill(null).map(() => new Array(1 << n).fill(null)); + + function dp(node, bitmask) { + if (bitmask === (1 << n) - 1) { + return distances[node][0]; + } + + if (memo[node][bitmask] !== null) { + return memo[node][bitmask]; + } + + let minDistance = Infinity; + for (let nextNode = 0; nextNode < n; nextNode++) { + if ((bitmask & (1 << nextNode)) === 0) { + const newDistance = distances[node][nextNode] + dp(nextNode, bitmask | (1 << nextNode)); + minDistance = Math.min(minDistance, newDistance); + } + } + + memo[node][bitmask] = minDistance; + return minDistance; + } + + const initialBitmask = 1; // Start from city 0 + const minDistance = dp(0, initialBitmask); + return minDistance; +} + +// Test case +const cities = ["A", "B", "C"]; +const distances = [ + [0, 10, 15], + [10, 0, 20], + [15, 20, 0], +]; + +const result = tspDynamicProgrammingBitmask(cities, distances); +console.log("Dynamic Programming (Bitmask) Optimal Distance:", result); diff --git a/DSA/Graphs/Travelling Salesman Problem/Dynamic_programming.js b/DSA/Graphs/Travelling Salesman Problem/Dynamic_programming.js new file mode 100644 index 0000000..f66fb90 --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/Dynamic_programming.js @@ -0,0 +1,44 @@ +function dynamicProgrammingTSP(cities, distances) { + const numCities = cities.length; + const numStates = 1 << numCities; // 2^n states to represent subsets of cities + const memo = Array(numCities) + .fill(null) + .map(() => Array(numStates).fill(null)); + + function tspDP(currentCity, state) { + if (state === (1 << numCities) - 1) { + // All cities visited, return to the starting city + return distances[currentCity][0]; + } + + if (memo[currentCity][state] !== null) { + return memo[currentCity][state]; + } + + let minDistance = Infinity; + for (let nextCity = 0; nextCity < numCities; nextCity++) { + if ((state & (1 << nextCity)) === 0) { + // Next city not visited + const newDistance = distances[currentCity][nextCity] + tspDP(nextCity, state | (1 << nextCity)); + minDistance = Math.min(minDistance, newDistance); + } + } + + memo[currentCity][state] = minDistance; + return minDistance; + } + + const optimalDistance = tspDP(0, 1); // Start from city 0 (the first city), with only city 0 visited + return optimalDistance; +} + +// Test case +const cities = ["A", "B", "C"]; +const distances = [ + [0, 10, 15], + [10, 0, 20], + [15, 20, 0], +]; + +const result = dynamicProgrammingTSP(cities, distances); +console.log("Dynamic Programming Optimal Distance:", result); diff --git a/DSA/Graphs/Travelling Salesman Problem/GeneticAlgorithm.js b/DSA/Graphs/Travelling Salesman Problem/GeneticAlgorithm.js new file mode 100644 index 0000000..c0ad8fd --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/GeneticAlgorithm.js @@ -0,0 +1,76 @@ +function generateRandomOrder(n) { + const order = Array.from({ length: n }, (_, i) => i); + for (let i = n - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [order[i], order[j]] = [order[j], order[i]]; // Swap elements randomly + } + return order; +} + +function calculateTotalDistance(order, distances) { + let totalDistance = 0; + for (let i = 0; i < order.length - 1; i++) { + totalDistance += distances[order[i]][order[i + 1]]; + } + return totalDistance; +} + +function geneticAlgorithmTSP(cities, distances, populationSize, generations) { + let population = Array.from({ length: populationSize }, () => generateRandomOrder(cities.length)); + let bestOrder = population[0]; + let minDistance = calculateTotalDistance(bestOrder, distances); + + for (let generation = 0; generation < generations; generation++) { + population = population.sort(() => 0.5 - Math.random()); // Shuffle population + + for (let i = 0; i < populationSize; i += 2) { + const parent1 = population[i]; + const parent2 = population[i + 1]; + const [child1, child2] = crossover(parent1, parent2); + mutate(child1); + mutate(child2); + + population[i] = child1; + population[i + 1] = child2; + } + + const newBestOrder = population[0]; + const newMinDistance = calculateTotalDistance(newBestOrder, distances); + if (newMinDistance < minDistance) { + bestOrder = newBestOrder; + minDistance = newMinDistance; + } + } + + return { order: bestOrder, distance: minDistance }; +} + +// Helper functions for Genetic Algorithm +function crossover(parent1, parent2) { + const n = parent1.length; + const start = Math.floor(Math.random() * n); + const end = Math.floor(Math.random() * (n - start)) + start; + const child1 = parent1.slice(start, end + 1).concat(parent2.filter((city) => !child1.includes(city))); + const child2 = parent2.slice(start, end + 1).concat(parent1.filter((city) => !child2.includes(city))); + return [child1, child2]; +} + +function mutate(order) { + const n = order.length; + const i = Math.floor(Math.random() * n); + const j = (i + 1) % n; + [order[i], order[j]] = [order[j], order[i]]; // Swap two cities +} + +// Test case +const cities = ["A", "B", "C", "D"]; +const distances = [ + [0, 10, 15, 20], + [10, 0, 35, 25], + [15, 35, 0, 30], + [20, 25, 30, 0], +]; + +const result = geneticAlgorithmTSP(cities, distances, 100, 1000); +console.log("Genetic Algorithm Order:", result.order.map((idx) => cities[idx]).join(" -> ")); +console.log("Genetic Algorithm Distance:", result.distance); diff --git a/DSA/Graphs/Travelling Salesman Problem/HeuristicApproach.js b/DSA/Graphs/Travelling Salesman Problem/HeuristicApproach.js new file mode 100644 index 0000000..d68cb97 --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/HeuristicApproach.js @@ -0,0 +1,44 @@ +function solveILPHeuristic() { + const coefficients = [2, 3, 5]; // Coefficients of the objective function + const constraintCoefficients = [ + [1, 2, 1], // Coefficients of the constraints + ]; + const constraintLimits = [0]; // Right-hand side of the constraints + + const numVariables = coefficients.length; + const numConstraints = constraintCoefficients.length; + + const solution = Array(numVariables).fill(0); + let objectiveValue = 0; + + for (let i = 0; i < numVariables; i++) { + // Calculate the marginal contribution of variable i to the objective function + const marginalContribution = coefficients[i]; + + // Check if adding variable i to the solution violates any constraints + let isFeasible = true; + for (let j = 0; j < numConstraints; j++) { + let constraintValue = 0; + for (let k = 0; k < numVariables; k++) { + constraintValue += solution[k] * constraintCoefficients[j][k]; + } + if (constraintValue + constraintCoefficients[j][i] > constraintLimits[j]) { + isFeasible = false; + break; + } + } + + // If adding variable i is feasible and improves the objective, include it in the solution + if (isFeasible && marginalContribution > 0) { + solution[i] = 1; + objectiveValue += marginalContribution; + } + } + + return { solution, objectiveValue }; +} + +// Test the heuristic approach for ILP +const result = solveILPHeuristic(); +console.log('Solution:', result.solution); +console.log('Objective Value (approximate):', result.objectiveValue); diff --git a/DSA/Graphs/Travelling Salesman Problem/IntegerLinearProgramming.js b/DSA/Graphs/Travelling Salesman Problem/IntegerLinearProgramming.js new file mode 100644 index 0000000..1d29fe4 --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/IntegerLinearProgramming.js @@ -0,0 +1,52 @@ +function solveILP() { + const coefficients = [2, 3, 5]; // Coefficients of the objective function + const constraintCoefficients = [ + [1, 2, 1], // Coefficients of the constraints + ]; + const constraintLimits = [0]; // Right-hand side of the constraints + + const numVariables = coefficients.length; + const numConstraints = constraintCoefficients.length; + + let bestObjectiveValue = -Infinity; + let bestSolution = Array(numVariables).fill(0); + + // Generate all possible binary combinations for the variables + for (let i = 0; i < Math.pow(2, numVariables); i++) { + const binary = (i >>> 0).toString(2).padStart(numVariables, '0').split('').map(Number); + let isFeasible = true; + + // Check if the binary combination satisfies the constraints + for (let j = 0; j < numConstraints; j++) { + let constraintValue = 0; + for (let k = 0; k < numVariables; k++) { + constraintValue += binary[k] * constraintCoefficients[j][k]; + } + if (constraintValue > constraintLimits[j]) { + isFeasible = false; + break; + } + } + + if (isFeasible) { + // Calculate the objective value for this combination + let objectiveValue = 0; + for (let k = 0; k < numVariables; k++) { + objectiveValue += binary[k] * coefficients[k]; + } + + // Update the best solution if this combination has a better objective value + if (objectiveValue > bestObjectiveValue) { + bestObjectiveValue = objectiveValue; + bestSolution = [...binary]; + } + } + } + + return { solution: bestSolution, objectiveValue: bestObjectiveValue }; +} + +// Test the ILP solver +const result = solveILP(); +console.log('Solution:', result.solution); +console.log('Optimal Objective Value:', result.objectiveValue); diff --git a/DSA/Graphs/Travelling Salesman Problem/IterativeImprovement(Heuristic).js b/DSA/Graphs/Travelling Salesman Problem/IterativeImprovement(Heuristic).js new file mode 100644 index 0000000..3fb118c --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/IterativeImprovement(Heuristic).js @@ -0,0 +1,48 @@ +function iterativeImprovementTSP(cities, distances) { + const numCities = cities.length; + let currentOrder = generateRandomOrder(numCities); + let currentDistance = calculateTotalDistance(currentOrder, distances); + let improvement = true; + + while (improvement) { + improvement = false; + + for (let i = 0; i < numCities - 1; i++) { + for (let j = i + 1; j < numCities; j++) { + const newOrder = twoOptSwap(currentOrder, i, j); + const newDistance = calculateTotalDistance(newOrder, distances); + + if (newDistance < currentDistance) { + currentOrder = newOrder; + currentDistance = newDistance; + improvement = true; + } + } + } + } + + return { order: currentOrder, distance: currentDistance }; +} + +function twoOptSwap(order, i, j) { + const newOrder = [...order]; + while (i < j) { + [newOrder[i], newOrder[j]] = [newOrder[j], newOrder[i]]; + i++; + j--; + } + return newOrder; +} + +// Test case +const cities = ["A", "B", "C", "D"]; +const distances = [ + [0, 10, 15, 20], + [10, 0, 35, 25], + [15, 35, 0, 30], + [20, 25, 30, 0], +]; + +const result = iterativeImprovementTSP(cities, distances); +console.log("Iterative Improvement Order:", result.order.map((idx) => cities[idx]).join(" -> ")); +console.log("Iterative Improvement Distance:", result.distance); diff --git a/DSA/Graphs/Travelling Salesman Problem/Lin-Kernighan.js b/DSA/Graphs/Travelling Salesman Problem/Lin-Kernighan.js new file mode 100644 index 0000000..79b0f88 --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/Lin-Kernighan.js @@ -0,0 +1,73 @@ +function linKernighanTSP(cities, distances) { + const n = cities.length; + let bestTour = []; + let bestCost = Infinity; + + function calculateTourCost(tour) { + let cost = 0; + for (let i = 0; i < n - 1; i++) { + const from = tour[i]; + const to = tour[i + 1]; + cost += distances[from][to]; + } + cost += distances[tour[n - 1]][tour[0]]; // Return to the starting city + return cost; + } + + function reverseSubtour(tour, i, j) { + while (i < j) { + const temp = tour[i]; + tour[i] = tour[j]; + tour[j] = temp; + i++; + j--; + } + } + + function explore(k, tour, gain, canRemove) { + if (k === n) { + const tourCost = calculateTourCost(tour); + if (tourCost < bestCost) { + bestTour = [...tour]; + bestCost = tourCost; + } + } else { + for (let i = k; i < n; i++) { + if (canRemove[tour[i]]) { + for (let j = 0; j < n; j++) { + if (!canRemove[tour[j]]) { + const nextTour = [...tour]; + reverseSubtour(nextTour, k, i); + nextTour[k] = tour[i]; + const newGain = gain - distances[tour[k - 1]][tour[k]] + distances[tour[i]][tour[i + 1]]; + + if (newGain < 0) { + explore(k + 1, nextTour, newGain, canRemove); + } + } + } + } + } + } + } + + const initialTour = Array.from({ length: n }, (_, i) => i); + const canRemove = Array(n).fill(true); + canRemove[0] = false; // Starting city cannot be removed + explore(1, initialTour, 0, canRemove); + + return { order: bestTour.map((idx) => cities[idx]), distance: bestCost }; +} + +// Test case +const cities = ["A", "B", "C", "D"]; +const distances = [ + [0, 10, 15, 20], + [10, 0, 35, 25], + [15, 35, 0, 30], + [20, 25, 30, 0], +]; + +const result = linKernighanTSP(cities, distances); +console.log("Lin-Kernighan Algorithm Order:", result.order.join(" -> ")); +console.log("Lin-Kernighan Algorithm Distance:", result.distance); diff --git a/DSA/Graphs/Travelling Salesman Problem/NearestNeighborAlgorithm.js b/DSA/Graphs/Travelling Salesman Problem/NearestNeighborAlgorithm.js new file mode 100644 index 0000000..9202d2e --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/NearestNeighborAlgorithm.js @@ -0,0 +1,38 @@ +function nearestNeighborTSP(cities, distances) { + const n = cities.length; + const visited = Array(n).fill(false); + const order = [0]; // Start from the first city (index 0) + let totalDistance = 0; + + visited[0] = true; + for (let i = 1; i < n; i++) { + let nearestIdx = -1; + let minDistance = Infinity; + + for (let j = 0; j < n; j++) { + if (!visited[j] && distances[order[i - 1]][j] < minDistance) { + nearestIdx = j; + minDistance = distances[order[i - 1]][j]; + } + } + + order.push(nearestIdx); + visited[nearestIdx] = true; + totalDistance += minDistance; + } + + totalDistance += distances[order[n - 1]][order[0]]; // Return to the starting city + return { order, distance: totalDistance }; +} + +// Test case +const cities = ["A", "B", "C"]; +const distances = [ + [0, 10, 15], + [10, 0, 20], + [15, 20, 0], +]; + +const result = nearestNeighborTSP(cities, distances); +console.log("Approximate Order:", result.order.map((idx) => cities[idx]).join(" -> ")); +console.log("Approximate Distance:", result.distance); diff --git a/DSA/Graphs/Travelling Salesman Problem/README.md b/DSA/Graphs/Travelling Salesman Problem/README.md new file mode 100644 index 0000000..d2f0d43 --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/README.md @@ -0,0 +1,57 @@ +# Travelling Salesman Problem + +The Traveling Salesman Problem (TSP) is a classic combinatorial optimization problem in the field of mathematics and computer science. It is a challenging problem that can be stated as follows: + +Given a list of cities and the distances between each pair of cities, the objective is to find the shortest possible route that visits each city exactly once and returns to the starting city. + +In other words, a traveling salesman needs to determine the most efficient way to visit all the cities in their itinerary without revisiting any city and returning to the starting point while minimizing the total distance traveled. The problem is often represented as a graph, where cities are nodes, and the distances between them are represented as edges. + +The Traveling Salesman Problem has numerous practical applications beyond sales, such as: + +1. Logistics and Transportation: Optimizing delivery routes for couriers, trucks, or drones to minimize travel time and fuel costs. + +2. Circuit Design: Designing the most efficient electronic circuit layout to connect a set of components. + +3. Manufacturing: Determining the order in which machines should process parts to minimize production time. + +4. DNA Sequencing: Finding the optimal order to sequence fragments of DNA in genomics research. + +5. Network Design: Planning the most efficient layout for connecting network nodes while minimizing data transmission costs. + +The TSP is a well-known NP-hard problem, which means that finding the optimal solution becomes increasingly difficult as the number of cities increases. There are various algorithms and heuristics used to approximate solutions to the TSP, such as brute force, dynamic programming, and various metaheuristic methods like genetic algorithms, simulated annealing, and ant colony optimization. + +Due to its computational complexity, finding the exact optimal solution for large instances of the TSP is often infeasible, and approximation algorithms are used to find near-optimal solutions that are practical for real-world applications. + +## Solution to the Travelling Salesman Problem + +### Exact Algorithms: + + 1. Brute Force: Enumerate all possible permutations of cities and calculate the total distance for each permutation to find the optimal solution. Practical only for small problem instances due to its exponential time complexity. + + 2. Dynamic Programming: The Held-Karp algorithm is a dynamic programming approach that improves efficiency by avoiding redundant calculations. It can solve TSP for moderate-sized instances but still has exponential time complexity in the worst case. + +### Approximation Algorithms: + + 1. Nearest Neighbor Algorithm: Start from a selected city and repeatedly choose the nearest unvisited city until all cities are visited. This is a simple and fast heuristic but may not always produce optimal solutions. + + 2. Christofides Algorithm: An approximation algorithm that guarantees a solution within 3/2 times the optimal solution for metric TSP instances (where distances satisfy the triangle inequality). It includes minimum spanning tree and minimum-weight perfect matching steps. + + 3. Lin-Kernighan Algorithm: An improvement heuristic that iteratively swaps edges in the tour to improve the solution quality. + +### Metaheuristic Algorithms: + + 1. Genetic Algorithms: Inspired by natural selection, these algorithms involve creating a population of candidate solutions and iteratively evolving them through selection, crossover, and mutation operations. Genetic algorithms can be effective for finding near-optimal solutions. + + 2. Simulated Annealing: Based on the annealing process in metallurgy, this algorithm explores the solution space by accepting suboptimal solutions with a decreasing probability as the search progresses. It can escape local optima. + + 3. Ant Colony Optimization: Inspired by the foraging behavior of ants, this algorithm models the exploration of solution space as ants deposit pheromones on edges. Over time, paths with higher pheromone concentrations are more likely to be chosen. + + 4. Integer Linear Programming (ILP): Formulate the TSP as an ILP problem and use ILP solvers like CPLEX or Gurobi to find exact solutions for small to moderately sized instances. + + 5. Heuristic Approaches: Various heuristics and custom algorithms can be designed specifically for certain types of TSP instances, such as planar TSP, Euclidean TSP, or TSP with time windows. + + 6. Hybrid Approaches: Combine multiple algorithms or heuristics to improve solution quality and efficiency. For example, a genetic algorithm might be enhanced with local search. + + 7. Preprocessing and Data Reduction: Reduce the problem size by removing dominated or redundant cities or by using geometric properties of the problem to simplify the search. + +The choice of method depends on factors such as the size and type of the TSP instance, the desired solution quality, and available computational resources. In practice, many large TSP instances are solved using approximation algorithms or metaheuristic methods to find high-quality solutions efficiently. diff --git a/DSA/Graphs/Travelling Salesman Problem/SimulatedAnnealing.js b/DSA/Graphs/Travelling Salesman Problem/SimulatedAnnealing.js new file mode 100644 index 0000000..907878a --- /dev/null +++ b/DSA/Graphs/Travelling Salesman Problem/SimulatedAnnealing.js @@ -0,0 +1,41 @@ +function simulatedAnnealingTSP(cities, distances, temperature, coolingRate) { + let currentOrder = generateRandomOrder(cities.length); + let currentDistance = calculateTotalDistance(currentOrder, distances); + let bestOrder = currentOrder.slice(); + let minDistance = currentDistance; + + while (temperature > 1) { + const i = Math.floor(Math.random() * cities.length); + const j = Math.floor(Math.random() * cities.length); + const newOrder = currentOrder.slice(); + [newOrder[i], newOrder[j]] = [newOrder[j], newOrder[i]]; // Swap two cities + const newDistance = calculateTotalDistance(newOrder, distances); + + const delta = newDistance - currentDistance; + if (delta < 0 || Math.random() < Math.exp(-delta / temperature)) { + currentOrder = newOrder; + currentDistance = newDistance; + if (currentDistance < minDistance) { + bestOrder = currentOrder.slice(); + minDistance = currentDistance; + } + } + + temperature *= coolingRate; + } + + return { order: bestOrder, distance: minDistance }; +} + +// Test case +const cities = ["A", "B", "C", "D"]; +const distances = [ + [0, 10, 15, 20], + [10, 0, 35, 25], + [15, 35, 0, 30], + [20, 25, 30, 0], +]; + +const result = simulatedAnnealingTSP(cities, distances, 1000, 0.99); +console.log("Simulated Annealing Order:", result.order.map((idx) => cities[idx]).join(" -> ")); +console.log("Simulated Annealing Distance:", result.distance); diff --git a/DSA/Miscelleneous/SmallestCommonMultiple.js b/DSA/Miscelleneous/SmallestCommonMultiple.js new file mode 100644 index 0000000..b18d7e8 --- /dev/null +++ b/DSA/Miscelleneous/SmallestCommonMultiple.js @@ -0,0 +1,36 @@ +/* + +Find the smallest common multiple of the provided parameters that can be evenly divided by both, as well as by +all sequential numbers in the range between these parameters. + +The range will be an array of two numbers that will not necessarily be in numerical order. + +For example, if given 1 and 3, find the smallest common multiple of both 1 and 3 that is also evenly divisible +by all numbers between 1 and 3. The answer here would be 6. + +*/ + +function smallestCommons(arr) { + var range = []; + for (var i = Math.max(arr[0], arr[1]); i >= Math.min(arr[0], arr[1]); i--) { + range.push(i); + } + + // could use reduce() in place of this block + var lcm = range[0]; + for (i = 1; i < range.length; i++) { + var GCD = gcd(lcm, range[i]); + lcm = (lcm * range[i]) / GCD; + } + return lcm; + + function gcd(x, y) { + if (y === 0) + return x; + else + return gcd(y, x%y); + } +} + +// test here +smallestCommons([1,5]); diff --git a/DSA/Miscelleneous/mark_and_sweep.js b/DSA/Miscelleneous/mark_and_sweep.js new file mode 100644 index 0000000..e78b511 --- /dev/null +++ b/DSA/Miscelleneous/mark_and_sweep.js @@ -0,0 +1,115 @@ +let HEAP = []; + +const A = { + language: "JavaScript", +}; + +HEAP.push(A); + +const root = () => HEAP[0]; + +const B = { + language: "Rust", +}; + +HEAP.push(B); + +A.B = B; + +const C = { + language: "Elm", +}; + +HEAP.push(C); + +A.C = C; + +// Let's remove the reference C +delete A.C; + +const D = { + language: "GoLang", +}; + +HEAP.push(D); + +// Object "D" is reachable from "B" and is allocated the memory +B.D = D; + +// "B" reference is removed from "A". +delete A.B; + +// It means that "D" still has the reference to it from "B" but it's +// not reachable (because B is not reachable anymore) + +// After these manipulations, the heap still contains four objects: +// [{ A }, { B }, { C }, { D }], but only the "A" object is reachable (root) + +// Garbage collector (uses mark and sweep algorithm ) +const gc = () => { + // Set __mark__ bits on the reachable objects to 1 + mark(); + + // Collect the garbage (objects with __mark__ bit not set to 1) + sweep(); +}; + +// Traverse all the reachable objects starting from the root and set the +// __mark__ bit on it to 1 +const mark = () => { + // Initially only the root is reachable + let reachables = [root()]; + + while (reachables.length) { + // Get the next object + let current = reachables.pop(); + // Mark the object if it is not already marked + if (!current.__markBit__) { + current.__markBit__ = 1; + // add all the reachable objects from the current object + // reachables array + for (let i in current) { + if (typeof current[i] === "object") { + // Add it to the reachables + reachables.push(current[i]); + } + } + } + } +}; + +// Traverse the heap and move all unmarked or unreachable objects to the free list. +const sweep = () => { + // Update the state + HEAP = HEAP.filter((current) => { + // For future Garbage collection cycles, reset the __markBit__ bit to 0 + if (current.__markBit__ === 1) { + current.__markBit__ = 0; + return true; + } else return false; // move it to the free list + }); +}; + +const main = () => { + console.log("\nHeap state before garbage collection: ", HEAP); + + // Make a call to garbage collector + gc(); + + console.log("\nHeap state after garbage collection: ", HEAP); +}; + +main(); + +/* +Output--> + +Heap state before garbage collection: [ + { language: 'JavaScript' }, + { language: 'Rust', D: { language: 'GoLang' } }, + { language: 'Elm' }, + { language: 'GoLang' } +] + +Heap state after garbage collection: [ { language: 'JavaScript', __markBit__: 0 } ] +*/ diff --git a/DSA/Strings/Capitalize.js b/DSA/Strings/Capitalize.js new file mode 100644 index 0000000..0333a33 --- /dev/null +++ b/DSA/Strings/Capitalize.js @@ -0,0 +1,16 @@ +// Convert a sentence to title case using Javascript +// example: Input: this is a phrase +// Output: This Is A Phrase + +const toTitleCase = (sentence) => { + let words = sentence.split(' '); + let capitalizedSentence = ''; + words.forEach((word) => { + capitalizedSentence += String(word).charAt(0).toUpperCase() + word.slice(1) + ' '; + }) + + return capitalizedSentence.trim(); +} +const sentence = 'this is a sentence' + +console.log(toTitleCase(sentence)); \ No newline at end of file diff --git a/DSA/Strings/ShortestSubstring.js b/DSA/Strings/ShortestSubstring.js new file mode 100644 index 0000000..e141cd7 --- /dev/null +++ b/DSA/Strings/ShortestSubstring.js @@ -0,0 +1,32 @@ +// This function compares two sets 'a' and 'b' to check if they have the same elements. +// It returns true if the sets have the same elements, and false otherwise. +const compareSets = (a, b) => a.size === b.size && [...a].every(e => b.has(e)) + +// This function, 'shortestSubstring', calculates the length of the shortest substring +// in the input string 's' that contains all unique characters present in the original string. +function shortestSubstring(s) { + let len = s.length; // Get the length of the input string. + let uniqueChars = new Set(Array.from(s)); // Create a set of unique characters from the input string. + let subString = ''; // Initialize an empty substring. + let mLen = len + 1; // Initialize 'mLen' to be greater than the length of the input string. + + // Nested loops to find all possible substrings. + for (let i = 0; i < len; i++) { + for (let j = i; j < len; j++) { + subString = subString + s[j]; // Add characters to the current substring. + + // Check if the unique characters of the current substring match the unique characters of the input string. + if (compareSets(new Set(subString), uniqueChars)) { + if (mLen > subString.length) { + mLen = subString.length; // Update 'mLen' if a shorter valid substring is found. + } + break; // Exit the inner loop once a valid substring is found. + } + } + subString = ''; // Reset the current substring for the next iteration. + } + + return mLen; // Return the length of the shortest valid substring. +} + +console.log(shortestSubstring('bcaacbc')); // Example usage of the function. diff --git a/EloquentJS/Notes/HOF.md b/EloquentJS/Notes/HOF.md index d952297..3f2376d 100644 --- a/EloquentJS/Notes/HOF.md +++ b/EloquentJS/Notes/HOF.md @@ -10,7 +10,7 @@ Abstractions hide details and give us the ability to talk about problems at a hi Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions. -``` +```js function greaterThan(n) { return m => m > n; } @@ -21,7 +21,7 @@ console.log(greaterThan10(11)); Another Example... -``` +```js function noisy(f) { return (...args) => { console.log("calling with", args); @@ -40,7 +40,7 @@ noisy(Math.min)(3, 2, 1); There is a built-in array method, forEach, that provides something like a for/of loop as a higher-order function. -``` +```js ["A", "B"].forEach(l => console.log(l)); // → A // → B @@ -54,7 +54,7 @@ It returns a new array that has filtered values. Suppose we have some SCRIPT data, then: -``` +```js SCRIPT.filter(s => s.direction == "ttb") ``` @@ -62,7 +62,7 @@ SCRIPT.filter(s => s.direction == "ttb") Map function is used for mapping each value of the passed iterator object to a particular another value based on the `transform` method passed. -``` +```js SCRIPT.map(s=> s.name); ``` @@ -74,12 +74,12 @@ It builds a value by repeatedly taking a single element from the array and combi Parameters to reduce are: Array, Combining function and a Start value. -``` +```js console.log([1, 2, 3, 4].reduce((a, b) => a + b)); // → 10 ``` -``` +```js function characterCount(script) { return script.ranges.reduce((count, [from, to]) => { return count + (to - from); @@ -97,7 +97,7 @@ console.log(SCRIPTS.reduce((a, b) => { -``` +```js function average(array) { return array.reduce((a, b) => a + b) / array.length; } diff --git a/InterviewQuestions/DecimaltoRoman.js b/InterviewQuestions/DecimaltoRoman.js new file mode 100644 index 0000000..5616166 --- /dev/null +++ b/InterviewQuestions/DecimaltoRoman.js @@ -0,0 +1,53 @@ +// javascript code implementation + +function integerToRoman(num) { + let roman = new Map(); // move outside + roman.set(1, 'I'); + roman.set(5, 'V'); + roman.set(10, 'X'); + roman.set(50, 'L'); + roman.set(100, 'C'); + roman.set(500, 'D'); + roman.set(1000, 'M'); + roman.set(5000, 'G'); + roman.set(10000, 'H'); + + let tmp = Array.from(String(num)); + let numDigits = tmp.length; + + let res = []; + for(let i=0;i= 5) { + res.push(roman.get(5*absolute)); + + let cnt = number-5; + while(cnt--) res.push(roman.get(absolute)); + } + else{ + if (number >= 4) { + res.push(roman.get(absolute)); + res.push(roman.get(5*absolute)); + } + else { + + let cnt = number; + while(cnt--) res.push(roman.get(absolute)); + } + } + } + return res; +} + +let ans = integerToRoman(3549).join(''); +console.log(ans); + +// This code is contributed by Nidhi goel. diff --git a/InterviewQuestions/README.md b/InterviewQuestions/README.md new file mode 100644 index 0000000..fcdfdfe --- /dev/null +++ b/InterviewQuestions/README.md @@ -0,0 +1,18 @@ +# JS Interview Questions Practice Resources + +### Interview Questions Blogs +- https://javascript.plainenglish.io/some-of-the-javascript-interview-questions-i-have-experienced-ce802e4e107d +- https://levelup.gitconnected.com/7-common-frontend-interview-questions-c8dddd3a9382 +- https://www.freecodecamp.org/news/3-questions-to-watch-out-for-in-a-javascript-interview-725012834ccb/ +- https://blog.usejournal.com/most-frequently-asked-topics-in-the-javascript-interview-part-ii-ac9468970d5d +- What would you ask in FE interview: https://www.quora.com/What-would-you-ask-in-a-JavaScript-frontend-interview +- http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/ + +### Concepts and Topics Resources +- Many Good JS Interview Practice Topics: https://skilled.dev/course +- Pub Sub Architecture by Gaurav Sen: https://www.youtube.com/watch?v=FMhbR_kQeHw +- Pub Sub Architecture by Hussain: https://www.youtube.com/watch?v=O1PgqUqZKTA +- RabbitMQ: https://www.youtube.com/watch?v=Cie5v59mrTg&t=44s +- REST API: https://www.youtube.com/watch?v=M3XQ6yEC51Q&list=PLQnljOFTspQXNP6mQchJVP3S-3oKGEuw9&index=1 +- Build a JavaScript Promise: https://skilled.dev/course/build-a-javascript-promise +- Essential Design Patterns: https://addyosmani.com/resources/essentialjsdesignpatterns/book/ \ No newline at end of file diff --git a/InterviewQuestions/customBind.js b/InterviewQuestions/customBind.js new file mode 100644 index 0000000..e69de29 diff --git a/InterviewQuestions/customList.js b/InterviewQuestions/customList.js new file mode 100644 index 0000000..57b5e40 --- /dev/null +++ b/InterviewQuestions/customList.js @@ -0,0 +1,7 @@ +function list() { + console.log(arguments); + return Array.prototype.slice.call(arguments); + } + + const lis = list(1,2,3) + console.log(lis) \ No newline at end of file diff --git a/InterviewQuestions/debounce.js b/InterviewQuestions/debounce.js new file mode 100644 index 0000000..cd865d3 --- /dev/null +++ b/InterviewQuestions/debounce.js @@ -0,0 +1,34 @@ +// Implementation 1 +const getData = () => { + console.log("Fetching Data..."); + }; + + const debounce = (fn, delay) => { + // returns a function that calls getData() only when x ms delay is observed + let timer; + return function () { + // call getData after some interval x + let context = this; + args = arguments; + clearTimeout(timer); + timer = setTimeout(() => { + fn(); + }, delay); + }; + }; + + const debounceFunction = debounce(getData, 1000); + + // Implementation 2 + + function debounce(delay, func){ + let timeoutID = null; + + return function(...args){ + if(timeoutID){ + clearTimeout(timeoutID); + } + + timeoutID = setTimeout(() => func(...args), delay); + } + } \ No newline at end of file diff --git a/InterviewQuestions/findSecondLargestElementInArray.js b/InterviewQuestions/findSecondLargestElementInArray.js new file mode 100644 index 0000000..088e6ed --- /dev/null +++ b/InterviewQuestions/findSecondLargestElementInArray.js @@ -0,0 +1,20 @@ +/** + * Problem statement: Find second largest element in the array. Consider the case wherein duplicates can exist + * arr = [12, 35, 1, 10, 34, 35, 35] - Here 35 occurs 3 times, but second largest element should be 34 + */ +function findSecondLargestElementInArray(arr) { + let largest = -1, + secondLargest = -1; + + for (let i = 0; i <= arr.length - 1; i++) { + if (arr[i] > largest) { + secondLargest = largest; + largest = arr[i]; + } else if (arr[i] > secondLargest && arr[i] != largest) { + secondLargest = arr[i]; + } + } + console.log(secondLargest); +} +let arr = [12, 35, 1, 10, 34, 35, 35]; +findSecondLargestElementInArray(arr); diff --git a/InterviewQuestions/flattenArray.js b/InterviewQuestions/flattenArray.js new file mode 100644 index 0000000..774c786 --- /dev/null +++ b/InterviewQuestions/flattenArray.js @@ -0,0 +1,20 @@ +const arr = [[1,2,3], 2,5,4,56, [4,5,[45,6,7]]]; + +const customFlat = function (arr, level, resArr=[]){ + if(level === 0 ) return arr; + + for(let item of arr){ + if(Array.isArray(item)){ + resArr.push(...item); + }else{ + resArr.push(item); + } + } + resArr = customFlat(resArr, --level); + + return resArr; +} + +const flatArr = customFlat(arr, 5); +console.log(flatArr); + diff --git a/InterviewQuestions/sumFunction.js b/InterviewQuestions/sumFunction.js new file mode 100644 index 0000000..1dd0401 --- /dev/null +++ b/InterviewQuestions/sumFunction.js @@ -0,0 +1,10 @@ +let sum = function(a){ + return function(b){ + if(b === undefined){ + return a; + } + return sum(a+b); + } + } + +console.log(sum(1)(2)(10)(5)()) \ No newline at end of file diff --git a/InterviewQuestions/throttle.js b/InterviewQuestions/throttle.js new file mode 100644 index 0000000..7e837f4 --- /dev/null +++ b/InterviewQuestions/throttle.js @@ -0,0 +1,36 @@ +// Implementation 1 +const getData = () => { + console.log("Fetching Data..."); +}; + +const throttle = (func, limit) => { + let flag = true + return function(){ + let context = this; + let args = arguments; + if(flag){ + func.apply(context, args); + flag = false; + setTimeout(() => { + flag=true; + }, limit); + } + + } +} + +// Implementation 2 + +const throttle2 = (func, limit) => { + let last = new Date().getTime(); + return function(){ + let curr = new Date().getTime(); + if(curr - last < limit){ + return + } + last = current; + return func(...args); + } +} + +const betterThrottle = throttle(getData, 300); \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day01/bg.jpg b/JavaScript Challenges/Javascript 30/Day01/bg.jpg new file mode 100644 index 0000000..869152c Binary files /dev/null and b/JavaScript Challenges/Javascript 30/Day01/bg.jpg differ diff --git a/JavaScript Challenges/Javascript 30/Day01/index.html b/JavaScript Challenges/Javascript 30/Day01/index.html new file mode 100644 index 0000000..3af2c82 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day01/index.html @@ -0,0 +1,139 @@ + + + + + + Drum Kit + + + +
+
+
Q
+
W
+
E
+
R
+
T
+
Y
+
U
+
I
+
O
+
P
+
+
+
A
+
S
+
D
+
F
+
G
+
H
+
J
+
K
+
L
+
+
+
Z
+
X
+
C
+
V
+
B
+
N
+
M
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day01/sounds/claps.wav b/JavaScript Challenges/Javascript 30/Day01/sounds/claps.wav new file mode 100644 index 0000000..991e83e Binary files /dev/null and b/JavaScript Challenges/Javascript 30/Day01/sounds/claps.wav differ diff --git a/JavaScript Challenges/Javascript 30/Day02/index.html b/JavaScript Challenges/Javascript 30/Day02/index.html new file mode 100644 index 0000000..5d2dc4d --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day02/index.html @@ -0,0 +1,99 @@ + + + + + + Clock + + + + +
+
+
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day03/index.html b/JavaScript Challenges/Javascript 30/Day03/index.html new file mode 100644 index 0000000..448d2c2 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day03/index.html @@ -0,0 +1,74 @@ + + + + + + CSS variables + + + + +

Updating CSS Variables with JS

+
+ + + + + + + + + + +
+ + Paris + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day03/paris.jpg b/JavaScript Challenges/Javascript 30/Day03/paris.jpg new file mode 100644 index 0000000..8ac3d37 Binary files /dev/null and b/JavaScript Challenges/Javascript 30/Day03/paris.jpg differ diff --git a/JavaScript Challenges/Javascript 30/Day04/index.html b/JavaScript Challenges/Javascript 30/Day04/index.html new file mode 100644 index 0000000..1e7876b --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day04/index.html @@ -0,0 +1,96 @@ + + + + + + Day 4 - Arrays + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day05/index.html b/JavaScript Challenges/Javascript 30/Day05/index.html new file mode 100644 index 0000000..776538a --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day05/index.html @@ -0,0 +1,142 @@ + + + + + + + Day 5 + + + +
+
+

Hey

+

Let's

+

Dance

+
+
+

Give

+

Take

+

Receive

+
+
+

Experience

+

It

+

Today

+
+
+

Give

+

All

+

You Can

+
+
+

Life

+

In

+

Motion

+
+
+ + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day06/index.html b/JavaScript Challenges/Javascript 30/Day06/index.html new file mode 100644 index 0000000..16a4061 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day06/index.html @@ -0,0 +1,143 @@ + + + + + + Day - 6 + + + + + +
+ +
    +
  • Filter for a city
  • +
  • or a state
  • +
+
+ + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day07/index.js b/JavaScript Challenges/Javascript 30/Day07/index.js new file mode 100644 index 0000000..15db855 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day07/index.js @@ -0,0 +1,45 @@ + +const people = [ + { name: 'Wes', year: 1988 }, + { name: 'Kait', year: 1986 }, + { name: 'Irv', year: 1970 }, + { name: 'Lux', year: 2015 } +]; + +const comments = [ + { text: 'Love this!', id: 523423 }, + { text: 'Super good', id: 823423 }, + { text: 'You are the best', id: 2039842 }, + { text: 'Ramen is my fav food ever', id: 123523 }, + { text: 'Nice Nice Nice!', id: 542328 } +]; + +// Some and Every Checks +// Array.prototype.some() // is at least one person 19 or older? + +const isAdult = people.some(person => ((new Date()).getFullYear()) - person.year >= 19); +console.log(isAdult); //true + +// Array.prototype.every() // is everyone 19 or older? +const allAdults = people.every(person => ((new Date()).getFullYear()) - person.year >= 19); +console.log(allAdults); //false + +// Array.prototype.find() +// Find is like filter, but instead returns just the one you are looking for +// find the comment with the ID of 823423 +let comment = comments.find(comment => comment.id === 823423) +console.log(comment); + +// Array.prototype.findIndex() +// Find the comment with this ID +let index = comments.findIndex(comment => comment.id === 823423); +console.log(index); + +// delete the comment with the ID of 823423 + comments.splice(index, 1); + +// alternative + const newComments = [ + ...comments.slice(0, index), + ...comments.slice(index + 1) +]; \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day08/index.html b/JavaScript Challenges/Javascript 30/Day08/index.html new file mode 100644 index 0000000..88eeb7a --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day08/index.html @@ -0,0 +1,80 @@ + + + + + + Day 8 - HTML Canvas + + + + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day09/index.html b/JavaScript Challenges/Javascript 30/Day09/index.html new file mode 100644 index 0000000..4df2b84 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day09/index.html @@ -0,0 +1,90 @@ + + + + + Console Tricks! + + + +

Ă—BREAKĂ—DOWNĂ—

+ + + + diff --git a/JavaScript Challenges/Javascript 30/Day10/index.html b/JavaScript Challenges/Javascript 30/Day10/index.html new file mode 100644 index 0000000..2c9a6da --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day10/index.html @@ -0,0 +1,117 @@ + + + + + + Day 10 + + + +
+
+ +

This is an inbox item

+
+
+ +

Check one item

+
+
+ +

Hold down you shift key

+
+
+ +

Check lower item

+
+
+ +

Everything in between should also be checked

+
+
+ +

Try to do it without any libraries

+
+
+ +

Just regular Javascript

+
+
+ +

Good luck

+
+
+ +

Don't forget to tweet your result

+
+
+ + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day11/index.html b/JavaScript Challenges/Javascript 30/Day11/index.html new file mode 100644 index 0000000..b20e799 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day11/index.html @@ -0,0 +1,26 @@ + + + + + + Day 11 - Html Video Player + + + +
+ + +
+
+
+
+ + + + + +
+
+ + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day11/index.js b/JavaScript Challenges/Javascript 30/Day11/index.js new file mode 100644 index 0000000..b77b556 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day11/index.js @@ -0,0 +1,93 @@ +const player = document.querySelector('.player') +const video = player.querySelector('video'); +const progress = player.querySelector('.progress'); +const progressBar = player.querySelector('.progress_filled'); +const toggle = player.querySelector('.toggle'); +const skipButtons = player.querySelectorAll('[data-skip]'); +const ranges = player.querySelectorAll('.player_slider'); + +// functions +function togglePlay() +{ + if(video.paused) + { + video.play(); + + } + else + { + video.pause(); + } +} + +function updateButton(){ + // const icon = this.paused ? 'â–ş' : 'âťš âťš'; + // toggle.textContent = icon; + const icon = this.paused ? 'â–ş' : '||'; + toggle.innerHTML = icon; +} + +function skip(){ + video.currentTime += parseFloat(this.dataset.skip); +} + +function handleRangeUpdate(){ + video[this.name] = this.value; + console.log(this); +} + +function handleProgress(){ + const percent = ( video.currentTime / video.duration ) * 100; + progressBar.style.flexBasis = `${percent}%`; +} + +function scrub(e){ + let scrubTime = ( e.offsetX / progress.offsetWidth ) * video.duration ; + video.currentTime = scrubTime; + console.log(e); +} + + + +// eventListeners + +// 1.play/pause button +video.addEventListener('click', togglePlay); +video.addEventListener('play', updateButton); +video.addEventListener('pause', updateButton); + +window.addEventListener('keydown', (e) => { + if(e.key === " ") + { + togglePlay(); + updateButton(); + } +}); + +toggle.addEventListener('click', togglePlay); + +// skip buttons +skipButtons.forEach(button => button.addEventListener('click', skip)); + +window.addEventListener('keydown',(e) => { + if(e.key === "ArrowLeft") + { + skipButtons[0].click(); + } + if(e.key === "ArrowRight") + { + skipButtons[1].click(); + } +}) + +// range inputs +ranges.forEach(range => range.addEventListener('change', handleRangeUpdate)) + +// progressBar +video.addEventListener('timeupdate', handleProgress) + +let mousedown = false; +progress.addEventListener('click', scrub) +progress.addEventListener('mousemove', (e) => mousedown && scrub(e) ); +progress.addEventListener('mousedown', () => mousedown = true ); +progress.addEventListener('mouseup', () => mousedown = false ); diff --git a/JavaScript Challenges/Javascript 30/Day11/style.css b/JavaScript Challenges/Javascript 30/Day11/style.css new file mode 100644 index 0000000..9dfa3cc --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day11/style.css @@ -0,0 +1,162 @@ +html{ + box-sizing: border-box; +} + +*,*::before,*::after{ + box-sizing: inherit; +} + +body{ + margin: 0; + padding: 0; + display: flex; + min-height: 100vh; + background: #7A419B; + background: linear-gradient(135deg, #7c1599 0%,#921099 48%,#7e4ae8 100%); + background-size: cover; + align-items: center; + justify-content: center; +} + +.player{ + max-width: 750px; + border: 5px solid rgba(0, 0, 0, 0.2); + box-shadow: 0 0 20px rgba(0, 0, 0, 0.2); + position: relative; + font-size: 0; + overflow: hidden; +} + +.player:fullscreen { + max-width: none; + width: 100%; +} +.player:-webkit-full-screen { + max-width: none; + width: 100%; +} + +.player_video{ + width: 100%; +} + + +.player_button { + background: transparent; + border: 0; + line-height: 1; + color: white; + text-align: center; + outline: 0; + padding: 0; + cursor: pointer; + max-width: 100px; +} + +.player_button:focus { + border-color: #ffc600; +} + +.player_slider{ + width: 10px; + height: 30px; +} + +.player_controls{ + display: flex; + position: absolute; + bottom: 0; + width: 100%; + transform: translateY(100%) translateY(-5px); + transition: all .3s; + flex-wrap: wrap; + background: rgba(0,0,0,0.1); +} + +.player:hover .player_controls{ + transform: translateY(0); +} + +.player_controls > * { + flex: 1; +} + +.progress { + flex: 10; + position: relative; + display: flex; + flex-basis: 100%; + height: 5px; + transition: height 0.3s; + background: rgba(0,0,0,0.5); + cursor: pointer; +} +.progress:hover{ + height: 10px; +} +.progress_filled { + background: #ffc600; + flex: 0; + flex-basis: 0%; +} + +input[type=range] { + -webkit-appearance: none; + background: transparent; + width: 100%; + margin: 0 5px; +} + +input[type=range]:focus { +outline: none; +} + +input[type='range']:focus{ + border: 0; + outline: none; +} + +input[type=range]::-webkit-slider-runnable-track { + width: 100%; + height: 3px; + cursor: pointer; + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0 0 1px rgba(13, 13, 13, 0); + background: rgba(255,255,255,0.8); + border-radius: 1.3px; + border: 0.2px solid rgba(1, 1, 1, 0); +} + + +input[type=range]::-webkit-slider-thumb { + height: 8px; + width: 15px; + border-radius: 50px; + background: #ffc600; + cursor: pointer; + -webkit-appearance: none; + margin-top: -3.5px; + box-shadow:0 0 2px rgba(0,0,0,0.2); +} + +input[type=range]:focus::-webkit-slider-runnable-track { + background: #bada55; +} + +input[type=range]::-moz-range-track { + width: 100%; + height: 3px; + cursor: pointer; + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0 0 1px rgba(13, 13, 13, 0); + background: #ffffff; + border-radius: 1.3px; + border: 0.2px solid rgba(1, 1, 1, 0); +} + +input[type=range]::-moz-range-thumb { + box-shadow: 0 0 0 rgba(0, 0, 0, 0), 0 0 0 rgba(13, 13, 13, 0); + height: 8px; + width: 8px; + border-radius: 50px; + background: #ffc600; + cursor: pointer; +} diff --git a/JavaScript Challenges/Javascript 30/Day11/vid.mp4 b/JavaScript Challenges/Javascript 30/Day11/vid.mp4 new file mode 100644 index 0000000..09ed31e Binary files /dev/null and b/JavaScript Challenges/Javascript 30/Day11/vid.mp4 differ diff --git a/JavaScript Challenges/Javascript 30/Day12/index.html b/JavaScript Challenges/Javascript 30/Day12/index.html new file mode 100644 index 0000000..ebdb582 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day12/index.html @@ -0,0 +1,25 @@ + + + + + + Day12 - Key Detection + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day13/index.html b/JavaScript Challenges/Javascript 30/Day13/index.html new file mode 100644 index 0000000..b42229a --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day13/index.html @@ -0,0 +1,149 @@ + + + + + Document + + + +
+ +

Slide in on Scroll

+ +

Consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariaturlores sunt esse magni, ut, dignissimos.

+

Lorem ipsum cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

+

Adipisicing elit. Tempore tempora rerum..

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt esse magni, ut, dignissimos.

+ + + +

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptates, deserunt facilis et iste corrupti omnis tenetur est. Iste ut est dicta dolor itaque adipisci, dolorum minima, veritatis earum provident error molestias. Ratione magni illo sint vel velit ut excepturi consectetur suscipit, earum modi accusamus voluptatem nostrum, praesentium numquam, reiciendis voluptas sit id quisquam. Consequatur in quis reprehenderit modi perspiciatis necessitatibus saepe, quidem, suscipit iure natus dignissimos ipsam, eligendi deleniti accusantium, rerum quibusdam fugit perferendis et optio recusandae sed ratione. Culpa, dolorum reprehenderit harum ab voluptas fuga, nisi eligendi natus maiores illum quas quos et aperiam aut doloremque optio maxime fugiat doloribus. Eum dolorum expedita quam, nesciunt

+ + + +

at provident praesentium atque quas rerum optio dignissimos repudiandae ullam illum quibusdam. Vel ad error quibusdam, illo ex totam placeat. Quos excepturi fuga, molestiae ea quisquam minus, ratione dicta consectetur officia omnis, doloribus voluptatibus? Veniam ipsum veritatis architecto, provident quas consequatur doloremque quam quidem earum expedita, ad delectus voluptatum, omnis praesentium nostrum qui aspernatur ea eaque adipisci et cumque ab? Ea voluptatum dolore itaque odio. Eius minima distinctio harum, officia ab nihil exercitationem. Tempora rem nemo nam temporibus molestias facilis minus ipsam quam doloribus consequatur debitis nesciunt tempore officiis aperiam quisquam, molestiae voluptates cum, fuga culpa. Distinctio accusamus quibusdam, tempore perspiciatis dolorum optio facere consequatur quidem ullam beatae architecto, ipsam sequi officiis dignissimos amet impedit natus necessitatibus tenetur repellendus dolor rem! Dicta dolorem, iure, facilis illo ex nihil ipsa amet officia, optio temporibus eum autem odit repellendus nisi. Possimus modi, corrupti error debitis doloribus dicta libero earum, sequi porro ut excepturi nostrum ea voluptatem nihil culpa? Ullam expedita eligendi obcaecati reiciendis velit provident omnis quas qui in corrupti est dolore facere ad hic, animi soluta assumenda consequuntur reprehenderit! Voluptate dolor nihil veniam laborum voluptas nisi pariatur sed optio accusantium quam consectetur, corrupti, sequi et consequuntur, excepturi doloremque. Tempore quis velit corporis neque fugit non sequi eaque rem hic. Facere, inventore, aspernatur. Accusantium modi atque, asperiores qui nobis soluta cumque suscipit excepturi possimus doloremque odit saepe perferendis temporibus molestiae nostrum voluptatum quis id sint quidem nesciunt culpa. Rerum labore dolor beatae blanditiis praesentium explicabo velit optio esse aperiam similique, voluptatem cum, maiores ipsa tempore. Reiciendis sed culpa atque inventore, nam ullam enim expedita consectetur id velit iusto alias vitae explicabo nemo neque odio reprehenderit soluta sint eaque. Aperiam, qui ut tenetur, voluptate doloremque officiis dicta quaerat voluptatem rerum natus magni. Eum amet autem dolor ullam.

+ + + +

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. Autem blanditiis

+ + +

laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

+ + + +

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. Autem blanditiis laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. Autem blanditiis laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

+ + + + +
+ + + + + + + diff --git a/JavaScript Challenges/Javascript 30/Day14/index.html b/JavaScript Challenges/Javascript 30/Day14/index.html new file mode 100644 index 0000000..83a4c08 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day14/index.html @@ -0,0 +1,65 @@ + + + + + Day14 - JS Reference vs Copy + + + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day15/bg.jpeg b/JavaScript Challenges/Javascript 30/Day15/bg.jpeg new file mode 100644 index 0000000..404dd52 Binary files /dev/null and b/JavaScript Challenges/Javascript 30/Day15/bg.jpeg differ diff --git a/JavaScript Challenges/Javascript 30/Day15/index.html b/JavaScript Challenges/Javascript 30/Day15/index.html new file mode 100644 index 0000000..e0eca00 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day15/index.html @@ -0,0 +1,76 @@ + + + + + + + Day 15 + + + + + +
+

LOCAL TAPAS

+

+
    +
  • Loading Tapas...
  • +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day15/style.css b/JavaScript Challenges/Javascript 30/Day15/style.css new file mode 100644 index 0000000..d689a36 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day15/style.css @@ -0,0 +1,94 @@ +html{ + box-sizing: border-box; + background: url('bg.jpeg') center no-repeat; + background-size: cover; + min-height: 100vh; + display: flex; + justify-content: center; + /* align-items: center; */ + text-align: center; + font-family: Futura, "Trebuchet MS", Arial, sans-serif; +} + + +*, *:before, *:after { + box-sizing: inherit; +} + +svg { + fill: white; + background: rgba(0, 0, 0, 0.4); + padding: 20px; + border-radius: 50%; + width: 200px; + margin-bottom: 50px; +} + +.wrapper{ + padding: 20px; + max-width: 350px; + background-color: rgba(255,255,255,0.95); + box-shadow: 0 0 0 10px rgba(0, 0, 0, 0.3); +} + +h2{ + text-align: center; + margin: 0; + font-weight: 200; +} + +.plates { + margin: 0; + padding: 0; + text-align: left; + list-style: none; +} + +.plates li{ + border-bottom: 1px solid rgba(0, 0, 0, 0.2); + padding: 10px 0; + font-weight: 100; + display: flex; +} + +.plates label { + flex: 1; + cursor: pointer; +} + +.plates input { + display: none; +} + +.plates input + label::before { + content: "⬜"; + margin-right: 10px; +} + +.plates input:checked + label::before { + content: "🍔"; +} + +.add-items { + margin-top: 20px; +} + +.add-items input { + padding: 10px; + outline: 0; + border: 1px solid rgba(0, 0, 0, 0.1); +} + +.add-items input[type="submit"]{ + background-color: grey; + color: black; + border: 2px solid balck; + border-radius: 7px; + font-weight: 400; + font-size: 15px; +} + +.add-items input[type="submit"]:hover{ + background-color: black; + color: white; +} \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day15/try.html b/JavaScript Challenges/Javascript 30/Day15/try.html new file mode 100644 index 0000000..174b023 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day15/try.html @@ -0,0 +1,65 @@ + + + + + + + Day 15 + + + + + +
+

LOCAL TAPAS

+

+
    +
  • Loading Tapas...
  • +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day16/index.html b/JavaScript Challenges/Javascript 30/Day16/index.html new file mode 100644 index 0000000..dd59ecd --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day16/index.html @@ -0,0 +1,67 @@ + + + + + + Day 16 - MouseMove + + + +
+

🔥WOAH!

+
+ + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day17/index.html b/JavaScript Challenges/Javascript 30/Day17/index.html new file mode 100644 index 0000000..2992df1 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day17/index.html @@ -0,0 +1,65 @@ + + + + + + Day - 17 + + + + +
    + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day18/index.html b/JavaScript Challenges/Javascript 30/Day18/index.html new file mode 100644 index 0000000..35c8ccf --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day18/index.html @@ -0,0 +1,210 @@ + + + + + + Videos + + + +
      +
    • + Video 1 +
    • +
    • + Video 2 +
    • +
    • + Video 3 +
    • +
    • + Video 4 +
    • +
    • + Video 5 +
    • +
    • + Video 6 +
    • +
    • + Video 7 +
    • +
    • + Video 8 +
    • +
    • + Video 9 +
    • +
    • + Video 10 +
    • +
    • + Video 11 +
    • +
    • + Video 12 +
    • +
    • + Video 13 +
    • +
    • + Video 14 +
    • +
    • + Video 15 +
    • +
    • + Video 16 +
    • +
    • + Video 17 +
    • +
    • + Video 18 +
    • +
    • + Video 19 +
    • +
    • + Video 20 +
    • +
    • + Video 21 +
    • +
    • + Video 22 +
    • +
    • + Video 23 +
    • +
    • + Video 24 +
    • +
    • + Video 25 +
    • +
    • + Video 26 +
    • +
    • + Video 27 +
    • +
    • + Video 28 +
    • +
    • + Video 29 +
    • +
    • + Video 30 +
    • +
    • + Video 31 +
    • +
    • + Video 32 +
    • +
    • + Video 33 +
    • +
    • + Video 34 +
    • +
    • + Video 35 +
    • +
    • + Video 36 +
    • +
    • + Video 37 +
    • +
    • + Video 38 +
    • +
    • + Video 39 +
    • +
    • + Video 40 +
    • +
    • + Video 41 +
    • +
    • + Video 42 +
    • +
    • + Video 43 +
    • +
    • + Video 44 +
    • +
    • + Video 45 +
    • +
    • + Video 46 +
    • +
    • + Video 47 +
    • +
    • + Video 48 +
    • +
    • + Video 49 +
    • +
    • + Video 50 +
    • +
    • + Video 51 +
    • +
    • + Video 52 +
    • +
    • + Video 53 +
    • +
    • + Video 54 +
    • +
    • + Video 55 +
    • +
    • + Video 56 +
    • +
    • + Video 57 +
    • +
    • + Video 58 +
    • +
    + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day19/index.html b/JavaScript Challenges/Javascript 30/Day19/index.html new file mode 100644 index 0000000..852221e --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day19/index.html @@ -0,0 +1,47 @@ + + + + + + + Day 19 + + + + + +
    + +
    + +
    + + + + +
    + + + + +
    + + + + +
    +
    + + + + + + +
    +
    + + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day19/scripts.js b/JavaScript Challenges/Javascript 30/Day19/scripts.js new file mode 100644 index 0000000..a80def4 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day19/scripts.js @@ -0,0 +1,99 @@ +let video = document.querySelector('.player'); +let canvas = document.querySelector('.photo'); +let ctx = canvas.getContext('2d'); +const strip = document.querySelector('.strip'); +const snap = document.querySelector('.snap'); + +function getVideo() { + navigator.mediaDevices.getUserMedia({ video: true, audio: false }) + .then(localMediaStream => { + // console.log(localMediaStream); + video.srcObject = localMediaStream; + video.play(); + }) + .catch(error => { + console.log("You have not allowed the camera.", error); + }) +} + +function paintToCanvas() { + const width = video.videoWidth; + const height = video.videoHeight; + + canvas.width = width; + canvas.height = height; + + return setInterval(() => { + ctx.drawImage(video, 0, 0, width, height); + + let pixels = ctx.getImageData(0, 0, width, height); + // pixels = redEffect(pixels); + // pixels = rgbSplit(pixels); + pixels = greenScreen(pixels); + + // ctx.globalAlpha = 0.1; // ghosting effect + // ctx.putImageData(pixels, 0, 0); + }, 16); +} + +function redEffect(pixels) { + for (let i = 0; i < pixels.data.length; i += 4) { + pixels.data[i] = pixels.data[i] + 100; //red + pixels.data[i + 1] = pixels.data[i + 1] - 50; //green + pixels.data[i + 2] = pixels.data[i + 2] * 0.5; //blue + } + return pixels; +} + +function rgbSplit(pixels) { + for (let i = 0; i < pixels.data.length; i += 4) { + pixels.data[i - 150] = pixels.data[i + 0]; //red + pixels.data[i + 100] = pixels.data[i + 1]; //green + pixels.data[i - 150] = pixels.data[i + 2]; //blue + } + return pixels; +} + +function greenScreen(pixels) { + const levels = {}; + + document.querySelectorAll('.rgb input').forEach((input) => { + levels[input.name] = input.value; + }); + + for (i = 0; i < pixels.data.length; i = i + 4) { + red = pixels.data[i + 0]; + green = pixels.data[i + 1]; + blue = pixels.data[i + 2]; + alpha = pixels.data[i + 3]; + + if (red >= levels.rmin + && green >= levels.gmin + && blue >= levels.bmin + && red <= levels.rmax + && green <= levels.gmax + && blue <= levels.bmax) { + // take it out! + pixels.data[i + 3] = 0; + } + } + + return pixels; +} + +function takePhoto() { + snap.currentTime = 0; + snap.play(); + + const data = canvas.toDataURL('image/jpeg'); + const link = document.createElement(`a`); + link.href = data; + link.setAttribute('download', 'me'); + // link.textContent = 'Download Image'; + link.innerHTML = `That Me!!`; + strip.insertBefore(link, strip.firstChild); +} + +getVideo(); + +video.addEventListener('canplay', paintToCanvas); \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day19/snap.mp3 b/JavaScript Challenges/Javascript 30/Day19/snap.mp3 new file mode 100644 index 0000000..16a2888 Binary files /dev/null and b/JavaScript Challenges/Javascript 30/Day19/snap.mp3 differ diff --git a/JavaScript Challenges/Javascript 30/Day19/style.css b/JavaScript Challenges/Javascript 30/Day19/style.css new file mode 100644 index 0000000..454c59b --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day19/style.css @@ -0,0 +1,85 @@ +html { + box-sizing: border-box; + font-size: 10px; + background-color: #ffc600; +} +*,*::before,*::after{ + box-sizing: inherit; +} + +.photobooth{ + background-color: white; + max-width: 150rem; + margin: 2rem auto; + border-radius: 2px; +} +.photobooth:after { + content: ''; + display: block; + clear: both; +} + +.controls{ + position: absolute; + right: 0; + width: 80%; + height: 150px; +} + +.controls button{ + background-color: black; + border: 2px solid black; + color: white; + border-radius: 4px; + padding: 1rem; +} + +.controls button:hover{ + background-color: white; + color: black; +} + +.controls .rgb{ + display: inline-block; + margin: 1rem 15rem; + font-size: 16px; +} + +.photo { + width: 95%; + height: 50vw; + float: left; + margin-top: 20rem; + margin-left: 3rem; + border-radius: 20px; +} + +.player { + border-radius: 50%; + position: absolute; + top: 30px; + left: 20px; + width:200px; +} + +.strip { + background-color: white; + width: 100%; + height: auto; + border-radius: 10px; + padding: 2rem; +} + +.strip img { + width: 100px; + overflow-x: scroll; + padding: 0.8rem 0.8rem 2.5rem 0.8rem; + box-shadow: 0 0 3px rgba(0,0,0,0.2); + background: white; +} + +.strip a:nth-child(5n+1) img { transform: rotate(10deg); } +.strip a:nth-child(5n+2) img { transform: rotate(-2deg); } +.strip a:nth-child(5n+3) img { transform: rotate(8deg); } +.strip a:nth-child(5n+4) img { transform: rotate(-11deg); } +.strip a:nth-child(5n+5) img { transform: rotate(12deg); } \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day20/index.html b/JavaScript Challenges/Javascript 30/Day20/index.html new file mode 100644 index 0000000..17b6f3b --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day20/index.html @@ -0,0 +1,82 @@ + + + + + + Day 20 - Speech Detection + + + +
    +
    + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day21/index.html b/JavaScript Challenges/Javascript 30/Day21/index.html new file mode 100644 index 0000000..12e6f1e --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day21/index.html @@ -0,0 +1,72 @@ + + + + + + Day 21 - Geolocation + + + + + +

    + 0 + KM/H +

    + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day21/package-lock.json b/JavaScript Challenges/Javascript 30/Day21/package-lock.json new file mode 100644 index 0000000..6784ba7 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day21/package-lock.json @@ -0,0 +1,1600 @@ +{ + "name": "gum", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "async-each-series": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz", + "integrity": "sha1-dhfBkXQB/Yykooqtzj266Yr+tDI=" + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "axios": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", + "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + }, + "dependencies": { + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + } + } + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-arraybuffer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "requires": { + "callsite": "1.0.0" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==" + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-sync": { + "version": "2.26.13", + "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.13.tgz", + "integrity": "sha512-JPYLTngIzI+Dzx+StSSlMtF+Q9yjdh58HW6bMFqkFXuzQkJL8FCvp4lozlS6BbECZcsM2Gmlgp0uhEjvl18X4w==", + "requires": { + "browser-sync-client": "^2.26.13", + "browser-sync-ui": "^2.26.13", + "bs-recipes": "1.3.4", + "bs-snippet-injector": "^2.0.1", + "chokidar": "^3.4.1", + "connect": "3.6.6", + "connect-history-api-fallback": "^1", + "dev-ip": "^1.0.1", + "easy-extender": "^2.3.4", + "eazy-logger": "3.1.0", + "etag": "^1.8.1", + "fresh": "^0.5.2", + "fs-extra": "3.0.1", + "http-proxy": "^1.18.1", + "immutable": "^3", + "localtunnel": "^2.0.0", + "micromatch": "^4.0.2", + "opn": "5.3.0", + "portscanner": "2.1.1", + "qs": "6.2.3", + "raw-body": "^2.3.2", + "resp-modifier": "6.0.2", + "rx": "4.1.0", + "send": "0.16.2", + "serve-index": "1.9.1", + "serve-static": "1.13.2", + "server-destroy": "1.0.1", + "socket.io": "2.1.1", + "ua-parser-js": "^0.7.18", + "yargs": "^15.4.1" + } + }, + "browser-sync-client": { + "version": "2.26.13", + "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.13.tgz", + "integrity": "sha512-p2VbZoYrpuDhkreq+/Sv1MkToHklh7T1OaIntDwpG6Iy2q/XkBcgwPcWjX+WwRNiZjN8MEehxIjEUh12LweLmQ==", + "requires": { + "etag": "1.8.1", + "fresh": "0.5.2", + "mitt": "^1.1.3", + "rxjs": "^5.5.6" + } + }, + "browser-sync-ui": { + "version": "2.26.13", + "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.13.tgz", + "integrity": "sha512-6NJ/pCnhCnBMzaty1opWo7ipDmFAIk8U71JMQGKJxblCUaGfdsbF2shf6XNZSkXYia1yS0vwKu9LIOzpXqQZCA==", + "requires": { + "async-each-series": "0.1.1", + "connect-history-api-fallback": "^1", + "immutable": "^3", + "server-destroy": "1.0.1", + "socket.io-client": "^2.0.4", + "stream-throttle": "^0.1.3" + } + }, + "bs-recipes": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz", + "integrity": "sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU=" + }, + "bs-snippet-injector": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz", + "integrity": "sha1-YbU5PxH1JVntEgaTEANDtu2wTdU=" + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "chokidar": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "dev-ip": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz", + "integrity": "sha1-p2o+0YVb56ASu4rBbLgPPADcKPA=" + }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "easy-extender": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", + "integrity": "sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==", + "requires": { + "lodash": "^4.17.10" + } + }, + "eazy-logger": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-3.1.0.tgz", + "integrity": "sha512-/snsn2JqBtUSSstEl4R0RKjkisGHAhvYj89i7r3ytNUKW12y178KDZwXLXIgwDqLW6E/VRMT9qfld7wvFae8bQ==", + "requires": { + "tfunk": "^4.0.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "engine.io": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, + "dependencies": { + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } + } + }, + "engine.io-client": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.4.tgz", + "integrity": "sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ==", + "requires": { + "component-emitter": "~1.3.0", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.2.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + } + }, + "engine.io-parser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", + "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.4", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "requires": { + "isarray": "2.0.1" + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + } + } + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "immutable": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", + "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=" + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-number-like": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", + "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", + "requires": { + "lodash.isfinite": "^3.3.2" + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, + "localtunnel": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.0.tgz", + "integrity": "sha512-g6E0aLgYYDvQDxIjIXkgJo2+pHj3sGg4Wz/XP3h2KtZnRsWPbOQY+hw1H8Z91jep998fkcVE9l+kghO+97vllg==", + "requires": { + "axios": "0.19.0", + "debug": "4.1.1", + "openurl": "1.1.1", + "yargs": "13.3.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "lodash.isfinite": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", + "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=" + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mitt": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", + "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "openurl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", + "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=" + }, + "opn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", + "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", + "requires": { + "is-wsl": "^1.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "parseqs": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" + }, + "parseuri": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" + }, + "portscanner": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz", + "integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=", + "requires": { + "async": "1.5.2", + "is-number-like": "^1.0.3" + } + }, + "qs": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", + "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", + "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.3", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "resp-modifier": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz", + "integrity": "sha1-sSTeXE+6/LpUH0j/pzlw9KpFa08=", + "requires": { + "debug": "^2.2.0", + "minimatch": "^3.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "rx": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", + "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" + }, + "rxjs": { + "version": "5.5.12", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "requires": { + "symbol-observable": "1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "engine.io-client": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "requires": { + "better-assert": "~1.0.0" + } + }, + "socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + } + }, + "socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" + }, + "socket.io-client": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.1.tgz", + "integrity": "sha512-YXmXn3pA8abPOY//JtYxou95Ihvzmg8U6kQyolArkIyLd0pgVhrfor/iMsox8cn07WCOOvvuJ6XKegzIucPutQ==", + "requires": { + "backo2": "1.0.2", + "component-bind": "1.0.0", + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "engine.io-client": "~3.4.0", + "has-binary2": "~1.0.2", + "indexof": "0.0.1", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + } + }, + "socket.io-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.1.tgz", + "integrity": "sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ==", + "requires": { + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "isarray": "2.0.1" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + }, + "stream-throttle": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz", + "integrity": "sha1-rdV8jXzHOoFjDTHNVdOWHPr7qcM=", + "requires": { + "commander": "^2.2.0", + "limiter": "^1.0.5" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + }, + "tfunk": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tfunk/-/tfunk-4.0.0.tgz", + "integrity": "sha512-eJQ0dGfDIzWNiFNYFVjJ+Ezl/GmwHaFTBTjrtqNPW0S7cuVDBrZrmzUz6VkMeCR4DZFqhd4YtLwsw3i2wYHswQ==", + "requires": { + "chalk": "^1.1.3", + "dlv": "^1.1.3" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "ua-parser-js": { + "version": "0.7.22", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz", + "integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q==" + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + } + } +} diff --git a/JavaScript Challenges/Javascript 30/Day21/package.json b/JavaScript Challenges/Javascript 30/Day21/package.json new file mode 100644 index 0000000..98bc2b5 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day21/package.json @@ -0,0 +1,14 @@ +{ + "name": "gum", + "version": "1.0.0", + "description": "", + "main": "scripts.js", + "scripts": { + "start": "browser-sync start --directory --server --files \"*.css, *.html, *.js\" --https" + }, + "author": "", + "license": "ISC", + "dependencies": { + "browser-sync": "^2.26.13" + } +} diff --git a/JavaScript Challenges/Javascript 30/Day22/index.html b/JavaScript Challenges/Javascript 30/Day22/index.html new file mode 100644 index 0000000..b2e6ff8 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day22/index.html @@ -0,0 +1,112 @@ + + + + + + Day 22 + + + + + +
    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Est explicabo unde natus necessitatibus esse obcaecati distinctio, aut itaque, qui vitae!

    +

    Aspernatur sapiente quae sint soluta modi, atque praesentium laborum pariatur earum quaerat cupiditate consequuntur facilis ullam dignissimos, aperiam quam veniam.

    +

    Cum ipsam quod, incidunt sit ex tempore placeat maxime corrupti possimus veritatis ipsum fugit recusandae est doloremque? Hic, quibusdam, nulla.

    +

    Esse quibusdam, ad, ducimus cupiditate nulla, quae magni odit totam ut consequatur eveniet sunt quam provident sapiente dicta neque quod.

    +

    Aliquam dicta sequi culpa fugiat consequuntur pariatur optio ad minima, maxime odio, distinctio magni impedit tempore enim repellendus repudiandae quas!

    +
    + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day23/index.html b/JavaScript Challenges/Javascript 30/Day23/index.html new file mode 100644 index 0000000..24c22cf --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day23/index.html @@ -0,0 +1,243 @@ + + + + + + + Day 23 - Text to Speech + + + + +
    +

    The Voiceinator 5000

    + + + + + + + + + + + +
    + + +
    +
    + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day24/index.html b/JavaScript Challenges/Javascript 30/Day24/index.html new file mode 100644 index 0000000..6efbdcb --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day24/index.html @@ -0,0 +1,306 @@ + + + + + + + Day 24 + + + + +
    +

    A story about getting lost.

    +
    + + + +
    + +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, + corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores + omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt + esse magni, ut, dignissimos.

    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, + corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores + omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt + esse magni, ut, dignissimos.

    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, + corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores + omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt + esse magni, ut, dignissimos.

    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, + corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores + omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt + esse magni, ut, dignissimos.

    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, + corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores + omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt + esse magni, ut, dignissimos.

    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, + corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores + omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt + esse magni, ut, dignissimos.

    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, + corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores + omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt + esse magni, ut, dignissimos.

    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, + corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores + omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt + esse magni, ut, dignissimos.

    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, + corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores + omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt + esse magni, ut, dignissimos.

    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore tempora rerum, est autem cupiditate, + corporis a qui libero ipsum delectus quidem dolor at nulla, adipisci veniam in reiciendis aut asperiores + omnis blanditiis quod quas laborum nam! Fuga ad tempora in aspernatur pariatur fugit quibusdam dolores sunt + esse magni, ut, dignissimos.

    + + + +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptates, deserunt facilis et iste corrupti omnis + tenetur est. Iste ut est dicta dolor itaque adipisci, dolorum minima, veritatis earum provident error + molestias. Ratione magni illo sint vel velit ut excepturi consectetur suscipit, earum modi accusamus + voluptatem nostrum, praesentium numquam, reiciendis voluptas sit id quisquam. Consequatur in quis + reprehenderit modi perspiciatis necessitatibus saepe, quidem, suscipit iure natus dignissimos ipsam, + eligendi deleniti accusantium, rerum quibusdam fugit perferendis et optio recusandae sed ratione. Culpa, + dolorum reprehenderit harum ab voluptas fuga, nisi eligendi natus maiores illum quas quos et aperiam aut + doloremque optio maxime fugiat doloribus. Eum dolorum expedita quam, nesciunt

    + + +

    at provident praesentium atque quas rerum optio dignissimos repudiandae ullam illum quibusdam. Vel ad error + quibusdam, illo ex totam placeat. Quos excepturi fuga, molestiae ea quisquam minus, ratione dicta + consectetur officia omnis, doloribus voluptatibus? Veniam ipsum veritatis architecto, provident quas + consequatur doloremque quam quidem earum expedita, ad delectus voluptatum, omnis praesentium nostrum qui + aspernatur ea eaque adipisci et cumque ab? Ea voluptatum dolore itaque odio. Eius minima distinctio harum, + officia ab nihil exercitationem. Tempora rem nemo nam temporibus molestias facilis minus ipsam quam + doloribus consequatur debitis nesciunt tempore officiis aperiam quisquam, molestiae voluptates cum, fuga + culpa. Distinctio accusamus quibusdam, tempore perspiciatis dolorum optio facere consequatur quidem ullam + beatae architecto, ipsam sequi officiis dignissimos amet impedit natus necessitatibus tenetur repellendus + dolor rem! Dicta dolorem, iure, facilis illo ex nihil ipsa amet officia, optio temporibus eum autem odit + repellendus nisi. Possimus modi, corrupti error debitis doloribus dicta libero earum, sequi porro ut + excepturi nostrum ea voluptatem nihil culpa? Ullam expedita eligendi obcaecati reiciendis velit provident + omnis quas qui in corrupti est dolore facere ad hic, animi soluta assumenda consequuntur reprehenderit! + Voluptate dolor nihil veniam laborum voluptas nisi pariatur sed optio accusantium quam consectetur, + corrupti, sequi et consequuntur, excepturi doloremque. Tempore quis velit corporis neque fugit non sequi + eaque rem hic. Facere, inventore, aspernatur. Accusantium modi atque, asperiores qui nobis soluta cumque + suscipit excepturi possimus doloremque odit saepe perferendis temporibus molestiae nostrum voluptatum quis + id sint quidem nesciunt culpa. Rerum labore dolor beatae blanditiis praesentium explicabo velit optio esse + aperiam similique, voluptatem cum, maiores ipsa tempore. Reiciendis sed culpa atque inventore, nam ullam + enim expedita consectetur id velit iusto alias vitae explicabo nemo neque odio reprehenderit soluta sint + eaque. Aperiam, qui ut tenetur, voluptate doloremque officiis dicta quaerat voluptatem rerum natus magni. + Eum amet autem dolor ullam.

    + + +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae + dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil + voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus + facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium + blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos + distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur + possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque + dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. + Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum + fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. + Autem blanditiis laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. + Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in + nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui + inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, + tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas + sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam + quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos + nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis + necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, + ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae + neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! + Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

    + + + +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae + dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil + voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus + facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium + blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos + distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur + possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque + dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. + Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum + fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. + Autem blanditiis laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. + Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in + nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui + inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, + tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas + sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam + quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos + nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis + necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, + ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae + neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! + Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio maiores adipisci quibusdam repudiandae + dolor vero placeat esse sit! Quibusdam saepe aperiam explicabo placeat optio, consequuntur nihil + voluptatibus expedita quia vero perferendis, deserunt et incidunt eveniet temporibus doloremque possimus + facilis. Possimus labore, officia dolore! Eaque ratione saepe, alias harum laboriosam deserunt laudantium + blanditiis eum explicabo placeat reiciendis labore iste sint. Consectetur expedita dignissimos, non quos + distinctio, eos rerum facilis eligendi. Asperiores laudantium, rerum ratione consequatur, culpa consectetur + possimus atque ab tempore illum non dolor nesciunt. Neque, rerum. A vel non incidunt, quod doloremque + dignissimos necessitatibus aliquid laboriosam architecto at cupiditate commodi expedita in, quae blanditiis. + Deserunt labore sequi, repellat laboriosam est, doloremque culpa reiciendis tempore excepturi. Enim nostrum + fugit itaque vel corporis ullam sed tenetur ipsa qui rem quam error sint, libero. Laboriosam rem, ratione. + Autem blanditiis laborum neque repudiandae quam, cumque, voluptate veritatis itaque, placeat veniam ad nisi. + Expedita, laborum reprehenderit ratione soluta velit natus, odit mollitia. Corporis rerum minima fugiat in + nostrum. Assumenda natus cupiditate hic quidem ex, quas, amet ipsum esse dolore facilis beatae maxime qui + inventore, iste? Maiores dignissimos dolore culpa debitis voluptatem harum, excepturi enim reiciendis, + tempora ab ipsam illum aspernatur quasi qui porro saepe iure sunt eligendi tenetur quaerat ducimus quas + sequi omnis aperiam suscipit! Molestiae obcaecati officiis quo, ratione eveniet, provident pariatur. Veniam + quasi expedita distinctio, itaque molestiae sequi, dolorum nisi repellendus quia facilis iusto dignissimos + nam? Tenetur fugit quos autem nihil, perspiciatis expedita enim tempore, alias ab maiores quis + necessitatibus distinctio molestias eum, quidem. Delectus impedit quidem laborum, fugit vel neque quo, + ipsam, quasi aspernatur quas odio nihil? Veniam amet reiciendis blanditiis quis reprehenderit repudiandae + neque, ab ducimus, odit excepturi voluptate saepe ipsam. Voluptatem eum error voluptas porro officiis, amet! + Molestias, fugit, ut! Tempore non magnam, amet, facere ducimus accusantium eos veritatis neque.

    +
    + + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day25/index.html b/JavaScript Challenges/Javascript 30/Day25/index.html new file mode 100644 index 0000000..75c0e40 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day25/index.html @@ -0,0 +1,80 @@ + + + + + + Day 25 + + + +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day26/index.html b/JavaScript Challenges/Javascript 30/Day26/index.html new file mode 100644 index 0000000..2144782 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day26/index.html @@ -0,0 +1,278 @@ + + + + + + + Day 26 + + + + +

    Cool

    + + + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day26/logo.jpg b/JavaScript Challenges/Javascript 30/Day26/logo.jpg new file mode 100644 index 0000000..b6868b9 Binary files /dev/null and b/JavaScript Challenges/Javascript 30/Day26/logo.jpg differ diff --git a/JavaScript Challenges/Javascript 30/Day27/index.html b/JavaScript Challenges/Javascript 30/Day27/index.html new file mode 100644 index 0000000..b0ae46f --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day27/index.html @@ -0,0 +1,74 @@ + + + + + + Day 27 + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day27/style.css b/JavaScript Challenges/Javascript 30/Day27/style.css new file mode 100644 index 0000000..a47cdc8 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day27/style.css @@ -0,0 +1,77 @@ +html { + box-sizing: border-box; + background: url('https://source.unsplash.com/NFs6dRTBgaM/2000x2000') fixed; + background-size: cover; +} + +*, *:before, *:after { + box-sizing: inherit; +} + +body { + min-height: 100vh; + display: flex; + justify-content: center; + align-items: center; + font-family: sans-serif; + font-size: 20px; + margin: 0; +} + +.items { + height: 600px; + padding: 100px; + width: 100%; + border: 1px solid white; + overflow-x: scroll; + overflow-y: hidden; + white-space: nowrap; + user-select: none; + cursor: pointer; + transition: all 0.2s; + transform: scale(0.98); + will-change: transform; + position: relative; + background: rgba(255,255,255,0.1); + font-size: 0; + perspective: 500px; +} + +.items.active { + background: rgba(255,255,255,0.3); + cursor: grabbing; + cursor: -webkit-grabbing; + transform: scale(1); +} + +.item { + width: 200px; + height: calc(100% - 40px); + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 80px; + font-weight: 100; + color: rgba(0,0,0,0.15); + box-shadow: inset 0 0 0 10px rgba(0,0,0,0.15); + /* overflow: hidden; */ +} + +.item img{ + width: 200px; + height: calc(100% - 40px); +} + +.item:nth-child(9n+1) { background: dodgerblue;} +.item:nth-child(9n+2) { background: goldenrod;} +.item:nth-child(9n+3) { background: paleturquoise;} +.item:nth-child(9n+4) { background: gold;} +.item:nth-child(9n+5) { background: cadetblue;} +.item:nth-child(9n+6) { background: tomato;} +.item:nth-child(9n+7) { background: lightcoral;} +.item:nth-child(9n+8) { background: darkslateblue;} +.item:nth-child(9n+9) { background: rebeccapurple;} + +.item:nth-child(even) { transform: scaleX(1.31) rotateY(40deg); } +.item:nth-child(odd) { transform: scaleX(1.31) rotateY(-40deg); } + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day28/index.html b/JavaScript Challenges/Javascript 30/Day28/index.html new file mode 100644 index 0000000..cd0dc65 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day28/index.html @@ -0,0 +1,89 @@ + + + + + + + Day 28 + + + + +
    + +
    +
    1x
    +
    +
    + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day29/index.html b/JavaScript Challenges/Javascript 30/Day29/index.html new file mode 100644 index 0000000..75be71c --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day29/index.html @@ -0,0 +1,31 @@ + + + + + + Day 29 + + + + +
    +
    + + + + + +
    + +
    +
    +
    +

    +

    +
    +
    + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day29/script.js b/JavaScript Challenges/Javascript 30/Day29/script.js new file mode 100644 index 0000000..001cf1b --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day29/script.js @@ -0,0 +1,80 @@ +let countdown; +const timerDisplay = document.querySelector('.display__time-left'); +const endTime = document.querySelector('.display__end-time'); +const buttons = document.querySelectorAll('[data-time]'); +const playPause = document.querySelector('#start-stop'); +let secondsLeft; +let timerStart = false; + +function timer(seconds) +{ + clearInterval(countdown);//clear all previous timers + timerStart = true; + const now = Date.now() ; // milliseconds + const then = (seconds * 1000) + now ; + + displayTimeLeft(seconds); + displayEndTime(then); + + countdown = setInterval(()=>{ + secondsLeft = Math.round((then - Date.now()) / 1000); + + if(secondsLeft < 0) + { + timerStart = false; + clearInterval(countdown); + return; + } + + displayTimeLeft(secondsLeft); + + },1000) + +} + +function displayTimeLeft(seconds) +{ + const hours = Math.floor(seconds / 3600) ; + seconds = seconds % 3600; + const minutes = Math.floor(seconds / 60) ; + const remainerSeconds = seconds % 60; + + const displayTime = `${hours<10&&hours>0?'0':''}${hours>0?hours+':':''}${minutes<10 ? '0' : ''}${minutes}:${remainerSeconds<10 ? '0' : ''}${remainerSeconds}`; + document.title = displayTime; + timerDisplay.textContent = displayTime; +} + +function displayEndTime(timestamp) +{ + const end = new Date(timestamp); + const hours = end.getHours(); + const minutes = end.getMinutes(); + endTime.textContent = `Be back at ${hours > 12 ? hours-12 : hours}:${minutes<10 ? '0': ''}${minutes}`; +} + +function startTimer() +{ + const seconds = parseInt(this.dataset.time); + timer(seconds); +} + +buttons.forEach(button => button.addEventListener('click', startTimer) ) +document.customForm.addEventListener('submit', function(e){ + e.preventDefault(); + const mins = this.minutes.value; + timer(mins*60); + this.reset(); +}) + + +playPause.addEventListener('click', (e)=> { + if(timerStart) + { + clearInterval(countdown); + timerStart = false; + } + else + { + timer(secondsLeft) + } +}) diff --git a/JavaScript Challenges/Javascript 30/Day29/style.css b/JavaScript Challenges/Javascript 30/Day29/style.css new file mode 100644 index 0000000..45fc66c --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day29/style.css @@ -0,0 +1,84 @@ +html { + box-sizing: border-box; + font-size: 10px; + background: #8E24AA; + background: linear-gradient(45deg, #42a5f5 0%,#478ed1 50%,#0d47a1 100%); +} + +*, *:before, *:after { + box-sizing: inherit; +} + +body { + margin: 0; + text-align: center; + font-family: 'Inconsolata', monospace; +} + +.display__time-left { + font-weight: 100; + font-size: 20rem; + margin: 0; + color: white; + text-shadow: 4px 4px 0 rgba(0,0,0,0.05); +} + +.timer { + display: flex; + min-height: 100vh; + flex-direction: column; +} + +.timer__controls { + display: flex; +} + +.timer__controls > * { + flex: 1; +} + +.timer__controls form { + flex: 1; + display: flex; +} + +.timer__controls input { + flex: 1; + border: 0; + padding: 2rem; +} + +.timer__button { + background: none; + border: 0; + cursor: pointer; + color: white; + font-size: 2rem; + text-transform: uppercase; + background: rgba(0,0,0,0.1); + border-bottom: 3px solid rgba(0,0,0,0.2); + border-right: 1px solid rgba(0,0,0,0.2); + padding: 1rem; + font-family: 'Inconsolata', monospace; +} + +.timer__button:hover, +.timer__button:focus { + background: rgba(0,0,0,0.2); + outline: 0; +} + + +.display { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + + +.display__end-time { + font-size: 4rem; + color: white; +} \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day30/dirt.svg b/JavaScript Challenges/Javascript 30/Day30/dirt.svg new file mode 100644 index 0000000..8726a9e --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day30/dirt.svg @@ -0,0 +1,40 @@ + + + + dirt + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day30/index.html b/JavaScript Challenges/Javascript 30/Day30/index.html new file mode 100644 index 0000000..b1a3abd --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day30/index.html @@ -0,0 +1,90 @@ + + + + + + Whack A Mole! + + + + + + +

    Whack-a-mole! 0

    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day30/mole.svg b/JavaScript Challenges/Javascript 30/Day30/mole.svg new file mode 100644 index 0000000..73769a1 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day30/mole.svg @@ -0,0 +1,56 @@ + + + + mole + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/Day30/script.js b/JavaScript Challenges/Javascript 30/Day30/script.js new file mode 100644 index 0000000..e69de29 diff --git a/JavaScript Challenges/Javascript 30/Day30/styles.css b/JavaScript Challenges/Javascript 30/Day30/styles.css new file mode 100644 index 0000000..5e33ca3 --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day30/styles.css @@ -0,0 +1,86 @@ +html { + box-sizing: border-box; + font-size: 10px; + background: #ffc600; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +body { + padding: 0; + margin: 0; + font-family: cursive; +} + +h1 { + text-align: center; + font-size: 10rem; + line-height: 1; + margin-bottom: 0; +} + +.start{ + padding: 1.5rem; + background: transparent; + border: 2px solid rgba(0, 0, 0, 0.5); + font-size: 2rem; + width: 10rem; + margin: 10px auto; + display: block; +} + +.start:hover{ + background-color: rgb(0, 0, 0); + color: #ffc600; +} + +.score { + background: rgba(255, 255, 255, 0.2); + padding: 0 3rem; + line-height: 1; + border-radius: 1rem; +} + +.game { + width: 600px; + height: 400px; + display: flex; + flex-wrap: wrap; + margin: 0 auto; +} + +.hole { + flex: 1 0 33.33%; + overflow: hidden; + position: relative; +} + +.hole:after { + display: block; + background: url(dirt.svg) bottom center no-repeat; + background-size: contain; + content: ""; + width: 100%; + height: 70px; + position: absolute; + z-index: 2; + bottom: -30px; +} + +.mole { + background: url("mole.svg") bottom center no-repeat; + background-size: 60%; + position: absolute; + top: 100%; + width: 100%; + height: 100%; + transition: all 0.4s; +} + +.hole.up .mole { + top: 0; +} diff --git a/JavaScript Challenges/Javascript 30/Day31/index.html b/JavaScript Challenges/Javascript 30/Day31/index.html new file mode 100644 index 0000000..a4cd55f --- /dev/null +++ b/JavaScript Challenges/Javascript 30/Day31/index.html @@ -0,0 +1,84 @@ + + + + + + Document + + + +
    +
    +
    + + + + + + +
    + +
    +
    + + + + \ No newline at end of file diff --git a/JavaScript Challenges/Javascript 30/readme.md b/JavaScript Challenges/Javascript 30/readme.md new file mode 100644 index 0000000..1e22f4a --- /dev/null +++ b/JavaScript Challenges/Javascript 30/readme.md @@ -0,0 +1,2 @@ +Complete code for JavaScript 30 Challenge. +Each day brings a new and intresting concept of JavaScript. diff --git a/NamasteJS/E01.md b/NamasteJS/E01 - How JavaScript Works & Execution Context.md similarity index 100% rename from NamasteJS/E01.md rename to NamasteJS/E01 - How JavaScript Works & Execution Context.md diff --git a/NamasteJS/E02.md b/NamasteJS/E02 - How is JavaScript Code executed & What is Call Stack.md similarity index 98% rename from NamasteJS/E02.md rename to NamasteJS/E02 - How is JavaScript Code executed & What is Call Stack.md index 2212bb4..3bbccd5 100644 --- a/NamasteJS/E02.md +++ b/NamasteJS/E02 - How is JavaScript Code executed & What is Call Stack.md @@ -2,7 +2,7 @@ Let us look at this code below. -``` +```js var n=2; function square(num){ var ans = num*num; @@ -11,12 +11,11 @@ function square(num){ var square2 = square(n); var square4 = square(4); - ``` When we run this code, a GLOBAL Execution context is created. It will have Memory and Code. -It is created in two phases. +It is created in two phases. 1. __First Phase(Memory Creation Phase)__: JS will allocate the memory to all variables and functions. Ex. in our code, it will reserve memory space for n. diff --git a/NamasteJS/E03.md b/NamasteJS/E03 - Hoisting in JavaScript (variables & functions).md similarity index 96% rename from NamasteJS/E03.md rename to NamasteJS/E03 - Hoisting in JavaScript (variables & functions).md index 013ab38..7fdfe2f 100644 --- a/NamasteJS/E03.md +++ b/NamasteJS/E03 - Hoisting in JavaScript (variables & functions).md @@ -2,18 +2,16 @@ Let us understand the concept by the following examples. -``` +```js // code example 1 var x = 7; - function getName(){ console.log("Namaste JavaScript"); } getName(); console.log(x); - ``` Output: @@ -22,26 +20,24 @@ Output: > 7 -``` +```js // code example 2 getName(); console.log(x); var x = 7; - function getName(){ console.log("Namaste JavaScript"); } - ``` - Output: +Output: > Namaste JavaScript > undefined -``` +```js // code example 3 getName(); @@ -50,7 +46,6 @@ console.log(x); function getName(){ console.log("Namaste JavaScript"); } - ``` Output: @@ -61,8 +56,7 @@ Output: __Hoisting__ is a concept which enables us to extract values of variables and functions even before defining them. -``` - +```js // code example 4 function getName(){ @@ -70,8 +64,6 @@ function getName(){ } console.log(getName) - - ``` Output: @@ -81,8 +73,7 @@ Output: } -``` - +```js // code example 5 getName(); @@ -92,7 +83,6 @@ console.log(getName) function getName(){ console.log("Namaste JavaScript"); } - ``` Output: @@ -104,7 +94,7 @@ Output: console.log("Namaste JavaScript); } -``` +```js // code example 6 console.log(getName) @@ -116,7 +106,6 @@ var getName = function () { var getName = () => { console.log("Namaste JavaScript"); } - ``` Output: @@ -131,17 +120,3 @@ __REASON OF WEIRDNESS__ * The answer lies in the Global Exection Context. In the memory phase, the variables will be initialized as *undefined* and functions will get the whole function code in their memory. * This is the reason why we are getting these outputs. - - - - - - - - - - - - - - diff --git a/NamasteJS/E04.md b/NamasteJS/E04 - How functions work in JS & Variable Environment.md similarity index 99% rename from NamasteJS/E04.md rename to NamasteJS/E04 - How functions work in JS & Variable Environment.md index 718f32c..dd99469 100644 --- a/NamasteJS/E04.md +++ b/NamasteJS/E04 - How functions work in JS & Variable Environment.md @@ -2,7 +2,7 @@ Let us understand the execution of the functions in JS by the simple example. -``` +```js // code example var x=1; @@ -19,7 +19,6 @@ function b(){ var x=100; console.log(x); } - ``` Outputs: diff --git a/NamasteJS/E05.md b/NamasteJS/E05 - SHORTEST JS Program - window & this keyword.md similarity index 99% rename from NamasteJS/E05.md rename to NamasteJS/E05 - SHORTEST JS Program - window & this keyword.md index ad88f59..f8e734f 100644 --- a/NamasteJS/E05.md +++ b/NamasteJS/E05 - SHORTEST JS Program - window & this keyword.md @@ -24,8 +24,9 @@ __GLOBAL SPACE__ * Whenever in a JS file, we create a global variable or a function, it gets attached with the *window* object and can be accessed through it. -``` +```js // code example 1 + a=10; console.log(window.a); console.log(a); diff --git a/NamasteJS/E06.md b/NamasteJS/E06 - undefined vs not defined in JS.md similarity index 100% rename from NamasteJS/E06.md rename to NamasteJS/E06 - undefined vs not defined in JS.md diff --git a/NamasteJS/E07.md b/NamasteJS/E07 - The Scope Chain, Scope & Lexical Environment.md similarity index 99% rename from NamasteJS/E07.md rename to NamasteJS/E07 - The Scope Chain, Scope & Lexical Environment.md index c9b4b6c..5bfff53 100644 --- a/NamasteJS/E07.md +++ b/NamasteJS/E07 - The Scope Chain, Scope & Lexical Environment.md @@ -2,7 +2,7 @@ Let us understand with the help of this code. -``` +```js // code example 1 function a(){ @@ -20,7 +20,7 @@ Output: > 10 -``` +```js // code example 2 function a(){ @@ -95,18 +95,3 @@ Output: 2. See example 2 for instance. * The variable b is searched in GEC's local memory. And since it is not found, it goes to its parent lexical environment; but since its GEC, so it will be *null*. And thus, it throws error! - - - - - - - - - - - - - - - diff --git a/NamasteJS/E08.md b/NamasteJS/E08 - let & const in JS - Temporal Dead Zone.md similarity index 98% rename from NamasteJS/E08.md rename to NamasteJS/E08 - let & const in JS - Temporal Dead Zone.md index 89adc86..54a0a5a 100644 --- a/NamasteJS/E08.md +++ b/NamasteJS/E08 - let & const in JS - Temporal Dead Zone.md @@ -2,17 +2,18 @@ > let and const declarations are hoisted; but differently. -``` +```js // code example 1 +console.log(b); console.log(a); let a = 10; var b = 100; - ``` Output: +> undefined > Uncaught ReferenceError: cannot access 'a' before initialization Technically, in JS if a is hoisted, then this error wasn't expected. @@ -30,7 +31,7 @@ Technically, in JS if a is hoisted, then this error wasn't expected. * window.b, this.b will print the value of b. But window.a and this.a will show it undefined as we know that window and this refer to variables in Global memory. Since, a is stored in seperate space, it cannot be accessed. -``` +```js // code example 2 const b; @@ -41,7 +42,7 @@ console.log(b); Outputs: > Uncaught SyntaxError: Missing initializer in const declaration -``` +```js // code example 3 const b=1000; @@ -111,18 +112,3 @@ The Errors that occurs if no reference is available for access. Can occur when t * If not, use let. * Avoid var. * Declare all variables with let at the top to avoid errors to shrink temporal dead zone to zero. - - - - - - - - - - - - - - - diff --git a/NamasteJS/E09.md b/NamasteJS/E09 - BLOCK SCOPE & Shadowing in JS.md similarity index 90% rename from NamasteJS/E09.md rename to NamasteJS/E09 - BLOCK SCOPE & Shadowing in JS.md index 0d650f3..8bcee50 100644 --- a/NamasteJS/E09.md +++ b/NamasteJS/E09 - BLOCK SCOPE & Shadowing in JS.md @@ -2,9 +2,9 @@ ### __What is Block?__ -* Block is also known as *Compound Statement*. We use it group many JS statements together. We need to group them because we can group multiple statements at a place where JS expects only one statement. +* Block is also known as *Compound Statement*. We use it to group many JS statements together. We need to group them because we can group multiple statements at a place where JS expects only one statement. -``` +```js //code example 1 if(true)some statement @@ -12,7 +12,7 @@ if(true)some statement But if we want to write more statements to execute after if condition; then: -``` +```js //code example 2 if(true){ @@ -31,8 +31,7 @@ if(true){ * What all variables and functions that can be accessed inside the block. -``` - +```js //code example 3 { @@ -62,7 +61,7 @@ Outputs: ### __What is SHADOWING in JS?__ -``` +```js //code example 4 var a= 100; @@ -84,7 +83,7 @@ Outputs: * So, a is reassigned to 10. Since both refers to same memory space i.e GLOBAL SPACE. -``` +```js //code example 5 let b = 100; @@ -116,7 +115,7 @@ Outputs: ### __What is Illegal Shadowing?__ -``` +```js // code example 6 let a = 20; @@ -138,26 +137,11 @@ Outputs: * Since var is function scoped, it is not a problem with the code below. -``` +```js // code example 6 let a = 20; function x() { var a = 20; } - ``` - - - - - - - - - - - - - - diff --git a/NamasteJS/E10 - Closures in JS.md b/NamasteJS/E10 - Closures in JS.md new file mode 100644 index 0000000..e410bfb --- /dev/null +++ b/NamasteJS/E10 - Closures in JS.md @@ -0,0 +1,79 @@ + + +--- + +# [Episode 10](https://www.youtube.com/watch?v=lW_erSjyMeM&list=PLlasXeu85E9cQ32gLCvAvr9vNaUccPVNP&index=12): Closures in JavaScript 🔥 + +In JavaScript, closures are a powerful concept that combines a function with its lexical environment, enabling the function to retain access to variables from its parent scope even after the parent function has finished executing. + +## Understanding Closures + +Let's delve into a few examples to understand how closures work: + +**Example 1:** +```js +function x() { + var a = 7; + function y() { + console.log(a); + } + return y; +} + +var z = x(); +console.log(z); // Output: f y(){ console.log(a); } +z(); // Output: 7 +``` + +In this example, the inner function `y` maintains a reference to the variable `a` from its lexical scope. Even though the outer function `x` has completed execution, `z` still prints `7` when invoked, demonstrating how the closure retains the environment. + +**Example 2:** +```js +function x() { + var a = 7; + function y() { + console.log(a); + } + a = 100; + return y; +} + +var z = x(); +console.log(z); // Output: f y(){ console.log(a); } +z(); // Output: 100 +``` + +Here, even after the value of `a` is changed to `100`, the closure retains the updated value when invoked through `z()`. + +**Example 3:** +```js +function z() { + var b = 900; + function x() { + var a = 7; + function y() { + console.log(a, b); + } + return y; + } +} + +var t = x(); +t(); // Output: 7 900 +``` + +This example highlights how closures encapsulate the lexical environments of all parent levels. + +## Applications of Closures + +Closures find application in various programming scenarios: + +- **Module Design Pattern**: Closures help create private variables and methods in JavaScript, facilitating the module design pattern. +- **Currying**: Closures enable the creation of curried functions, allowing the transformation of functions with multiple arguments into a sequence of functions with a single argument. +- **Memoization**: Closures can be used to implement memoization, a technique that stores the results of expensive function calls and returns the cached result when the same inputs occur again. +- **Asynchronous State Management**: Closures aid in maintaining state in asynchronous programming, enabling functions to access their lexical environment even after the parent function has completed execution. +- **Timeouts and Iterators**: Closures are instrumental in scenarios such as managing timeouts and creating custom iterators. + +Understanding closures is crucial for harnessing the full power of JavaScript and developing efficient and robust applications. + +--- diff --git a/NamasteJS/E10.md b/NamasteJS/E10.md deleted file mode 100644 index 25dc1b4..0000000 --- a/NamasteJS/E10.md +++ /dev/null @@ -1,100 +0,0 @@ -# [Episode 10](https://www.youtube.com/watch?v=lW_erSjyMeM&list=PLlasXeu85E9cQ32gLCvAvr9vNaUccPVNP&index=12): Closures in JS 🔥 - -* Closure: A function bind together with its lexical environment. - -Function along with its lexical scope forms a closure. - -Function bundled along with the environment. - -``` -Example 1 - -function x(){ - var a=7; - function y(){ - console.log(a); - } - return y; -} - -var z = x(); -console.log(z); -z(); -``` - -Output: ->f y(){ - console.log(a); -} ->7 - -### Observation - -Function x() returns a `function y` which prints `variable a` on the console. Here, `a` is not in scope of y() and so the JS engine will search for `a` in its parent's lexical environment. Here, `a` is defined equal to `7`. - -Here after the line `var z = x()` the function x is over and thus it is completely removed from the execution context. - -But now when we call `z()`, given that `x()` is completely gone from the context, what should it print? - -It prints `7`. This means that `x()` didn't return `function y` but a closure. Since closure is a `function` + `its lexical env`, when `z()` is called, it remembers its lexical environment and thus prints `7`. - -Thus, `Closure` is nothing but a function + lexical environment(it has reference of values of vars and funcs). - -``` -Example 2 - -function x(){ - var a=7; - function y(){ - console.log(a); - } - a=100; - return y; -} - -var z = x(); -console.log(z); -z(); -``` - -Output: ->f y(){ - console.log(a); -} ->100 - -``` -Example 3 -function z(){ - var b = 900; - function x(){ - var a=7; - function y(){ - console.log(a, b); - } - return y; - } -} - -var t = x(); -t(); -``` - -Output: ->7 900 - -Above example shows that Closure bundles the lexical environment of all the parent levels. - -### Applications of Closures - -- Module Design Pattern -- Currying -- Functions like `once` -- Memoize -- Maintaining state in `async` world -- Set timeout -- Iterators etc. - - - - diff --git a/NamasteJS/E11.md b/NamasteJS/E11 - setTimeout + Closures Interview Question.md similarity index 98% rename from NamasteJS/E11.md rename to NamasteJS/E11 - setTimeout + Closures Interview Question.md index 924c4c8..8e7d356 100644 --- a/NamasteJS/E11.md +++ b/NamasteJS/E11 - setTimeout + Closures Interview Question.md @@ -2,7 +2,7 @@ Let us understand by a simple example. -``` +```js function x(){ for(var i=0; i<=5; i++){ setTimeout(function (){ @@ -13,6 +13,7 @@ function x(){ } x(); ``` + Expected: >Namaste JS > 1 (after 1s) @@ -42,7 +43,7 @@ Here, all the `setTimeout`s are closures, and thus they have reference of lexica ### How to solve this? -``` +```js function x(){ for(let i=0; i<=5; i++){ setTimeout(function (){ @@ -53,6 +54,7 @@ function x(){ } x(); ``` + Output: >Namaste JS > 1 (after 1s) @@ -70,7 +72,7 @@ And so, in async queue, all `setTimeout` has unique value of `i` at a different ### How to solve this without using `let`? -``` +```js function x(){ for(var i=0; i<=5; i++){ function close(x){ @@ -90,14 +92,3 @@ x(); We enclose the `setTimeout` inside a `close()` function. And everytime in a loop, we call `close(i)` which passes a unique value of `i` to each time `setTimeout` is called as `x` is already inside the lexical environment. In this way the problem is tackled. - - - - - - - - - - - diff --git a/NamasteJS/E12.md b/NamasteJS/E12 - CRAZY JS INTERVIEW - ft. Closures.md similarity index 94% rename from NamasteJS/E12.md rename to NamasteJS/E12 - CRAZY JS INTERVIEW - ft. Closures.md index b9450b6..6ad55a4 100644 --- a/NamasteJS/E12.md +++ b/NamasteJS/E12 - CRAZY JS INTERVIEW - ft. Closures.md @@ -2,8 +2,8 @@ ### Examples to Demonstrate Closures in Interviews -``` -Example 1 +```js +// Example 1 function outer(){ var a=10; @@ -22,14 +22,15 @@ Output: **Explanation** `outer()()` can be literally translated to: -``` +```js var close = outer(); close(); ``` + Here `Closure` is the `inner` function + its `lexical env`. -``` -Example 2 +```js +// Example 2 function outest(){ var c = 20; @@ -46,6 +47,7 @@ let a=100; var close = (outest())("helloworld); close(); ``` + Output: >10 helloworld 20 @@ -53,13 +55,13 @@ Output: Data Hiding : Suppose if we have a variable and we want to have data privacy over it. So we can encapsulate that data so others cant access it. -``` -Example 3 +```js +// Example 3 function counter(){ var count = 0; return function incrementCounter(){ - counter++; + count++; console.log(count) } } @@ -69,12 +71,13 @@ console.log(counter1()) var counter2 = counter(); console.log(counter2()) ``` + Output: >1 >1 -``` -Example 3 +```js +// Example 4 function Counter(){ var count = 0; @@ -106,8 +109,8 @@ We make a constructor function that has two functions increment and decrement. S It is a type of Program in the JavaScript Engine/Browser which frees up the unutlilized memory. -``` -Example 4 +```js +// Example 5 function a(){ var x=0; @@ -121,8 +124,8 @@ If a closure is formed, then it cannot be freed up from the memory. Garbage coll ### Smart Memory Collections -``` -Example 5 +```js +// Example 6 function a(){ var x=0; @@ -132,17 +135,5 @@ function a(){ } } ``` -Smart Garbage collection is done by modern engines and browsers. Here z is not used in anywhere and closure is not formed with that variable. Hence, z is garbage collected. - - - - - - - - - - - - +Smart Garbage collection is done by modern engines and browsers. Here z is not used in anywhere and closure is not formed with that variable. Hence, z is garbage collected. diff --git a/NamasteJS/E13.md b/NamasteJS/E13 - FIRST CLASS FUNCTIONS - ft. Anonymous Functions.md similarity index 97% rename from NamasteJS/E13.md rename to NamasteJS/E13 - FIRST CLASS FUNCTIONS - ft. Anonymous Functions.md index 1216327..a71ec7f 100644 --- a/NamasteJS/E13.md +++ b/NamasteJS/E13 - FIRST CLASS FUNCTIONS - ft. Anonymous Functions.md @@ -2,7 +2,7 @@ ### Function Statement or Function Declaration -``` +```js function a(){ console.log("a") } @@ -11,7 +11,7 @@ a(); ### Function Expression -``` +```js var b = function (){ console.log("b"); } @@ -20,7 +20,7 @@ b(); ### Anonymous Function -``` +```js function () { } @@ -31,13 +31,14 @@ It is unnamed function. ### Named Function Expression -``` +```js var b = function xyz(){ console.log(xyz); } b(); ``` + We can also name functions in JS func expressions. ### Parameters vs. Arguments @@ -49,4 +50,3 @@ Arguments: The variables, entities that we pass in a function call. ### First Class Functions Functions are first class citizens in JS. They can be passed as an argument, returned or stored as a value. - diff --git a/NamasteJS/E14.md b/NamasteJS/E14 - Callback Functions in JS ft. Event Listeners.md similarity index 71% rename from NamasteJS/E14.md rename to NamasteJS/E14 - Callback Functions in JS ft. Event Listeners.md index 4fb7fbb..de63149 100644 --- a/NamasteJS/E14.md +++ b/NamasteJS/E14 - Callback Functions in JS ft. Event Listeners.md @@ -3,7 +3,7 @@ ### Callback Function in JS -``` +```js setTimeout(function (){ console.log("timer"); },5000); @@ -18,11 +18,12 @@ x(function y(){ ``` Output: ->timer >x ->y +>undefined +>Timer **Explanation** +Here y is never logged out...ur passing y as arg. in x but never using it Settimeout is an async function; it takes a function and executes after x miliseconds. @@ -30,13 +31,13 @@ The JS thread continues to execute other code and the call stack is filled and e Once the call stack is empty, it checks if the async queue is filled; then it executes those functions in the queue. -Thus output is x, y and then timer. +Thus output is x, undefined and then timer. JS is single threaded synchronous language. ### Important Interview Question -``` +```js function attachEventListeners(){ let count=0; document.getElementById("clickMe").addEventListener("click", console.log("Button", ++count)); @@ -49,4 +50,14 @@ attachEventListeners(); Event Listeners are memory-heavy. Thus we must use removeEventListeners. +### Let us Understand callbacks in a more cleaner way with an example +```js +function add(a, b, callback){ + console.log(`The Sum of ${a} and ${b} is ${a+b}`); + callback(); +} +add(2, 3, function disp(){ + console.log("Print the line after addition"): +}); +``` diff --git a/NamasteJS/E15.md b/NamasteJS/E15 - Asynchronous JavaScript & EVENT LOOP from scratch.md similarity index 99% rename from NamasteJS/E15.md rename to NamasteJS/E15 - Asynchronous JavaScript & EVENT LOOP from scratch.md index 6a16204..b56b70c 100644 --- a/NamasteJS/E15.md +++ b/NamasteJS/E15 - Asynchronous JavaScript & EVENT LOOP from scratch.md @@ -15,7 +15,8 @@ All the web APIs etc. are pushed in this. Microtask Queue: This is of higher priority than the Callback Queue. It does same thing as Callback Queue. It contains the Callbacks relating to those of "Promises" and Mutations. Event Loop: It is a Gate keeper. It keeps check that: -``` + +```js if(Call Stack === Empty && Callback Queue !== Empty){ x = Callback Queue.pop() Call Stack.push(x); @@ -24,6 +25,3 @@ else{ wait(till Call Stack is not empty) } ``` - - - diff --git a/NamasteJS/E16.md b/NamasteJS/E16 - JS Engine EXPOSED - Google's V8 Architecture.md similarity index 99% rename from NamasteJS/E16.md rename to NamasteJS/E16 - JS Engine EXPOSED - Google's V8 Architecture.md index b62a348..a204766 100644 --- a/NamasteJS/E16.md +++ b/NamasteJS/E16 - JS Engine EXPOSED - Google's V8 Architecture.md @@ -40,5 +40,3 @@ V8 compiler: TurboFan -> Creates Optimized Machine Code -> Byte code Compiler Optimizes and Interpreter executes. Garbage collector: Orinoco, Oilpan - - diff --git a/NamasteJS/E17.md b/NamasteJS/E17 - TRUST ISSUES with setTimeout().md similarity index 100% rename from NamasteJS/E17.md rename to NamasteJS/E17 - TRUST ISSUES with setTimeout().md diff --git a/NamasteJS/README.md b/NamasteJS/README.md new file mode 100644 index 0000000..cf35dee --- /dev/null +++ b/NamasteJS/README.md @@ -0,0 +1,3 @@ +### __Resources📚__: + +* [NamasteJavaScript](https://www.youtube.com/playlist?list=PLlasXeu85E9cQ32gLCvAvr9vNaUccPVNP) by [Akshay Saini](https://www.linkedin.com/in/akshaymarch7/?originalSubdomain=in) \ No newline at end of file diff --git a/README.md b/README.md index 4806f0c..55feb21 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,39 @@ # < JavaScriptONLY />👨‍💻 🙏 -### Its an attempt to provide high quality, well-written set of notes for anyone who wants to learn and refer JavaScript concepts in deep. +### Its an attempt to provide high quality, well-written set of notes and code-snippets for anyone who wants to learn and refer JavaScript concepts in deep. + +--- ----- #### This repository will be your go-to place when you feel to write better and cleaner code for your project, want to debug without frustration and cursing JS or to praise the beauty of this language in real sense. + --- > JavaScript is Beautiful ♥. But it takes the eyes of the coder to admire ~ *anonymous*✨ + --- -### __Resources📚__: +### **We love Contributions💖**: -* [NamasteJavaScript](https://www.youtube.com/playlist?list=PLlasXeu85E9cQ32gLCvAvr9vNaUccPVNP) by [Akshay Saini](https://www.linkedin.com/in/akshaymarch7/?originalSubdomain=in) ---- -### __We love Contributions💖__: -Feel free to create an issue about what topic you want to add explanations or code snippets that covers core JS concepts in a better and lucid way. Link a PR with it and we are ready to accept your contributions! +Feel free to create an issue about what topic you want to add explanations or code snippets that covers core JS concepts in a better and lucid way. Link a PR with it and we are ready to accept your contributions! Refer [this](https://github.com/sohamsshah/JavaScriptONLY/blob/master/CONTRIBUTING.md) for more insights. + +### How can I contribute? + +- If you are into Data Structures and Algorithms ft. JavaScript, contribute by adding your favourite ones to [here](/DSA) +- Following Striver's [SDE-Sheet](https://docs.google.com/document/d/1SM92efk8oDl8nyVw8NHPnbGexTS9W-1gmTEYfEurLWQ/edit)? We believe that it is a good resource to prepare for DSA rounds. Contribute your JS Solutions from the sheet [here](/SDE_Sheet)! +- If you are practicing JavaScript Interview Questions, share your approach and learnings [here](/InterviewQuestions) +- Have got Code Snippets in JavaScript? Dump them in [here](/Snippets) +- Love taking Notes? We are looking for contributions to [NamasteJS](/NamasteJS) and [EloquentJS](/EloquentJS) currently! +- Into Documentation? Presently, a lot of code isn't well documented. We need to maintain a README.md for each sections! Help will be appreciated there. +- Feel Free to Raise Issues and create PRs :) --- + ### Contributors💻: -* [sohamsshah](https://github.com/sohamsshah) ---- +As always, thanks to our amazing contributors who are making the world fall in love with JavaScript 💛! + + + + +--- diff --git a/ReferenceBooks/Daniel_Parker-JavaScript_with_Promises-EN.pdf b/ReferenceBooks/Daniel_Parker-JavaScript_with_Promises-EN.pdf new file mode 100644 index 0000000..51fc8ab Binary files /dev/null and b/ReferenceBooks/Daniel_Parker-JavaScript_with_Promises-EN.pdf differ diff --git a/ReferenceBooks/JavaScript-The-Definitive-Guide-Master-The-Worlds-Most-Used-Programming-Language-7th-Edition.pdf b/ReferenceBooks/JavaScript-The-Definitive-Guide-Master-The-Worlds-Most-Used-Programming-Language-7th-Edition.pdf new file mode 100644 index 0000000..1ee9fdd Binary files /dev/null and b/ReferenceBooks/JavaScript-The-Definitive-Guide-Master-The-Worlds-Most-Used-Programming-Language-7th-Edition.pdf differ diff --git a/SDE_Sheet/IntersectionOfTwoLinkedLists.js b/SDE_Sheet/IntersectionOfTwoLinkedLists.js new file mode 100644 index 0000000..898fd17 --- /dev/null +++ b/SDE_Sheet/IntersectionOfTwoLinkedLists.js @@ -0,0 +1,56 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ + +/** + * @param {ListNode} headA + * @param {ListNode} headB + * @return {ListNode} + */ +var getIntersectionNode = function(headA, headB) { + + let shortList + let longList + let sizeA = headA + let sizeB = headB + let lengthA = 0 + let lengthB = 0 + while (sizeA!==null || sizeB!==null){ + if(sizeA !== null) { + sizeA = sizeA.next + lengthA ++ + } + if(sizeB !==null) { + sizeB = sizeB.next + lengthB ++ + } + } + //starts the longest list index, to the starting point of short list + //the idea is that an intersection of a node will ALWAYS be at the end. + //therefore, SAME SIZE lists will reach the intersection value at the same time + let sizeDiff = Math.abs(lengthA - lengthB) + + if(lengthB > lengthA) { + shortList = headA + longList = headB + } else { + shortList = headB + longList = headA + } + + while(shortList.next !== null || longList.next !== null){ + if(sizeDiff<1){ + if(shortList === longList) return shortList + shortList = shortList.next + } + longList = longList.next + sizeDiff-- + } + //catch any 1 length lists + if(shortList === longList) return shortList + return shortList.next +}; diff --git a/SDE_Sheet/LongestSubstringWithoutRepeatingCharacters.js b/SDE_Sheet/LongestSubstringWithoutRepeatingCharacters.js new file mode 100644 index 0000000..fae2648 --- /dev/null +++ b/SDE_Sheet/LongestSubstringWithoutRepeatingCharacters.js @@ -0,0 +1,23 @@ +class Solution { + public int lengthOfLongestSubstring(String s) { + int maxl = 0; + Map charIdxMap = new HashMap(); //O(1) space + + char c; + int startIdx = 0; + int i; + for(i=0; i= startIdx){ + maxl = Math.max(maxl, i-startIdx); + startIdx = charIdxMap.get(c) + 1; + } + + charIdxMap.put(c, i); + } + + maxl = Math.max(maxl, i-startIdx); + + return maxl; + } +} diff --git a/SDE_Sheet/MiddleOfTheLinkedList.js b/SDE_Sheet/MiddleOfTheLinkedList.js new file mode 100644 index 0000000..d20f3a3 --- /dev/null +++ b/SDE_Sheet/MiddleOfTheLinkedList.js @@ -0,0 +1,22 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode middleNode(ListNode head) { + ListNode slow = head; + ListNode fast = head; + + while(fast != null && fast.next != null){ + fast = fast.next.next; + slow = slow.next; + } + return slow; + } +} diff --git a/SDE_Sheet/ReverseLinkedList.js b/SDE_Sheet/ReverseLinkedList.js new file mode 100644 index 0000000..12ed87d --- /dev/null +++ b/SDE_Sheet/ReverseLinkedList.js @@ -0,0 +1,29 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode reverseList(ListNode head) { + Stack stack =new Stack(); + while(head!=null) + { + stack.push(head); + head = head.next; + } + ListNode dummy = new ListNode(-1); + head=dummy; + while(!stack.isEmpty()) + { + ListNode current= stack.pop(); + head.next=new ListNode(current.val); + head=head.next; + } + return dummy.next; + } +} diff --git a/SDE_Sheet/findDuplicate.js b/SDE_Sheet/findDuplicate.js new file mode 100644 index 0000000..572d581 --- /dev/null +++ b/SDE_Sheet/findDuplicate.js @@ -0,0 +1,21 @@ +/** + * @param {number[]} nums + * @return {number} + */ + var findDuplicate = function(arr) { + var slow = arr[0] + var fast = arr[0] + + do{ + slow = arr[slow] + fast = arr[arr[fast]] + }while(slow !== fast) + + fast = arr[0] + while(slow != fast){ + fast = arr[fast] + slow = arr[slow] + } + return fast + +}; \ No newline at end of file diff --git a/SDE_Sheet/mergeIntervals.js b/SDE_Sheet/mergeIntervals.js new file mode 100644 index 0000000..8b59100 --- /dev/null +++ b/SDE_Sheet/mergeIntervals.js @@ -0,0 +1,20 @@ +/** + * @param {number[][]} intervals + * @return {number[][]} + */ + var merge = function(intervals) { + intervals.sort((a,b) => a[0]-b[0]) + var res = [] + + var tempInterval = intervals[0] + for(let i=0; i < intervals.length; i++){ + if(tempInterval[1] >= intervals[i][0]){ + tempInterval[1] = Math.max(intervals[i][1], tempInterval[1]) + } else{ + res.push(tempInterval) + tempInterval = intervals[i] + } + } + res.push(tempInterval) + return res + }; \ No newline at end of file diff --git a/SDE_Sheet/mergeTwoSortedArrays.js b/SDE_Sheet/mergeTwoSortedArrays.js new file mode 100644 index 0000000..db537c6 --- /dev/null +++ b/SDE_Sheet/mergeTwoSortedArrays.js @@ -0,0 +1,23 @@ +class Solution { + + //Function to merge the arrays. + merge(arr1, arr2, n, m) { + function updateArr(arr){ + for(let i = 1; i < arr.length; i++){ + if(arr[i] < arr[i-1]){ + [arr[i], arr[i-1]] = [arr[i-1], arr[i]] + } + } + return arr + } + + + for(let i=0; i < arr1.length; i++){ + if(arr1[i] > arr2[0]){ + [arr1[i], arr2[0]] = [arr2[0], arr1[i]] + arr2 = updateArr(arr2); + } + } + + } +} \ No newline at end of file diff --git a/SDE_Sheet/nextPermutation.js b/SDE_Sheet/nextPermutation.js new file mode 100644 index 0000000..b54fc1d --- /dev/null +++ b/SDE_Sheet/nextPermutation.js @@ -0,0 +1,33 @@ +/** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ + var nextPermutation = function(nums) { + let index_1 = -1; + let index_2 = -1; + for(let i=nums.length-2; i>=0; i--){ + if(nums[i] < nums[i+1]){ + index_1 = i; + break; + } + } + for(let i=nums.length-1; i>=0; i--){ + if(nums[i] > nums[index_1]){ + index_2 = i; + break; + } + } + // swap + [nums[index_1], nums[index_2]] = [nums[index_2], nums[index_1]] + + // reverse the latter half + let x = index_1 + 1; + let y = nums.length - 1 + + while (x < y){ + [nums[x], nums[y]] = [nums[y], nums[x]] + x++; + y--; + } + +}; \ No newline at end of file diff --git a/SDE_Sheet/pascalTriangle.js b/SDE_Sheet/pascalTriangle.js new file mode 100644 index 0000000..1921e45 --- /dev/null +++ b/SDE_Sheet/pascalTriangle.js @@ -0,0 +1,28 @@ +/** + * @param {number} numRows + * @return {number[][]} + */ + var generate = function(numRows) { + let firstCol = [1]; + let secondCol = [1,1] + + if(numRows === 1){ + return [firstCol]; + } + if(numRows === 2){ + return [firstCol,secondCol] + } + + let res = [firstCol, secondCol]; + + for(let i=0; i < numRows - 2; i++){ + let temp = [...res].pop() + let col = [] + for(let j=0; j < temp.length-1; j++){ + col.push(temp[j]+temp[j+1]) + } + res.push([1, ...col, 1]) + } + return (res); + +}; \ No newline at end of file diff --git a/SDE_Sheet/setMatrixZeros.js b/SDE_Sheet/setMatrixZeros.js new file mode 100644 index 0000000..0fa233a --- /dev/null +++ b/SDE_Sheet/setMatrixZeros.js @@ -0,0 +1,33 @@ +/** + * @param {number[][]} matrix + * @return {void} Do not return anything, modify matrix in-place instead. + */ + var setZeroes = function(matrix) { + let col0 = 1; + let rows = matrix.length; + let cols = matrix[0].length; + + for(let i=0; i < rows; i++){ + if(matrix[i][0] === 0){ + col0 = 0; + } + for(let j=1; j < cols; j++){ + if(matrix[i][j] === 0){ + matrix[i][0] = 0; + matrix[0][j] = 0; + } + } + } + + for(let i=rows-1; i >= 0; i--){ + for(let j=cols-1; j>=1; j--){ + if(matrix[i][0] === 0 || matrix[0][j] == 0){ + matrix[i][j] = 0; + } + } + if(col0 === 0){ + matrix[i][0] = 0; + } + } + +}; \ No newline at end of file diff --git a/SDE_Sheet/sortColors.js b/SDE_Sheet/sortColors.js new file mode 100644 index 0000000..23f6fc7 --- /dev/null +++ b/SDE_Sheet/sortColors.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ + var sortColors = function(nums) { + low = 0; + mid = 0; + high = nums.length -1 + + while(mid <= high){ + if(nums[mid] === 0){ + [nums[mid], nums[low]] = [nums[low], nums[mid]] + mid++ + low++ + } else if(nums[mid] === 1){ + mid++ + } else if(nums[mid] === 2){ + [nums[mid], nums[high]] = [nums[high], nums[mid]] + high-- + } + } + +}; \ No newline at end of file diff --git a/SDE_Sheet/stocksBuyAndSell.js b/SDE_Sheet/stocksBuyAndSell.js new file mode 100644 index 0000000..eb13ce1 --- /dev/null +++ b/SDE_Sheet/stocksBuyAndSell.js @@ -0,0 +1,16 @@ +/** + * @param {number[]} prices + * @return {number} + */ + var maxProfit = function(prices) { + let maxProfit = 0; + let minPrice = Number.POSITIVE_INFINITY; + for(let x in prices){ + minPrice = Math.min(minPrice, prices[x]); + maxProfit = Math.max(maxProfit, prices[x] - minPrice); + } + + + return maxProfit + +}; \ No newline at end of file diff --git a/SDE_Sheet/twoSum.js b/SDE_Sheet/twoSum.js new file mode 100644 index 0000000..11b4c71 --- /dev/null +++ b/SDE_Sheet/twoSum.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +/* A brute-force approach. Traverse the nums array via two pointers i and j and return + indexes stored in an array if the total matches the target*/ +var twoSum = function (nums, target) { + let targetResult = []; + // traverse the array via two pointers + for (let i = 0; i < nums.length; i++) { + for (let j = i + 1; j < nums.length; j++) { + // check if the sum of two numbers is equal to the target + if (nums[i] + nums[j] === target) { + targetResult.push(i); + targetResult.push(j); + } + } + } + // return the array with indexes + return targetResult; +}; \ No newline at end of file diff --git a/Snippets/Arrays/arraySubset.js b/Snippets/Arrays/arraySubset.js new file mode 100644 index 0000000..5523e39 --- /dev/null +++ b/Snippets/Arrays/arraySubset.js @@ -0,0 +1,25 @@ +const arr1 = [2, 3, 4, 5, 6, 88, 9]; +const arr2 = [3, 3, 3, 5, 100]; + +function isSubset(arr1, arr2) { + const arr1Set = []; + const arr2Set = []; + + arr1.forEach((item) => { + if (!arr1Set.includes(item)) { + arr1Set.push(item); + } + }); + arr2.forEach((item) => { + if (!arr2Set.includes(item)) { + arr2Set.push(item); + } + }); + + const res = arr1Set.reduce((previousValue, currentValue) => { + return previousValue + +arr2Set.includes(currentValue); + }, 0); + return res === arr2Set.length; +} + +console.log(isSubset(arr1, arr2)); diff --git a/Snippets/Arrays/atPolyfill.js b/Snippets/Arrays/atPolyfill.js new file mode 100644 index 0000000..3853401 --- /dev/null +++ b/Snippets/Arrays/atPolyfill.js @@ -0,0 +1,10 @@ +Array.prototype.myAt = myAt; + +function myAt(index) { + if (index >= 0) { + return this[index]; + } + return this[this.length - -index]; +} + +console.log([1, 2, 3].myAt(-4)); diff --git a/Snippets/Arrays/checkItemPresentInArray.js b/Snippets/Arrays/checkItemPresentInArray.js new file mode 100644 index 0000000..fa16a88 --- /dev/null +++ b/Snippets/Arrays/checkItemPresentInArray.js @@ -0,0 +1,27 @@ +/* + * Problem: Checks whether the dish you wish to eat is available in the menu + */ + +let polarBearMenu = [ + "Chocolate Fudge", + "Death by chocolate", + "Gudbud", + "Fruit zest", +]; + +let isYourDishAvailable = false; +let itemYouWishToEat = "Gudbud"; + +for (let itemNumber = 0; itemNumber < polarBearMenu.length; itemNumber++) { + if (polarBearMenu[itemNumber] === itemYouWishToEat) { + console.log("Yay " + itemYouWishToEat + " is there in the menu"); + isYourDishAvailable = true; + break; + } else { + isYourDishAvailable = false; + } +} + +if (!isYourDishAvailable) { + console.log("Oops! " + itemYouWishToEat + " is not available. Try searching at a different place."); +} diff --git a/Snippets/Arrays/checkItemPresentInArrayUsingMethod.js b/Snippets/Arrays/checkItemPresentInArrayUsingMethod.js new file mode 100644 index 0000000..e88329a --- /dev/null +++ b/Snippets/Arrays/checkItemPresentInArrayUsingMethod.js @@ -0,0 +1,18 @@ +/** + * Problem: Checks whether pizza is available in the menu + */ + +let polarBearMenu = [ + "Chocolate Fudge", + "Death by chocolate", + "Gudbud", + "Fruit zest", +]; + +let itemYouWishToEat = "Gudbud"; + +if (polarBearMenu.includes(itemYouWishToEat)) { + console.log(itemYouWishToEat + " is present in the menu "); +} else { + console.log(itemYouWishToEat + " is not present in the menu"); +} \ No newline at end of file diff --git a/Snippets/Arrays/checkPositionOfElementInArray.js b/Snippets/Arrays/checkPositionOfElementInArray.js new file mode 100644 index 0000000..0553384 --- /dev/null +++ b/Snippets/Arrays/checkPositionOfElementInArray.js @@ -0,0 +1,7 @@ +/** + * Check the position of IPL teams in 2021 + */ + +let iplTeams = ["CSK", "KKR", "DC", "RCB", "MI", "PBKS", "RR", "SRH"]; +let iplTeamPositionYouWantToKnow = "MI"; +console.log(iplTeams.indexOf(iplTeamPositionYouWantToKnow) + 1); diff --git a/Snippets/Arrays/convertArrayToString.js b/Snippets/Arrays/convertArrayToString.js new file mode 100644 index 0000000..9852912 --- /dev/null +++ b/Snippets/Arrays/convertArrayToString.js @@ -0,0 +1,12 @@ +/** + * Convert given array to string + */ + +const numbers = [1, 2, 3, 4, 5]; +console.log(Array.isArray(numbers)); // true since numbers is an array +console.log(numbers.join(",")); // 1,2,3,4,5 +console.log(typeof numbers.join(",")); // string + +const names = ["Javascript", "Python", "PHP"]; +console.log(names.join(",")); // 'Javascript', 'Python', 'PHP' + diff --git a/Snippets/Arrays/filterPolyfill.js b/Snippets/Arrays/filterPolyfill.js new file mode 100644 index 0000000..d70c249 --- /dev/null +++ b/Snippets/Arrays/filterPolyfill.js @@ -0,0 +1,14 @@ +Array.prototype.myFilter = myFilter; + +function myFilter(cb) { + const filteredArr = []; + this.forEach((item) => { + if (cb(item)) { + filteredArr.push(item); + } + }); + return filteredArr; +} + +const arr = [1, 2, 3, 4]; +console.log(arr.myFilter((item) => item !== 2)); diff --git a/Snippets/Arrays/flattenADeeplyNestedArray.js b/Snippets/Arrays/flattenADeeplyNestedArray.js new file mode 100644 index 0000000..379f66c --- /dev/null +++ b/Snippets/Arrays/flattenADeeplyNestedArray.js @@ -0,0 +1,27 @@ +function flattenArray(arr, n = Infinity) { + let res = []; + for (i in arr) { + if (n !== 0 && Array.isArray(arr[i])) { + res.push(...flattenArray(arr[i], n - 1)); + } else { + res.push(arr[i]); + } + } + return res; +} +let input = [ + 1, + 2, + 3, + [4], + [5, 6, [7], [8, [9, [10]]]], + 11, + 12, + 13, + [14, [[[[[15, [16]]]]]]], + 17, + 18, + [19, [20, [21, [22, [23, [24, [[[[[25]]]]]]]]]]], +]; + +console.log(flattenArray(input, 2)); diff --git a/Snippets/Arrays/groupBy.js b/Snippets/Arrays/groupBy.js new file mode 100644 index 0000000..d4d0731 --- /dev/null +++ b/Snippets/Arrays/groupBy.js @@ -0,0 +1,125 @@ +const arr = [6.1, 2.4, 2.7, 6.8]; + +function groupBy(arr, property) { + const groupByString = (arr, query) => { + let res = {}; + + arr.forEach((item, index) => { + const queryList = query.split("."); + + let currKey; + let currItem = item; + let count = 0; + for (let i = 0; i < queryList.length; i++) { + currKey = queryList[i]; + if (!currItem[currKey]) { + break; + } else { + count += 1; + currItem = currItem[currKey]; + } + } + + if (count !== queryList.length) { + currItem = undefined; + } + if (!res[currItem]) { + res[currItem] = [item]; + } else { + res[currItem].push(item); + } + }); + return res; + }; + const groupByCallback = (arr, cb) => { + let res = {}; + arr.forEach((item) => { + const ans = cb.call(null, item); + + if (Object.keys(res).includes(ans.toString())) { + res[ans].push(item); + } else { + res[ans] = [item]; + } + }); + return res; + }; + + let res; + switch (typeof property) { + case "function": + res = groupByCallback(arr, property); + break; + case "string": + res = groupByString(arr, property); + break; + default: + return new Error("Invalid Property Type"); + } + + return res; +} + +// groupBy(arr, Math.floor); +console.log(groupBy(arr, Math.ceil)); +console.log(groupBy([6.1, 4.2, 6.3], Math.floor)); +console.log(groupBy(["one", "two", "three"], "length")); +console.log( + groupBy( + [{ a: { b: { c: 1 } } }, { a: { b: { c: 1 } } }, { a: { b: { c: 2 } } }], + "b.a.c" + ) +); + +console.log( + groupBy( + [{ a: { b: { c: 1 } } }, { a: { b: { c: 1 } } }, { a: { b: { c: 2 } } }], + "a.b.c" + ) +); + +// alternate solution +function groupByAlternative(collection, property) { + const output = {}; + + if (!collection || typeof collection !== "object") { + return output; + } + + const isPropertyFunction = typeof property === "function"; + const isPropertyPath = typeof property === "string"; + + for (const value of Object.values(collection)) { + let current = undefined; + + if (isPropertyFunction) { + current = property(value); + } else if (isPropertyPath) { + // a.b.c -> [a, b, c]; + const path = property.split("."); + let i; + let currentKey; + let currentItem = value; // { a: { b: { c: 1 } } } + + for (i = 0; i < path.length; i++) { + // [a, b, c] -> currentKey: path[0] -> a + // [a, b, c] -> currentKey: path[1] -> b + // [a, b, c] -> currentKey: path[2] -> c + currentKey = path[i]; + + if (!currentItem[currentKey]) { + currentItem = undefined; + break; + } + currentItem = currentItem[currentKey]; + } + + current = currentItem; + } + + output[current] = output[current] || []; + output[current].push(value); + } + + return output; +} diff --git a/Snippets/Arrays/mapPolyfill.js b/Snippets/Arrays/mapPolyfill.js new file mode 100644 index 0000000..4caf00c --- /dev/null +++ b/Snippets/Arrays/mapPolyfill.js @@ -0,0 +1,12 @@ +Array.prototype.myMap = myMap; + +function myMap(cb) { + const newArr = []; + for (let i = 0; i < this.length; i++) { + newArr.push(cb(this[i])); + } + return newArr; +} +const arr = [1, 2, 3, 4, 5]; + +console.log(arr.myMap((item) => item + 2)); diff --git a/Snippets/Arrays/pushPolyfill.js b/Snippets/Arrays/pushPolyfill.js new file mode 100644 index 0000000..ce9c9e2 --- /dev/null +++ b/Snippets/Arrays/pushPolyfill.js @@ -0,0 +1,9 @@ +Array.prototype.myPush = myPush; + +function myPush(item) { + this[this.length] = item; + return this; +} +const arr = [1, 2, 3]; +arr.myPush(2).push(2); // chaining possible +console.log(arr); diff --git a/Snippets/Arrays/reducePolyfill.js b/Snippets/Arrays/reducePolyfill.js new file mode 100644 index 0000000..ede890b --- /dev/null +++ b/Snippets/Arrays/reducePolyfill.js @@ -0,0 +1,17 @@ +Array.prototype.myReduce = myReduce; + +function myReduce(cb, initialValue = this[0]) { + let result = initialValue; + this.forEach((item) => { + result = cb(result, item); + }); + return result; +} + +const array1 = [1, 2, 3, 4]; +const sumWithInitial = array1.myReduce( + (previousValue, currentValue) => previousValue + currentValue, + 0 +); + +console.log(sumWithInitial); diff --git a/Snippets/Arrays/removeDuplicates.js b/Snippets/Arrays/removeDuplicates.js new file mode 100644 index 0000000..a493295 --- /dev/null +++ b/Snippets/Arrays/removeDuplicates.js @@ -0,0 +1,16 @@ +const arr = [1, 2, 2, 3]; + +const updatedArrWithSet = [...new Set(arr)]; + +const updatedArrWithFilter = arr.filter((c, index) => { + return index !== arr.indexOf(c); +}); + +const updatedArrWithIncludes = []; +arr.forEach((c) => { + if (!updatedArrWithIncludes.includes(c)) { + updatedArrWithIncludes.push(c); + } +}); + +console.log(updatedArrWithIncludes); diff --git a/Snippets/Arrays/unshiftPolyfill.js b/Snippets/Arrays/unshiftPolyfill.js new file mode 100644 index 0000000..dfa1f65 --- /dev/null +++ b/Snippets/Arrays/unshiftPolyfill.js @@ -0,0 +1,19 @@ +Array.prototype.myUnshift = myUnshift; + +function myUnshift(item) { + let prevItem = item; + const originalLength = this.length; + for (let i = 0; i <= originalLength; i++) { + let temp = this[i]; + this[i] = prevItem; + prevItem = temp; + } + return this; +} + +const arr = [1, 2, 3, 4]; +arr + .myUnshift(2) + .myUnshift(100) + .myUnshift(() => console.log("WOW")); +console.log(arr); diff --git a/Snippets/Closures/armyOfFunctions.js b/Snippets/Closures/armyOfFunctions.js new file mode 100644 index 0000000..9157e9a --- /dev/null +++ b/Snippets/Closures/armyOfFunctions.js @@ -0,0 +1,23 @@ +function makeArmy() { + let shooters = []; + + let i = 0; + while (i < 10) { + // we can use for loop with let i to avoid the problem + let a = i; // avoid the closure problem of referencing same variable + let shooter = function () { + // create a shooter function, + console.log(a); // that should show its number + }; + shooters.push(shooter); // and add it to the array + i++; + } + + // ...and return the array of shooters + return shooters; +} + +let army = makeArmy(); + +army[1](); +army[9](); diff --git a/Snippets/Closures/filterThroughFunction.js b/Snippets/Closures/filterThroughFunction.js new file mode 100644 index 0000000..00a02c4 --- /dev/null +++ b/Snippets/Closures/filterThroughFunction.js @@ -0,0 +1,18 @@ +const inBetween = (left, right) => { + return function (x) { + return x >= left && x <= right; + }; +}; + +const inArray = (arr) => { + return function (x) { + return arr.includes(x); + }; +}; + +let arr = [1, 2, 3, 4, 5, 6, 7]; + +console.log(arr.filter(inBetween(3, 6))); +// or console.log(arr.filter((item) => inBetween(3, 6)(item))); + +console.log(arr.filter(inArray([1, 2, 10]))); diff --git a/Snippets/Closures/makeCounter.js b/Snippets/Closures/makeCounter.js new file mode 100644 index 0000000..1ae6657 --- /dev/null +++ b/Snippets/Closures/makeCounter.js @@ -0,0 +1,17 @@ +function makeCounter() { + let count = 0; + + return function () { + return ++count; + }; +} + +let counter = makeCounter(); + +counter(); +counter(); +counter(); + +const count = counter(); + +console.log(count); diff --git a/Snippets/Closures/sortByFields.js b/Snippets/Closures/sortByFields.js new file mode 100644 index 0000000..f299a4c --- /dev/null +++ b/Snippets/Closures/sortByFields.js @@ -0,0 +1,18 @@ +let users = [ + { name: "John", age: 20, surname: "Johnson" }, + { name: "Pete", age: 18, surname: "Peterson" }, + { name: "Ann", age: 19, surname: "Hathaway" }, +]; + +// Normal Approach will be +//users.sort((a, b) => (a.name > b.name ? 1 : -1)); +//users.sort((a, b) => (a.age > b.age ? 1 : -1)); + +// cleaner way +const byField = (fieldName) => { + return function (x, y) { + return x[fieldName] > y[fieldName] ? 1 : -1; + }; +}; + +console.log(users.sort(byField("age"))); diff --git a/Snippets/Currying/advancedCurryImplementation.js b/Snippets/Currying/advancedCurryImplementation.js new file mode 100644 index 0000000..a8debcf --- /dev/null +++ b/Snippets/Currying/advancedCurryImplementation.js @@ -0,0 +1,33 @@ +function sum(a, b, c) { + return a + b + c; +} + +// function curry(fn) { +// return function curried(...args) { +// if (args.length >= fn.length) { +// return fn.apply(this, args); +// } else { +// return function (...args2) { +// return curried.apply(this, args.concat(args2)); +// }; +// } +// }; +// } + +function curry(func) { + return function curried(...args) { + if (args.length >= func.length) { + return func.apply(this, args); + } else { + return function (...args2) { + return curried.apply(this, args.concat(args2)); + }; + } + }; +} + +let curriedSum = curry(sum); + +console.log(curriedSum(1, 2, 3)); // 6, still callable normally +console.log(curriedSum(1)(2, 3)); // 6, currying of 1st arg +console.log(curriedSum(1)(2)(3)); diff --git a/Snippets/Currying/sumOfNNumbers.js b/Snippets/Currying/sumOfNNumbers.js new file mode 100644 index 0000000..bdf2008 --- /dev/null +++ b/Snippets/Currying/sumOfNNumbers.js @@ -0,0 +1,11 @@ +let sum = function (a) { + return function (b) { + if (b) { + return sum(a + b); + } + return a; + }; +}; + +const total = sum(1)(2)(3)(); +console.log(total); diff --git a/Snippets/DataTypes/methodsOfPrimitives.js b/Snippets/DataTypes/methodsOfPrimitives.js new file mode 100644 index 0000000..e69de29 diff --git a/Snippets/Functional_Programming/arrayLength.js b/Snippets/FunctionalProgramming/General/arrayLength.js similarity index 88% rename from Snippets/Functional_Programming/arrayLength.js rename to Snippets/FunctionalProgramming/General/arrayLength.js index bc17b1a..b1fd1e6 100644 --- a/Snippets/Functional_Programming/arrayLength.js +++ b/Snippets/FunctionalProgramming/General/arrayLength.js @@ -1,3 +1,5 @@ +// finds array length + function arrayLength(arr){ let len = 0; while(arr[len] !== undefined){ diff --git a/Snippets/Functional_Programming/charAt.js b/Snippets/FunctionalProgramming/General/charAt.js similarity index 100% rename from Snippets/Functional_Programming/charAt.js rename to Snippets/FunctionalProgramming/General/charAt.js diff --git a/Snippets/Functional_Programming/findMax.js b/Snippets/FunctionalProgramming/General/findMax.js similarity index 100% rename from Snippets/Functional_Programming/findMax.js rename to Snippets/FunctionalProgramming/General/findMax.js diff --git a/Snippets/Functional_Programming/findMin.js b/Snippets/FunctionalProgramming/General/findMin.js similarity index 100% rename from Snippets/Functional_Programming/findMin.js rename to Snippets/FunctionalProgramming/General/findMin.js diff --git a/Snippets/Functional_Programming/hexagonArea.js b/Snippets/FunctionalProgramming/General/hexagonArea.js similarity index 100% rename from Snippets/Functional_Programming/hexagonArea.js rename to Snippets/FunctionalProgramming/General/hexagonArea.js diff --git a/Snippets/Functional_Programming/indexOf.js b/Snippets/FunctionalProgramming/General/indexOf.js similarity index 100% rename from Snippets/Functional_Programming/indexOf.js rename to Snippets/FunctionalProgramming/General/indexOf.js diff --git a/Snippets/Functional_Programming/mergeArray.js b/Snippets/FunctionalProgramming/General/mergeArray.js similarity index 100% rename from Snippets/Functional_Programming/mergeArray.js rename to Snippets/FunctionalProgramming/General/mergeArray.js diff --git a/Snippets/Functional_Programming/minDate.js b/Snippets/FunctionalProgramming/General/minDate.js similarity index 100% rename from Snippets/Functional_Programming/minDate.js rename to Snippets/FunctionalProgramming/General/minDate.js diff --git a/Snippets/Functional_Programming/power.js b/Snippets/FunctionalProgramming/General/power.js similarity index 100% rename from Snippets/Functional_Programming/power.js rename to Snippets/FunctionalProgramming/General/power.js diff --git a/Snippets/Functional_Programming/replace.js b/Snippets/FunctionalProgramming/General/replace.js similarity index 100% rename from Snippets/Functional_Programming/replace.js rename to Snippets/FunctionalProgramming/General/replace.js diff --git a/Snippets/Functional_Programming/reverseWords.js b/Snippets/FunctionalProgramming/General/reverseWords.js similarity index 100% rename from Snippets/Functional_Programming/reverseWords.js rename to Snippets/FunctionalProgramming/General/reverseWords.js diff --git a/Snippets/Functional_Programming/secretCode.js b/Snippets/FunctionalProgramming/General/secretCode.js similarity index 100% rename from Snippets/Functional_Programming/secretCode.js rename to Snippets/FunctionalProgramming/General/secretCode.js diff --git a/Snippets/Functional_Programming/toSentenceCase.js b/Snippets/FunctionalProgramming/General/toSentenceCase.js similarity index 100% rename from Snippets/Functional_Programming/toSentenceCase.js rename to Snippets/FunctionalProgramming/General/toSentenceCase.js diff --git a/Snippets/Functional_Programming/triangleType.js b/Snippets/FunctionalProgramming/General/triangleType.js similarity index 100% rename from Snippets/Functional_Programming/triangleType.js rename to Snippets/FunctionalProgramming/General/triangleType.js diff --git a/Snippets/Functional_Programming/wordCounter.js b/Snippets/FunctionalProgramming/General/wordCounter.js similarity index 100% rename from Snippets/Functional_Programming/wordCounter.js rename to Snippets/FunctionalProgramming/General/wordCounter.js diff --git a/Snippets/FunctionalProgramming/HigherOrderFunctions/README.md b/Snippets/FunctionalProgramming/HigherOrderFunctions/README.md new file mode 100644 index 0000000..d4daf81 --- /dev/null +++ b/Snippets/FunctionalProgramming/HigherOrderFunctions/README.md @@ -0,0 +1,3 @@ +# The One + +Write a function `compose()` that can take any number of arguments of functions and return a function which will run the given functions in order when called an argument. \ No newline at end of file diff --git a/Snippets/FunctionalProgramming/HigherOrderFunctions/TheOne.js b/Snippets/FunctionalProgramming/HigherOrderFunctions/TheOne.js new file mode 100644 index 0000000..50e8b1c --- /dev/null +++ b/Snippets/FunctionalProgramming/HigherOrderFunctions/TheOne.js @@ -0,0 +1,13 @@ +// Composing functions +const increment = (n) => n + 1; +const square = (n) => n * n; +const cube = (n) => n*n*n + +// Compose Util Function +function compose(...args){ + return (num) => args.reduce((acc, cur) => cur(acc), num); +} + +// Main +const incrementThenSquareThenCube = compose(increment, square, cube); +console.log(incrementThenSquareThenCube(5)); \ No newline at end of file diff --git a/Snippets/Functions/bind.js b/Snippets/Functions/bind.js new file mode 100644 index 0000000..001aa36 --- /dev/null +++ b/Snippets/Functions/bind.js @@ -0,0 +1,21 @@ +let user = { + firstName: "John", + sayHi() { + alert(`Hello, ${this.firstName}!`); + }, +}; + +let sayHi = user.sayHi.bind(user); // (*) + +// can run it without an object +sayHi(); // Hello, John! + +setTimeout(sayHi, 1000); // Hello, John! + +// even if the value of user changes within 1 second +// sayHi uses the pre-bound value which is reference to the old user object +user = { + sayHi() { + alert("Another user in setTimeout!"); + }, +}; diff --git a/Snippets/Functions/bindAll.js b/Snippets/Functions/bindAll.js new file mode 100644 index 0000000..8d1acf2 --- /dev/null +++ b/Snippets/Functions/bindAll.js @@ -0,0 +1,19 @@ +// If an object has many methods and we plan to actively pass it around, then we could bind them all in a loop + +const user = { + func1() { + console.log("func 1"); + }, + func2() { + console.log("func 2"); + }, + func3() { + console.log("func 3"); + }, +}; + +for (let key in user) { + if (typeof user[key] == "function") { + user[key] = user[key].bind(user); + } +} diff --git a/Snippets/Functions/boundFunctionMethod.js b/Snippets/Functions/boundFunctionMethod.js new file mode 100644 index 0000000..4e2d792 --- /dev/null +++ b/Snippets/Functions/boundFunctionMethod.js @@ -0,0 +1,11 @@ +"use strict"; +function f() { + console.log(this); // null +} + +let user = { + g: f.bind(null), +}; + +// f(); +user.g(); diff --git a/Snippets/Functions/call.js b/Snippets/Functions/call.js new file mode 100644 index 0000000..76fc2eb --- /dev/null +++ b/Snippets/Functions/call.js @@ -0,0 +1,27 @@ +"use strict"; +let worker = { + someMethod() { + return 1; + }, + slow(x) { + console.log("Called with", x); + return x + this.someMethod(); // need a reference for this + }, +}; + +function cachingDecorator(func) { + const cache = new Map(); + return function (x) { + if (cache.has(x)) { + return cache.get(x); + } + const res = func.call(this, x); + cache.set(x, res); + return res; + }; +} + +worker.slow = cachingDecorator(worker.slow); // now make it caching + +console.log(worker.slow(2)); // works +console.log(worker.slow(2)); // works, doesn't call the original (cached) diff --git a/Snippets/Functions/customSetInterval.js b/Snippets/Functions/customSetInterval.js new file mode 100644 index 0000000..a3a7080 --- /dev/null +++ b/Snippets/Functions/customSetInterval.js @@ -0,0 +1,15 @@ +const mySetInterval = (callback, delay, ...args) => { + let timerId = setTimeout( + function tick(...args) { + callback(...args); + timerId = setTimeout(tick, delay, ...args); + }, + delay, + ...args + ); +}; + +function cb(x, y) { + console.log(x, y); +} +mySetInterval(cb, 2000, 1, 2); diff --git a/Snippets/Functions/debounceDecorator.js b/Snippets/Functions/debounceDecorator.js new file mode 100644 index 0000000..a3381c4 --- /dev/null +++ b/Snippets/Functions/debounceDecorator.js @@ -0,0 +1,18 @@ +function debounce(func, delay) { + let timeout; + return function (...args) { + if (timeout) { + clearTimeout(timeout); + } + timeout = setTimeout(() => { + func(...args); + // func.apply(this, args) + }, delay); + }; +} + +let f = debounce(console.log, 2000); + +f("a"); +setTimeout(() => f("b"), 200); +setTimeout(() => f("c"), 500); diff --git a/Snippets/Functions/delayDecorator.js b/Snippets/Functions/delayDecorator.js new file mode 100644 index 0000000..ba21328 --- /dev/null +++ b/Snippets/Functions/delayDecorator.js @@ -0,0 +1,18 @@ +function f(x) { + console.log(x); +} + +function delay(func, delay) { + return function (...args) { + setTimeout(() => { + func.call(this, ...args); + }, delay); + }; +} + +// create wrappers +let f1000 = delay(f, 1000); +let f1500 = delay(f, 1500); + +f1000("test"); // shows "test" after 1000ms +f1500("test"); // shows "test" after 1500ms diff --git a/Snippets/Functions/fixFunctionThis.js b/Snippets/Functions/fixFunctionThis.js new file mode 100644 index 0000000..4c12b1e --- /dev/null +++ b/Snippets/Functions/fixFunctionThis.js @@ -0,0 +1,21 @@ +function askPassword(ok, fail) { + let password = "rockstar"; + if (password == "rockstar") ok(); + else fail(); +} + +let user = { + name: "John", + + loginOk() { + console.log(`${this.name} logged in`); + }, + + loginFail() { + console.log(`${this.name} failed to log in`); + }, +}; + +askPassword(user.loginOk.bind(user), user.loginFail.bind(user)); + +// askPassword(() => user.loginOk(), () => user.loginFail()); diff --git a/Snippets/Functions/globalPartialFunctions.js b/Snippets/Functions/globalPartialFunctions.js new file mode 100644 index 0000000..7df8409 --- /dev/null +++ b/Snippets/Functions/globalPartialFunctions.js @@ -0,0 +1,22 @@ +function partial(func, ...argsBound) { + return function (...args) { + // (*) + return func.call(this, ...argsBound, ...args); + }; +} + +// Usage: +let user = { + firstName: "John", + say(time, phrase) { + alert(`[${time}] ${this.firstName}: ${phrase}!`); + }, +}; + +// add a partial method with fixed time +user.sayNow = partial( + user.say, + new Date().getHours() + ":" + new Date().getMinutes() +); + +user.sayNow("Hello"); diff --git a/Snippets/Functions/makeCounter.js b/Snippets/Functions/makeCounter.js new file mode 100644 index 0000000..1d90f60 --- /dev/null +++ b/Snippets/Functions/makeCounter.js @@ -0,0 +1,24 @@ +const makeCounter = () => { + const counter = () => { + return counter.count++; + }; + counter.set = (val) => { + counter.count = val; + return counter.count; + }; + + counter.decrease = () => { + counter.count--; + return counter.count; + }; + + counter.count = 0; + + return counter; +}; + +const counter = makeCounter(); + +console.log(counter()); +console.log(counter.set(10)); +console.log(counter.decrease()); diff --git a/Snippets/Functions/memoizeOne.js b/Snippets/Functions/memoizeOne.js new file mode 100644 index 0000000..db4db13 --- /dev/null +++ b/Snippets/Functions/memoizeOne.js @@ -0,0 +1,38 @@ +/** + * Do not change the function name + **/ + +function memoizeOne(fn, isEqual) { + let cache = {}; + + function hasher(args) { + return args.join(","); + } + return function (...args) { + const hash = hasher(args); + if (cache[hash]) { + return cache[hash]; + } + cache = {}; + const res = fn.apply(null, args); + cache[hash] = res; + return res; + }; +} + +function add(a, b) { + console.print("called"); + return a + b; +} + +function isEqual(a, b) { + if (a === b) { + return true; + } + return false; +} +const memoizeAdd = memoizeOne(add, isEqual); +console.print(memoizeAdd(2, 3)); +console.print(memoizeAdd(2, 3)); +console.print(memoizeAdd(3, 4)); +console.print(memoizeAdd(5, 6)); diff --git a/Snippets/Functions/multiArgumentCaching.js b/Snippets/Functions/multiArgumentCaching.js new file mode 100644 index 0000000..33618d6 --- /dev/null +++ b/Snippets/Functions/multiArgumentCaching.js @@ -0,0 +1,30 @@ +const worker = { + slow(min, max) { + console.log(`Called with ${min},${max}`); + return min + max; + }, +}; + +function cachingDecorator(func, hash) { + const cache = new Map(); + return function (...args) { + let key = hash(args); + if (cache.has(key)) { + return cache.get(key); + } + let res = func.apply(this, args); + // or let res = func.call(this, ...args) + cache.set(key, res); + return res; + }; +} + +function hash(args) { + // [].join.call(arguments) + return args.join(); +} + +worker.slow = cachingDecorator(worker.slow, hash); + +console.log(worker.slow(3, 5)); // works +console.log("Again " + worker.slow(3, 5)); // same (cached) diff --git a/Snippets/Functions/namedFunctionExpression.js b/Snippets/Functions/namedFunctionExpression.js new file mode 100644 index 0000000..1adfb70 --- /dev/null +++ b/Snippets/Functions/namedFunctionExpression.js @@ -0,0 +1,12 @@ +let sayHi = function func(who) { + if (who) { + console.log(`Hello, ${who}`); + } else { + func("Guest"); // Error: sayHi is not a function + } +}; + +let welcome = sayHi; +sayHi = null; + +welcome(); // Error, the nested sayHi call doesn't work any more! diff --git a/Snippets/Functions/nestedSetTimeout.js b/Snippets/Functions/nestedSetTimeout.js new file mode 100644 index 0000000..7bbe30d --- /dev/null +++ b/Snippets/Functions/nestedSetTimeout.js @@ -0,0 +1,12 @@ +let delay = 5000; + +let timerId = setTimeout(function request() { + console.log("Send Request to server", delay); + if (true) { + // request failed due to server overload + // increase the interval to the next run + delay *= 2; + } + + timerId = setTimeout(request, delay); +}, delay); diff --git a/Snippets/Functions/newFunctionSyntax.js b/Snippets/Functions/newFunctionSyntax.js new file mode 100644 index 0000000..217d9e2 --- /dev/null +++ b/Snippets/Functions/newFunctionSyntax.js @@ -0,0 +1,7 @@ +let sum = new Function("a", "b", "return a + b"); + +alert(sum(1, 2)); // 3 + +let sayHi = new Function('alert("Hello")'); + +sayHi(); // Hello diff --git a/Snippets/Functions/outputEverySecond.js b/Snippets/Functions/outputEverySecond.js new file mode 100644 index 0000000..50f4306 --- /dev/null +++ b/Snippets/Functions/outputEverySecond.js @@ -0,0 +1,50 @@ +function printNumbers(from, to) { + const timerId = setInterval( + function f(to) { + console.log(from); + if (to === from) { + clearInterval(timerId); + } + from = from + 1; + }, + 1000, + to + ); +} + +printNumbers(1, 10); + +// with nested setTimeout + +function printNumbers(from, to) { + let current = from; + + setTimeout(function go() { + alert(current); + if (current < to) { + setTimeout(go, 1000); + } + current++; + }, 1000); +} + +// usage: +printNumbers(5, 10); + +// runs immediately +function printNumbers(from, to) { + let current = from; + + function go() { + alert(current); + if (current == to) { + clearInterval(timerId); + } + current++; + } + + go(); + let timerId = setInterval(go, 1000); +} + +printNumbers(5, 10); diff --git a/Snippets/Functions/partialFunctions.js b/Snippets/Functions/partialFunctions.js new file mode 100644 index 0000000..fd674d6 --- /dev/null +++ b/Snippets/Functions/partialFunctions.js @@ -0,0 +1,22 @@ +function mul(a, b) { + return a * b; +} + +const triple = mul.bind(null, 3); // alternative to this is to curry functions + +console.log(triple(4)); + +const user = { + firstName: "Samyak Shah", +}; +function send(from, text, to) { + return ` + By: ${from} + To: ${to} + Message: + ${text}, ${this.firstName}`; +} + +const sendTo = send.bind(user, "soham@invact.com"); + +console.log(sendTo("Hello World", "samyak@neog.com")); diff --git a/Snippets/Functions/partialLogin.js b/Snippets/Functions/partialLogin.js new file mode 100644 index 0000000..216436d --- /dev/null +++ b/Snippets/Functions/partialLogin.js @@ -0,0 +1,15 @@ +function askPassword(ok, fail) { + let password = prompt("Password?", ""); + if (password == "rockstar") ok(); + else fail(); +} + +let user = { + name: "John", + + login(result) { + alert(this.name + (result ? " logged in" : " failed to log in")); + }, +}; + +askPassword(user.login.bind(user, true), user.login.bind(user, false)); // ? diff --git a/Snippets/Functions/polymorphism.js b/Snippets/Functions/polymorphism.js new file mode 100644 index 0000000..a218e64 --- /dev/null +++ b/Snippets/Functions/polymorphism.js @@ -0,0 +1,19 @@ +function ask(question, ...handlers) { + let isYes = confirm(question); + + for (let handler of handlers) { + if (handler.length == 0) { + if (isYes) handler(); + } else { + handler(isYes); + } + } +} + +// for positive answer, both handlers are called +// for negative answer, only the second one +ask( + "Question?", + () => alert("You said yes"), + (result) => alert(result) +); diff --git a/Snippets/Functions/properties.js b/Snippets/Functions/properties.js new file mode 100644 index 0000000..3ebcb14 --- /dev/null +++ b/Snippets/Functions/properties.js @@ -0,0 +1,48 @@ +function sayHi() { + console.log("Hi"); +} + +console.log(sayHi.name); +console.log(function () {}.name); // empty string + +function f1(a) {} +function f2(a, b) {} +function many(a, b, ...more) {} + +console.log(f1.length); // 1 +console.log(f2.length); // 2 +console.log(many.length); // 2 + +// custom property + +function sayHi() { + console.log("Hi"); + + // let's count how many times we run + sayHi.counter++; +} +sayHi.counter = 0; // initial value + +sayHi(); // Hi +sayHi(); // Hi + +console.log(`Called ${sayHi.counter} times`); // Called 2 times + +// counter with custom property + +function makeCounter() { + // instead of: + // let count = 0 + + function counter() { + return counter.count++; + } + + counter.count = 0; + + return counter; +} + +let counter = makeCounter(); +alert(counter()); // 0 +alert(counter()); // 1 diff --git a/Snippets/Functions/secondBind.js b/Snippets/Functions/secondBind.js new file mode 100644 index 0000000..4684187 --- /dev/null +++ b/Snippets/Functions/secondBind.js @@ -0,0 +1,10 @@ +// A function cannot be re-bound +function f() { + console.log(this.name); +} + +f = f.bind({ name: "John" }); +z = f.bind({ name: "Ann" }); + +f(); // John +z(); // John diff --git a/Snippets/Functions/setInterval.js b/Snippets/Functions/setInterval.js new file mode 100644 index 0000000..40e0b84 --- /dev/null +++ b/Snippets/Functions/setInterval.js @@ -0,0 +1,4 @@ +// let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...) + +// repeat with the interval of 2 seconds +let timerId = setInterval(() => alert("tick"), 2000); diff --git a/Snippets/Functions/setTimeout.js b/Snippets/Functions/setTimeout.js new file mode 100644 index 0000000..7983b60 --- /dev/null +++ b/Snippets/Functions/setTimeout.js @@ -0,0 +1,20 @@ +// let timerId = setTimeout(func|code, [delay], [arg1], [arg2], ...) + +function sayHi(phrase, who) { + alert(phrase + ", " + who); +} + +setTimeout(sayHi, 1000, "Hello", "John"); // Hello, John + +// string also works +setTimeout("alert('Hello')", 1000); + +// recommended +setTimeout(() => alert("Hello"), 1000); + +// wrong! +setTimeout(sayHi(), 1000); + +// clear timeout +let timerId = setTimeout(() => alert("Hi")); +clearTimeout(timerId); diff --git a/Snippets/Functions/spyDecorator.js b/Snippets/Functions/spyDecorator.js new file mode 100644 index 0000000..0d769cd --- /dev/null +++ b/Snippets/Functions/spyDecorator.js @@ -0,0 +1,29 @@ +function work(a, b) { + console.log(a + b); // work is an arbitrary function or method +} + +function spy(func) { + wrapper.calls = []; + function wrapper(...args) { + const key = hash(args); + func.call(this, ...args); + wrapper.calls.push(key); + } + + return wrapper; +} + +const hash = (args) => { + return args.join(); +}; + +work = spy(work); + +work(1, 2); // 3 +work(4, 5); // 9 + +console.log(work); + +for (let args of work.calls) { + console.log("call:" + args); // "call:1,2", "call:4,5" +} diff --git a/Snippets/Functions/sumWithArbitaryAmountOfBrackets.js b/Snippets/Functions/sumWithArbitaryAmountOfBrackets.js new file mode 100644 index 0000000..5ce5198 --- /dev/null +++ b/Snippets/Functions/sumWithArbitaryAmountOfBrackets.js @@ -0,0 +1,32 @@ +const sum = (x) => { + let total = x; + return function by(y) { + if (y === undefined) { + return total; + } else { + total += y; + return by; + } + }; +}; + +console.log(sum(1)(2)(5)()); + +// But what if we need exactly like this: sum(1)(2)(5) for the result +function sum(a) { + let currentSum = a; + + function f(b) { + currentSum += b; + return f; + } + + f.toString = function () { + return currentSum; + }; + + return f; +} + +const val = sum(1)(8); // 3 +alert(val); // alert calls val.toString(). We can modify this function for our use case diff --git a/Snippets/Functions/throttleDecorator.js b/Snippets/Functions/throttleDecorator.js new file mode 100644 index 0000000..fbc0daf --- /dev/null +++ b/Snippets/Functions/throttleDecorator.js @@ -0,0 +1,19 @@ +function throttle(func, delay) { + let flag = true; + return function (...args) { + if (flag) { + flag = false; + setTimeout(() => { + func.apply(this, args); + flag = true; + }); + } + }; +} + +const f = (text) => { + console.log(text); +}; + +const f1000 = throttle(f, 1000); +f1000("Hi I am 1000s throttle function"); diff --git a/Snippets/Functions/timeBomb.js b/Snippets/Functions/timeBomb.js new file mode 100644 index 0000000..f72451a --- /dev/null +++ b/Snippets/Functions/timeBomb.js @@ -0,0 +1,10 @@ +// 5,4,3,2,1, Bang! + +function timeBomb(i) { + return i === 0 ? "Bang" : i; +} +for (let i = 5; i >= 0; i--) { + setTimeout(() => { + console.log(timeBomb(i)); + }, [(5 - i) * 1000]); +} diff --git a/Snippets/Functions/transparentCaching.js b/Snippets/Functions/transparentCaching.js new file mode 100644 index 0000000..ef3f4a2 --- /dev/null +++ b/Snippets/Functions/transparentCaching.js @@ -0,0 +1,26 @@ +const delay = (data, ms) => { + setTimeout(() => console.log("computing", data), ms); +}; +let slow = async (x) => { + await delay(x, 3000); + return x; +}; + +const cachingDecorator = (func) => { + const cache = new Map(); + return function (x) { + if (cache.has(x)) { + return cache.get(x); + } + const res = func(x); + cache.set(x, res); + return res; + }; +}; + +slow = cachingDecorator(slow); + +slow(4).then(slow(5)).then(slow(4)); + +console.log(await slow(5)); +console.log(await slow(4)); diff --git a/Snippets/Objects/accumulator.js b/Snippets/Objects/accumulator.js new file mode 100644 index 0000000..5b5098b --- /dev/null +++ b/Snippets/Objects/accumulator.js @@ -0,0 +1,13 @@ +function Accumulator(initValue) { + this.value = initValue; + this.read = (payload) => { + this.value += payload; + }; +} + +let accumulator = new Accumulator(1); // initial value 1 + +accumulator.read(1); +accumulator.read(8); + +console.log(accumulator.value); diff --git a/Snippets/Objects/bindPolyFill.js b/Snippets/Objects/bindPolyFill.js new file mode 100644 index 0000000..633ecd0 --- /dev/null +++ b/Snippets/Objects/bindPolyFill.js @@ -0,0 +1,18 @@ +Function.prototype.myBind = myBind; + +function myBind(context, ...args1) { + const newContext = this; + return function (...args2) { + newContext.apply(context, [...args1, ...args2]); + }; +} + +let user = { + firstName: "John", + sayHi(area, birthdate) { + console.log(`Hello, ${this.firstName} from ${area}, born on ${birthdate}!`); + }, +}; + +let sayHi = user.sayHi.myBind(user, "Ahmedabad"); // (*) +sayHi("26/06"); diff --git a/Snippets/Objects/calculator.js b/Snippets/Objects/calculator.js new file mode 100644 index 0000000..fc4fb44 --- /dev/null +++ b/Snippets/Objects/calculator.js @@ -0,0 +1,90 @@ +class Calculator { + constructor(a, b) { + this.a = a; + this.b = b; + } + + sum() { + console.log(this.a); + console.log(this.a + this.b); + return this; + } + + mul() { + console.log(this.a * this.b); + return this; + } +} + +const calculator = new Calculator(1, 2); +calculator.sum(); +calculator.mul(); + +// alternate way + +function Calc(a, b) { + this.a = a; + this.b = b; + + this.sum = () => { + return this.a + this.b; + }; + this.mul = () => { + return this.a * this.b; + }; +} + +const calc = new Calc(5, 2); +console.log(calc.sum()); +console.log(calc.mul()); + +// approach 2: with chaining + +function Calculator(initialValue) { + this.total = initialValue; + this.sum = function (a) { + this.total += a; + return this; + }; + this.sub = function (a) { + this.total -= a; + return this; + }; + this.misc = function (cb) { + this.total = cb(this.total); + return this; + }; + this.val = function () { + return this.total; + }; +} + +const cal = new Calculator(2); +console.print( + cal + .sum(2) + .misc((val) => val + 100) + .val() +); + +// approach 3: using functions + +function cal(initialValue) { + let total = initialValue; + + function add(a) { + total += a; + return cal(total); + } + + function val() { + return total; + } + + return { + add, + val, + }; +} + +console.print(cal(2).add(2).add(2).val()); diff --git a/Snippets/Objects/cloneObject.js b/Snippets/Objects/cloneObject.js new file mode 100644 index 0000000..093088c --- /dev/null +++ b/Snippets/Objects/cloneObject.js @@ -0,0 +1,40 @@ +// using copying properties + +let user = { + name: "John", + age: 30, +}; + +let clone = {}; // the new empty object + +// let's copy all user properties into it +for (let key in user) { + clone[key] = user[key]; +} + +// now clone is a fully independent object with the same content +clone.name = "Pete"; // changed the data in it + +console.log(user.name); // still John in the original object + +// Using Object.assign + +let permissions1 = { canView: true }; +let permissions2 = { canEdit: true }; + +// copies all properties from permissions1 and permissions2 into user +Object.assign(user, permissions1, permissions2); + +// now user = { name: "John", canView: true, canEdit: true } + +Object.assign(user, { name: "Pete" }); + +console.log(user.name); // now user = { name: "Pete" } + +let clone2 = Object.assign({}, user); // shallow copy + +console.log(clone2); + +// clone in a different way + +let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj)); diff --git a/Snippets/Objects/colorUtils.js b/Snippets/Objects/colorUtils.js new file mode 100644 index 0000000..13ca9d4 --- /dev/null +++ b/Snippets/Objects/colorUtils.js @@ -0,0 +1,103 @@ +class ColorUtils { + constructor(r, g, b) { + this.r = r; + this.g = g; + this.b = b; + } + + getRGB() { + return `rgb(${this.r}, ${this.g}, ${this.b})`; + } + + getHSL() { + const hsl = this.rgbToHsl(this.r, this.g, this.b); + return `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`; + } + + getHexCode() { + return `#${this.componentToHex(this.r)}${this.componentToHex( + this.g + )}${this.componentToHex(this.b)}`; + } + + getOppositeColor() { + return new ColorUtils(255 - this.r, 255 - this.g, 255 - this.b); + } + + brightenColor(percent) { + const factor = 1 + percent / 100; + const brightenedR = this.clamp(this.r * factor); + const brightenedG = this.clamp(this.g * factor); + const brightenedB = this.clamp(this.b * factor); + return new ColorUtils(brightenedR, brightenedG, brightenedB); + } + + lightenColor(percent) { + const factor = 1 + percent / 100; + const lightenedR = this.clamp(this.r + (255 - this.r) * (1 - factor)); + const lightenedG = this.clamp(this.g + (255 - this.g) * (1 - factor)); + const lightenedB = this.clamp(this.b + (255 - this.b) * (1 - factor)); + return new ColorUtils(lightenedR, lightenedG, lightenedB); + } + + rgbToHsl(r, g, b) { + r /= 255; + g /= 255; + b /= 255; + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + let h, + s, + l = (max + min) / 2; + + if (max === min) { + h = s = 0; // achromatic + } else { + const d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + + h = Math.round(h * 360); + s = Math.round(s * 100); + l = Math.round(l * 100); + + return [h, s, l]; + } + + componentToHex(c) { + const hex = c.toString(16); + return hex.length === 1 ? "0" + hex : hex; + } + + clamp(value) { + return Math.min(255, Math.max(0, value)); + } +} + +// Example usage: +const color = new ColorUtils(100, 150, 200); + +console.log(color.getRGB()); // "rgb(100, 150, 200)" +console.log(color.getHSL()); // "hsl(210, 50%, 60%)" +console.log(color.getHexCode()); // "#6496c8" + +const oppositeColor = color.getOppositeColor(); +console.log(oppositeColor.getRGB()); // "rgb(155, 105, 55)" + +const brightenedColor = color.brightenColor(20); +console.log(brightenedColor.getRGB()); // "rgb(120, 180, 240)" + +const lightenedColor = color.lightenColor(20); +console.log(lightenedColor.getRGB()); // "rgb(124, 172, 216)" diff --git a/Snippets/Objects/computedProperties.js b/Snippets/Objects/computedProperties.js new file mode 100644 index 0000000..424e15f --- /dev/null +++ b/Snippets/Objects/computedProperties.js @@ -0,0 +1,12 @@ +const obj = {}; + +for (let i = 0; i < 10; i++) { + obj[`field${i}`] = 1; +} + +console.log(obj); + +let fruit = "apple"; +let bag = { + [fruit + "Computers"]: 5, // bag.appleComputers = 5 +}; diff --git a/Snippets/Objects/deepCopy.js b/Snippets/Objects/deepCopy.js new file mode 100644 index 0000000..e335bce --- /dev/null +++ b/Snippets/Objects/deepCopy.js @@ -0,0 +1,20 @@ +const x = { b: [{ a: [1, 2, 3], b: [4, 5, 6], c: [7, 8, 9] }] }; +const y = { b: [{ a: [1, 2, 3], b: [4, 5, 6], c: [7, 8, 9] }] }; + +const z = deepCopy(x); + +function deepCopy(obj) { + let target = {}; + const keys = Object.keys(obj); + keys.forEach((key) => { + if (typeof obj[key] === "object") { + target[key] = deepCopy(obj[key]); + } else { + target[key] = obj[key]; + } + }); + return target; +} + +console.log(z); +console.log(z === x); diff --git a/Snippets/Objects/immediatelyCalledConstructorFunction.js b/Snippets/Objects/immediatelyCalledConstructorFunction.js new file mode 100644 index 0000000..e974d0e --- /dev/null +++ b/Snippets/Objects/immediatelyCalledConstructorFunction.js @@ -0,0 +1,9 @@ +// create a function and immediately call it with new +let user = new (function () { + this.name = "John"; + this.isAdmin = false; + + // ...other code for user creation + // maybe complex logic and statements + // local variables etc +})(); diff --git a/Snippets/Objects/isEmpty.js b/Snippets/Objects/isEmpty.js new file mode 100644 index 0000000..75fee18 --- /dev/null +++ b/Snippets/Objects/isEmpty.js @@ -0,0 +1,11 @@ +const isEmpty = (obj) => { + return Object.keys(obj).length; +}; + +let schedule = {}; + +console.log(isEmpty(schedule)); // true + +schedule["8:30"] = "get up"; + +console.log(isEmpty(schedule)); // false diff --git a/Snippets/Objects/ladder.js b/Snippets/Objects/ladder.js new file mode 100644 index 0000000..c1482d4 --- /dev/null +++ b/Snippets/Objects/ladder.js @@ -0,0 +1,19 @@ +// chaining + +let ladder = { + step: 0, + up() { + this.step++; + return this; + }, + down() { + this.step--; + return this; + }, + showStep: function () { + // shows the current step + console.log(this.step); + }, +}; + +ladder.up().down(); diff --git a/Snippets/Objects/methodsAndthis.js b/Snippets/Objects/methodsAndthis.js new file mode 100644 index 0000000..bf2b805 --- /dev/null +++ b/Snippets/Objects/methodsAndthis.js @@ -0,0 +1,36 @@ +let user = { + name: "Soham", + age: 5, + sayHi: function () { + console.log("Hi " + this.name); + }, +}; + +let user2 = { + name: "Ashutosh", + age: 15, +}; + +function makeUser() { + return { + name: "John", + ref: this, + }; +} + +let user3 = makeUser(); + +console.log(user3.ref); // undefined in node / Error in browser + +function makeUser2() { + return { + name: "John", + ref() { + return this; + }, + }; +} + +let user4 = makeUser2(); + +console.log(user4.ref().name); // John diff --git a/Snippets/Objects/multiplyNumeric.js b/Snippets/Objects/multiplyNumeric.js new file mode 100644 index 0000000..2fdfb41 --- /dev/null +++ b/Snippets/Objects/multiplyNumeric.js @@ -0,0 +1,16 @@ +const multiplyNumeric = (obj) => { + for (key in obj) { + if (typeof obj[key] === "number") { + obj[key] *= 2; + } + } + console.log(obj); +}; +// before the call +let menu = { + width: 200, + height: 300, + title: "My menu", +}; + +multiplyNumeric(menu); diff --git a/Snippets/Objects/objectToPrimitiveConversion.js b/Snippets/Objects/objectToPrimitiveConversion.js new file mode 100644 index 0000000..e69de29 diff --git a/Snippets/Objects/orderedLikeObject.js b/Snippets/Objects/orderedLikeObject.js new file mode 100644 index 0000000..7ac6166 --- /dev/null +++ b/Snippets/Objects/orderedLikeObject.js @@ -0,0 +1,25 @@ +let codes = { + "+49": "Germany", + "+41": "Switzerland", + "+44": "Great Britain", + // .., + "+1": "USA", +}; + +for (let code in codes) { + console.log(+code); // 49, 41, 44, 1 +} + +codes = { + 49: "Germany", + 41: "Switzerland", + 44: "Great Britain", + // .., + 1: "USA", +}; + +console.log(codes); + +for (let code in codes) { + console.log(code); // 1, 41, 44, 49 +} diff --git a/Snippets/Objects/propertyDescriptors.js b/Snippets/Objects/propertyDescriptors.js new file mode 100644 index 0000000..d84689a --- /dev/null +++ b/Snippets/Objects/propertyDescriptors.js @@ -0,0 +1,30 @@ +let user = { + name: "John", +}; + +// get property +let descriptor = Object.getOwnPropertyDescriptor(user, "name"); + +console.log(descriptor); + +// define property +Object.defineProperty(user, "name", { + value: "Soham", +}); + +// non-writable +Object.defineProperty(user, "name", { + writable: false, +}); + +// non-enumerable + +Object.defineProperty(user, "toString", { + enumerable: false, +}); + +// non-configurable + +Object.defineProperty(user, "name", { configurable: false }); + +// cannot even change other ennumberable and writable diff --git a/Snippets/Objects/propertyGetterSetter.js b/Snippets/Objects/propertyGetterSetter.js new file mode 100644 index 0000000..9bd6a80 --- /dev/null +++ b/Snippets/Objects/propertyGetterSetter.js @@ -0,0 +1,31 @@ +let obj = { + name: "Soham", + surname: "Shah", + get fullName() { + return `${this.name} ${this.surname}`; + }, + set propName(value) { + [this.name, this.surname] = value.split(" "); + }, +}; + +// hiding a variable + +let user = { + get name() { + return this._name; + }, + + set name(value) { + if (value.length < 4) { + alert("Name is too short, need at least 4 characters"); + return; + } + this._name = value; + }, +}; + +user.name = "Pete"; +alert(user.name); // Pete + +user.name = ""; diff --git a/Snippets/Objects/reference.js b/Snippets/Objects/reference.js new file mode 100644 index 0000000..89ea186 --- /dev/null +++ b/Snippets/Objects/reference.js @@ -0,0 +1,17 @@ +const user = { + name: "Soham", +}; + +const admin = user; + +console.log(admin); + +admin.name = "Dhruvi"; + +console.log(admin); + +user.name = "Samyak"; + +console.log(admin); + +console.log(admin == { name: "Samyak" }); diff --git a/Snippets/Objects/restAndspread.js b/Snippets/Objects/restAndspread.js new file mode 100644 index 0000000..8c8792a --- /dev/null +++ b/Snippets/Objects/restAndspread.js @@ -0,0 +1,71 @@ +// Rest + +function sumAll(...args) { + // args is the name for the array + let sum = 0; + + for (let arg of args) sum += arg; + + return sum; +} + +console.log(sumAll(1, 2, 3)); + +function showName(firstName, lastName, ...titles) { + console.log(firstName + " " + lastName); // Julius Caesar + + // the rest go into titles array + // i.e. titles = ["Consul", "Imperator"] + console.log(titles[0]); // Consul + console.log(titles[1]); // Imperator + console.log(titles.length); // 2 +} + +showName("Julius", "Caesar", "Consul", "Imperator"); + +// arguments array + +function showName2() { + console.log(arguments.length); + console.log(arguments[0]); + console.log(arguments[1]); + + // it's iterable + // for(let arg of arguments) console.log(arg); +} + +// shows: 2, Julius, Caesar +showName2("Julius", "Caesar"); + +// shows: 1, Ilya, undefined (no second argument) +showName2("Ilya"); + +// BEWARE: Arrow Functions dont have "arguments" + +function f() { + // If we access the arguments object from an arrow function, it takes them from the outer “normal” function. + + let showArg = () => console.log(arguments[0]); + showArg(); +} + +f(1); // 1 + +// Spread + +let arr1 = [1, -2, 3, 4]; +let arr2 = [8, 3, -8, 1]; + +console.log(Math.max(...arr1, ...arr2)); // 8 + +let str = "Hello"; + +// Array.from converts an iterable and array-like object into an array +console.log(Array.from(str)); // H,e,l,l,o + +// Array-like is an object that index and length property + +let arrLike = { 0: "foo", 5: "bar", length: 6 }; +console.log(Array.from(arrLike)); + +console.log(Array.from([1, 2, 3], (x) => x + x)); diff --git a/Snippets/Polyfill/bind-polyfill.js b/Snippets/Polyfill/bind-polyfill.js new file mode 100644 index 0000000..c3d6e7b --- /dev/null +++ b/Snippets/Polyfill/bind-polyfill.js @@ -0,0 +1,10 @@ +// bind polyfill + +Function.prototype.customBind = function (...args) { + let context = this; + let params = args.slice(1); + + return function (...args2) { + context.apply(args[0], [...params, ...args2]); + }; +}; diff --git a/Snippets/Polyfill/filter-polyfill.js b/Snippets/Polyfill/filter-polyfill.js new file mode 100644 index 0000000..80fd40c --- /dev/null +++ b/Snippets/Polyfill/filter-polyfill.js @@ -0,0 +1,12 @@ +// filter polyfill + +Array.prototype.customFilter = function (callbackFn) { + const result = []; + + for (let i = 0; i < this.length; i++) { + if (callbackFn.call(this, this[i], i)) { + result.push(this[i]); + } + } + return result; +}; diff --git a/Snippets/Polyfill/forEach-polyfill.js b/Snippets/Polyfill/forEach-polyfill.js new file mode 100644 index 0000000..faeaa84 --- /dev/null +++ b/Snippets/Polyfill/forEach-polyfill.js @@ -0,0 +1,7 @@ +// forEach polyfill + +Array.prototype.customForEach = function (callbackFn) { + for (let i = 0; i < this.length; i++) { + callbackFn.call(this, this[i], i); + } +}; diff --git a/Snippets/Polyfill/map-polyfill.js b/Snippets/Polyfill/map-polyfill.js new file mode 100644 index 0000000..27326cf --- /dev/null +++ b/Snippets/Polyfill/map-polyfill.js @@ -0,0 +1,10 @@ +// map polyfill + +Array.prototype.customMap = function (callbackFn) { + const result = []; + + for (let i = 0; i < this.length; i++) { + result.push(callbackFn.call(this, this[i], i)); + } + return result; +}; diff --git a/Snippets/Polyfill/promiseAll-polyfill.js b/Snippets/Polyfill/promiseAll-polyfill.js new file mode 100644 index 0000000..9a53798 --- /dev/null +++ b/Snippets/Polyfill/promiseAll-polyfill.js @@ -0,0 +1,21 @@ +// promise polyfill + +Promise.customAll = function (promiseArray) { + return new Promise((resolve, reject) => { + let completed = 0; + const promiseResults = []; + + promiseArray.forEach((value, index) => { + Promise.resolve(value) + .then((result) => { + completed++; + promiseResults[index] = result; + + if (completed === promiseArray.length) { + resolve(promiseResults); + } + }) + .catch((err) => reject(err)); + }); + }); +}; diff --git a/Snippets/Polyfill/reduce-polyfill.js b/Snippets/Polyfill/reduce-polyfill.js new file mode 100644 index 0000000..9a31b2e --- /dev/null +++ b/Snippets/Polyfill/reduce-polyfill.js @@ -0,0 +1,14 @@ +// reduce polyfill + +Array.prototype.customReduce = function (callbackFn, initialValue) { + let accumulator = initialValue; + + for (let i = 0; i < this.length; i++) { + if (accumulator !== undefined) { + accumulator = callbackFn.call(undefined, accumulator, this[i], i, this); + } else { + accumulator = this[i]; + } + } + return accumulator; +}; diff --git a/Snippets/Promises/asyncAwait.js b/Snippets/Promises/asyncAwait.js new file mode 100644 index 0000000..82a5a24 --- /dev/null +++ b/Snippets/Promises/asyncAwait.js @@ -0,0 +1,21 @@ +function loadJson(url) { + return fetch(url).then((response) => { + if (response.status == 200) { + return response.json(); + } else { + throw new Error(response.status); + } + }); +} + +loadJson("https://javascript.info/no-such-user.json").catch(alert); // Error: 404 + +async function loadJsonAsyncAwait(url) { + const response = await fetch(url); + if (response.status === 200) { + return response.json(); + } + throw new Error(response.status); +} + +loadJsonAsyncAwait("https://javascript.info/no-such-user.json").catch(alert); // Error: 404 diff --git a/Snippets/Promises/callAsyncFromNonAsync.js b/Snippets/Promises/callAsyncFromNonAsync.js new file mode 100644 index 0000000..d06f398 --- /dev/null +++ b/Snippets/Promises/callAsyncFromNonAsync.js @@ -0,0 +1,12 @@ +async function wait() { + await new Promise((resolve) => setTimeout(resolve, 3000)); + + return 10; +} + +function f() { + // get value from the promise by calling async code in sync func + wait().then((value) => console.log(value)); +} + +f(); diff --git a/Snippets/Promises/microtask.js b/Snippets/Promises/microtask.js new file mode 100644 index 0000000..e1b2397 --- /dev/null +++ b/Snippets/Promises/microtask.js @@ -0,0 +1,11 @@ +const a = "5"; +const promise = new Promise((resolve, reject) => { + setTimeout(() => resolve(1), 3000); + console.log("Inside promise"); // 1 +}); + +promise.then((val) => console.log("Promise", val)); // 3 + +setTimeout(() => console.log("Set Timeout ran"), 3000); // 4 + +console.log(a); // 2 diff --git a/Snippets/Promises/noNeedToReturnPromiseInThenChain.js b/Snippets/Promises/noNeedToReturnPromiseInThenChain.js new file mode 100644 index 0000000..99e2144 --- /dev/null +++ b/Snippets/Promises/noNeedToReturnPromiseInThenChain.js @@ -0,0 +1,11 @@ +function first(num) { + return Promise.resolve(num); // starting the then chain by returning a promise +} + +function second(num) { + return num + 1; // no need to return promise as this function is in 'then' chain +} + +first(4) + .then((valueOne) => second(valueOne)) + .then((valueTwo) => console.log(valueTwo)); diff --git a/Snippets/Promises/promiseAPI.js b/Snippets/Promises/promiseAPI.js new file mode 100644 index 0000000..c19513b --- /dev/null +++ b/Snippets/Promises/promiseAPI.js @@ -0,0 +1,20 @@ +/* +There are 6 static methods of Promise class: + +Promise.all(promises) – waits for all promises to resolve and returns an array of their results. If any of the given promises rejects, it becomes the error of Promise.all, and all other results are ignored. +Promise.allSettled(promises) (recently added method) – waits for all promises to settle and returns their results as an array of objects with: +status: "fulfilled" or "rejected" +value (if fulfilled) or reason (if rejected). +Promise.race(promises) – waits for the first promise to settle, and its result/error becomes the outcome. +Promise.any(promises) (recently added method) – waits for the first promise to fulfill, and its result becomes the outcome. If all of the given promises are rejected, AggregateError becomes the error of Promise.any. +Promise.resolve(value) – makes a resolved promise with the given value. +Promise.reject(error) – makes a rejected promise with the given error. + +*/ +Promise.race([ + new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)), + new Promise((resolve, reject) => + setTimeout(() => reject(new Error("Whoops!")), 2000) + ), + new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000)), +]).then((value) => console.log(value)); diff --git a/Snippets/Promises/promiseAll.js b/Snippets/Promises/promiseAll.js new file mode 100644 index 0000000..651e672 --- /dev/null +++ b/Snippets/Promises/promiseAll.js @@ -0,0 +1,33 @@ +Promise.myAll = function (promises) { + return new Promise((resolve, reject) => { + let results = []; + let count = 0; + let toBeRejected = false; + + promises.forEach((promise, index) => { + if (toBeRejected) return; + Promise.resolve(promise) + .then((res) => { + count += 1; + results[index] = res; // maintaining the order + if (count === promises.length) { + resolve(results); + } + }) + .catch((err) => { + reject(err); + toBeRejected = true; + }); + }); + }); +}; + +const promise1 = Promise.resolve(1); +const promise2 = new Promise((resolve, reject) => + setTimeout(() => resolve(2), 3000) +); +const promise3 = 3; + +Promise.myAll([Promise.reject("bar"), promise1, promise2, promise3]) + .then((value) => console.log(value)) + .catch((err) => console.log(err)); diff --git a/Snippets/Promises/promiseAllSettled.js b/Snippets/Promises/promiseAllSettled.js new file mode 100644 index 0000000..bdbf1f8 --- /dev/null +++ b/Snippets/Promises/promiseAllSettled.js @@ -0,0 +1,33 @@ +Promise.myAllSettled = function (promises) { + let results = []; + let count = 0; + return new Promise((resolve, reject) => { + promises.forEach((promise, index) => { + Promise.resolve(promise) + .then((value) => { + count += 1; + results[index] = value; + if (count === promises.length) { + resolve(results); + } + }) + .catch((err) => { + count += 1; + results[index] = "Error: " + err; + if (count === promises.length) { + resolve(results); + } + }); + }); + }); +}; + +const promise1 = Promise.resolve(1); +const promise2 = new Promise((resolve, reject) => + setTimeout(() => resolve(2), 3000) +); +const promise3 = 3; + +Promise.myAllSettled([Promise.reject("bar"), promise1, promise2, promise3]) + .then((value) => console.log(value)) + .catch((err) => console.log(err)); diff --git a/Snippets/Promises/promiseAny.js b/Snippets/Promises/promiseAny.js new file mode 100644 index 0000000..b163a07 --- /dev/null +++ b/Snippets/Promises/promiseAny.js @@ -0,0 +1,46 @@ +Promise.myAny = function (promises) { + let errList = []; + let errCount = 0; + return new Promise((resolve, reject) => { + promises.forEach((promise, index) => { + Promise.resolve(promise).then( + (value) => { + return resolve(value); + }, + (reason) => { + errList[index] = reason; + errCount += 1; + if (errCount === promises.length) { + return reject([ + new AggregateError([errList], "All promises were rejected"), + ]); + } + } + ); + }); + }); +}; + +const promise1 = Promise.resolve(1); +const promise2 = new Promise((resolve, reject) => + setTimeout(() => resolve(2), 3000) +); +const promise3 = Promise.resolve(3); + +Promise.myAny([ + Promise.reject("bar"), + Promise.reject("foo"), + Promise.reject("nice"), + Promise.reject("wow"), +]) + .then((value) => console.log(value)) + .catch((err) => console.log(err)); + +Promise.any([ + Promise.reject("bar"), + Promise.reject("foo"), + Promise.reject("nice"), + Promise.reject("wow"), +]) + .then((value) => console.log(value)) + .catch((err) => console.log(err)); diff --git a/Snippets/Promises/promiseRace.js b/Snippets/Promises/promiseRace.js new file mode 100644 index 0000000..94fb770 --- /dev/null +++ b/Snippets/Promises/promiseRace.js @@ -0,0 +1,24 @@ +Promise.myRace = function (promises) { + return new Promise((resolve, reject) => { + promises.forEach((promise) => { + Promise.resolve(promise).then( + (value) => resolve(value), + (reason) => reject(reason) + ); + }); + }); +}; + +const promise1 = Promise.resolve(1); +const promise2 = new Promise((resolve, reject) => + setTimeout(() => resolve(2), 3000) +); +const promise3 = Promise.resolve(3); + +Promise.myRace([Promise.reject(new Error("bar")), promise1, promise2, promise3]) + .then((value) => console.log(value)) + .catch((err) => console.log("error")); + +Promise.race([Promise.reject("bar"), promise1, promise2, promise3]) + .then((value) => console.log(value)) + .catch((err) => console.log("error")); diff --git a/Snippets/Promises/resolveVsReturn.js b/Snippets/Promises/resolveVsReturn.js new file mode 100644 index 0000000..1cf7ee7 --- /dev/null +++ b/Snippets/Promises/resolveVsReturn.js @@ -0,0 +1,17 @@ +function second() { + return new Promise((resolve, reject) => { + // resolve/reject happens only one time + resolve(1); + reject("Failed"); + resolve(2); + console.log("After resolve/reject"); // this will be printed first because aLl lines will be executed + }); +} + +function first() { + second() + .then((value) => console.log(value)) + .catch((err) => console.log(err)); +} + +first(); diff --git a/Snippets/Promises/retryNTimes.js b/Snippets/Promises/retryNTimes.js new file mode 100644 index 0000000..d244d18 --- /dev/null +++ b/Snippets/Promises/retryNTimes.js @@ -0,0 +1,51 @@ +// wait function +const wait = (ms) => { + return new Promise((resolve) => { + setTimeout(() => resolve(), ms); + }); +}; + +const retryWithDelay = ( + operation, + retries = 3, + delay = 50, + finalErr = "Retry Failed" +) => { + return new Promise((resolve, reject) => + operation() + .then(resolve) + .catch((reason) => { + console.log(retries); + if (retries > 0) { + return wait(delay) + .then( + retryWithDelay.bind(null, operation, retries - 1, delay, finalErr) + ) + .then(resolve) + .catch(reject); + } + // throw final error + return reject(finalErr); + }) + ); +}; + +const getTestFunc = () => { + let callCounter = 0; + return async () => { + callCounter += 1; + + if (callCounter) { + throw new Error("Not yet"); + } + }; +}; + +// Test the code +const test = async () => { + await retryWithDelay(getTestFunc(), 10, 1000); + console.log("success"); +}; + +// Print the result +test().catch(console.error); diff --git a/Snippets/Promises/throwingErrorOutsidePromiseChain.js b/Snippets/Promises/throwingErrorOutsidePromiseChain.js new file mode 100644 index 0000000..53327b0 --- /dev/null +++ b/Snippets/Promises/throwingErrorOutsidePromiseChain.js @@ -0,0 +1,14 @@ +function first() { + throw new Error("lol"); // error wont be caught in .catch() + return Promise.resolve(1); +} + +function second(num) { + throw new Error("lol"); // error will be caught in .catch() + return num + 2; +} + +first() + .then((valueOne) => second(valueOne)) + .then((valueTwo) => console.log(valueTwo)) + .catch((err) => console.log(err)); diff --git a/Snippets/Promises/tryCatch.js b/Snippets/Promises/tryCatch.js new file mode 100644 index 0000000..21625d8 --- /dev/null +++ b/Snippets/Promises/tryCatch.js @@ -0,0 +1,20 @@ +async function first() { + try { + // return await second(); // remains synchronous for the function if used await + return second(); //asynchronous returning the function + } catch (err) { + console.log("Try/Catch", err); + } +} + +function second() { + return Promise.reject("Something went wrong!"); +} + +first() + .then(() => { + console.log("End"); + }) + .catch((err) => { + console.log("From .catch()", err); + }); diff --git a/Snippets/Prototype/basic.js b/Snippets/Prototype/basic.js new file mode 100644 index 0000000..24921f0 --- /dev/null +++ b/Snippets/Prototype/basic.js @@ -0,0 +1,29 @@ +let arr = ["Soham", "Dhruvi"]; + +let obj = { + name: "Soham", + city: "Ahmedabad", + getIntro: function () { + console.log(this.name + "from" + this.city); + }, +}; + +function fun() { + console.log("hello"); +} + +/* +Learnings +arr.__proto__ === Array.prototype +arr.__proto__.__proto__ === Object.prototype +arr.__proto__.__proto__ === null + +obj.__proto__ === Object.prototype +obj.__proto__proto__ === null + +fun.__proto__ === Function.prototype +fun.__proto__.__proto__ === Object.prototype +fun.__proto__.__proto__.__prototype === null + +Everything is object in JavaScript +*/ diff --git a/Snippets/Prototype/forInLoop.js b/Snippets/Prototype/forInLoop.js new file mode 100644 index 0000000..2c716a9 --- /dev/null +++ b/Snippets/Prototype/forInLoop.js @@ -0,0 +1,25 @@ +let animal = { + eats: true, +}; + +let rabbit = { + jumps: true, + __proto__: animal, +}; + +// Object.keys only returns own keys +console.log(Object.keys(rabbit)); // jumps + +// for..in loops over both own and inherited keys +for (let prop in rabbit) console.log(prop); // jumps, then eats + +// only loop in own keys and ignore inherited keys +for (let prop in rabbit) { + let isOwn = rabbit.hasOwnProperty(prop); + + if (isOwn) { + alert(`Our: ${prop}`); // Our: jumps + } else { + alert(`Inherited: ${prop}`); // Inherited: eats + } +} diff --git a/Snippets/Prototype/getAndset.js b/Snippets/Prototype/getAndset.js new file mode 100644 index 0000000..8b7964b --- /dev/null +++ b/Snippets/Prototype/getAndset.js @@ -0,0 +1,25 @@ +let user = { + name: "John", + surname: "Smith", + + set fullName(value) { + [this.name, this.surname] = value.split(" "); + }, + + get fullName() { + return `${this.name} ${this.surname}`; + }, +}; + +let admin = { + __proto__: user, + isAdmin: true, +}; + +console.log(admin.fullName); // John Smith + +// setter triggers! +admin.fullName = "Alice Cooper"; + +console.log(admin.fullName); // Alice Cooper, state of admin modified +console.log(user.fullName); // John Smith, state of user protected diff --git a/Snippets/Prototype/nativePrototypes.js b/Snippets/Prototype/nativePrototypes.js new file mode 100644 index 0000000..48db9fd --- /dev/null +++ b/Snippets/Prototype/nativePrototypes.js @@ -0,0 +1,23 @@ +Function.prototype.defer = function (ms) { + setTimeout(this, ms); +}; + +function f() { + console.log("Hello!"); +} + +f.defer(1000); // shows "Hello!" after 1 sec + +Function.prototype.defer2 = function (ms) { + let k = this; + return function (...args) { + setTimeout(() => k.apply(this, args), ms); + }; +}; + +// check it +function k(a, b) { + console.log(a + b); +} + +k.defer(1000)(1, 2); // shows 3 after 1 sec diff --git a/Snippets/Prototype/prototype.js b/Snippets/Prototype/prototype.js new file mode 100644 index 0000000..14e0e12 --- /dev/null +++ b/Snippets/Prototype/prototype.js @@ -0,0 +1,35 @@ +let animal = { + eats: true, +}; + +function Rabbit(name) { + this.name = name; +} + +Rabbit.prototype = animal; + +let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal + +let rabbit2 = new rabbit.constructor("Black Rabbit"); // another way to create a new object + +// re-assigning prototype of Rabbit +Rabbit.prototype = { + jumps: true, +}; + +let rabbit3 = new Rabbit(); +console.log(rabbit.constructor === Rabbit); // false + +// Not overwrite Rabbit.prototype totally +// just add to it +Rabbit.prototype.jumps = true; +// the default Rabbit.prototype.constructor is preserved + +let rabbit4 = new Rabbit(); +console.log(rabbit.constructor === Rabbit); // false + +// Other alternative way +Rabbit.prototype = { + jumps: true, + constructor: Rabbit, +}; diff --git a/Snippets/Prototype/searchingAlgorithm.js b/Snippets/Prototype/searchingAlgorithm.js new file mode 100644 index 0000000..04b89df --- /dev/null +++ b/Snippets/Prototype/searchingAlgorithm.js @@ -0,0 +1,34 @@ +/* +Problem statement +Use __proto__ to assign prototypes in a way that any property lookup will follow the path: pockets → bed → table → head. For instance, pockets.pen should be 3 (found in table), and bed.glasses should be 1 (found in head). +Answer the question: is it faster to get glasses as pockets.glasses or head.glasses? Benchmark if needed. +*/ + +let head = { + glasses: 1, +}; + +let table = { + pen: 3, + __proto__: head, +}; + +let bed = { + sheet: 1, + pillow: 2, + __proto__: table, +}; + +let pockets = { + money: 2000, + __proto__: bed, +}; + +console.log(pockets.pen); // 3 +console.log(bed.glasses); // 1 + +/* +In modern engines, performance-wise, there’s no difference whether we take a property from an object or its prototype. They remember where the property was found and reuse it in the next request. + +For instance, for pockets.glasses they remember where they found glasses (in head), and next time will search right there. They are also smart enough to update internal caches if something changes, so that optimization is safe. +*/ diff --git a/Snippets/Prototype/this.js b/Snippets/Prototype/this.js new file mode 100644 index 0000000..2f4508f --- /dev/null +++ b/Snippets/Prototype/this.js @@ -0,0 +1,22 @@ +// animal has methods +let animal = { + walk() { + if (!this.isSleeping) { + console.log(`I walk`); + } + }, + sleep() { + this.isSleeping = true; + }, +}; + +let rabbit = { + name: "White Rabbit", + __proto__: animal, +}; + +// modifies rabbit.isSleeping +rabbit.sleep(); + +console.log(rabbit.isSleeping); // true +console.log(animal.isSleeping); // undefined (no such property in the prototype) diff --git a/Snippets/Prototype/whyAreBothHamstersFull.js b/Snippets/Prototype/whyAreBothHamstersFull.js new file mode 100644 index 0000000..dc3059f --- /dev/null +++ b/Snippets/Prototype/whyAreBothHamstersFull.js @@ -0,0 +1,45 @@ +let hamster = { + stomach: [], + eat(food) { + this.stomach.push(food); + }, +}; + +let speedy = { + __proto__: hamster, +}; + +let lazy = { + __proto__: hamster, +}; + +// This one found the food +speedy.eat("apple"); +console.log(speedy.stomach); // apple + +// This one also has it, why? +console.log(lazy.stomach); // apple + +/* +Reason: + +speedy.eat() -> couldn't find in its obj -> finds it in hamster +Now, this = speedy +In this.stomach.push() -> it searches for stomach value -> couldn't find in speedy -> found in hamster +So, this.stomach.push actually pushes food to the hamster object's stomach; which is common for both of them +*/ + +/* +Solution: + +let speedy = { + __proto__: hamster, + stomach: [] +}; + +let lazy = { + __proto__: hamster, + stomach: [] +}; + +*/ diff --git a/Snippets/Recursion/factorial.js b/Snippets/Recursion/factorial.js new file mode 100644 index 0000000..2bca7aa --- /dev/null +++ b/Snippets/Recursion/factorial.js @@ -0,0 +1,8 @@ +const factorial = (num) => { + if (num === 1) { + return 1; + } + return num * factorial(num - 1); +}; + +console.log(factorial(5)); diff --git a/Snippets/Recursion/fibonacci.js b/Snippets/Recursion/fibonacci.js new file mode 100644 index 0000000..bc17d9f --- /dev/null +++ b/Snippets/Recursion/fibonacci.js @@ -0,0 +1,26 @@ +// fibonacci + +const fibonacci = (num) => { + if (num === 1) { + return 1; + } + if (num === 0) { + return 0; + } + return fibonacci(num - 2) + fibonacci(num - 1); +}; + +console.log(fibonacci(7)); + +// DP Approach + +function fib(n) { + let a = 1; + let b = 1; + for (let i = 3; i <= n; i++) { + let c = a + b; + a = b; + b = c; + } + return b; +} diff --git a/Snippets/Recursion/linkedList.js b/Snippets/Recursion/linkedList.js new file mode 100644 index 0000000..eb13922 --- /dev/null +++ b/Snippets/Recursion/linkedList.js @@ -0,0 +1,22 @@ +let list = { + value: 1, + next: { + value: 2, + next: { + value: 3, + next: { + value: 4, + next: null, + }, + }, + }, +}; + +const printList = (obj) => { + console.log(obj.value); + if (obj.next !== null) { + printList(obj.next); + } +}; + +console.log(printList(list)); diff --git a/Snippets/Recursion/power.js b/Snippets/Recursion/power.js new file mode 100644 index 0000000..967bacf --- /dev/null +++ b/Snippets/Recursion/power.js @@ -0,0 +1,9 @@ +const power = (x, n) => { + console.log(x, n); + if (n === 1) { + return x; + } + return x * power(x, n - 1); +}; + +console.log(power(2, 3)); diff --git a/Snippets/Recursion/recursiveTraversal.js b/Snippets/Recursion/recursiveTraversal.js new file mode 100644 index 0000000..f85bc4a --- /dev/null +++ b/Snippets/Recursion/recursiveTraversal.js @@ -0,0 +1,46 @@ +let company = { + sales: [ + { + name: "John", + salary: 1000, + }, + { + name: "Alice", + salary: 1600, + }, + ], + + development: { + sites: [ + { + name: "Peter", + salary: 2000, + }, + { + name: "Alex", + salary: 1800, + }, + ], + + internals: [ + { + name: "Jack", + salary: 1300, + }, + ], + }, +}; + +const computeSalary = (department, salary) => { + if (Array.isArray(department)) { + return department.reduce((prev, current) => prev + current.salary, 0); + } else { + let sum = 0; + for (let subDep of Object.values(department)) { + sum += computeSalary(subDep); + } + return sum; + } +}; + +console.log(computeSalary(company)); diff --git a/Snippets/Recursion/sumTo.js b/Snippets/Recursion/sumTo.js new file mode 100644 index 0000000..0ab4e8e --- /dev/null +++ b/Snippets/Recursion/sumTo.js @@ -0,0 +1,10 @@ +const sumTo = (n) => { + if (n === 1) { + return 1; + } else { + return n + sumTo(n - 1); + } +}; + +console.log(sumTo(5)); // 15 +console.log(sumTo(100000)); // error diff --git a/Snippets/Strings/lowerCaseConverter.js b/Snippets/Strings/lowerCaseConverter.js new file mode 100644 index 0000000..6c88127 --- /dev/null +++ b/Snippets/Strings/lowerCaseConverter.js @@ -0,0 +1,7 @@ +// toLowerCase() method changes the string to lowercase letters. +let favLanguage = "JavasCript"; +console.log(favLanguage.toLowerCase()); // javascript +let standard = "ECMA"; +console.log(standard.toLowerCase()); // ecma +let oneMoreLangugae = "PHP"; +console.log(oneMoreLangugae.toLowerCase()); // php diff --git a/Snippets/Strings/repeat.js b/Snippets/Strings/repeat.js new file mode 100644 index 0000000..ed5cd94 --- /dev/null +++ b/Snippets/Strings/repeat.js @@ -0,0 +1,5 @@ +/** + * repeat methods creates specified n copies and concatenates together and returns it. Original string will be unaltered + */ +let stringToBeRepeated = "love-Javascript"; +console.log(stringToBeRepeated.repeat(5)); //love-Javascriptlove-Javascriptlove-Javascriptlove-Javascriptlove-Javascript diff --git a/Snippets/Strings/search.js b/Snippets/Strings/search.js new file mode 100644 index 0000000..d06cdb3 --- /dev/null +++ b/Snippets/Strings/search.js @@ -0,0 +1,7 @@ +/** + * search a word in the sentence and find out at which position it is found for first time. + */ + +let jsLove = "Javascript is awesome. I am a Javascript lover. You have to experience this awesomeness"; +let searchWord = "awesome"; +console.log(searchWord + " found at " + (jsLove.search(searchWord) + 1) + " position"); // 14 diff --git a/Snippets/Strings/trim.js b/Snippets/Strings/trim.js new file mode 100644 index 0000000..46fb77d --- /dev/null +++ b/Snippets/Strings/trim.js @@ -0,0 +1,7 @@ +/** + * trim removes whitespaces in the beginning of the string and end of the string but not in the middle + */ + +let string = " Data Structures "; +console.log(string); // Data Structures +console.log(string.trim()); //Data Structures diff --git a/Snippets/Strings/upperCaseConverter.js b/Snippets/Strings/upperCaseConverter.js new file mode 100644 index 0000000..3a6acf9 --- /dev/null +++ b/Snippets/Strings/upperCaseConverter.js @@ -0,0 +1,7 @@ +// toUpperCase() method changes the string to upper letters. +let favLanguage = "JavasCript"; +console.log(favLanguage.toUpperCase()); // JAVASCRIPT +let firstName = "ECMA"; +console.log(firstName.toUpperCase()); // ECMA +let oneMoreLangugae = "Python"; +console.log(oneMoreLangugae.toUpperCase()); // PYTHON