From 2a29d443434e0ecce592dbefab15d54ae0622c79 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:25:18 +0530 Subject: [PATCH 01/37] Created: README.md --- .../README.md | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 L-A/0010 Design Cancellable Function (L-A)/README.md diff --git a/L-A/0010 Design Cancellable Function (L-A)/README.md b/L-A/0010 Design Cancellable Function (L-A)/README.md new file mode 100644 index 0000000..fbcad22 --- /dev/null +++ b/L-A/0010 Design Cancellable Function (L-A)/README.md @@ -0,0 +1,74 @@ +# 2650. Design Cancellable Function +[LeetCode](https://leetcode.com/problems/design-cancellable-function/) + +Sometimes you have a long running task, and you may wish to cancel it before it completes. To help with this goal, write a function `cancellable` that accepts a generator object and returns an array of two values: a cancel function and a promise. +You may assume the generator function will only yield promises. It is your function's responsibility to pass the values resolved by the promise back to the generator. If the promise rejects, your function should throw that error back to the generator. +If the cancel callback is called before the generator is done, your function should throw an error back to the generator. That error should be the string `"Cancelled"` (Not an `Error` object). If the error was caught, the returned promise should resolve with the next value that was yielded or returned. Otherwise, the promise should reject with the thrown error. No more code should be executed. + +When the generator is done, the promise your function returned should resolve the value the generator returned. If, however, the generator throws an error, the returned promise should reject with the error. + +An example of how your code would be used: +```javascript +function* tasks() { + const val = yield new Promise(resolve => resolve(2 + 2)); + yield new Promise(resolve => setTimeout(resolve, 100)); + return val + 1; // calculation shouldn't be done. +} +const [cancel, promise] = cancellable(tasks()); +setTimeout(cancel, 50); +promise.catch(console.log); // logs "Cancelled" at t=50ms +``` +If instead `cancel()` was not called or was called after `t=100ms`, the promise would have resolved 5. + + +## Example 1: + +Input: +```javascript +generatorFunction = function*() { + return 42; +} +cancelledAt = 100 +``` +**Output:** {"resolved": 42} +**Explanation:** +```javascript +const generator = generatorFunction(); +const [cancel, promise] = cancellable(generator); +setTimeout(cancel, 100); +promise.then(console.log); // resolves 42 at t=0ms +``` +The generator immediately yields 42 and finishes. Because of that, the returned promise immediately resolves 42. Note that cancelling a finished generator does nothing. + +## Example 2: + +Input: +```javascript +generatorFunction = function*() { + const msg = yield new Promise(res => res("Hello")); + throw `Error: ${msg}`; +} +cancelledAt = null +``` +**Output:** {"rejected": "Error: Hello"} +**Explanation:** +A promise is yielded. The function handles this by waiting for it to resolve and then passes the resolved value back to the generator. Then an error is thrown which has the effect of causing the promise to reject with the same thrown error. + +## Example 3: + +Input: +```javascript +generatorFunction = function*() { + yield new Promise(res => setTimeout(res, 200)); + return "Success"; +} +cancelledAt = 100 +``` +**Output:** {"rejected": "Cancelled"} +**Explanation:** +While the function is waiting for the yielded promise to resolve, cancel() is called. This causes an error message to be sent back to the generator. Since this error is uncaught, the returned promise rejected with this error. + +## Constraints: + +`cancelledAt == null or 0 <= cancelledAt <= 1000` +`generatorFunction` returns a generator object From 71c98e4b3218631cf968e251a2328d7461562d4a Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:26:25 +0530 Subject: [PATCH 02/37] Created: Design Cancellable Function - Solution --- .../Design Cancellable Function.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 L-A/0010 Design Cancellable Function (L-A)/Design Cancellable Function.js diff --git a/L-A/0010 Design Cancellable Function (L-A)/Design Cancellable Function.js b/L-A/0010 Design Cancellable Function (L-A)/Design Cancellable Function.js new file mode 100644 index 0000000..bfe1952 --- /dev/null +++ b/L-A/0010 Design Cancellable Function (L-A)/Design Cancellable Function.js @@ -0,0 +1,22 @@ +const cancellable = (generator) => { + let cancel; + const cancelPromise = new Promise((_, reject) => { + cancel = () => reject("Cancelled"); + }); + // Every Promise rejection has to be caught. + cancelPromise.catch(() => {}); + + const promise = (async () => { + let next = generator.next(); + while (!next.done) { + try { + next = generator.next(await Promise.race([next.value, cancelPromise])); + } catch (e) { + next = generator.throw(e); + } + } + return next.value; + })(); + + return [cancel, promise]; +}; From dbe713265275b6eb41c7d311e0d5d0d0ad6526c3 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:27:27 +0530 Subject: [PATCH 03/37] Updated: README.md --- L-A/0010 Design Cancellable Function (L-A)/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/L-A/0010 Design Cancellable Function (L-A)/README.md b/L-A/0010 Design Cancellable Function (L-A)/README.md index fbcad22..ab63d50 100644 --- a/L-A/0010 Design Cancellable Function (L-A)/README.md +++ b/L-A/0010 Design Cancellable Function (L-A)/README.md @@ -30,7 +30,7 @@ generatorFunction = function*() { } cancelledAt = 100 ``` -**Output:** {"resolved": 42} +**Output:** `{"resolved": 42}`
**Explanation:** ```javascript const generator = generatorFunction(); @@ -50,7 +50,7 @@ generatorFunction = function*() { } cancelledAt = null ``` -**Output:** {"rejected": "Error: Hello"} +**Output:** `{"rejected": "Error: Hello"}`
**Explanation:** A promise is yielded. The function handles this by waiting for it to resolve and then passes the resolved value back to the generator. Then an error is thrown which has the effect of causing the promise to reject with the same thrown error. @@ -64,7 +64,7 @@ generatorFunction = function*() { } cancelledAt = 100 ``` -**Output:** {"rejected": "Cancelled"} +**Output:** `{"rejected": "Cancelled"}`
**Explanation:** While the function is waiting for the yielded promise to resolve, cancel() is called. This causes an error message to be sent back to the generator. Since this error is uncaught, the returned promise rejected with this error. From b6fd900e0f658b3b945f4ae4a2045c4c637a7ffd Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:28:20 +0530 Subject: [PATCH 04/37] Updated: README.md Corrected MarkDown Formatting --- L-A/0010 Design Cancellable Function (L-A)/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/L-A/0010 Design Cancellable Function (L-A)/README.md b/L-A/0010 Design Cancellable Function (L-A)/README.md index ab63d50..5d88b31 100644 --- a/L-A/0010 Design Cancellable Function (L-A)/README.md +++ b/L-A/0010 Design Cancellable Function (L-A)/README.md @@ -70,5 +70,5 @@ While the function is waiting for the yielded promise to resolve, cancel() is ca ## Constraints: -`cancelledAt == null or 0 <= cancelledAt <= 1000` +`cancelledAt == null or 0 <= cancelledAt <= 1000`
`generatorFunction` returns a generator object From c3e24970c1c601dd5ef2e43520090c5eb90cf7ba Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:34:13 +0530 Subject: [PATCH 05/37] Created: README.md for `Seven Boom!` --- L-B/0025 Seven Boom!/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 L-B/0025 Seven Boom!/README.md diff --git a/L-B/0025 Seven Boom!/README.md b/L-B/0025 Seven Boom!/README.md new file mode 100644 index 0000000..694f8f1 --- /dev/null +++ b/L-B/0025 Seven Boom!/README.md @@ -0,0 +1,17 @@ +# Seven Boom! +[Edabit Problem](https://edabit.com/challenge/6R6gReGTGwzpwuffD) + +Create a function that takes an array of numbers and return `"Boom!"` if the digit 7 appears in the array. Otherwise, return `"there is no 7 in the array"`. + +Examples: +```javascript +sevenBoom([1, 2, 3, 4, 5, 6, 7]) ➞ "Boom!" +// 7 contains the number seven. + +sevenBoom([8, 6, 33, 100]) ➞ "there is no 7 in the array" +// None of the items contain 7 within them. + +sevenBoom([2, 55, 60, 97, 86]) ➞ "Boom!" +// 97 contains the number seven. +``` + From 29ef0765644bef33802c17f1bd26082980ffd907 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:34:57 +0530 Subject: [PATCH 06/37] Created: Solution for SevenBoom! --- L-B/0025 Seven Boom!/SevenBoom.js | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 L-B/0025 Seven Boom!/SevenBoom.js diff --git a/L-B/0025 Seven Boom!/SevenBoom.js b/L-B/0025 Seven Boom!/SevenBoom.js new file mode 100644 index 0000000..efa2f28 --- /dev/null +++ b/L-B/0025 Seven Boom!/SevenBoom.js @@ -0,0 +1,8 @@ +function sevenBoom(arr) { + for (let i = 0; i < arr.length; i++) { + if (String(arr[i]).includes('7')) { + return 'Boom!'; + } + } + return 'there is no 7 in the array'; +} From f2f1ace1a63bf428390dba534e342800d042dc80 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:41:01 +0530 Subject: [PATCH 07/37] Created: README.md for The Fiscal Code --- L-A/0011 The Fiscal Code/README.md | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 L-A/0011 The Fiscal Code/README.md diff --git a/L-A/0011 The Fiscal Code/README.md b/L-A/0011 The Fiscal Code/README.md new file mode 100644 index 0000000..4d6b381 --- /dev/null +++ b/L-A/0011 The Fiscal Code/README.md @@ -0,0 +1,57 @@ +# The Fiscal Code +**[Edabit Solution](https://edabit.com/challenge/Pa2rHJ6KeRBTF28Pg)** + +Each person in Italy has an unique identifying ID code issued by the national tax office after the birth registration: the Fiscal Code ([Codice Fiscale](https://en.wikipedia.org/wiki/Italian_fiscal_code_card)). + +Given an object containing the personal data of a person (name, surname, gender and date of birth) return the 11 code characters as a string following these steps: + +-Generate 3 capital letters from the surname, if it has: + + - At least 3 consonants then the first three consonants are used. (Newman -> NWM). + - Less than 3 consonants then vowels will replace missing characters in the same order they appear (Fox -> FXO | Hope -> HPO). + - Less than three letters then "X" will take the third slot after the consonant and the vowel (Yu -> YUX). + +- Generate 3 capital letters from the name, if it has: + + - Exactly 3 consonants then consonants are used in the order they appear (Matt -> MTT). + - More than 3 consonants then first, third and fourth consonant are used (Samantha -> SNT | Thomas -> TMS). + - Less than 3 consonants then vowels will replace missing characters in the same order they appear (Bob -> BBO | Paula -> PLA). + - Less than three letters then "X" will take the the third slot after the consonant and the vowel (Al -> LAX). + +- Generate 2 numbers, 1 letter and 2 numbers from date of birth and gender: + + - Take the last two digits of the year of birth (1985 -> 85). + - Generate a letter corresponding to the month of birth (January -> A | December -> T) using the table for conversion included in the code. + - For males take the day of birth adding one zero at the start if is less than 10 (any 9th day -> 09 | any 20th day -> 20). + - For females take the day of birth and sum 40 to it (any 9th day -> 49 | any 20th day -> 60). + +### Examples: + +```javascipt +fiscalCode({ + name: "Matt", + surname: "Edabit", + gender: "M", + dob: "1/1/1900" +}) ➞ "DBTMTT00A01" + +fiscalCode({ + name: "Helen", + surname: "Yu", + gender: "F", + dob: "1/12/1950" +}) ➞ "YUXHLN50T41" + +fiscalCode({ + name: "Mickey", + surname: "Mouse", + gender: "M", + dob: "16/1/1928" +}) ➞ "MSOMKY28A16" +``` + +**Notes:** +- Code letters must be uppercase. +- Date of birth is given in D/M/YYYY format. +- The conversion table for months is already in the starting code. +- Y is not a vowel. From 5a2fd51ed02dd04751897b8455f0be686797052a Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:41:29 +0530 Subject: [PATCH 08/37] Updated README.md Formatting --- L-A/0011 The Fiscal Code/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/L-A/0011 The Fiscal Code/README.md b/L-A/0011 The Fiscal Code/README.md index 4d6b381..52f0dcc 100644 --- a/L-A/0011 The Fiscal Code/README.md +++ b/L-A/0011 The Fiscal Code/README.md @@ -5,7 +5,7 @@ Each person in Italy has an unique identifying ID code issued by the national ta Given an object containing the personal data of a person (name, surname, gender and date of birth) return the 11 code characters as a string following these steps: --Generate 3 capital letters from the surname, if it has: +- Generate 3 capital letters from the surname, if it has: - At least 3 consonants then the first three consonants are used. (Newman -> NWM). - Less than 3 consonants then vowels will replace missing characters in the same order they appear (Fox -> FXO | Hope -> HPO). From ec9cce24900e1d14d6c533cfa3ef9bd49cfa5a08 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:42:00 +0530 Subject: [PATCH 09/37] Updated: README.md Formatting --- L-A/0011 The Fiscal Code/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/L-A/0011 The Fiscal Code/README.md b/L-A/0011 The Fiscal Code/README.md index 52f0dcc..3465b45 100644 --- a/L-A/0011 The Fiscal Code/README.md +++ b/L-A/0011 The Fiscal Code/README.md @@ -1,5 +1,5 @@ # The Fiscal Code -**[Edabit Solution](https://edabit.com/challenge/Pa2rHJ6KeRBTF28Pg)** +**[Edabit Problem](https://edabit.com/challenge/Pa2rHJ6KeRBTF28Pg)** Each person in Italy has an unique identifying ID code issued by the national tax office after the birth registration: the Fiscal Code ([Codice Fiscale](https://en.wikipedia.org/wiki/Italian_fiscal_code_card)). From 8bff86ee5c15d43682c3eb8af946208bdc3876ed Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:43:28 +0530 Subject: [PATCH 10/37] Created: TheFiscalCode Solution --- L-A/0011 The Fiscal Code/TheFiscalCode.js | 79 +++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 L-A/0011 The Fiscal Code/TheFiscalCode.js diff --git a/L-A/0011 The Fiscal Code/TheFiscalCode.js b/L-A/0011 The Fiscal Code/TheFiscalCode.js new file mode 100644 index 0000000..f1f8a2d --- /dev/null +++ b/L-A/0011 The Fiscal Code/TheFiscalCode.js @@ -0,0 +1,79 @@ +function fiscalCode(data) { + const monthsConversion = { + '01': 'A', '02': 'B', '03': 'C', '04': 'D', '05': 'E', '06': 'H', + '07': 'L', '08': 'M', '09': 'P', '10': 'R', '11': 'S', '12': 'T' + }; + + // Helper function to generate code for names and surnames + function generateCode(name, isSurname) { + const vowels = 'AEIOU'; + let consonants = ''; + let code = ''; + + // Helper function to check if a character is a consonant + function isConsonant(char) { + return /[BCDFGHJKLMNPQRSTVWXYZ]/.test(char); + } + + for (let i = 0; i < name.length && consonants.length < 3; i++) { + const char = name[i].toUpperCase(); + if (isConsonant(char)) { + consonants += char; + } + } + + if (consonants.length < 3) { + for (let i = 0; i < name.length && consonants.length < 3; i++) { + const char = name[i].toUpperCase(); + if (vowels.includes(char)) { + consonants += char; + } + } + } + + if (consonants.length < 3) { + consonants += 'X'.repeat(3 - consonants.length); + } + + code = consonants; + + if (isSurname) { + code += 'XXX'; + } else { + code += name.length >= 3 ? name[0] + name[2] + name[3] : name + 'XX'; + } + + return code; + } + + const surnameCode = generateCode(data.surname, true); + const nameCode = generateCode(data.name, false); + + const year = data.dob.split('/')[2].slice(-2); + const month = monthsConversion[data.dob.split('/')[1]]; + const day = (data.gender === 'F' ? 40 + parseInt(data.dob.split('/')[0]) : parseInt(data.dob.split('/')[0])).toString().padStart(2, '0'); + + return `${surnameCode}${nameCode}${year}${month}${day}`; +} + +// Examples +console.log(fiscalCode({ + name: "Matt", + surname: "Edabit", + gender: "M", + dob: "1/1/1900" +})); // ➞ "DBTMTT00A01" + +console.log(fiscalCode({ + name: "Helen", + surname: "Yu", + gender: "F", + dob: "1/12/1950" +})); // ➞ "YUXHLN50T41" + +console.log(fiscalCode({ + name: "Mickey", + surname: "Mouse", + gender: "M", + dob: "16/1/1928" +})); // ➞ "MSOMKY28A16" From f9faeea358ceafdb0116df5fbc4d58df9b000d77 Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:45:52 +0530 Subject: [PATCH 11/37] Created: README.md --- L-A/0012 SVG Path Data Parser/README.md | 54 +++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 L-A/0012 SVG Path Data Parser/README.md diff --git a/L-A/0012 SVG Path Data Parser/README.md b/L-A/0012 SVG Path Data Parser/README.md new file mode 100644 index 0000000..24c40f4 --- /dev/null +++ b/L-A/0012 SVG Path Data Parser/README.md @@ -0,0 +1,54 @@ +# SVG Path Data Parser +[Edabit Problem](https://edabit.com/challenge/ysMrKPGby3FXiYtQn) + +A `` element can usually be found inside an `` element and has an attribute **d** that represents the definition of the outline of a shape. + +A brief summary about this attribute: + +It contains commands (letters) and coordinates (numbers) +All instructions are expressed as one character (e.g., a moveto is expressed as an **M**). +Superfluous white space and separators such as commas can be eliminated (e.g., M 10 10 L 20 20 contains unnecessary spaces and could be expressed more compactly as `M10 10L20 20`). +The command letter can be eliminated on subsequent commands if the same command is used multiple times in a row (e.g., you can drop the second L in `M 10 20 L 20 10 L -10 -20` and use `M 10 20 L 20 10 -10 -20` instead). + +Your job is to build a parser that will convert this string in an array of commands, where each array element is an object with the `command` letter and an array of `parameters`. + +This summary is incomplete but should get you started, for more information please refer to the W3C specification found in the resources tab. + +## Examples + +```javascript +pathDataParser("") ➞ [] + +pathDataParser("M 0 0") ➞ [{command: 'M', parameters: [0, 0]}] + +pathDataParser("M 1 1.5 L 0 1.5 0 0.5 1 0.5 0.5 0 0 0.5 1 1.5 1 0.5 0 1.5" ➞ [ + {command: "M", parameters: [1, 1.5]}, + {command: "L", parameters: [0, 1.5, 0, 0.5, 1, 0.5, 0.5, 0, 0, 0.5, 1, 1.5, 1, 0.5, 0, 1.5]} +] + +pathDataParser("M 0,1 h 1 v -1 h 1 v 1 h 1 C 2,1 3,3 1.5,3 C 0,3 1,1 0,1 z" ➞ [ + {command: "M", parameters: [0, 1]}, + {command: "h", parameters: [1]}, + {command: "v", parameters: [-1]}, + {command: "h", parameters: [1]}, + {command: "v", parameters: [1]}, + {command: "h", parameters: [1]}, + {command: "C", parameters: [2, 1, 3, 3, 1.5, 3]}, + {command: "C", parameters: [0, 3, 1, 1, 0, 1]}, + {command: "z", parameters: []} +] +``` + +## Notes: + +- Return an empty array if no commands are found (example #1) +- The z (or Z) command is the only one without parameters, in this case return an empty array (see last command of example #4) +- The parameters array contains numbers, not strings, so you'll have to convert them +- Sometimes numbers can be very compressed to save space, let's look at some examples that might trip you up: + - Decimal numbers can start with a dot: .4 is the same as 0.4 + - If a negative number comes after another number, the space is optional: 0-4 is equal to 0 -4 + - Multiple decimal numbers in a row can be very tricky, remember that a number CAN NOT have more than 1 dot, so this: 1.2.34 is actually 2 different numbers: 1.2 and 0.34 +- Some examples have commas, some do not, some have multiline strings, some are a single line, remember to take into account all valid cases! Check out the tests tab to find out more. + +## By: arindal1 +***[GitHub](https://github.com/arindal1)*** From ea76ac441c6b4c50c01f37e287665c98da5bc4ff Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:47:28 +0530 Subject: [PATCH 12/37] Created: `SVGDataParser` Solution --- .../SVGDataParser.js | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 L-A/0012 SVG Path Data Parser/SVGDataParser.js diff --git a/L-A/0012 SVG Path Data Parser/SVGDataParser.js b/L-A/0012 SVG Path Data Parser/SVGDataParser.js new file mode 100644 index 0000000..931a790 --- /dev/null +++ b/L-A/0012 SVG Path Data Parser/SVGDataParser.js @@ -0,0 +1,40 @@ +function pathDataParser(data) { + const commands = []; + let currentCommand = null; + let currentParams = []; + let currentParam = ''; + + for (let i = 0; i < data.length; i++) { + const char = data[i]; + + if (char === ' ' || char === ',') { + if (currentParam !== '') { + currentParams.push(parseFloat(currentParam)); + currentParam = ''; + } + } else if (/[a-zA-Z]/.test(char)) { + if (currentCommand !== null) { + commands.push({ command: currentCommand, parameters: currentParams }); + currentParams = []; + } + currentCommand = char; + } else { + currentParam += char; + } + } + + if (currentCommand !== null) { + if (currentParam !== '') { + currentParams.push(parseFloat(currentParam)); + } + commands.push({ command: currentCommand, parameters: currentParams }); + } + + return commands; +} + +// Examples +console.log(pathDataParser("")); +console.log(pathDataParser("M 0 0")); +console.log(pathDataParser("M 1 1.5 L 0 1.5 0 0.5 1 0.5 0.5 0 0 0.5 1 1.5 1 0.5 0 1.5")); +console.log(pathDataParser("M 0,1 h 1 v -1 h 1 v 1 h 1 C 2,1 3,3 1.5,3 C 0,3 1,1 0,1 z")); From 782f3d04dfc7f50f8c7e7c6aa1ca0004ea2829ab Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:52:04 +0530 Subject: [PATCH 13/37] Created: **Caesar's Cipher/README.md** --- L-A/0013 Caesar's Cipher/README.md | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 L-A/0013 Caesar's Cipher/README.md diff --git a/L-A/0013 Caesar's Cipher/README.md b/L-A/0013 Caesar's Cipher/README.md new file mode 100644 index 0000000..20500cc --- /dev/null +++ b/L-A/0013 Caesar's Cipher/README.md @@ -0,0 +1,34 @@ +# Caesar's Cipher +[Edabit Problem](https://edabit.com/challenge/a33jdGXkaQRtK9ZTs) + +Julius Caesar protected his confidential information by encrypting it using a cipher. Caesar's cipher (check ***Resources*** tab for more info) shifts each letter by a number of letters. If the shift takes you past the end of the alphabet, just rotate back to the front of the alphabet. In the case of a rotation by *3, w, x, y* and *z* would map to *z, a, b* and *c*. + +Create a function that takes a string *s* (text to be encrypted) and an integer *k* (the rotation factor). It should return an encrypted string. + +## Example: +```javascript +caesarCipher("middle-Outz", 2) ➞ "okffng-Qwvb" + +// m -> o +// i -> k +// d -> f +// d -> f +// l -> n +// e -> g +// - - +// O -> Q +// u -> w +// t -> v +// z -> b + +caesarCipher("Always-Look-on-the-Bright-Side-of-Life", 5) +➞ "Fqbfdx-Qttp-ts-ymj-Gwnlmy-Xnij-tk-Qnkj" + +caesarCipher("A friend in need is a friend indeed", 20) +➞ "U zlcyhx ch hyyx cm u zlcyhx chxyyx" +``` + +### Notes: All test input will be a valid ASCII string. + +## By: arindal1 +***[GitHub](https://github.com/arindal1)*** From 9fd706efe731dd3b70f25075f06ea03068b1a5cc Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:52:44 +0530 Subject: [PATCH 14/37] Updated: `Caesar's Cipher/README.md` --- L-A/0013 Caesar's Cipher/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/L-A/0013 Caesar's Cipher/README.md b/L-A/0013 Caesar's Cipher/README.md index 20500cc..ef84879 100644 --- a/L-A/0013 Caesar's Cipher/README.md +++ b/L-A/0013 Caesar's Cipher/README.md @@ -1,5 +1,5 @@ # Caesar's Cipher -[Edabit Problem](https://edabit.com/challenge/a33jdGXkaQRtK9ZTs) +[Edabit Problem](https://edabit.com/challenge/a33jdGXkaQRtK9ZTs) Julius Caesar protected his confidential information by encrypting it using a cipher. Caesar's cipher (check ***Resources*** tab for more info) shifts each letter by a number of letters. If the shift takes you past the end of the alphabet, just rotate back to the front of the alphabet. In the case of a rotation by *3, w, x, y* and *z* would map to *z, a, b* and *c*. From 64b510c9b0d0c51dfb176c566d24569df646556f Mon Sep 17 00:00:00 2001 From: Arindal Char <110285827+arindal1@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:54:23 +0530 Subject: [PATCH 15/37] Created: Solution for `Caesar's Cipher` --- L-A/0013 Caesar's Cipher/CaesarsCipher.js | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 L-A/0013 Caesar's Cipher/CaesarsCipher.js diff --git a/L-A/0013 Caesar's Cipher/CaesarsCipher.js b/L-A/0013 Caesar's Cipher/CaesarsCipher.js new file mode 100644 index 0000000..0c46e12 --- /dev/null +++ b/L-A/0013 Caesar's Cipher/CaesarsCipher.js @@ -0,0 +1,31 @@ +function caesarCipher(str, k) { + // Helper function to shift a single character by k positions + function shiftChar(char, k) { + const isUpperCase = /[A-Z]/.test(char); + const alphabetSize = 26; + + const baseCharCode = isUpperCase ? 'A'.charCodeAt(0) : 'a'.charCodeAt(0); + const shiftedCharCode = ((char.charCodeAt(0) - baseCharCode + k) % alphabetSize + alphabetSize) % alphabetSize + baseCharCode; + + return String.fromCharCode(shiftedCharCode); + } + + let result = ''; + + for (let i = 0; i < str.length; i++) { + const char = str[i]; + + if (/[A-Za-z]/.test(char)) { + result += shiftChar(char, k); + } else { + result += char; // Non-alphabetic characters remain unchanged + } + } + + return result; +} + +// Examples +console.log(caesarCipher("middle-Outz", 2)); // ➞ "okffng-Qwvb" +console.log(caesarCipher("Always-Look-on-the-Bright-Side-of-Life", 5)); // ➞ "Fqbfdx-Qttp-ts-ymj-Gwnlmy-Xnij-tk-Qnkj" +console.log(caesarCipher("A friend in need is a friend indeed", 20)); // ➞ "U zlcyhx ch hyyx cm u zlcyhx chxyyx" From ad6d187b208354cda350632517960f95b41f3880 Mon Sep 17 00:00:00 2001 From: Femil Savaliya Date: Thu, 5 Oct 2023 12:49:47 +0000 Subject: [PATCH 16/37] add three sum problem's solution --- L-I/0011 ThreeSum/README.md | 127 ++++++++++++++++++++++++++++++++++ L-I/0011 ThreeSum/threeSum.js | 58 ++++++++++++++++ 2 files changed, 185 insertions(+) create mode 100644 L-I/0011 ThreeSum/README.md create mode 100644 L-I/0011 ThreeSum/threeSum.js diff --git a/L-I/0011 ThreeSum/README.md b/L-I/0011 ThreeSum/README.md new file mode 100644 index 0000000..b4547d9 --- /dev/null +++ b/L-I/0011 ThreeSum/README.md @@ -0,0 +1,127 @@ +# 0011 ThreeSum ( L-I ) + +## Problem +Three Sum (3SUM) + +Given an array nums of n integers, are there elements  `a, b, c`   in nums such that   `a + b + c = target` ? Find all unique triplets in the array which gives the sum is equal to  `target`  . + + + +## Solution + +```javascript +// 1. Brute Force Solution +const threeSum_brute_Force = (nums, target) => { + let result = []; + for (let i = 0; i < nums.length; i++) { + for (let j = i + 1; j < nums.length; j++) { + for (let k = j + 1; k < nums.length; k++) { + if (nums[i] + nums[j] + nums[k] === target) { + result.push([nums[i], nums[j], nums[k]]); + } + } + } + } + return result; +} + +// 2. Using a hash table +const threeSum_hash_table = (nums, target) => { + let result = []; + const hash = {}; + for (let i = 0; i < nums.length; i++) { + for (let j = i + 1; j < nums.length; j++) { + const complement = target - (nums[i] + nums[j]); + if (complement in hash) { + result.push([nums[i], nums[j], complement]); + } else { + hash[nums[j]] = true; + } + } + } + + return result; +} + +// 3. Two Pointer Technique +const threeSum_two_pointer = (nums, target) => { + let result = []; + nums.sort((a, b) => a - b); + for (let i = 0; i < nums.length - 2; i++) { + if (i > 0 && nums[i] === nums[i - 1]) continue; + let left = i + 1; + let right = nums.length - 1; + while (left < right) { + const sum = nums[i] + nums[left] + nums[right]; + if (sum === target) { + result.push([nums[i], nums[left], nums[right]]); + while (left < right && nums[left] === nums[left + 1]) left++; + while (left < right && nums[right] === nums[right - 1]) right--; + left++; + right--; + } else if (sum < target) { + left++; + } else { + right--; + } + } + } + return result; +} +``` + +## How it works +### 1. Brute Force Steps + +1. Initialize an empty array result to store the unique triplets that sum to the target value. + +2. Use three nested loops to iterate through the elements of the nums array. The outermost loop (indexed by i) iterates from the first element to the second-to-last element. + +3. The second loop (indexed by j) iterates from the element after the i-th element to the second-to-last element. + +4. The innermost loop (indexed by k) iterates from the element after the j-th element to the last element of the nums array. + +5. Within the innermost loop, check if the sum of the elements at indices i, j, and k is equal to the target value. + +6. If the sum is equal to the target, create a triplet by selecting the elements at these indices (nums[i], nums[j], nums[k]) and push it into the result array. + +7. Continue iterating through the loops to find all such triplets. + +8. Finally, return the result array containing all unique triplets that sum to the target value. + +### 2. Hash Table Steps + +1. Initialize an empty array result to store the unique triplets. +2. Create an empty hash table hash to store the values encountered in the inner loop. +3. Use two nested loops to iterate through the nums array. +4. Calculate the complement by subtracting the sum of nums[i] and nums[j] from the target. +5. Check if the complement exists in the hash table. +6. If found, add [nums[i], nums[j], complement] to the result array. +7. If not found, store nums[j] in the hash table. +8. Return the result array containing all unique triplets that sum to the target value. + +### 3. Two Pointer Technique Steps + +1. Sort the nums array in ascending order. +2. Iterate through the sorted array with a loop, selecting an element nums[i] as the first element of a potential triplet. +3. Use two pointers, left and right, to search for a pair of elements that sum up to the complement of nums[i] (i.e., target - nums[i]). +4. If found, add [nums[i], nums[left], nums[right]] to the result array, and move both pointers while skipping duplicates. +5. Continue the iteration until all unique triplets that sum to the target are found. +6. Return the result array containing all unique triplets. + + +## References +- [Wikipedia](https://en.wikipedia.org/wiki/3SUM) +- [Leetcode](https://leetcode.com/problems/3sum/) + + +## Problem Added By +- [PortFolio](https://femil-savaliya.netlify.app) +- [GitHub](https://www.github.com/Femil32) +- [LinkedIn](https://www.linkedin.com/in/femil-savaliya) + + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. \ No newline at end of file diff --git a/L-I/0011 ThreeSum/threeSum.js b/L-I/0011 ThreeSum/threeSum.js new file mode 100644 index 0000000..17cdb52 --- /dev/null +++ b/L-I/0011 ThreeSum/threeSum.js @@ -0,0 +1,58 @@ +// 1. Brute Force Solution +const threeSum_brute_Force = (nums, target) => { + let result = []; + for (let i = 0; i < nums.length; i++) { + for (let j = i + 1; j < nums.length; j++) { + for (let k = j + 1; k < nums.length; k++) { + if (nums[i] + nums[j] + nums[k] === target) { + result.push([nums[i], nums[j], nums[k]]); + } + } + } + } + return result; +} + +// 2. Using a hash table +const threeSum_hash_table = (nums, target) => { + let result = []; + const hash = {}; + for (let i = 0; i < nums.length; i++) { + for (let j = i + 1; j < nums.length; j++) { + const complement = target - (nums[i] + nums[j]); + if (complement in hash) { + result.push([nums[i], nums[j], complement]); + } else { + hash[nums[j]] = true; + } + } + } + + return result; +} + +// 3. Two Pointer Technique +const threeSum_two_pointer = (nums, target) => { + let result = []; + nums.sort((a, b) => a - b); + for (let i = 0; i < nums.length - 2; i++) { + if (i > 0 && nums[i] === nums[i - 1]) continue; + let left = i + 1; + let right = nums.length - 1; + while (left < right) { + const sum = nums[i] + nums[left] + nums[right]; + if (sum === target) { + result.push([nums[i], nums[left], nums[right]]); + while (left < right && nums[left] === nums[left + 1]) left++; + while (left < right && nums[right] === nums[right - 1]) right--; + left++; + right--; + } else if (sum < target) { + left++; + } else { + right--; + } + } + } + return result; +} \ No newline at end of file From 5dc98c26473f99dd09287ac809b1421502268367 Mon Sep 17 00:00:00 2001 From: Femil Savaliya Date: Thu, 5 Oct 2023 12:51:32 +0000 Subject: [PATCH 17/37] Initial commit From 432e7a35857545d65603f3cc0ce15f38964748e3 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:25:41 +0530 Subject: [PATCH 18/37] Create 0014 Memoize II --- L-A/0014 Memoize II | 1 + 1 file changed, 1 insertion(+) create mode 100644 L-A/0014 Memoize II diff --git a/L-A/0014 Memoize II b/L-A/0014 Memoize II new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/L-A/0014 Memoize II @@ -0,0 +1 @@ + From 3ffe7a9b43cce0127bd338770dbd306f43ff3ecd Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:32:25 +0530 Subject: [PATCH 19/37] Delete L-A/0014 Memoize II --- L-A/0014 Memoize II | 1 - 1 file changed, 1 deletion(-) delete mode 100644 L-A/0014 Memoize II diff --git a/L-A/0014 Memoize II b/L-A/0014 Memoize II deleted file mode 100644 index 8b13789..0000000 --- a/L-A/0014 Memoize II +++ /dev/null @@ -1 +0,0 @@ - From 6dcd124f2c4aa709bb1bded581891931d366dafc Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:36:12 +0530 Subject: [PATCH 20/37] Create README.md --- L-A/0014 Memoize II/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 L-A/0014 Memoize II/README.md diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/L-A/0014 Memoize II/README.md @@ -0,0 +1 @@ + From c440ce5f001edd9433d177fe13de7725ce033086 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:36:48 +0530 Subject: [PATCH 21/37] Create MemoizeII.js --- L-A/0014 Memoize II/MemoizeII.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 L-A/0014 Memoize II/MemoizeII.js diff --git a/L-A/0014 Memoize II/MemoizeII.js b/L-A/0014 Memoize II/MemoizeII.js new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/L-A/0014 Memoize II/MemoizeII.js @@ -0,0 +1 @@ + From 66972cee8fa3cf067cb2099ed0dfbf70c8ceefdb Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:37:27 +0530 Subject: [PATCH 22/37] Update README.md --- L-A/0014 Memoize II/README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index 8b13789..d6ca538 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -1 +1,26 @@ +# Memoize II +[LeetCode Problem]https://leetcode.com/problems/memoize-ii/ +Given a function fn, return a memoized version of that function. + +A memoized function is a function that will never be called twice with the same inputs. Instead it will return a cached value. + +fn can be any function and there are no constraints on what type of values it accepts. Inputs are considered identical if they are === to each other. + +## Example 1: +```javascript +Input: +getInputs = () => [[2,2],[2,2],[1,2]] +fn = function (a, b) { return a + b; } +Output: [{"val":4,"calls":1},{"val":4,"calls":1},{"val":3,"calls":2}] +Explanation: +const inputs = getInputs(); +const memoized = memoize(fn); +for (const arr of inputs) { + memoized(...arr); +} + +For the inputs of (2, 2): 2 + 2 = 4, and it required a call to fn(). +For the inputs of (2, 2): 2 + 2 = 4, but those inputs were seen before so no call to fn() was required. +For the inputs of (1, 2): 1 + 2 = 3, and it required another call to fn() for a total of 2. +``` From b4033142c23793b51b04d9e638f1bc74a7f0b65e Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:39:34 +0530 Subject: [PATCH 23/37] Update README.md --- L-A/0014 Memoize II/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index d6ca538..96174d6 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -24,3 +24,25 @@ For the inputs of (2, 2): 2 + 2 = 4, and it required a call to fn(). For the inputs of (2, 2): 2 + 2 = 4, but those inputs were seen before so no call to fn() was required. For the inputs of (1, 2): 1 + 2 = 3, and it required another call to fn() for a total of 2. ``` + +## Example 2: +```javascript +Input: +getInputs = () => [[{},{}],[{},{}],[{},{}]] +fn = function (a, b) { return ({...a, ...b}); } +Output: [{"val":{},"calls":1},{"val":{},"calls":2},{"val":{},"calls":3}] +Explanation: +Merging two empty objects will always result in an empty object. It may seem like there should only be 1 call to fn() because of cache-hits, however none of those objects are === to each other. +``` + + +## Example 3: +```javascript +Input: +getInputs = () => { const o = {}; return [[o,o],[o,o],[o,o]]; } +fn = function (a, b) { return ({...a, ...b}); } +Output: [{"val":{},"calls":1},{"val":{},"calls":1},{"val":{},"calls":1}] +Explanation: +Merging two empty objects will always result in an empty object. The 2nd and 3rd third function calls result in a cache-hit. This is because every object passed in is identical. +``` + From 3192dce42138eff151d04e56f32241837d88efc3 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:40:40 +0530 Subject: [PATCH 24/37] Update README.md --- L-A/0014 Memoize II/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index 96174d6..c5b0de5 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -46,3 +46,9 @@ Explanation: Merging two empty objects will always result in an empty object. The 2nd and 3rd third function calls result in a cache-hit. This is because every object passed in is identical. ``` +### Constraints: +```javascript +1 <= inputs.length <= 105 +0 <= inputs.flat().length <= 105 +inputs[i][j] != NaN +``` From 5604e6ba203972c7e5cd4f028ee8ec9bce528aa8 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Fri, 6 Oct 2023 00:10:27 +0530 Subject: [PATCH 25/37] Update README.md --- L-A/0014 Memoize II/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index c5b0de5..5f57e92 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -52,3 +52,18 @@ Merging two empty objects will always result in an empty object. The 2nd and 3rd 0 <= inputs.flat().length <= 105 inputs[i][j] != NaN ``` + +## Approach: +Map is perfect for storing single argument. Each consecutive argument must have cache based on previous argument, which will form a tree like structure, like this: +```javascript +fn(1,3,4) // { 1: { 3: { 4: {}}}}; +fn(1,4,3) // { 1: { 3: { 4: {}}, 4: { 3: {}}}}; +``` +The only problem, is how do we store our result. It's been never stated, that memoized function will be called with the same amount of arguments every time. We need a way to store our result anywhere on the path and also make sure that it will never be misteaken with argument. Here is example. +```javascript +fn(1,3) // { 1: { 3: 4}}; +-> 4 +fn(1) // { 1: { 3: 4}}; +-> { 3: 4 } // returning cache branch as result +``` +There are different aproaches to overcome this. But since every Symbol() call is guaranteed to return a unique Symbol we can use it to store actual result with guarantee, that it will never match any argument. From 0ab66011c21ccb39c03cfa531ce164020849de11 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Fri, 6 Oct 2023 00:21:58 +0530 Subject: [PATCH 26/37] Update MemoizeII.js --- L-A/0014 Memoize II/MemoizeII.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/L-A/0014 Memoize II/MemoizeII.js b/L-A/0014 Memoize II/MemoizeII.js index 8b13789..3d7f3c8 100644 --- a/L-A/0014 Memoize II/MemoizeII.js +++ b/L-A/0014 Memoize II/MemoizeII.js @@ -1 +1,26 @@ +const RES = Symbol("result"); + +/** + * @param {Function} fn + */ +function memoize(fn) { + const globalCache = new Map(); + + return (...params) => { + let currentCache = globalCache; + for(const param of params) { + if (!currentCache.has(param)) { + currentCache.set(param, new Map()); + } + currentCache = currentCache.get(param); + } + + if (currentCache.has(RES)) return currentCache.get(RES); + + const result = fn(...params); + + currentCache.set(RES, result); + return result; + } +} From 08f1ca8ad71488c17072cab1d9fa14da7af9e6af Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Fri, 6 Oct 2023 00:23:56 +0530 Subject: [PATCH 27/37] Update README.md --- L-A/0014 Memoize II/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index 5f57e92..40aa91a 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -67,3 +67,7 @@ fn(1) // { 1: { 3: 4}}; -> { 3: 4 } // returning cache branch as result ``` There are different aproaches to overcome this. But since every Symbol() call is guaranteed to return a unique Symbol we can use it to store actual result with guarantee, that it will never match any argument. + +## Problem Added By + +-[deveshidwivedi](https://github.com/deveshidwivedi) From 5394024c2759ce916b20e3fcdc2c4a038cfdf8b7 Mon Sep 17 00:00:00 2001 From: Deveshi Dwivedi <120312681+deveshidwivedi@users.noreply.github.com> Date: Fri, 6 Oct 2023 00:24:24 +0530 Subject: [PATCH 28/37] Update README.md --- L-A/0014 Memoize II/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index 40aa91a..e46913d 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -70,4 +70,4 @@ There are different aproaches to overcome this. But since every Symbol() call is ## Problem Added By --[deveshidwivedi](https://github.com/deveshidwivedi) +- [deveshidwivedi](https://github.com/deveshidwivedi) From 457427281727b74bc00ef629542d6aa18bd33ba6 Mon Sep 17 00:00:00 2001 From: DevvSakib Date: Fri, 6 Oct 2023 10:41:59 +0600 Subject: [PATCH 29/37] Update README.md --- L-A/0014 Memoize II/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/L-A/0014 Memoize II/README.md b/L-A/0014 Memoize II/README.md index e46913d..5e046c3 100644 --- a/L-A/0014 Memoize II/README.md +++ b/L-A/0014 Memoize II/README.md @@ -71,3 +71,10 @@ There are different aproaches to overcome this. But since every Symbol() call is ## Problem Added By - [deveshidwivedi](https://github.com/deveshidwivedi) + + + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. From 51947b2ba91ec4550d41257615ee65fad4fbcbfe Mon Sep 17 00:00:00 2001 From: himanshukoshti Date: Fri, 6 Oct 2023 22:54:51 +0530 Subject: [PATCH 30/37] longest valid parentheses --- .../LongestValidParentheses.js | 8 +++ L-A/0015 Longest Valid Parentheses/README.md | 60 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 L-A/0015 Longest Valid Parentheses/LongestValidParentheses.js create mode 100644 L-A/0015 Longest Valid Parentheses/README.md diff --git a/L-A/0015 Longest Valid Parentheses/LongestValidParentheses.js b/L-A/0015 Longest Valid Parentheses/LongestValidParentheses.js new file mode 100644 index 0000000..b19384a --- /dev/null +++ b/L-A/0015 Longest Valid Parentheses/LongestValidParentheses.js @@ -0,0 +1,8 @@ +var longestValidParentheses = function(S) { + let stack = [-1], ans = 0 + for (let i = 0; i < S.length; i++) + if (S[i] === '(') stack.push(i) + else if (stack.length === 1) stack[0] = i + else stack.pop(), ans = Math.max(ans, i - stack[stack.length-1]) + return ans +}; \ No newline at end of file diff --git a/L-A/0015 Longest Valid Parentheses/README.md b/L-A/0015 Longest Valid Parentheses/README.md new file mode 100644 index 0000000..60a6ddb --- /dev/null +++ b/L-A/0015 Longest Valid Parentheses/README.md @@ -0,0 +1,60 @@ +# Longest Valid Parentheses +[LeetCode Problem]https://leetcode.com/problems/longest-valid-parentheses/description/ + +Given a string containing just the characters '(' and ')', return the length of the longest valid (well-formed) parentheses substring. + +## Example 1 +``` +Input: s = "(()" +Output: 2 +Explanation: The longest valid parentheses substring is "()". +``` + +## Example 2: +``` +Input: s = ")()())" +Output: 4 +Explanation: The longest valid parentheses substring is "()()". +``` + +## Example 3: +``` +Input: s = "" +Output: 0 +``` + +### Constraints: +```javascript +0 <= s.length <= 3 * 104 +s[i] is '(', or ')' +``` + +## Approach: +One of the key things to realize about valid parentheses strings is that they're entirely self-satisfied, meaning that while you can have one substring that is entirely inside another, you can't have two substrings that only partially overlap. + +This means that we can use a greedy O(N) time complexity solution to this problem without the need for any kind of backtracking. In fact, we should be able to use a very standard stack-based valid parentheses string algorithm with just three very minor modifications. + +In a stadard valid parentheses string algorithm, we iterate through the string (S) and push the index (i) of any '(' to our stack. Whenever we find a ')', we match it with the last entry on the stack and pop said entry off. We know the string is not valid if we find a ')' while there are no '(' indexes in the stack with which to match it, and also if we have leftover '(' in the stack when we reach the end of S. + +For this problem, we will need to add in a step that updates our answer (ans) when we close a parentheses pair. Since we stored the index of the '(' in our stack, we can easily find the difference between the ')' at i and the last entry in the stack, which should be the length of the valid substring which was just closed. + +But here we run into a problem, because consecutive valid substrings can be grouped into a larger valid substring (ie, '()()' = 4). So instead of counting from the last stack entry, we should actually count from the second to last entry, to include any other valid closed substrings since the most recent '(' that will still remain after we pop the just-matched last stack entry off. + +This, of course, brings us to the second and third changes. Since we're checking the second to last stack entry, what happens in the case of '()()' when you close the second valid substring yet there's only the one stack entry left at the time? + +To avoid this issue, we can just wrap the entire string in another imaginary set of parentheses by starting with stack = [-1], indicating that there's an imaginary '(' just before the beginning of the string at i = 0. + +The other issue is that we will want to continue even if the string up to i becomes invalid due to a ')' appearing when the stack is "empty", or in this case has only our imaginary index left. In that case, we can just effectively restart our stack by updating our imaginary '(' index (stack[0] = i) and continue on. + +Then, once we reach the end of S, we can just return ans. + +## Problem Added By + +- [himanshukoshti](https://github.com/himanshukoshti) + + + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. From ab7436a7360925649dff8b878494caa2761969ac Mon Sep 17 00:00:00 2001 From: Tipchan Songtheng Date: Sat, 7 Oct 2023 18:35:51 +0530 Subject: [PATCH 31/37] Add DNA_Matching problem to (L-I). --- L-I/0011 DNA_Matching/DNA_Matching.js | 22 ++++++++ L-I/0011 DNA_Matching/README.md | 78 +++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 L-I/0011 DNA_Matching/DNA_Matching.js create mode 100644 L-I/0011 DNA_Matching/README.md diff --git a/L-I/0011 DNA_Matching/DNA_Matching.js b/L-I/0011 DNA_Matching/DNA_Matching.js new file mode 100644 index 0000000..9c511b3 --- /dev/null +++ b/L-I/0011 DNA_Matching/DNA_Matching.js @@ -0,0 +1,22 @@ +function dnaMatch(dna1, dna2) { + // Check if the lengths of the two DNA sequences are different + if (dna1.length !== dna2.length) { + return false; // Different lengths, not a match + } + + // Iterate through each character of the DNA sequences + for (let i = 0; i < dna1.length; i++) { + // Compare characters at the current position + if (dna1[i] !== dna2[i]) { + return false; // Characters don't match, not a match + } + } + + // If we reach this point, all characters match, so it's a match + return true; +} + +// Test cases +console.log(dnaMatch("ACGT", "ACGT")); // true +console.log(dnaMatch("ACGT", "ACTG")); // false +console.log(dnaMatch("AACT", "AACC")); // false diff --git a/L-I/0011 DNA_Matching/README.md b/L-I/0011 DNA_Matching/README.md new file mode 100644 index 0000000..c125365 --- /dev/null +++ b/L-I/0011 DNA_Matching/README.md @@ -0,0 +1,78 @@ +# 0011 DNA_Matching ( L-I ) + +## Problem + +You are given two DNA sequences as strings, representing the genetic code of two individuals. Each DNA sequence consists of a series of characters, where each character can be one of four options: 'A' (adenine), 'C' (cytosine), 'G' (guanine), or 'T' (thymine). + +Write a JavaScript function called dnaMatch that takes these two DNA sequences as input and returns true if they are a match and false otherwise. Two DNA sequences are considered a match if they have the same characters in the same order. + +**Example** + +``` +If the input DNA sequences are "ACGT" and "ACGT", the function should return true because they are an exact match. +If the input DNA sequences are "ACGT" and "ACTG", the function should return false because the order of characters is different. +If the input DNA sequences are "AACT" and "AACC", the function should return true because some characters do not match. +``` + +**Here's an example of how the function should work:** + +```javascript +console.log(dnaMatch("ACGT", "ACGT")); // true +console.log(dnaMatch("ACGT", "ACTG")); // false +console.log(dnaMatch("AACT", "AACC")); // false +``` + +## Solutions + +```javascript +function dnaMatch(dna1, dna2) { + // Check if the lengths of the two DNA sequences are different + if (dna1.length !== dna2.length) { + return false; // Different lengths, not a match + } + + // Iterate through each character of the DNA sequences + for (let i = 0; i < dna1.length; i++) { + // Compare characters at the current position + if (dna1[i] !== dna2[i]) { + return false; // Characters don't match, not a match + } + } + + // If we reach this point, all characters match, so it's a match + return true; +} + +// Test cases +console.log(dnaMatch("ACGT", "ACGT")); // true +console.log(dnaMatch("ACGT", "ACTG")); // false +console.log(dnaMatch("AACT", "AACC")); // false +``` + +## How it works + +1. The `dnaMatch` function takes two input arguments: `dna1` and `dna2`, which are the two DNA sequences we want to compare. + +2. First, it checks if the lengths of `dna1` and `dna2` are different using the `if (dna1.length !== dna2.length)` conditional statement. If they have different lengths, the function immediately returns `false` because sequences of different lengths cannot be a match. + +3. If the lengths are the same, the function proceeds to compare the characters of the two DNA sequences. + +4. It enters a `for` loop that iterates through the characters of the sequences. The loop is controlled by the variable `i`, which starts at 0 and goes up to `dna1.length - 1`. This loop allows us to compare characters at the same position in both sequences. + +5. Inside the loop, the code compares the characters at the current position `i` using the conditional statement `if (dna1[i] !== dna2[i])`. If the characters at position `i` are not the same in both sequences, the function immediately returns `false` because it found a mismatch. + +6. If the loop completes without finding any mismatches, meaning it has compared all characters in both sequences, the function returns `true`. This indicates that the two DNA sequences are identical and, therefore, a match. + +## References + +- [ChatGPT](https://chat.openai.com/) + +## Problem Added By + +- [Tipchan](https://github.com/tsongtheng) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. From 77433078943ba5ef5c12fad3a2f1dcf40859762a Mon Sep 17 00:00:00 2001 From: Tipchan Songtheng Date: Sat, 7 Oct 2023 21:57:05 +0530 Subject: [PATCH 32/37] Add Largest Prime Palindrome to (L-A). --- .../LargestPrimePalindrome.js | 39 +++++++++ L-A/0015 Largest Prime Palindrome/README.md | 81 +++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 L-A/0015 Largest Prime Palindrome/LargestPrimePalindrome.js create mode 100644 L-A/0015 Largest Prime Palindrome/README.md diff --git a/L-A/0015 Largest Prime Palindrome/LargestPrimePalindrome.js b/L-A/0015 Largest Prime Palindrome/LargestPrimePalindrome.js new file mode 100644 index 0000000..e7e2df6 --- /dev/null +++ b/L-A/0015 Largest Prime Palindrome/LargestPrimePalindrome.js @@ -0,0 +1,39 @@ +function isPrime(num) { + if (num <= 1) { + return false; + } + if (num <= 3) { + return true; + } + if (num % 2 === 0 || num % 3 === 0) { + return false; + } + let i = 5; + while (i * i <= num) { + if (num % i === 0 || num % (i + 2) === 0) { + return false; + } + i += 6; + } + return true; +} + +function isPalindrome(num) { + const numStr = num.toString(); + const reversedStr = numStr.split("").reverse().join(""); + return numStr === reversedStr; +} + +function largestPrimePalindrome(n) { + for (let i = n; i >= 2; i--) { + if (isPrime(i) && isPalindrome(i)) { + return i; + } + } + return null; // No prime palindrome found in the range +} + +// Test cases +console.log(largestPrimePalindrome(100)); // 7 +console.log(largestPrimePalindrome(50)); // 7 +console.log(largestPrimePalindrome(10)); // 7 diff --git a/L-A/0015 Largest Prime Palindrome/README.md b/L-A/0015 Largest Prime Palindrome/README.md new file mode 100644 index 0000000..3617356 --- /dev/null +++ b/L-A/0015 Largest Prime Palindrome/README.md @@ -0,0 +1,81 @@ +# 0015 Largest Prime Palindrome ( L-A ) + +## Problem + +Write a JavaScript function called largestPrimePalindrome that takes an integer **n** as input and returns the largest prime palindrome that is less than or equal to **n**. A prime palindrome is a number that is both prime and reads the same forward and backward. + +**Example** + +``` +If the input n is 100, the function should return 7 because the largest prime palindrome less than or equal to 100 is 7. + +If the input n is 50, the function should return 7 because 7 is the largest prime palindrome less than or equal to 50. + +If the input n is 10, the function should return 7 because 7 is the largest prime palindrome less than or equal to 10. +``` + +## Solutions + +```javascript +function isPrime(num) { + if (num <= 1) { + return false; + } + if (num <= 3) { + return true; + } + if (num % 2 === 0 || num % 3 === 0) { + return false; + } + let i = 5; + while (i * i <= num) { + if (num % i === 0 || num % (i + 2) === 0) { + return false; + } + i += 6; + } + return true; +} + +function isPalindrome(num) { + const numStr = num.toString(); + const reversedStr = numStr.split("").reverse().join(""); + return numStr === reversedStr; +} + +function largestPrimePalindrome(n) { + for (let i = n; i >= 2; i--) { + if (isPrime(i) && isPalindrome(i)) { + return i; + } + } + return null; // No prime palindrome found in the range +} + +// Test cases +console.log(largestPrimePalindrome(100)); // 7 +console.log(largestPrimePalindrome(50)); // 7 +console.log(largestPrimePalindrome(10)); // 7 +``` + +## How it works + +1. The isPrime function checks whether a given number is prime using a primality test that efficiently eliminates multiples of 2 and 3 and then checks for divisibility by numbers of the form 6k ± 1. + +2. The isPalindrome function checks whether a given number is a palindrome by converting it to a string, reversing the string, and comparing it to the original string. + +3. The largestPrimePalindrome function starts from the given number n and counts down to 2, checking each number in reverse order. It uses the isPrime and isPalindrome functions to find the largest prime palindrome in the given range. + +## References + +- [ChatGPT](https://chat.openai.com/) + +## Problem Added By + +- [Tipchan](https://github.com/tsongtheng) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. From e076482c12437c4dea1226c116b443a770a149a8 Mon Sep 17 00:00:00 2001 From: Tipchan Songtheng Date: Sat, 7 Oct 2023 22:12:32 +0530 Subject: [PATCH 33/37] Add Calculate Tip to (L-B). --- L-B/0026 Calculate Tip/CalculateTip.js | 9 +++++ L-B/0026 Calculate Tip/README.md | 56 ++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 L-B/0026 Calculate Tip/CalculateTip.js create mode 100644 L-B/0026 Calculate Tip/README.md diff --git a/L-B/0026 Calculate Tip/CalculateTip.js b/L-B/0026 Calculate Tip/CalculateTip.js new file mode 100644 index 0000000..1443820 --- /dev/null +++ b/L-B/0026 Calculate Tip/CalculateTip.js @@ -0,0 +1,9 @@ +function calculateTip(totalCost, tipPercentage) { + // Calculate the tip amount by multiplying totalCost by tipPercentage divided by 100 + const tipAmount = (totalCost * tipPercentage) / 100; + return tipAmount; +} + +// Test cases +console.log(calculateTip(50, 15)); // 7.5 +console.log(calculateTip(75, 20)); // 15 diff --git a/L-B/0026 Calculate Tip/README.md b/L-B/0026 Calculate Tip/README.md new file mode 100644 index 0000000..45af127 --- /dev/null +++ b/L-B/0026 Calculate Tip/README.md @@ -0,0 +1,56 @@ +# 0026 Calculate Tip ( L-B ) + +## Problem + +You are at a restaurant, and you want to calculate the tip for your meal. Write a JavaScript function called **calculateTip** that takes two inputs: the total cost of the meal and the tip percentage.Your function should calculate the tip amount and return it. + +**Example** + +``` +If the total cost is $50 and the tip percentage is 15%, the function should return $7.5 because 15% of $50 is $7.5. + +If the total cost is $75 and the tip percentage is 20%, the function should return $15 because 20% of $75 is $15. +``` + +- **_You can assume that the tip percentage is provided as a whole number (e.g., 15 for 15%) and that the total cost is a positive number._** + +**Here's an example of how the function should work:** + +```javascript +console.log(calculateTip(50, 15)); // 7.5 +console.log(calculateTip(75, 20)); // 15 +``` + +## Solutions + +```javascript +function calculateTip(totalCost, tipPercentage) { + // Calculate the tip amount by multiplying totalCost by tipPercentage divided by 100 + const tipAmount = (totalCost * tipPercentage) / 100; + return tipAmount; +} + +// Test cases +console.log(calculateTip(50, 15)); // 7.5 +console.log(calculateTip(75, 20)); // 15 +``` + +## How it works + +1. We define a function calculateTip that takes two parameters: totalCost (the total cost of the meal) and tipPercentage (the percentage of the tip to be calculated). + +2. Inside the function, we calculate the tip amount by multiplying totalCost by tipPercentage divided by 100. This is because tip percentages are usually provided as whole numbers (e.g., 15 for 15%). + +## References + +- [ChatGPT](https://chat.openai.com/) + +## Problem Added By + +- [Tipchan](https://github.com/tsongtheng) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. From 9362b781e9cbf84a431ec05562437c2d1f3558d4 Mon Sep 17 00:00:00 2001 From: aladin002dz Date: Tue, 10 Oct 2023 14:24:30 +0100 Subject: [PATCH 34/37] get extension from a file name --- L-B/0026 FileExtension/FileExtension.js | 17 ++++++++ L-B/0026 FileExtension/FileExtension.test.js | 40 +++++++++++++++++++ L-B/0026 FileExtension/README.md | 41 ++++++++++++++++++++ L-B/0026 FileExtension/jest.config.json | 1 + 4 files changed, 99 insertions(+) create mode 100644 L-B/0026 FileExtension/FileExtension.js create mode 100644 L-B/0026 FileExtension/FileExtension.test.js create mode 100644 L-B/0026 FileExtension/README.md create mode 100644 L-B/0026 FileExtension/jest.config.json diff --git a/L-B/0026 FileExtension/FileExtension.js b/L-B/0026 FileExtension/FileExtension.js new file mode 100644 index 0000000..6987c7f --- /dev/null +++ b/L-B/0026 FileExtension/FileExtension.js @@ -0,0 +1,17 @@ +function extractFileExtension(fileName) { + // Split the file name into an array of strings at the dot character. + const splitFileName = fileName.split('.'); + + // Check if the split file name array has more than one element. + if (splitFileName.length > 1) { + // Get the last element in the array, which is the file extension. + const fileExtension = splitFileName.pop(); + + // Return the file extension. + return fileExtension; + } + // The file name does not have an extension, so return an empty string. + return ''; +} + +module.exports = extractFileExtension; diff --git a/L-B/0026 FileExtension/FileExtension.test.js b/L-B/0026 FileExtension/FileExtension.test.js new file mode 100644 index 0000000..86bdb7f --- /dev/null +++ b/L-B/0026 FileExtension/FileExtension.test.js @@ -0,0 +1,40 @@ + +const extractFileExtension = require('./FileExtension') + +describe('extractFileExtension', () => { + it('should return the file extension when given a valid file name', () => { + expect(extractFileExtension('example.txt')).toBe('txt'); + expect(extractFileExtension('document.docx')).toBe('docx'); + expect(extractFileExtension('image.jpg')).toBe('jpg'); + }); + + it('should return an empty string when given a file name without an extension', () => { + expect(extractFileExtension('README')).toBe(''); + expect(extractFileExtension('LICENSE')).toBe(''); + }); + + it('should return an empty string when given an empty string', () => { + expect(extractFileExtension('')).toBe(''); + }); +}); + +/* +test output: + PASS ./FileExtension.test.js + extractFileExtension + √ should return the file extension when given a valid file name (4 ms) + √ should return an empty string when given a file name without an extension (1 ms) + √ should return an empty string when given an empty string + +Test Suites: 1 passed, 1 total +Tests: 3 passed, 3 total +Snapshots: 0 total +Time: 0.958 s, estimated 1 s +Ran all test suites. +*/ + +/* +Testing with Jest global installation: +> npm install -g jest +> jest +*/ diff --git a/L-B/0026 FileExtension/README.md b/L-B/0026 FileExtension/README.md new file mode 100644 index 0000000..a84b3fc --- /dev/null +++ b/L-B/0026 FileExtension/README.md @@ -0,0 +1,41 @@ +# Get the file extension + +## Problem + +Write a function that takes a string and returns the file extension, which is the string after the last dot (.) in the string. If there is no dot in the string, return undefined. + +## Solution + +```javascript +function extractFileExtension(fileName) { + // Split the file name into an array of strings at the dot character. + const splitFileName = fileName.split("."); + + // Get the last element in the array, which is the file extension. + const fileExtension = splitFileName.pop(); + + // Return the file extension. + return fileExtension; +} +``` + +## How it works + +- The `extractFileExtension` function takes a string as an argument. +- The `split` method is used to split the string into an array of strings at the dot character. +- The `pop` method is used to get the last element in the array, which is the file extension. +- The file extension is returned. + +## References + +- [String.prototype.split()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split) + +## Problem Added By + +- [GitHub](https://github.com/aladin002dz) + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. diff --git a/L-B/0026 FileExtension/jest.config.json b/L-B/0026 FileExtension/jest.config.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/L-B/0026 FileExtension/jest.config.json @@ -0,0 +1 @@ +{} \ No newline at end of file From 16e30ac3a712e24088044002ecc97ee809b524fd Mon Sep 17 00:00:00 2001 From: aladin002dz Date: Tue, 10 Oct 2023 14:29:56 +0100 Subject: [PATCH 35/37] FileExtension readme update --- L-B/0026 FileExtension/README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/L-B/0026 FileExtension/README.md b/L-B/0026 FileExtension/README.md index a84b3fc..d69f24a 100644 --- a/L-B/0026 FileExtension/README.md +++ b/L-B/0026 FileExtension/README.md @@ -2,7 +2,7 @@ ## Problem -Write a function that takes a string and returns the file extension, which is the string after the last dot (.) in the string. If there is no dot in the string, return undefined. +Write a function that takes a string and returns the file extension, which is the string after the last dot (.) in the string. If there is no dot in the string, return empty string. ## Solution @@ -11,11 +11,16 @@ function extractFileExtension(fileName) { // Split the file name into an array of strings at the dot character. const splitFileName = fileName.split("."); - // Get the last element in the array, which is the file extension. - const fileExtension = splitFileName.pop(); + // Check if the split file name array has more than one element. + if (splitFileName.length > 1) { + // Get the last element in the array, which is the file extension. + const fileExtension = splitFileName.pop(); - // Return the file extension. - return fileExtension; + // Return the file extension. + return fileExtension; + } + // The file name does not have an extension, so return an empty string. + return ""; } ``` From 595b53fa1dea5672e7edf1f1c69e5eb1ee3e1b01 Mon Sep 17 00:00:00 2001 From: rimsha-shoukat Date: Tue, 23 Dec 2025 20:13:50 +0500 Subject: [PATCH 36/37] remove duplicates from array/string --- L-B/0027 Remove duplicates/README.md | 62 +++++++++++++++++++ .../removeDuplicates.js | 18 ++++++ 2 files changed, 80 insertions(+) create mode 100644 L-B/0027 Remove duplicates/README.md create mode 100644 L-B/0027 Remove duplicates/removeDuplicates.js diff --git a/L-B/0027 Remove duplicates/README.md b/L-B/0027 Remove duplicates/README.md new file mode 100644 index 0000000..5e79830 --- /dev/null +++ b/L-B/0027 Remove duplicates/README.md @@ -0,0 +1,62 @@ +# 0027 removeDuplicates ( L-B ) + +## Problem +Write a function that removes duplicate values from the given input. +- If the input is an array, return a new array with unique values. +- If the input is a string, return a new string with duplicate characters removed. +- The original order must be preserved. + +## Solution +```js +function removeDuplicates(input) { + let unique = []; + for (let i = 0; i < input.length; i++) { + if (!unique.includes(input[i])) { + unique.push(input[i]); + } + } + if(typeof(input) === "string"){ + unique = unique.toString().replace(/,/g, ''); + } + console.log(unique); + return unique; +} +``` + +## Test Cases +```js +removeDuplicates([2, 4, 8, 4, 2, 6, 9, 2, 6, 8, 10]); +// Output: [2, 4, 8, 6, 9, 10] + +removeDuplicates([1, 1, 1, 4, 0, 6, -2, 2, 6, 7, 10]); +// Output: [1, 4, 0, 6, -2, 2, 7, 10] + +removeDuplicates("zoom"); +// Output: "zom" + +removeDuplicates("hello world"); +// Output: "helo wrd" +``` + +## How it works +- Create an empty array called unique +- Loop through each character or element in the input +- Check if the current value already exists in unique +- If it does not exist, we add it to unique +- After the loop: +- If the input is a string, we convert the array into a string +- Remove commas using replace +- Finally, return the result + +## References +- [MDN – Array.prototype.includes()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes) +- [MDN – typeof operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) + + +## Problem Added By +- [GitHub](https://github.com/rimsha-shoukat) + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. diff --git a/L-B/0027 Remove duplicates/removeDuplicates.js b/L-B/0027 Remove duplicates/removeDuplicates.js new file mode 100644 index 0000000..29f6dba --- /dev/null +++ b/L-B/0027 Remove duplicates/removeDuplicates.js @@ -0,0 +1,18 @@ +function removeDuplicates(input) { + let unique = []; + for (let i = 0; i < input.length; i++) { + if (!unique.includes(input[i])) { + unique.push(input[i]); + } + } + if(typeof(input) === "string"){ + unique = unique.toString().replace(/,/g, ''); + } + console.log(unique); + return unique; +} + +removeDuplicates([2, 4, 8, 4, 2, 6, 9, 2, 6, 8, 10]); +removeDuplicates([1, 1, 1, 4, 0, 6, -2, 2, 6, 7, 10]); +removeDuplicates("zoom"); +removeDuplicates("hello world"); \ No newline at end of file From 8799e77949cc48fc3a63382581b2f55d9ae9b387 Mon Sep 17 00:00:00 2001 From: rimsha-shoukat Date: Tue, 23 Dec 2025 20:16:39 +0500 Subject: [PATCH 37/37] length conveter --- L-I/0012 Length converter/README.md | 79 ++++++++++++++++++++ L-I/0012 Length converter/lengthConverter.js | 29 +++++++ 2 files changed, 108 insertions(+) create mode 100644 L-I/0012 Length converter/README.md create mode 100644 L-I/0012 Length converter/lengthConverter.js diff --git a/L-I/0012 Length converter/README.md b/L-I/0012 Length converter/README.md new file mode 100644 index 0000000..82560ba --- /dev/null +++ b/L-I/0012 Length converter/README.md @@ -0,0 +1,79 @@ +# 0012 lengthConverter ( L-I ) + +## Problem +Create a function that converts a given length value from one unit to another. +The function should: +- Accept a numeric length +- Accept a fromUnit and toUnit +- Support common metric and imperial units +- Return the converted value rounded to 5 decimal places +- Throw an error if an invalid unit is provided + +## Supported Units +- meters +- kilometers +- centimeters +- millimeters +- inches +- feet +- yards +- miles + +## Solution +```js +function lengthConverter(length, fromUnit, toUnit) { + const units = { + "meters": 1, + "kilometers": 1000, + "centimeters": 0.01, + "millimeters": 0.001, + "inches": 0.0254, + "feet": 0.3048, + "yards": 0.9144, + "miles": 1609.34 + }; + + if (!units[fromUnit] || !units[toUnit]) { + throw new Error("Invalid unit"); + } + const meters = length * units[fromUnit]; + console.log((meters / units[toUnit]).toFixed(3)); + return (meters / units[toUnit]).toFixed(3); +} +``` + +## Test Cases +```js +removeDuplicates([2, 4, 8, 4, 2, 6, 9, 2, 6, 8, 10]); +// Output: [2, 4, 8, 6, 9, 10] + +removeDuplicates([1, 1, 1, 4, 0, 6, -2, 2, 6, 7, 10]); +// Output: [1, 4, 0, 6, -2, 2, 7, 10] + +removeDuplicates("zoom"); +// Output: "zom" + +removeDuplicates("hello world"); +// Output: "helo wrd" +``` + +## How it works +- Define a units object where each unit is mapped to its value in meters +- Validate both fromUnit and toUnit +- The input length is first converted into meters +- Then we convert meters into the target unit +- The result is rounded to 5 decimal places using toFixed(5) +- Finally, the converted value is returned + +## References +- [Wikipedia – Unit conversion](https://en.wikipedia.org/wiki/Unit_conversion) +- [MDN – JavaScript Objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects) + + +## Problem Added By +- [GitHub](https://github.com/rimsha-shoukat) + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. \ No newline at end of file diff --git a/L-I/0012 Length converter/lengthConverter.js b/L-I/0012 Length converter/lengthConverter.js new file mode 100644 index 0000000..d6a78f1 --- /dev/null +++ b/L-I/0012 Length converter/lengthConverter.js @@ -0,0 +1,29 @@ +function lengthConverter(length, fromUnit, toUnit) { + const units = { + "meters": 1, + "kilometers": 1000, + "centimeters": 0.01, + "millimeters": 0.001, + "inches": 0.0254, + "feet": 0.3048, + "yards": 0.9144, + "miles": 1609.34 + }; + + if (!units[fromUnit] || !units[toUnit]) { + throw new Error("Invalid unit"); + } + + const meters = length * units[fromUnit]; + console.log((meters / units[toUnit]).toFixed(2)); + return (meters / units[toUnit]).toFixed(2); +} + +lengthConverter(100, "meters", "kilometers"); +lengthConverter(5, "miles", "feet"); +lengthConverter(12, "inches", "centimeters"); +lengthConverter(2500, "centimeters", "meters"); +lengthConverter(3, "kilometers", "miles"); +lengthConverter(10, "feet", "yards"); +lengthConverter(5000, "millimeters", "meters"); +lengthConverter(2, "yards", "inches"); \ No newline at end of file