├── .husky
├── .gitignore
└── pre-commit
├── .prettierignore
├── src
├── design
│ ├── OrderSaleMaximizer
│ │ └── index.spec.js
│ ├── DiscordCmdCooldowns
│ │ └── index.js
│ ├── Observable
│ │ └── index.js
│ ├── BufferSequence
│ │ └── index.js
│ └── BehaviorSubject
│ │ └── index.js
├── fromJob
│ ├── README.md
│ └── flattenObjectOfArrays
│ │ └── index.spec.js
├── intro
│ └── basicAlgos
│ │ └── function-intro.png
├── data_structures
│ ├── Graphs
│ │ ├── graph-parts.jpg
│ │ ├── airports-weighted-graph.jpg
│ │ ├── Dijkstras-video-screencap.png
│ │ ├── connected-vs-complete-graph.jpg
│ │ ├── directed-vs-undirected-graph.jpg
│ │ ├── depth-vs-breadth-search-first.gif
│ │ ├── cyclic-vs-acyclic-directed-graph.jpg
│ │ └── travelingSalesman
│ │ │ ├── travelingSalesman.md
│ │ │ └── travelingSalesman.js
│ ├── Queue
│ │ └── QueueUsingTwoStacks.png
│ └── Trie
│ │ ├── intro.md
│ │ └── index.js
├── DOM
│ ├── displayFolderStructure
│ │ ├── folderStructure.png
│ │ └── index.html
│ └── iterativelyRenderTree
│ │ ├── index.html
│ │ └── index.js
├── recursion
│ ├── intro-notes
│ │ ├── call-stack-order-debug.png
│ │ ├── factorial-code-animation.gif
│ │ └── fibonacci-recursion-animation.gif
│ ├── generateAnagrams
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── inOrderSubsets
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── reverseStr
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── binaryStringExpansion
│ │ └── index.spec.js
│ ├── sumToOneDigit
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── sumArr
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── recursiveSigma
│ │ └── index.spec.js
│ ├── factorial
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── removeConsecDupeWords
│ │ └── index.spec.js
│ ├── binarySearch
│ │ └── index.spec.js
│ ├── coronaVirusFloodFill
│ │ └── index.spec.js
│ ├── fibonacci
│ │ └── index.spec.js
│ ├── lowestCommonMult
│ │ └── index.spec.js
│ ├── greatestCommonFactor
│ │ ├── index.spec.js
│ │ └── index.js
│ └── generateCoinChange
│ │ └── index.js
├── bit_arithmetic
│ ├── decimalToBinary
│ │ └── index.js
│ ├── binaryToDecimal
│ │ └── index.js.js
│ ├── decimalToHexidecimal
│ │ └── index.js.js
│ ├── encodeBytesTo32
│ │ └── index.js.js
│ └── hexidecimalToDecimal
│ │ └── index.js.js
├── sorts
│ ├── intro.md
│ ├── radixSort
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── bubbleSort
│ │ └── index.spec.js
│ ├── quickSort
│ │ └── index.spec.js
│ ├── insertionSort
│ │ └── index.spec.js
│ ├── selectionSort
│ │ └── index.spec.js
│ └── mergeSort
│ │ └── index.spec.js
├── strings
│ ├── rehash
│ │ └── index.spec.js
│ ├── trim
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── stringToWordArray
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── dupesBetweenSeparators
│ │ └── index.spec.js
│ ├── decodeStr
│ │ └── index.spec.js
│ ├── vowelsFirst
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── capitalization
│ │ └── index.spec.js
│ ├── getQuoteFromCaret
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── reverseWords
│ │ └── index.spec.js
│ ├── bracesValid
│ │ └── index.spec.js
│ ├── reverseString
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── reverseWordOrder
│ │ └── index.spec.js
│ ├── bookIndex
│ │ └── index.spec.js
│ ├── isPalindrome
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── caseInsensitiveStringCompare
│ │ └── index.spec.js
│ ├── removeDupeWords
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── stringDedupe
│ │ └── index.spec.js
│ ├── kaprekarsConstant
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── encodeStr
│ │ └── index.spec.js
│ ├── acronymize
│ │ └── index.spec.js
│ ├── questionMarks
│ │ └── index.spec.js
│ ├── addHonorific
│ │ └── index.spec.js
│ ├── isAnagram
│ │ └── index.spec.js
│ ├── longestPalindromicSubstring
│ │ └── index.spec.js
│ ├── palindromeFromSubstr
│ │ └── index.js
│ ├── parensValid
│ │ └── index.spec.js
│ ├── isRotation
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── rotateStr
│ │ └── index.spec.js
│ ├── backspaceStringCompare
│ │ └── index.spec.js
│ ├── lengthOfLongestSubstring
│ │ └── index.spec.js
│ ├── canBuildS1FromS2
│ │ └── index.spec.js
│ ├── canStringBecomePalindrome
│ │ └── index.spec.js
│ ├── outputToJson
│ │ ├── index.js
│ │ └── output.txt
│ ├── largestCommonSubstring
│ │ └── index.spec.js
│ ├── compareVersionNumbers
│ │ └── index.spec.js
│ └── rot13
│ │ └── index.js
├── misc
│ ├── swapTwoInts
│ │ └── index.js
│ └── clockHandAngles
│ │ └── index.js
├── arrays
│ ├── firstNonConsecutive
│ │ ├── index.js
│ │ └── index.spec.js
│ ├── sumArrColumns
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── balanceIndex
│ │ └── index.spec.js
│ ├── balancePoint
│ │ └── index.spec.js
│ ├── countEvenNegatives
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── minToFront
│ │ └── index.spec.js
│ ├── reverseArr
│ │ └── index.spec.js
│ ├── findTriplets
│ │ └── index.spec.js
│ ├── flatten2dArray
│ │ └── index.spec.js
│ ├── allNonConsecutive
│ │ └── index.spec.js
│ ├── tacoTruck
│ │ └── index.js
│ ├── binarySearch
│ │ └── index.spec.js
│ ├── dedupeSorted
│ │ └── index.spec.js
│ ├── diagonalDifference
│ │ └── index.spec.js
│ ├── concatSelf
│ │ └── index.spec.js
│ ├── indexOfMinVal
│ │ └── index.spec.js
│ ├── firstNonRepeated
│ │ └── index.spec.js
│ ├── socialDistancingEnforcer
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── containerWithMostWater
│ │ └── index.spec.js
│ ├── oddOccurrencesInArray
│ │ └── index.spec.js
│ ├── matrixSearch
│ │ └── index.js
│ ├── missingValue
│ │ └── index.spec.js
│ ├── mode
│ │ └── index.spec.js
│ ├── interleaveArrays
│ │ └── index.spec.js
│ ├── nthLast
│ │ └── index.spec.js
│ ├── checkTicTacToeWinner
│ │ └── index.spec.js
│ ├── kMostFrequent
│ │ └── index.spec.js
│ ├── removeAt
│ │ └── index.spec.js
│ └── twoSum
│ │ └── index.spec.js
├── objects
│ ├── invertObj
│ │ ├── index.spec.js
│ │ └── index.js
│ ├── fewestCoinChange
│ │ └── index.spec.js
│ ├── zipArraysIntoMap
│ │ └── index.spec.js
│ ├── insert
│ │ └── index.spec.js
│ ├── findObjects
│ │ └── index.spec.js
│ ├── lens
│ │ └── index.spec.js
│ ├── coronaVirusAtRisk
│ │ └── index.spec.js
│ ├── makeFrequencyTable
│ │ └── index.spec.js
│ ├── santasNaughtyList
│ │ └── index.spec.js
│ ├── getMaxServings
│ │ └── index.spec.js
│ ├── updateInventory
│ │ └── index.spec.js
│ └── groupObjects
│ │ └── index.spec.js
├── amazon
│ ├── shortestDeliveries
│ │ └── index.spec.js
│ └── musicRuntime
│ │ └── index.spec.js
├── recreated_methods
│ ├── Array
│ │ ├── concat
│ │ │ └── index.spec.js
│ │ ├── unshift
│ │ │ └── index.spec.js
│ │ ├── push
│ │ │ └── index.spec.js
│ │ ├── shift
│ │ │ └── index.spec.js
│ │ ├── indexOf
│ │ │ └── index.spec.js
│ │ ├── join
│ │ │ └── index.spec.js
│ │ └── pop
│ │ │ └── index.spec.js
│ └── Object
│ │ └── entries
│ │ └── index.test.js
├── sets
│ ├── intro.md
│ └── orderedIntersection
│ │ └── index.spec.js
├── callbacks
│ └── dropIt
│ │ └── index.spec.js
└── intervals
│ └── mergeSortedIntervals
│ └── index.spec.js
├── .prettierrc.json
├── spec
├── support
│ └── jasmine.json
└── temp.js
├── pair-programming.md
├── package.json
├── README.md
├── jasmine.md
└── schedules
└── web_fund.md
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules/
--------------------------------------------------------------------------------
/src/design/OrderSaleMaximizer/index.spec.js:
--------------------------------------------------------------------------------
1 | // TODO
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npm run pretty-quick
5 |
--------------------------------------------------------------------------------
/src/fromJob/README.md:
--------------------------------------------------------------------------------
1 | # From Job Algos
2 |
3 | - Extracted logic from solving a problem on the job.
4 |
--------------------------------------------------------------------------------
/src/intro/basicAlgos/function-intro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/intro/basicAlgos/function-intro.png
--------------------------------------------------------------------------------
/src/data_structures/Graphs/graph-parts.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/data_structures/Graphs/graph-parts.jpg
--------------------------------------------------------------------------------
/src/data_structures/Queue/QueueUsingTwoStacks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/data_structures/Queue/QueueUsingTwoStacks.png
--------------------------------------------------------------------------------
/src/DOM/displayFolderStructure/folderStructure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/DOM/displayFolderStructure/folderStructure.png
--------------------------------------------------------------------------------
/src/data_structures/Graphs/airports-weighted-graph.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/data_structures/Graphs/airports-weighted-graph.jpg
--------------------------------------------------------------------------------
/src/recursion/intro-notes/call-stack-order-debug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/recursion/intro-notes/call-stack-order-debug.png
--------------------------------------------------------------------------------
/src/recursion/intro-notes/factorial-code-animation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/recursion/intro-notes/factorial-code-animation.gif
--------------------------------------------------------------------------------
/src/data_structures/Graphs/Dijkstras-video-screencap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/data_structures/Graphs/Dijkstras-video-screencap.png
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "trailingComma": "es5",
4 | "singleQuote": false,
5 | "printWidth": 80,
6 | "tabWidth": 2,
7 | "useTabs": false
8 | }
9 |
--------------------------------------------------------------------------------
/src/data_structures/Graphs/connected-vs-complete-graph.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/data_structures/Graphs/connected-vs-complete-graph.jpg
--------------------------------------------------------------------------------
/src/data_structures/Graphs/directed-vs-undirected-graph.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/data_structures/Graphs/directed-vs-undirected-graph.jpg
--------------------------------------------------------------------------------
/src/recursion/intro-notes/fibonacci-recursion-animation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/recursion/intro-notes/fibonacci-recursion-animation.gif
--------------------------------------------------------------------------------
/src/data_structures/Graphs/depth-vs-breadth-search-first.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/data_structures/Graphs/depth-vs-breadth-search-first.gif
--------------------------------------------------------------------------------
/src/data_structures/Graphs/cyclic-vs-acyclic-directed-graph.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheCodingDojo/algorithms/HEAD/src/data_structures/Graphs/cyclic-vs-acyclic-directed-graph.jpg
--------------------------------------------------------------------------------
/spec/support/jasmine.json:
--------------------------------------------------------------------------------
1 | {
2 | "spec_dir": "/",
3 | "spec_files": ["**/*.spec.js"],
4 | "helpers": ["helpers/**/*.js"],
5 | "stopSpecOnExpectationFailure": false,
6 | "random": false
7 | }
8 |
--------------------------------------------------------------------------------
/pair-programming.md:
--------------------------------------------------------------------------------
1 | # Pair Programming
2 |
3 | - Students are **_expected_** to assume [these roles](https://docs.google.com/document/d/1kK74NhJwHzM3xnZ6FffZKVLBsQTCBf6WSxh4U-9u9i4/edit#) within a few minutes of entering their breakout rooms.
4 |
--------------------------------------------------------------------------------
/src/bit_arithmetic/decimalToBinary/index.js:
--------------------------------------------------------------------------------
1 | function decimalToBinary(decimal) {
2 | let str = "";
3 | while (decimal > 0) {
4 | const char = decimal % 2;
5 | decimal = Math.floor(decimal / 2);
6 | str = char + str;
7 | }
8 | return "0b" + str;
9 | }
10 |
11 | console.log(decimalToBinary(14));
12 |
--------------------------------------------------------------------------------
/spec/temp.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | //
6 |
7 | testCases.forEach(({ args, expected }, i) => {
8 | describe(`when given testCases[${i}]`, () => {
9 | it("", () => {
10 | expect(testFn(...args)).toEqual(expected);
11 | });
12 | });
13 | });
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/src/bit_arithmetic/binaryToDecimal/index.js.js:
--------------------------------------------------------------------------------
1 | /*
2 | Binary to Decimal
3 |
4 | For practice, convert the following from binary to decimal. Example: 0b100111 becomes 39 . 0b10100101 0b111 0b1111000 0b110110 0b000 0b11 -0b1010 0b100110 0b1010101010 0b111001 0b100101
5 | */
6 |
7 | function binaryToDecimal(binary) {
8 | let count = 0,
9 | power = 0;
10 | for (let i = binary.length - 1; i >= 2; i--) {
11 | count += binary[i] * Math.pow(2, power++);
12 | }
13 | return count;
14 | }
15 |
--------------------------------------------------------------------------------
/src/bit_arithmetic/decimalToHexidecimal/index.js.js:
--------------------------------------------------------------------------------
1 | /*
2 | Decimal to Hexadecimal
3 |
4 |
5 | */
6 |
7 | function decimalToHexadecimal(decimal) {
8 | const map = {
9 | 10: "A",
10 | 11: "B",
11 | 12: "C",
12 | 13: "D",
13 | 14: "E",
14 | 15: "F",
15 | };
16 |
17 | let str = "";
18 | while (decimal > 0) {
19 | const remainder = decimal % 16;
20 | decimal = Math.floor(decimal / 16);
21 | str = (remainder < 10 ? remainder : map[remainder]) + str;
22 | }
23 | return "0x" + str;
24 | }
25 |
--------------------------------------------------------------------------------
/src/bit_arithmetic/encodeBytesTo32/index.js.js:
--------------------------------------------------------------------------------
1 | /*
2 | Encode Bytes to 32
3 |
4 | Input: four values between 0-255,
5 | Output: encode them into a 32-bit integer
6 | First should map to most significant 8 bits. Given [0xF0, 0xC3, 0x96, 0x59] , return 4039349849 ( 0xF0C39659 ).
7 | */
8 |
9 | const hexadecimalToDecimal = require("../2_Tue/hexidecimalToDecimal");
10 |
11 | function encodeBytesTo32(arr) {
12 | const combined = arr.map((digits) => digits.slice(2)).join("");
13 |
14 | return hexadecimalToDecimal("0x" + combined);
15 | }
16 |
--------------------------------------------------------------------------------
/src/sorts/intro.md:
--------------------------------------------------------------------------------
1 | # Sorts
2 |
3 | - [Sorts Visualize Step by Step](https://www.hackerearth.com/practice/algorithms/sorting/merge-sort/visualize/)
4 | - [Sorts Visualized](https://visualgo.net/en/sorting)
5 |
6 | ## Terminology
7 |
8 | ### [Stable](https://www.geeksforgeeks.org/stability-in-sorting-algorithms/)
9 |
10 | - It is stable if when there are duplicates, the duplicates are left in original order relative to one another
11 | - Making a sort stable incurs overhead (takes more time)
12 | - Click the above link for an example of when stability is needed
13 |
--------------------------------------------------------------------------------
/src/DOM/displayFolderStructure/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |

13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/strings/rehash/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "b70a164c32a20c10";
6 | const expected1 = "a184b70c42";
7 |
8 | const testCases = [{ arg: str1, expected: expected1 }];
9 |
10 | testCases.forEach(({ arg, expected }, i) => {
11 | describe(`when given "${arg}:`, () => {
12 | it("should return the correctly rehashed string.", () => {
13 | expect(testFn(arg)).toEqual(expected);
14 | });
15 | });
16 | });
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/src/misc/swapTwoInts/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Interview question that I received.
3 |
4 | Given two vars, x and y that store integers, swap their values WITHOUT
5 | creating any new variables or using any data types.
6 |
7 | Don't worry about creating a function either.
8 | */
9 |
10 | var x = 5;
11 | var y = 3;
12 |
13 | console.log(x, y);
14 |
15 | // Your code here.
16 |
17 | console.log(x, y);
18 |
19 | /*****************************************************************************/
20 | var a = 5;
21 | var b = 3;
22 |
23 | a = a - b; // 5 - 3 = 2
24 | b = b + a; // 3 + 2 = 5
25 | a = b - a; // 5 - 2 = 3
26 |
--------------------------------------------------------------------------------
/src/strings/trim/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = " hello world ";
6 | const expected1 = "hello world";
7 |
8 | const testCases = [{ arg: str1, expected: expected1 }];
9 |
10 | testCases.forEach(({ arg, expected }, i) => {
11 | describe(`when given testCases[${i}]`, () => {
12 | it("should return a string that is the given string with all leading and trailing spaces removed.", () => {
13 | expect(testFn(arg)).toEqual(expected);
14 | });
15 | });
16 | });
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/src/strings/stringToWordArray/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "Life is not a drill!";
6 | const expected1 = ["Life", "is", "not", "a", "drill!"];
7 |
8 | const testCases = [{ arg: str1, expected: expected1 }];
9 |
10 | testCases.forEach(({ arg, expected }, i) => {
11 | describe(`when given testCases[${i}]`, () => {
12 | it("should convert a string of space separated words into an array of words.", () => {
13 | expect(testFn(arg)).toEqual(expected);
14 | });
15 | });
16 | });
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/src/strings/dupesBetweenSeparators/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "to be,; --or\tnot : ;;; to-:: be";
6 | const expected1 = ["to", "be"];
7 |
8 | const testCases = [{ args: [str1], expected: expected1 }];
9 |
10 | testCases.forEach(({ args, expected }, i) => {
11 | describe(`when given testCases[${i}]`, () => {
12 | it("should return an array of the duplicate words between the specified separators.", () => {
13 | expect(testFn(...args)).toEqual(expected);
14 | });
15 | });
16 | });
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/src/design/DiscordCmdCooldowns/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | In discord bot development, commands are created that can be executed by a
3 | message with a special prefix, such as:
4 |
5 | dojo.find john
6 |
7 | where 'dojo.' is a prefix that is checked for and the cmd name is 'find'
8 | and the argument(s) are 'john'. This will trigger a function in the code
9 | with the arguments.
10 |
11 | However, some commands need to be given a cooldown so they are not executed
12 | too frequently. Use OOP to design a way to give commands a cooldown and
13 | keep track of who is on cooldown and for which commands using a command
14 | name, command cooldown, and a unique username as your relevant properties.
15 | */
16 |
--------------------------------------------------------------------------------
/src/recursion/generateAnagrams/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "lim";
6 | const expected1 = ["ilm", "iml", "lim", "lmi", "mil", "mli"];
7 | // Order of the output array does not matter
8 |
9 | const testCases = [{ arg: str1, expected: expected1 }];
10 |
11 | testCases.forEach(({ arg: arg, expected }, i) => {
12 | describe(`when given ${arg}`, () => {
13 | it("should return an array of all the anagrams of the given string.", () => {
14 | expect(testFn(arg)).toEqual(jasmine.arrayContaining(expected));
15 | });
16 | });
17 | });
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/src/recursion/inOrderSubsets/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const string1 = "abc";
6 | // In any order:
7 | const expected1 = ["", "c", "b", "bc", "a", "ac", "ab", "abc"];
8 |
9 | const testCases = [{ arg: string1, expected: expected1 }];
10 |
11 | testCases.forEach(({ arg, expected }, i) => {
12 | describe(`when given "${arg}"`, () => {
13 | it("should generate an array with every possible in-order character subset of the given string.", () => {
14 | expect(testFn(arg)).toEqual(jasmine.arrayContaining(expected));
15 | });
16 | });
17 | });
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/src/recursion/reverseStr/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "abc";
6 | const expected1 = "cba";
7 |
8 | const str2 = "";
9 | const expected2 = "";
10 |
11 | const testCases = [
12 | { arg: str1, expected: expected1 },
13 | { arg: str2, expected: expected2 },
14 | ];
15 |
16 | testCases.forEach(({ arg, expected }, i) => {
17 | describe(`when given "${arg}"`, () => {
18 | it("should return a string that is the reverse of the given string.", () => {
19 | expect(testFn(arg)).toEqual(expected);
20 | });
21 | });
22 | });
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/src/bit_arithmetic/hexidecimalToDecimal/index.js.js:
--------------------------------------------------------------------------------
1 | /*
2 | Hexadecimal to Decimal
3 |
4 |
5 | */
6 |
7 | function hexadecimalToDecimal(hexadecimal) {
8 | const map = {
9 | A: 10,
10 | B: 11,
11 | C: 12,
12 | D: 13,
13 | E: 14,
14 | F: 15,
15 | };
16 |
17 | let count = 0,
18 | power = 0;
19 | for (let i = hexadecimal.length - 1; i >= 2; i--) {
20 | const char = hexadecimal[i];
21 | // If not a number, access map for value
22 | // otherwise, use the char, because it is a number
23 | // then do the multiplication before concatenating
24 | count += (isNaN(+char) ? map[char] : char) * Math.pow(16, power++);
25 | }
26 | return count;
27 | }
28 |
29 | module.exports = hexadecimalToDecimal;
30 |
--------------------------------------------------------------------------------
/src/arrays/firstNonConsecutive/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Given an array of integers, return the first non-consecutive integer
3 | - a non-consecutive integer is one that is NOT exactly 1 larger
4 | than the previous number
5 | */
6 |
7 | const nums1 = [];
8 | const expected1 = null;
9 |
10 | const nums2 = [1, 2, 3, 4, 6, 7, 8];
11 | const expected2 = 6;
12 |
13 | const nums3 = [1, 4, 5, 6];
14 | const expected3 = 4;
15 |
16 | function firstNonConsecutive(nums) {
17 | for (let i = 1; i < nums.length; i++) {
18 | const prevNum = nums[i - 1];
19 | const currNum = nums[i];
20 |
21 | if (prevNum + 1 !== currNum) {
22 | return currNum;
23 | }
24 | }
25 | return null;
26 | }
27 |
28 | module.exports = { firstNonConsecutive };
29 |
--------------------------------------------------------------------------------
/src/objects/invertObj/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const obj1 = { name: "Zaphod", charm: "high", morals: "dicey" };
6 | const expected1 = { Zaphod: "name", high: "charm", dicey: "morals" };
7 |
8 | const testCases = [{ args: [obj1], expected: expected1 }];
9 |
10 | testCases.forEach(({ args, expected }, i) => {
11 | describe(`when given testCases[${i}]`, () => {
12 | it("should return an object that has the keys and values from the given object swapped so that the values are the keys.", () => {
13 | expect(testFn(...args)).toEqual(expected);
14 | });
15 | });
16 | });
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/src/recursion/binaryStringExpansion/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "1?0?";
6 | const expected1 = ["1000", "1001", "1100", "1101"];
7 | // output list order does not matter
8 |
9 | const testCases = [{ args: [str1], expected: expected1 }];
10 |
11 | testCases.forEach(({ args, expected }, i) => {
12 | describe(`when given testCases[${i}]`, () => {
13 | it("should return an array of string representing all variations of the given string's question marks replaced with either 0 or 1.", () => {
14 | expect(testFn(...args)).toEqual(jasmine.arrayContaining(expected));
15 | });
16 | });
17 | });
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/src/arrays/sumArrColumns/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arrA1 = [1, 2, 3];
6 | const arrB1 = [4, 5, 6];
7 | const expected1 = [5, 7, 9];
8 |
9 | const testCases = [
10 | {
11 | args: [arrA1, arrB1],
12 | expected: expected1,
13 | description: "a 3x3 matrix",
14 | },
15 | ];
16 |
17 | testCases.forEach(({ args, expected, description }) => {
18 | describe("when given " + description, () => {
19 | it("should return a new array that is the sum of the columns of the two given arrays.", () => {
20 | expect(testFn(...args)).toEqual(expected);
21 | });
22 | });
23 | });
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/src/amazon/shortestDeliveries/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const coordinates1 = [
6 | [-2, 5],
7 | [3, 4],
8 | [1, 0],
9 | ];
10 | const numDeliveries1 = 2;
11 | /*
12 | Explanation: [1, 0] is the shortest distance from [0, 0]
13 | and [3, 4] is the 2nd shortest.
14 | */
15 | const expected1 = [
16 | [1, 0],
17 | [3, 4],
18 | ];
19 |
20 | [[[coordinates1, numDeliveries1], expected1]].forEach(
21 | ([args, expected], i) => {
22 | describe(`when given testCases[${i}]`, () => {
23 | it("", () => {
24 | expect(testFn(...args)).toEqual(expected);
25 | });
26 | });
27 | }
28 | );
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/src/strings/decodeStr/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "a3b2c1d3";
6 | const expected1 = "aaabbcddd";
7 |
8 | const str2 = "a3b2c12d10";
9 | const expected2 = "aaabbccccccccccccdddddddddd";
10 |
11 | const testCases = [
12 | { arg: str1, expected: expected1 },
13 | { arg: str2, expected: expected2 },
14 | ];
15 |
16 | testCases.forEach(({ arg, expected }, i) => {
17 | describe(`when given "${arg}"`, () => {
18 | it("should return a decoded version of the given string such that each char is repeated based on the integer that follows.", () => {
19 | expect(testFn(arg)).toEqual(expected);
20 | });
21 | });
22 | });
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/src/strings/vowelsFirst/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "hello world";
6 | const expected1 = "eoohll wrld";
7 |
8 | const str2 = "More people have been to Hawaii than I have.";
9 | const expected2 = "oeeoeaeeeoaaiiaIaeMr ppl hv bn t Hw thn hv.";
10 |
11 | const testCases = [
12 | { arg: str1, expected: expected1 },
13 | { arg: str2, expected: expected2 },
14 | ];
15 |
16 | testCases.forEach(({ arg, expected }, i) => {
17 | describe(`when given testCases[${i}]`, () => {
18 | it("should move all the vowels of a string to the front.", () => {
19 | expect(testFn(arg)).toEqual(expected);
20 | });
21 | });
22 | });
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/src/recursion/sumToOneDigit/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const num1 = 5;
6 | const expected1 = 5;
7 |
8 | const num2 = 10;
9 | const expected2 = 1;
10 |
11 | const num3 = 25;
12 | const expected3 = 7;
13 |
14 | const testCases = [
15 | { arg: num1, expected: expected1 },
16 | { arg: num2, expected: expected2 },
17 | { arg: num3, expected: expected3 },
18 | ];
19 |
20 | testCases.forEach(({ arg, expected }, i) => {
21 | describe(`when given ${arg}`, () => {
22 | it("should sum the given int's digits until it becomes one digit and return that result.", () => {
23 | expect(testFn(arg)).toEqual(expected);
24 | });
25 | });
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/recursion/sumArr/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [1, 2, 3];
6 | const expected1 = 6;
7 |
8 | const nums2 = [1];
9 | const expected2 = 1;
10 |
11 | const nums3 = [];
12 | const expected3 = 0;
13 |
14 | const testCases = [
15 | { arg: nums1, expected: expected1 },
16 | { arg: nums2, expected: expected2 },
17 | { arg: nums3, expected: expected3 },
18 | ];
19 |
20 | testCases.forEach(({ arg, expected }, i) => {
21 | describe(`when given an array of ${arg.length} items`, () => {
22 | it("should return the sum of the given array using recursion.", () => {
23 | expect(testFn(arg)).toEqual(expected);
24 | });
25 | });
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/strings/capitalization/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const strings1 = ["hello", "world"];
6 | const expectedStrings1 = ["Hello", "World"];
7 |
8 | const testCases = [
9 | {
10 | arr: strings1,
11 | expected: expectedStrings1,
12 | },
13 | ];
14 |
15 | testCases.forEach(({ arr, expected }, i) => {
16 | describe(`when given testCases[${i}]`, () => {
17 | const actual = testFn(arr);
18 |
19 | it("should have capitalized the first letter of each word.", () => {
20 | expect(actual).toEqual(expected);
21 | });
22 |
23 | it("should have mutated the given array", () => {
24 | expect(arr).toBe(actual);
25 | });
26 | });
27 | });
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/src/recursion/recursiveSigma/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const num1 = 5;
6 | const expected1 = 15;
7 | // Explanation: (1+2+3+4+5)
8 |
9 | const num2 = 2.5;
10 | const expected2 = 3;
11 | // Explanation: (1+2)
12 |
13 | const num3 = -1;
14 | const expected3 = 0;
15 |
16 | const testCases = [
17 | { arg: num1, expected: expected1 },
18 | { arg: num2, expected: expected2 },
19 | { arg: num3, expected: expected3 },
20 | ];
21 |
22 | testCases.forEach(({ arg, expected }, i) => {
23 | describe(`when given ${arg}`, () => {
24 | it("should return the sum of 1 through the given int inclusive.", () => {
25 | expect(testFn(arg)).toEqual(expected);
26 | });
27 | });
28 | });
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/src/strings/getQuoteFromCaret/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = `wow "jabascript cool" lol "foo"`;
6 | const idx1 = 10;
7 | const expected1 = "jabascript cool";
8 |
9 | const str2 = `hello "world", good morning.`;
10 | const idx2 = 2;
11 | const expected2 = "";
12 |
13 | const testCases = [
14 | { args: [str1, idx1], expected: expected1 },
15 | { args: [str2, idx2], expected: expected2 },
16 | ];
17 |
18 | testCases.forEach(({ args, expected }, i) => {
19 | describe(`when given testCases[${i}]`, () => {
20 | it("return the string enclosed in double quotes that the caret idx is within.", () => {
21 | expect(testFn(...args)).toEqual(expected);
22 | });
23 | });
24 | });
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/src/strings/reverseWords/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "hello";
6 | const expected1 = "olleh";
7 |
8 | const str2 = "hello world";
9 | const expected2 = "olleh dlrow";
10 |
11 | const str3 = "abc def ghi";
12 | const expected3 = "cba fed ihg";
13 |
14 | const testCases = [
15 | { arg: str1, expected: expected1 },
16 | { arg: str2, expected: expected2 },
17 | { arg: str3, expected: expected3 },
18 | ];
19 |
20 | testCases.forEach(({ arg, expected }, i) => {
21 | describe(`when given "${arg}"`, () => {
22 | it("should reverse each word's characters in the given string of space separated words.", () => {
23 | expect(testFn(arg)).toEqual(expected);
24 | });
25 | });
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/recreated_methods/Array/concat/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arrA1 = ["a", "b"];
6 | const arrB1 = [1, 2, 3];
7 | const expected1 = ["a", "b", 1, 2, 3];
8 |
9 | const arrA2 = [1, 2, 3];
10 | const arrB2 = ["a", "b"];
11 | const expected2 = [1, 2, 3, "a", "b"];
12 |
13 | const testCases = [
14 | { args: [arrA1, arrB1], expected: expected1 },
15 | { args: [arrA2, arrB2], expected: expected2 },
16 | ];
17 |
18 | testCases.forEach(({ args, expected }, i) => {
19 | describe(`when given testCases[${i}]`, () => {
20 | it("should return a new array that has all the first given array's items and then the second given array's items.", () =>
21 | expect(testFn(...args)).toEqual(expected));
22 | });
23 | });
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "algorithms",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "npx jasmine",
8 | "prepare": "husky install",
9 | "pretty-quick": "pretty-quick --staged",
10 | "format": "prettier --write ."
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/TheCodingDojo/algorithms.git"
15 | },
16 | "author": {
17 | "name": "Neil Mosunic",
18 | "email": "neilm813@gmail.com",
19 | "url": "https://github.com/neilm813"
20 | },
21 | "license": "ISC",
22 | "bugs": {
23 | "url": "https://github.com/TheCodingDojo/algorithms/issues"
24 | },
25 | "homepage": "https://github.com/TheCodingDojo/algorithms#readme",
26 | "devDependencies": {
27 | "husky": "^6.0.0",
28 | "jasmine": "^3.5.0",
29 | "prettier": "^2.3.1",
30 | "pretty-quick": "^3.1.1"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/arrays/balanceIndex/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [-2, 5, 7, 0, 3];
6 | const expected1 = 2;
7 |
8 | const nums2 = [9, 9];
9 | const expected2 = -1;
10 |
11 | const testCases = [
12 | {
13 | args: [nums1],
14 | expected: expected1,
15 | description: "middle balanced array",
16 | },
17 | { args: [nums2], expected: expected2, description: "unbalanced array" },
18 | ];
19 |
20 | testCases.forEach(({ args, expected, description }) => {
21 | describe("when given " + description, () => {
22 | it("should return the index where the sum to the left and the right of the index are equal, or -1.", () => {
23 | expect(testFn(...args)).toEqual(expected);
24 | });
25 | });
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/recursion/factorial/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const num1 = 3;
6 | const expected1 = 6;
7 | // Explanation: 1*2*3 = 6
8 |
9 | const num2 = 6.8;
10 | const expected2 = 720;
11 | // Explanation: 1*2*3*4*5*6 = 720
12 |
13 | const num3 = 0;
14 | const expected3 = 1;
15 |
16 | const testCases = [
17 | { args: [num1], expected: expected1 },
18 | { args: [num2], expected: expected2 },
19 | { args: [num3], expected: expected3 },
20 | ];
21 |
22 | testCases.forEach(({ args, expected }, i) => {
23 | describe(`when given testCases[${i}]`, () => {
24 | it("should return the product of 1 through the given int inclusive.", () => {
25 | expect(testFn(...args)).toEqual(expected);
26 | });
27 | });
28 | });
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/src/strings/bracesValid/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "W(a{t}s[o(n{ c}o)m]e )h[e{r}e]!";
6 | const expected1 = true;
7 |
8 | const str2 = "D(i{a}l[ t]o)n{e";
9 | const expected2 = false;
10 |
11 | const str3 = "A(1)s[O (n]0{t) 0}k";
12 | const expected3 = false;
13 |
14 | const testCases = [
15 | { args: [str1], expected: expected1 },
16 | { args: [str2], expected: expected2 },
17 | { args: [str3], expected: expected3 },
18 | ];
19 |
20 | testCases.forEach(({ args, expected }, i) => {
21 | describe(`when given testCases[${i}]`, () => {
22 | it("should return whether or not the braces in the given string are valid.", () => {
23 | expect(testFn(...args)).toEqual(expected);
24 | });
25 | });
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/DOM/iterativelyRenderTree/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 | -
12 | A
13 |
14 | -
15 | B
16 |
19 |
20 | -
21 | C
22 |
25 |
26 | -
27 | D
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/strings/reverseString/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "creature";
6 | const expected1 = "erutaerc";
7 |
8 | const str2 = "dog";
9 | const expected2 = "god";
10 |
11 | const str3 = "hello";
12 | const expected3 = "olleh";
13 |
14 | const str4 = "";
15 | const expected4 = "";
16 |
17 | const testCases = [
18 | { arg: str1, expected: expected1 },
19 | { arg: str2, expected: expected2 },
20 | { arg: str3, expected: expected3 },
21 | { arg: str4, expected: expected4 },
22 | ];
23 |
24 | testCases.forEach(({ arg, expected }, i) => {
25 | describe(`when given "${arg}"`, () => {
26 | it("should return a string that is the reverse of the given string.", () => {
27 | expect(testFn(arg)).toEqual(expected);
28 | });
29 | });
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/strings/reverseWordOrder/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "This is a test";
6 | const expected1 = "test a is This";
7 |
8 | const str2 = "hello";
9 | const expected2 = "hello";
10 |
11 | const str3 = " This is a test ";
12 | const expected3 = "test a is This";
13 |
14 | const testCases = [
15 | { arg: str1, expected: expected1 },
16 | { arg: str2, expected: expected2 },
17 | { arg: str3, expected: expected3 },
18 | ];
19 |
20 | testCases.forEach(({ arg, expected }, i) => {
21 | describe(`when given "${arg}"`, () => {
22 | it("should return a string with the order of the space separated words reversed, but the words themselves should not be reversed.", () => {
23 | expect(testFn(arg)).toEqual(expected);
24 | });
25 | });
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/strings/bookIndex/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [1, 13, 14, 15, 37, 38, 70];
6 | const expected1 = "1, 13-15, 37-38, 70";
7 |
8 | const nums2 = [5, 6, 7, 8, 9];
9 | const expected2 = "5-9";
10 |
11 | const nums3 = [1, 2, 3, 7, 9, 15, 16, 17];
12 | const expected3 = "1-3, 7, 9, 15-17";
13 |
14 | const testCases = [
15 | { args: [nums1], expected: expected1 },
16 | { args: [nums2], expected: expected2 },
17 | { args: [nums3], expected: expected3 },
18 | ];
19 |
20 | testCases.forEach(({ args, expected }, i) => {
21 | describe(`when given testCases[${i}]`, () => {
22 | it("should return a string formatted as comma separated pages and page ranges when needed.", () => {
23 | expect(testFn(...args)).toEqual(expected);
24 | });
25 | });
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/strings/isPalindrome/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "a x a";
6 | const expected1 = true;
7 |
8 | const str2 = "racecar";
9 | const expected2 = true;
10 |
11 | const str3 = "Dud";
12 | const expected3 = false;
13 |
14 | const str4 = "oho!";
15 | const expected4 = false;
16 |
17 | const testCases = [
18 | { args: [str1], expected: expected1 },
19 | { args: [str2], expected: expected2 },
20 | { args: [str3], expected: expected3 },
21 | { args: [str4], expected: expected4 },
22 | ];
23 |
24 | testCases.forEach(({ args, expected }, i) => {
25 | describe(`when given testCases[${i}]`, () => {
26 | it("should return whether or not the given string is a palindrome.", () => {
27 | expect(testFn(...args)).toEqual(expected);
28 | });
29 | });
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/strings/caseInsensitiveStringCompare/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const strA1 = "ABC";
6 | const strB1 = "abc";
7 | const expected1 = true;
8 |
9 | const strA2 = "ABC";
10 | const strB2 = "abd";
11 | const expected2 = false;
12 |
13 | const strA3 = "ABC";
14 | const strB3 = "bc";
15 | const expected3 = false;
16 |
17 | const testCases = [
18 | { args: [strA1, strB1], expected: expected1 },
19 | { args: [strA2, strB2], expected: expected2 },
20 | { args: [strA3, strB3], expected: expected3 },
21 | ];
22 |
23 | testCases.forEach(({ args, expected }, i) => {
24 | describe(`when given testCases[${i}]`, () => {
25 | it("should return whether the strings are equal while ignoring case.", () => {
26 | expect(testFn(...args)).toEqual(expected);
27 | });
28 | });
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/src/strings/removeDupeWords/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const s1 = "";
6 | const expected1 = "";
7 |
8 | const s2 = "hi";
9 | const expected2 = "hi";
10 |
11 | const s3 = "hi hi hi";
12 | const expected3 = "hi";
13 |
14 | const s4 = "hello flat hello flat world";
15 | const expected4 = "hello flat world";
16 |
17 | const testCases = [
18 | { arg: s1, expected: expected1 },
19 | { arg: s2, expected: expected2 },
20 | { arg: s3, expected: expected3 },
21 | { arg: s4, expected: expected4 },
22 | ];
23 |
24 | testCases.forEach(({ arg, expected }, i) => {
25 | describe(`when given "${arg}"`, () => {
26 | it("should remove duplicate words from the given string and return the deduped string.", () => {
27 | expect(testFn(arg)).toEqual(expected);
28 | });
29 | });
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/strings/stringDedupe/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "abcABC";
6 | const expected1 = "abcABC";
7 |
8 | const str2 = "helloo";
9 | const expected2 = "helo";
10 |
11 | const str3 = "";
12 | const expected3 = "";
13 |
14 | const str4 = "aa";
15 | const expected4 = "a";
16 |
17 | const testCases = [
18 | { args: [str1], expected: expected1 },
19 | { args: [str2], expected: expected2 },
20 | { args: [str3], expected: expected3 },
21 | { args: [str4], expected: expected4 },
22 | ];
23 |
24 | testCases.forEach(({ args, expected }, i) => {
25 | describe(`when given testCases[${i}]`, () => {
26 | it("should return a string that is the given string with duplicate characters removed.", () => {
27 | expect(testFn(...args)).toEqual(expected);
28 | });
29 | });
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/recursion/removeConsecDupeWords/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const s1 = "";
6 | const expected1 = "";
7 |
8 | const s2 = "one two two three";
9 | const expected2 = "one two three";
10 |
11 | const s3 = "one one two";
12 | const expected3 = "one two";
13 |
14 | const s4 = "one one one two two two";
15 | const expected4 = "one two";
16 |
17 | const testCases = [
18 | { arg: s1, expected: expected1 },
19 | { arg: s2, expected: expected2 },
20 | { arg: s3, expected: expected3 },
21 | { arg: s4, expected: expected4 },
22 | ];
23 |
24 | testCases.forEach(({ arg, expected }, i) => {
25 | describe(`when given "${arg}"`, () => {
26 | it("should recursively remove consecutive dupe words from a string.", () => {
27 | expect(testFn(arg)).toEqual(expected);
28 | });
29 | });
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/strings/kaprekarsConstant/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const number1 = 3524;
6 | /*
7 | Explanation:
8 | 1. 5432 - 2345 = 3087
9 | 2. 8730 - 0378 = 8352
10 | 3. 8532 - 2358 = 6174
11 | */
12 | const expected1 = 3;
13 |
14 | const number2 = 2111;
15 | const expected2 = 5;
16 |
17 | const number3 = 9831;
18 | const expected3 = 7;
19 |
20 | const testCases = [
21 | { arg: number1, expected: expected1 },
22 | { arg: number2, expected: expected2 },
23 | { arg: number3, expected: expected3 },
24 | ];
25 |
26 | testCases.forEach(({ arg, expected }, i) => {
27 | describe(`when given ${arg}`, () => {
28 | it("The number of summing operations required to reach kaprekars constant (6174).", () => {
29 | expect(testFn(arg)).toEqual(expected);
30 | });
31 | });
32 | });
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/src/arrays/balancePoint/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [1, 2, 3, 4, 10];
6 | const expected1 = true;
7 | // Explanation: between indices 3 & 4
8 |
9 | const nums2 = [1, 2, 4, 2, 1];
10 | const expected2 = false;
11 |
12 | const testCases = [
13 | {
14 | args: [nums1],
15 | expected: expected1,
16 | description: "array where last number is the sum of the rest",
17 | },
18 | { args: [nums2], expected: expected2, description: "unbalanced array" },
19 | ];
20 |
21 | testCases.forEach(({ args, expected, description }) => {
22 | describe("when given " + description, () => {
23 | it("should return whether there exists a point between indexes where the sum to the left and the right are equal.", () => {
24 | expect(testFn(...args)).toEqual(expected);
25 | });
26 | });
27 | });
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/src/recursion/binarySearch/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [1, 3, 5, 6];
6 | const searchNum1 = 4;
7 | const expected1 = false;
8 |
9 | const nums2 = [4, 5, 6, 8, 12];
10 | const searchNum2 = 5;
11 | const expected2 = true;
12 |
13 | const nums3 = [3, 4, 6, 8, 12];
14 | const searchNum3 = 3;
15 | const expected3 = true;
16 |
17 | const testCases = [
18 | { args: [nums1, searchNum1], expected: expected1 },
19 | { args: [nums2, searchNum2], expected: expected2 },
20 | { args: [nums3, searchNum3], expected: expected3 },
21 | ];
22 |
23 | testCases.forEach(({ args, expected }, i) => {
24 | describe(`when given testCases[${i}]`, () => {
25 | it("should return whether or not the given array contains the given int.", () => {
26 | expect(testFn(...args)).toEqual(expected);
27 | });
28 | });
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/src/strings/encodeStr/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "aaaabbcddd";
6 | const expected1 = "a4b2c1d3";
7 |
8 | const str2 = "";
9 | const expected2 = "";
10 |
11 | const str3 = "a";
12 | const expected3 = "a";
13 |
14 | const str4 = "bbcc";
15 | const expected4 = "bbcc";
16 |
17 | const testCases = [
18 | { args: [str1], expected: expected1 },
19 | { args: [str2], expected: expected2 },
20 | { args: [str3], expected: expected3 },
21 | { args: [str4], expected: expected4 },
22 | ];
23 |
24 | testCases.forEach(({ args, expected }, i) => {
25 | describe(`when given testCases[${i}]`, () => {
26 | it("should return the given string encoded so that consecutively repeated chars are replaced with an int of its frequency.", () => {
27 | expect(testFn(...args)).toEqual(expected);
28 | });
29 | });
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/recursion/coronaVirusFloodFill/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const socialSpaceGrid = [
6 | ["Jon2", "Jane2", null, null],
7 | [null, "Jon1", "Jane1", null],
8 | ["Jane4", "patient zero", null, "Jon3"],
9 | ["Jon4", null, "Jane3", null],
10 | ];
11 | const patientZeroPoint = { x: 1, y: 2 };
12 | const expected = ["Jane4", "Jon4", "Jon1", "Jane1", "Jane2", "Jon2"];
13 | // order of output list does not matter
14 |
15 | const testCases = [
16 | { args: [socialSpaceGrid, patientZeroPoint], expected: expected },
17 | ];
18 |
19 | testCases.forEach(({ args, expected }, i) => {
20 | describe(`when given testCases[${i}]`, () => {
21 | it("should return an array of the names new corona virus cases based on flood fill from a starting point.", () => {
22 | expect(testFn(...args)).toEqual(expected);
23 | });
24 | });
25 | });
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/src/objects/fewestCoinChange/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const cents1 = 25;
6 | const expected1 = { quarter: 1 };
7 |
8 | const cents2 = 50;
9 | const expected2 = { quarter: 2 };
10 |
11 | const cents3 = 9;
12 | const expected3 = { nickel: 1, penny: 4 };
13 |
14 | const cents4 = 99;
15 | const expected4 = { quarter: 3, dime: 2, penny: 4 };
16 |
17 | const testCases = [
18 | { cents: cents1, expected: expected1 },
19 | { cents: cents2, expected: expected2 },
20 | { cents: cents3, expected: expected3 },
21 | { cents: cents4, expected: expected4 },
22 | ];
23 |
24 | testCases.forEach(({ cents, expected }, i) => {
25 | describe(`when given case ${cents} cents`, () => {
26 | it("should return an object detailing the fewest coins needed to get to the given cents.", () =>
27 | expect(testFn(cents)).toEqual(expected));
28 | });
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/src/strings/acronymize/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "abstraction polymorphism inheritance encapsulation";
6 | const expected1 = "APIE";
7 |
8 | const str2 = "object oriented programming";
9 | const expected2 = "OOP";
10 |
11 | const str3 = "software development life cycle";
12 | const expected3 = "SDLC";
13 |
14 | const str4 = " global information tracker ";
15 | const expected4 = "GIT";
16 |
17 | const testCases = [
18 | { arg: str1, expected: expected1 },
19 | { arg: str2, expected: expected2 },
20 | { arg: str3, expected: expected3 },
21 | { arg: str4, expected: expected4 },
22 | ];
23 |
24 | testCases.forEach(({ arg, expected }, i) => {
25 | describe(`when given testCases[${i}]`, () => {
26 | it("should return the acronym version of the given string.", () => {
27 | expect(testFn(arg)).toEqual(expected);
28 | });
29 | });
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/strings/questionMarks/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "aa6?9";
6 | const expected1 = false;
7 |
8 | const str2 = "acc?7??sss?3rr1??????5";
9 | const expected2 = true;
10 |
11 | const str3 = "?3?d?dad?7??????3";
12 | const expected3 = true;
13 |
14 | const str4 = "7??????3";
15 | // Explanation: too many question marks.
16 | const expected4 = false;
17 |
18 | const testCases = [
19 | { arg: str1, expected: expected1 },
20 | { arg: str2, expected: expected2 },
21 | { arg: str3, expected: expected3 },
22 | { arg: str4, expected: expected4 },
23 | ];
24 |
25 | testCases.forEach(({ arg, expected }, i) => {
26 | describe(`when given "${arg}"`, () => {
27 | it("should return whether or not the given string contains exactly 3 questions marks between every two ints that sum to 10.", () => {
28 | expect(testFn(arg)).toEqual(expected);
29 | });
30 | });
31 | });
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/src/objects/zipArraysIntoMap/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const keys1 = ["abc", 3, "yo"];
6 | const vals1 = [42, "wassup", true];
7 | const expected1 = {
8 | abc: 42,
9 | 3: "wassup",
10 | yo: true,
11 | };
12 |
13 | const keys2 = [];
14 | const vals2 = [];
15 | const expected2 = {};
16 |
17 | const testCases = [
18 | {
19 | args: [keys1, vals1],
20 | expected: expected1,
21 | description: "3 key value pairs",
22 | },
23 | {
24 | args: [keys2, vals2],
25 | expected: expected2,
26 | description: "an empty array for both keys and values",
27 | },
28 | ];
29 |
30 | testCases.forEach(({ args, expected }, i) => {
31 | describe(`when given testCases[${i}]`, () => {
32 | it("should return an object that has the keys and values from the two given arrays.", () =>
33 | expect(testFn(...args)).toEqual(expected));
34 | });
35 | });
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/src/sorts/radixSort/index.js:
--------------------------------------------------------------------------------
1 | // setup
2 | function getPosition(num, place) {
3 | return Math.floor(Math.abs(num) / Math.pow(10, place)) % 10;
4 | }
5 |
6 | // get num with most digits
7 | function getMax(arr) {
8 | let max = 0;
9 | for (let num of arr) {
10 | if (max < num.toString().length) {
11 | max = num.toString().length;
12 | }
13 | }
14 | return max;
15 | }
16 |
17 | // setup
18 | function radixSort(arr) {
19 | const max = getMax(arr); // length of the max digit in the array
20 |
21 | for (let i = 0; i < max; i++) {
22 | let buckets = Array.from({ length: 10 }, () => []);
23 | }
24 | return arr;
25 | }
26 |
27 | function radixSort(arr) {
28 | const max = getMax(arr); // length of the max digit in the array
29 |
30 | for (let i = 0; i < max; i++) {
31 | let buckets = Array.from({ length: 10 }, () => []);
32 | for (let j = 0; j < arr.length; j++) {
33 | buckets[getPosition(arr[j], i)].push(arr[j]); // pushing into buckets
34 | }
35 | arr = [].concat(...buckets);
36 | }
37 | return arr;
38 | }
39 |
40 | module.exports = {
41 | radixSort,
42 | };
43 |
--------------------------------------------------------------------------------
/src/strings/addHonorific/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const honorific1 = "Mr.";
6 | const names1 = [];
7 | const expected1 = [];
8 |
9 | const honorific2 = "Sir";
10 | const names2 = ["Sanchez, Rick", "Smith, Jerry"];
11 | const expected2 = ["Sir Rick Sanchez", "Sir Jerry Smith"];
12 |
13 | const honorific3 = "Mrs.";
14 | const names3 = ["HorseDoctor, Beth"];
15 | const expected3 = ["Mrs. Beth HorseDoctor"];
16 |
17 | const testCases = [
18 | { args: [honorific1, names1], expected: expected1 },
19 | { args: [honorific2, names2], expected: expected2 },
20 | { args: [honorific3, names3], expected: expected3 },
21 | ];
22 |
23 | testCases.forEach(({ args, expected }, i) => {
24 | describe(`when given testCases[${i}]`, () => {
25 | it("should return an array of the given names in the format of: Honorific FirstName LastName.", () => {
26 | expect(testFn(...args)).toEqual(expected);
27 | });
28 | });
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/src/strings/isAnagram/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const strA1 = "yes";
6 | const strB1 = "eys";
7 | const expected1 = true;
8 |
9 | const strA2 = "yes";
10 | const strB2 = "eYs";
11 | const expected2 = true;
12 |
13 | const strA3 = "no";
14 | const strB3 = "noo";
15 | const expected3 = false;
16 |
17 | const strA4 = "silent";
18 | const strB4 = "listen";
19 | const expected4 = true;
20 |
21 | const testCases = [
22 | { args: [strA1, strB1], expected: expected1 },
23 | { args: [strA2, strB2], expected: expected2 },
24 | { args: [strA3, strB3], expected: expected3 },
25 | { args: [strA4, strB4], expected: expected4 },
26 | ];
27 |
28 | testCases.forEach(({ args, expected }, i) => {
29 | describe(`when given testCases[${i}]`, () => {
30 | it("should return whether or not the 1st given string is an anagram of the 2nd.", () => {
31 | expect(testFn(...args)).toEqual(expected);
32 | });
33 | });
34 | });
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/src/misc/clockHandAngles/index.js:
--------------------------------------------------------------------------------
1 | // For input of 3600 secs (equivalent to 1:00:00), print "Hour hand: 30 degs. Minute hand: 0 degs. Second hand: 0 degs."
2 | clockHandAngles(3600);
3 |
4 | // For an input parameter seconds of 119730 (which is equivalent to 9:15:30 plus 24 hours!), you should log "Hour hand: 277.745 degs. Minute hand: 93 degs. Second hand: 180 degs." Note: in the second example, the angle for the minute hand is not simply 90 degrees; it has advanced a bit further, because of the additional 30 seconds in that minute so far.
5 |
6 | // "Hour hand: 277.745 degs. Minute hand: 93 degs. Second hand: 180 degs."
7 | clockHandAngles(119730);
8 |
9 | function clockHandAngles(sec) {
10 | var h = 0.0;
11 | var m = 0.0;
12 | while (sec >= 3600) {
13 | if (h >= 24) {
14 | h = 0;
15 | }
16 | h++;
17 | sec -= 3600;
18 | }
19 | while (sec >= 60) {
20 | if (m >= 60) {
21 | m = 0;
22 | }
23 | m++;
24 | sec -= 60;
25 | }
26 |
27 | sd = sec * 6;
28 | md = m * 6 + sec / 10;
29 | hd = h * 30 + md / 12;
30 |
31 | return `Hour hand: ${hd} degrees, minute hand: ${md} degrees, second hand: ${sd} degrees.`;
32 | }
33 |
--------------------------------------------------------------------------------
/src/arrays/countEvenNegatives/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [1, 5, -1, 2, -4, 9, -10, 0, -3, -2];
6 | const expected1 = 3;
7 |
8 | const nums2 = [];
9 | const expected2 = 0;
10 |
11 | const nums3 = [-4, -2, -6];
12 | const expected3 = 3;
13 |
14 | const testCases = [
15 | {
16 | args: [nums1],
17 | expected: expected1,
18 | description: "an unordered mixture",
19 | },
20 | {
21 | args: [nums2],
22 | expected: expected2,
23 | description: "an empty array",
24 | },
25 | {
26 | args: [nums3],
27 | expected: expected3,
28 | description: "all negative evens",
29 | },
30 | ];
31 |
32 | testCases.forEach(({ args, expected, description }) => {
33 | describe("when given " + description, () => {
34 | it("should return a count of how many numbers are both negative and even.", () => {
35 | expect(testFn(...args)).toEqual(expected);
36 | });
37 | });
38 | });
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/src/recursion/fibonacci/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const num1 = 0;
6 | const expected1 = 0;
7 |
8 | const num2 = 1;
9 | const expected2 = 1;
10 |
11 | const num3 = 2;
12 | const expected3 = 1;
13 |
14 | const num4 = 3;
15 | const expected4 = 2;
16 |
17 | const num5 = 4;
18 | const expected5 = 3;
19 |
20 | const num6 = 8;
21 | const expected6 = 21;
22 |
23 | const testCases = [
24 | { arg: num1, expected: expected1 },
25 | { arg: num2, expected: expected2 },
26 | { arg: num3, expected: expected3 },
27 | { arg: num4, expected: expected4 },
28 | { arg: num5, expected: expected5 },
29 | { arg: num6, expected: expected6 },
30 | ];
31 |
32 | testCases.forEach(({ arg, expected }, i) => {
33 | describe(`when given ${arg}`, () => {
34 | it("should return the number from the fibonacci sequence at the given ints position (nth fibonacci num).", () => {
35 | expect(testFn(arg)).toEqual(expected);
36 | });
37 | });
38 | });
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/src/strings/removeDupeWords/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Given in an interview.
3 |
4 | Given a string of words
5 | return a string with the duplicate words removed
6 |
7 | no built in methods
8 | */
9 |
10 | const s1 = "";
11 | const expected1 = "";
12 |
13 | const s2 = "hi";
14 | const expected2 = "hi";
15 |
16 | const s3 = "hi hi hi";
17 | const expected3 = "hi";
18 |
19 | const s4 = "hello flat hello flat world";
20 | const expected4 = "hello flat world";
21 |
22 | function removeDupeWords(str) {}
23 |
24 | /*****************************************************************************/
25 |
26 | function removeDupeWords(str) {
27 | let deduped = "";
28 | const seen = {};
29 | let word = "";
30 |
31 | for (let i = 0; i < str.length; i++) {
32 | if (str[i] !== " ") {
33 | word += str[i];
34 | }
35 |
36 | if ((str[i] === " " || i === str.length - 1) && word.length > 0) {
37 | if (!seen.hasOwnProperty(word)) {
38 | deduped.length !== 0 && (deduped += " ");
39 | deduped += word;
40 | seen[word] = true;
41 | }
42 | word = "";
43 | }
44 | }
45 | return deduped;
46 | }
47 |
48 | module.exports = { removeDupeWords };
49 |
--------------------------------------------------------------------------------
/src/arrays/minToFront/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [1, 5, 2, 9];
6 | const expected1 = [1, 5, 2, 9];
7 |
8 | const nums2 = [5, 1, 0, 2, 3, 0];
9 | const expected2 = [0, 5, 1, 2, 3, 0];
10 |
11 | const testCases = [
12 | {
13 | args: [nums1],
14 | expected: expected1,
15 | description: "the minimum at the front",
16 | },
17 | {
18 | args: [nums2],
19 | expected: expected2,
20 | description: "the minimum near the front and at the end",
21 | },
22 | ];
23 |
24 | testCases.forEach(({ args, expected, description }) => {
25 | describe("when given " + description, () => {
26 | const ret = testFn(...args);
27 |
28 | it("should move the min value in the given array to the front and return the given array.", () => {
29 | expect(ret).toEqual(expected);
30 | });
31 |
32 | it("should return the given array, not a new array.", () => {
33 | expect(ret).toBe(args[0]);
34 | });
35 | });
36 | });
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/src/data_structures/Graphs/travelingSalesman/travelingSalesman.md:
--------------------------------------------------------------------------------
1 | # Traveling Salesman
2 |
3 | ## Overview
4 |
5 | Given a list of cities and the distances between each pair of cities, what is
6 | the shortest possible route that visits each city exactly once and returns to
7 | the origin city?
8 |
9 | ### In Technical Terms
10 |
11 | Given a complete graph with weighted edges (as an adjacency matrix) what is the
12 | Hamiltonian cycle (path that visits every node once) of minimum cost?
13 |
14 | ### Time Complexity
15 |
16 | - Brute Force - O(n!) - Factorial, checks every possible path.
17 | - Dynamic Programming: O(n^2 \* 2^n)
18 |
19 | | n | n! | n^2 \* 2^n |
20 | | --- | --------------- | ---------- |
21 | | 1 | 1 | 2 |
22 | | 2 | 2 | 16 |
23 | | 3 | 6 | 72 |
24 | | 4 | 24 | 256 |
25 | | 5 | 120 | 800 |
26 | | 6 | 720 | 2304 |
27 | | ... | ... | ... |
28 | | 15 | 1307674368000 | 7372800 |
29 | | 16 | 20922789888000 | 16777216 |
30 | | 17 | 355687428096000 | 37879808 |
31 |
32 | ### Dynamic Programming Approach
33 |
--------------------------------------------------------------------------------
/src/recursion/sumArr/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Recursively sum an arr of ints
3 | */
4 |
5 | const nums1 = [1, 2, 3];
6 | const expected1 = 6;
7 |
8 | const nums2 = [1];
9 | const expected2 = 1;
10 |
11 | const nums3 = [];
12 | const expected3 = 0;
13 |
14 | /**
15 | * Add params if needed for recursion
16 | * Recursively sums the given array.
17 | * - Time: O(?).
18 | * - Space: O(?).
19 | * @param {Array} nums
20 | * @returns {number} The sum of the given nums.
21 | */
22 | function sumArr(nums) {}
23 |
24 | /*****************************************************************************/
25 |
26 | /**
27 | * Recursively sums the given array.
28 | * - Time: O(n) linear.
29 | * - Space: O(n) linear due to the call stack.
30 | * @param {Array} nums
31 | * @returns {number} The sum of the given nums.
32 | */
33 | function sumArr(nums = [], i = 0) {
34 | if (i === nums.length) {
35 | return 0;
36 | }
37 | return nums[i] + sumArr(nums, i + 1);
38 | }
39 |
40 | function sumArr2(nums = [], sum = 0, i = 0) {
41 | if (i === nums.length) {
42 | return sum;
43 | }
44 | return sumArr2(nums, sum + nums[i], i + 1);
45 | }
46 |
47 | module.exports = { sumArr, sumArr2 };
48 |
--------------------------------------------------------------------------------
/src/arrays/firstNonConsecutive/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [];
6 | const expected1 = null;
7 |
8 | const nums2 = [1, 2, 3, 4, 6, 7, 8];
9 | const expected2 = 6;
10 |
11 | const nums3 = [1, 4, 5, 6];
12 | const expected3 = 4;
13 |
14 | const testCases = [
15 | {
16 | args: [nums1],
17 | expected: expected1,
18 | description: "an empty array",
19 | },
20 | {
21 | args: [nums2],
22 | expected: expected2,
23 | description: "a non consecutive number near the middle",
24 | },
25 | {
26 | args: [nums3],
27 | expected: expected3,
28 | description: "a non consecutive number near the start",
29 | },
30 | ];
31 |
32 | testCases.forEach(({ args, expected, description }) => {
33 | describe("when given " + description, () => {
34 | it("should return the first number that is not exactly 1 larger than the previous.", () => {
35 | expect(testFn(...args)).toEqual(expected);
36 | });
37 | });
38 | });
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/src/arrays/reverseArr/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arr1 = [1, 2, 3];
6 | const expected1 = [3, 2, 1];
7 |
8 | const arr2 = ["a", "b"];
9 | const expected2 = ["b", "a"];
10 |
11 | const arr3 = ["a"];
12 | const expected3 = ["a"];
13 |
14 | const arr4 = [];
15 | const expected4 = [];
16 |
17 | const testCases = [
18 | { inputArr: arr1, expected: expected1 },
19 | { inputArr: arr2, expected: expected2 },
20 | { inputArr: arr3, expected: expected3 },
21 | { inputArr: arr4, expected: expected4 },
22 | ];
23 |
24 | testCases.forEach(({ inputArr, expected, description }) => {
25 | describe("when given " + description, () => {
26 | const outputArr = testFn(inputArr);
27 |
28 | it("should reverse the given array in place and return the given array.", () => {
29 | expect(outputArr).toEqual(expected);
30 | });
31 |
32 | it("should return the same array, not a new array.", () => {
33 | expect(inputArr).toBe(outputArr);
34 | });
35 | });
36 | });
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/src/sorts/radixSort/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const numsOrdered = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
6 | const numsRandomOrder = [9, 2, 5, 6, 4, 3, 7, 10, 1, 8];
7 | const numsReversed = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
8 | const expected = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
9 |
10 | const testCases = [
11 | {
12 | arg: numsOrdered,
13 | expected: expected,
14 | description: "an already sorted array",
15 | },
16 | {
17 | arg: numsRandomOrder,
18 | expected: expected,
19 | description: "a randomly ordered array",
20 | },
21 | {
22 | arg: numsReversed,
23 | expected: expected,
24 | description: "a reverse-ordered array",
25 | },
26 | ];
27 |
28 | testCases.forEach(({ arg, expected, description }, i) => {
29 | describe(`when given ${description}`, () => {
30 | const actual = testFn(arg);
31 |
32 | it("should return a sorted array.", () => {
33 | expect(actual).toEqual(expected);
34 | });
35 | });
36 | });
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/src/arrays/findTriplets/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [0, -1, 2, -3, 1];
6 | const expected1 = true;
7 |
8 | const nums2 = [3, 1, 2, 6, 4];
9 | const expected2 = false;
10 |
11 | const nums3 = [5, -1, 3, 2, -4, 1, 6];
12 | const expected3 = true;
13 |
14 | const testCases = [
15 | {
16 | args: [nums1],
17 | expected: expected1,
18 | description: "a mix of positives, negatives, and zero",
19 | },
20 | {
21 | args: [nums2],
22 | expected: expected2,
23 | description: "all positive numbers",
24 | },
25 | {
26 | args: [nums3],
27 | expected: expected3,
28 | description: "a mix of positive and negative numbers",
29 | },
30 | ];
31 |
32 | testCases.forEach(({ args, expected, description }) => {
33 | describe("when given " + description, () => {
34 | it("should return whether or not there are 3 ints that add up to 0.", () => {
35 | expect(testFn(...args)).toEqual(expected);
36 | });
37 | });
38 | });
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/src/strings/longestPalindromicSubstring/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "what up, daddy-o?";
6 | const expected1 = "dad";
7 |
8 | const str2 = "uh, not much";
9 | const expected2 = "u";
10 |
11 | const str3 = "Yikes! my favorite racecar erupted!";
12 | const expected3 = "e racecar e";
13 |
14 | const str4 = "a1001x20002y5677765z";
15 | const expected4 = "5677765";
16 |
17 | const str5 = "a1001x20002y567765z";
18 | const expected5 = "567765";
19 |
20 | const testCases = [
21 | { args: [str1], expected: expected1 },
22 | { args: [str2], expected: expected2 },
23 | { args: [str3], expected: expected3 },
24 | { args: [str4], expected: expected4 },
25 | { args: [str5], expected: expected5 },
26 | ];
27 |
28 | testCases.forEach(({ args, expected }, i) => {
29 | describe(`when given testCases[${i}]`, () => {
30 | it("should return the longest palindrome contained within the given string.", () => {
31 | expect(testFn(...args)).toEqual(expected);
32 | });
33 | });
34 | });
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/src/strings/palindromeFromSubstr/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This helper function avoids having to visit the chars multiple times to both
3 | * check if it is a palindrome and to then slice to get the palindrome.
4 | * - Time: O(n) linear. n = right - left which could be the full string.
5 | * - Space: O(n) linear.
6 | * @param {string} str
7 | * @param {number} left The left idx to start at inclusive.
8 | * @param {number} right The left idx to end at exclusive.
9 | * @returns {string} The palindrome or an empty string.
10 | */
11 | function getPalindrome(str, left = 0, right = str.length) {
12 | let leftStr = "";
13 | let rightStr = "";
14 | const len = right - left;
15 | const half = Math.floor(len / 2);
16 | let leftIdx = left - 1;
17 |
18 | for (let i = 0; i < half; i++) {
19 | leftIdx += 1;
20 | const rightIdx = right - 1 - i;
21 |
22 | if (str[leftIdx] !== str[rightIdx]) {
23 | return "";
24 | }
25 |
26 | leftStr += str[leftIdx];
27 | rightStr = str[rightIdx] + rightStr;
28 | }
29 |
30 | // For odd palindromes we need to save middle letter since loop skips it.
31 | if (len % 2 !== 0) {
32 | leftStr += str[leftIdx + 1];
33 | }
34 |
35 | return leftStr + rightStr;
36 | }
37 |
--------------------------------------------------------------------------------
/src/arrays/flatten2dArray/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const twoDimArr1 = [
6 | [1, 2, 3],
7 | [4, 5, 6],
8 | [7, 8, 9],
9 | ];
10 | const expected1 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
11 |
12 | const twoDimArr2 = [[1], [2], [3]];
13 | const expected2 = [1, 2, 3];
14 |
15 | const twoDimArr3 = [[], [], [10, 20]];
16 | const expected3 = [10, 20];
17 |
18 | const testCases = [
19 | { args: [twoDimArr1], expected: expected1, description: "a 3x3 matrix" },
20 | { args: [twoDimArr2], expected: expected2, description: "a 1x3 matrix" },
21 | {
22 | args: [twoDimArr3],
23 | expected: expected3,
24 | description: "a mixed length matrix with some empty nested arrays",
25 | },
26 | ];
27 |
28 | testCases.forEach(({ args, expected, description }) => {
29 | describe("when given " + description, () => {
30 | it("should flatten the given 2d array into a 1d array and preserver the order of the items.", () => {
31 | expect(testFn(...args)).toEqual(expected);
32 | });
33 | });
34 | });
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/src/recursion/lowestCommonMult/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const num1A = 1;
6 | const num1B = 1;
7 | const expected1 = 1;
8 |
9 | const num2A = 5;
10 | const num2B = 10;
11 | const expected2 = 10;
12 |
13 | const num3A = 10;
14 | const num3B = 5;
15 | const expected3 = 10;
16 |
17 | const num4A = 6;
18 | const num4B = 8;
19 | const expected4 = 24;
20 |
21 | const num5A = 15;
22 | const num5B = 25;
23 | const expected5 = 75;
24 |
25 | const testCases = [
26 | { args: [num1A, num1B], expected: expected1 },
27 | { args: [num2A, num2B], expected: expected2 },
28 | { args: [num3A, num3B], expected: expected3 },
29 | { args: [num4A, num4B], expected: expected4 },
30 | { args: [num5A, num5B], expected: expected5 },
31 | ];
32 |
33 | testCases.forEach(({ args: [a, b], expected }, i) => {
34 | describe(`when given (${(a, b)})`, () => {
35 | it("should return the lowest common multiple of the two given ints.", () => {
36 | expect(testFn(a, b)).toEqual(expected);
37 | });
38 | });
39 | });
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/src/strings/parensValid/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "Y(3(p)p(3)r)s";
6 | const expected1 = true;
7 |
8 | const str2 = "N(0(p)3";
9 | const expected2 = false;
10 | // Explanation: not every parenthesis is closed.
11 |
12 | const str3 = "N(0)t ) 0(k";
13 | const expected3 = false;
14 | // Explanation: because the underlined ")" is premature: there is nothing open for it to close.
15 |
16 | const str4 = "a(b))(c";
17 | const expected4 = false;
18 | // Explanation: same number of opens and closes but the 2nd closing closes nothing
19 |
20 | const testCases = [
21 | { args: [str1], expected: expected1 },
22 | { args: [str2], expected: expected2 },
23 | { args: [str3], expected: expected3 },
24 | { args: [str4], expected: expected4 },
25 | ];
26 |
27 | testCases.forEach(({ args, expected }, i) => {
28 | describe(`when given testCases[${i}]`, () => {
29 | it("should return whether or not the parenthesis in the given string are valid.", () => {
30 | expect(testFn(...args)).toEqual(expected);
31 | });
32 | });
33 | });
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/src/strings/isRotation/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const strA1 = "ABCD";
6 | const strB1 = "CDAB";
7 | // Explanation: if you start from A in the 2nd string, the letters are in the same order, just rotated
8 | const expected1 = true;
9 |
10 | const strA2 = "ABCD";
11 | const strB2 = "CDBA";
12 | // Explanation: all same letters in 2nd string, but out of order
13 | const expected2 = false;
14 |
15 | const strA3 = "ABCD";
16 | const strB3 = "BCDAB";
17 | // Explanation: same letters in correct order but there is an extra letter.
18 | const expected3 = false;
19 |
20 | const testCases = [
21 | { args: [strA1, strB1], expected: expected1 },
22 | { args: [strA2, strB2], expected: expected2 },
23 | { args: [strA3, strB3], expected: expected3 },
24 | ];
25 |
26 | testCases.forEach(({ args, expected }, i) => {
27 | describe(`when given testCases[${i}]`, () => {
28 | it("should return whether or not the 1st given string is a rotation of the 2nd given string.", () => {
29 | expect(testFn(...args)).toEqual(expected);
30 | });
31 | });
32 | });
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/src/design/Observable/index.js:
--------------------------------------------------------------------------------
1 | class Observable {
2 | constructor(functionThatTakesObserver) {
3 | this._functionThatTakesObserver = functionThatTakesObserver;
4 | }
5 |
6 | subscribe(observer) {
7 | return this._functionThatTakesObserver(observer);
8 | }
9 | }
10 |
11 | const testObservable = new Observable((observer) => {
12 | observer.next("data 1");
13 | observer.next("data 2");
14 |
15 | setInterval(() => {
16 | if (Math.random() < 0.5) {
17 | observer.next("async data refreshed");
18 | } else {
19 | observer.error("error getting data");
20 | }
21 | observer.complete();
22 | }, 5000);
23 | });
24 |
25 | const observer1 = {
26 | next(data) {
27 | console.log("\nobserver1️⃣ ", data);
28 | },
29 | error(e) {
30 | console.log("\nobserver1️⃣ ", e);
31 | },
32 | complete() {
33 | console.log(`observer1️⃣ complete\n${"-".repeat(20)}`);
34 | },
35 | };
36 |
37 | const observer2 = {
38 | next(data) {
39 | console.log("\nobserver2️⃣ ", data);
40 | },
41 | error(e) {
42 | console.log("\nobserver2️⃣ ", e);
43 | },
44 | complete() {
45 | console.log(`observer2️⃣ complete\n${"~".repeat(20)}`);
46 | },
47 | };
48 |
49 | testObservable.subscribe(observer1);
50 | testObservable.subscribe(observer2);
51 |
--------------------------------------------------------------------------------
/src/strings/rotateStr/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str = "Hello World";
6 |
7 | const rotateAmnt1 = 0;
8 | const expected1 = "Hello World";
9 |
10 | const rotateAmnt2 = 1;
11 | const expected2 = "dHello Worl";
12 |
13 | const rotateAmnt3 = 2;
14 | const expected3 = "ldHello Wor";
15 |
16 | const rotateAmnt4 = 4;
17 | const expected4 = "orldHello W";
18 |
19 | const rotateAmnt5 = 13;
20 | const expected5 = "ldHello Wor";
21 |
22 | const testCases = [
23 | { args: [str, rotateAmnt1], expected: expected1 },
24 | { args: [str, rotateAmnt2], expected: expected2 },
25 | { args: [str, rotateAmnt3], expected: expected3 },
26 | { args: [str, rotateAmnt4], expected: expected4 },
27 | { args: [str, rotateAmnt5], expected: expected5 },
28 | ];
29 |
30 | testCases.forEach(({ args, expected }, i) => {
31 | describe(`when given testCases[${i}]`, () => {
32 | it("should return a string that is the given string with chars rotated to the right by the given int amount.", () => {
33 | expect(testFn(...args)).toEqual(expected);
34 | });
35 | });
36 | });
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/src/strings/vowelsFirst/index.js:
--------------------------------------------------------------------------------
1 | // given a string, return a new string that has all the vowels of the given string first
2 |
3 | /**
4 | * Moves all the vowels of a string to the front.
5 | * - Time: O(?).
6 | * - Space: O(?).
7 | * @param {string} str
8 | * @returns {string}
9 | */
10 | function vowelsFirst(str) {}
11 |
12 | /*****************************************************************************/
13 |
14 | /**
15 | * Moves all the vowels of a string to the front.
16 | * - Time: O(n) linear.
17 | * - Space: O(n) linear, as n (length of str) grows we store that much more
18 | * memory in the vars.
19 | * @param {string} str
20 | * @returns {string}
21 | */
22 | function vowelsFirst(str) {
23 | let vowelsStr = "";
24 | let consonantsStr = "";
25 |
26 | for (let i = 0; i < str.length; i++) {
27 | const char = str[i];
28 | const lowerCaseChar = char.toLocaleLowerCase();
29 |
30 | if (
31 | lowerCaseChar === "a" ||
32 | lowerCaseChar === "e" ||
33 | lowerCaseChar === "i" ||
34 | lowerCaseChar === "o" ||
35 | lowerCaseChar === "u"
36 | ) {
37 | vowelsStr += char;
38 | } else {
39 | consonantsStr += char;
40 | }
41 | }
42 | return vowelsStr + consonantsStr;
43 | }
44 |
45 | module.exports = { vowelsFirst };
46 |
--------------------------------------------------------------------------------
/src/arrays/allNonConsecutive/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [1, 2, 3, 4, 6, 7, 8, 10];
6 | const expected1 = [
7 | { i: 4, n: 6 },
8 | { i: 7, n: 10 },
9 | ];
10 |
11 | const nums2 = [];
12 | const expected2 = [];
13 |
14 | const nums3 = [1, 3, 7, 9];
15 | const expected3 = [
16 | { i: 1, n: 3 },
17 | { i: 2, n: 7 },
18 | { i: 3, n: 9 },
19 | ];
20 |
21 | const testCases = [
22 | {
23 | args: [nums1],
24 | expected: expected1,
25 | description: "non-consecutive one through ten",
26 | },
27 | {
28 | args: [nums2],
29 | expected: expected2,
30 | description: "an empty array",
31 | },
32 | {
33 | args: [nums3],
34 | expected: expected3,
35 | description: "all odds",
36 | },
37 | ];
38 |
39 | testCases.forEach(({ args, expected, description }) => {
40 | describe("when given " + description, () => {
41 | it("should return all the non consecutive ints in the given sorted array of ints.", () =>
42 | expect(testFn(...args)).toEqual(expected));
43 | });
44 | });
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/src/arrays/tacoTruck/index.js:
--------------------------------------------------------------------------------
1 | // https://login.codingdojo.com/m/667/15334/111786
2 |
3 | function distanceBetweenTwoPoints(pointA, pointB) {
4 | const firstDistance = Math.abs(pointA[0] - pointB[0]);
5 | const secondDistance = Math.abs(pointA[1] - pointB[1]);
6 | return firstDistance + secondDistance;
7 | }
8 |
9 | /**
10 | *
11 | */
12 | function findOptimalTruckLocation(customerLocations = []) {
13 | let shortestAverageDistance = 0;
14 | let locationWithShortestAverageDistance = null;
15 |
16 | // For each point
17 | for (let i = 0; i < customerLocations.length; i++) {
18 | let totalDistance = 0;
19 |
20 | // Find it's distance to every other point
21 | for (let j = 0; j < arr.length; j++) {
22 | if (i === j) {
23 | continue;
24 | }
25 |
26 | totalDistance += distanceBetweenTwoPoints(
27 | customerLocations[i],
28 | customerLocations[j]
29 | );
30 | }
31 |
32 | // To get an average distance
33 | let averageDistance = totalDistance / (customerLocations.length - 1);
34 |
35 | if (averageDistance < shortestAverageDistance) {
36 | shortestAverageDistance = averageDistance;
37 | locationWithShortestAverageDistance = customerLocations[i];
38 | }
39 |
40 | console.log(averageDistance);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/recursion/inOrderSubsets/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | String: In-Order Subsets
3 |
4 | Create strSubsets(str). Return an array with every possible in-order
5 | character subset of str. The resultant array itself need not be in any
6 | specific order – it is the subset of letters in each string that must be in
7 | the same order as they were in the original string.
8 |
9 | Input: "abc" ,
10 | Output: return an array that includes ["", "c", "b", "bc", "a", "ac", "ab", "abc"] (in any order).
11 | */
12 |
13 | const string1 = "abc";
14 | // In any order:
15 | const expected1 = ["", "c", "b", "bc", "a", "ac", "ab", "abc"];
16 |
17 | /**
18 | * Generates an array with every possible in-order character subset of the
19 | * given string.
20 | * Add additional params for recursion as needed.
21 | * @param {string} str
22 | */
23 | function inOrderSubsets(str) {}
24 |
25 | /*****************************************************************************/
26 |
27 | function inOrderSubsets(str, solutions = [], partial = "") {
28 | solutions.push(partial);
29 |
30 | for (let i = 0; i < str.length; i++) {
31 | const sliced = str.slice(i + 1);
32 | inOrderSubsets(sliced, solutions, partial + str[i]);
33 | }
34 |
35 | return solutions;
36 | }
37 |
38 | module.exports = {
39 | inOrderSubsets,
40 | };
41 |
--------------------------------------------------------------------------------
/src/arrays/binarySearch/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [1, 3, 5, 6];
6 | const searchNum1 = 4;
7 | const expected1 = false;
8 |
9 | const nums2 = [4, 5, 6, 8, 12];
10 | const searchNum2 = 5;
11 | const expected2 = true;
12 |
13 | const nums3 = [3, 4, 6, 8, 12];
14 | const searchNum3 = 3;
15 | const expected3 = true;
16 |
17 | const testCases = [
18 | {
19 | args: [nums1, searchNum1],
20 | expected: expected1,
21 | description: "small array with no match",
22 | },
23 | {
24 | args: [nums2, searchNum2],
25 | expected: expected2,
26 | description: "small array second index match.",
27 | },
28 | {
29 | args: [nums3, searchNum3],
30 | expected: expected3,
31 | description: "small array first index match",
32 | },
33 | ];
34 |
35 | testCases.forEach(({ args, expected, description }) => {
36 | describe("when given " + description, () => {
37 | it("should return whether the search number exists in the array.", () => {
38 | expect(testFn(...args)).toEqual(expected);
39 | });
40 | });
41 | });
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/src/arrays/dedupeSorted/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [1, 1, 1, 1];
6 | const expected1 = [1];
7 |
8 | const nums2 = [1, 1, 2, 2, 3, 3];
9 | const expected2 = [1, 2, 3];
10 |
11 | const nums3 = [1, 1, 2, 3, 3, 4];
12 | const expected3 = [1, 2, 3, 4];
13 |
14 | const nums4 = [1, 1];
15 | const expected4 = [1];
16 |
17 | const testCases = [
18 | { args: [nums1], expected: expected1, description: "four ones" },
19 | {
20 | args: [nums2],
21 | expected: expected2,
22 | description: "1-3 with two of each",
23 | },
24 | {
25 | args: [nums3],
26 | expected: expected3,
27 | description: "1-4 with some dupes",
28 | },
29 | {
30 | args: [nums4],
31 | expected: expected4,
32 | description: "two of the same number",
33 | },
34 | ];
35 |
36 | testCases.forEach(({ args, expected, description }) => {
37 | describe("when given " + description, () => {
38 | it("should return an array with duplicate values removed.", () => {
39 | expect(testFn(...args)).toEqual(expected);
40 | });
41 | });
42 | });
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/src/design/BufferSequence/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | From Microsoft interview March 2021
3 |
4 | Make a Buffer that receives an int and prints the value, but only if the given
5 | value is in sequence with the previous given int. If it isn’t, then wait until
6 | the buffer receives the missing values before printing the rest of the
7 | sequence.
8 |
9 | Create a class
10 | */
11 |
12 | class BufferSequence {
13 | constructor() {
14 | this.lastPrintedNum = null;
15 | this.storage = {};
16 | }
17 |
18 | print(num) {
19 | this.lastPrintedNum = num;
20 | console.log(num);
21 | }
22 |
23 | handler(num) {
24 | this.storage[num] = num;
25 |
26 | if (this.lastPrintedNum === null) {
27 | this.print(num);
28 | return;
29 | }
30 |
31 | if (num === this.lastPrintedNum + 1) {
32 | while (this.storage.hasOwnProperty(this.lastPrintedNum + 1)) {
33 | this.print(this.lastPrintedNum + 1);
34 | }
35 | }
36 | }
37 | }
38 |
39 | const buffer = new BufferSequence();
40 |
41 | /* Uncomment one line at a time to test. */
42 | buffer.handler(5); // prints 5
43 | // buffer.handler(6); // prints 6
44 | // buffer.handler(10); // no print
45 | // buffer.handler(9); // no print
46 | // buffer.handler(7); // prints 7
47 | // buffer.handler(8); // prints 8, 9, 10 on new lines.
48 |
--------------------------------------------------------------------------------
/src/strings/backspaceStringCompare/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const S1 = "ab#c";
6 | const T1 = "ad#c";
7 | const expected1 = true;
8 | // Explanation: Both S and T become "ac"
9 |
10 | const S2 = "ab##";
11 | const T2 = "c#d#";
12 | const expected2 = true;
13 | // Explanation: Both S and T become ""
14 |
15 | const S3 = "a##c";
16 | const T3 = "#a#c";
17 | const expected3 = true;
18 | // Explanation: Both S and T become "c"
19 |
20 | const S4 = "a#c";
21 | const T4 = "b";
22 | const expected4 = false;
23 | // Explanation: S becomes "c" while T becomes "b".
24 |
25 | const testCases = [
26 | { args: [S1, T1], expected: expected1 },
27 | { args: [S2, T2], expected: expected2 },
28 | { args: [S3, T3], expected: expected3 },
29 | { args: [S4, T4], expected: expected4 },
30 | ];
31 |
32 | testCases.forEach(({ args, expected }, i) => {
33 | describe(`when given testCases[${i}]`, () => {
34 | it("should return whether or not the strings are equal after processing the backspaces.", () => {
35 | expect(testFn(...args)).toEqual(expected);
36 | });
37 | });
38 | });
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/src/strings/lengthOfLongestSubstring/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "abcabcbb";
6 | const expected1 = 3;
7 | // Explanation: The answer is "abc", with the length of 3.
8 |
9 | const str2 = "bbbbb";
10 | const expected2 = 1;
11 | // Explanation: The answer is "b", with the length of 1.
12 |
13 | const str3 = "pwwkew";
14 | const expected3 = 3;
15 | /* Explanation: The answer is "wke", with the length of 3.
16 | Note that the answer must be a substring, "pwke" is a subsequence and not a substring. */
17 |
18 | const str4 = "dvadf";
19 | const expected4 = 4;
20 | // Explanation: "vadf"
21 |
22 | const testCases = [
23 | { arg: str1, expected: expected1 },
24 | { arg: str2, expected: expected2 },
25 | { arg: str3, expected: expected3 },
26 | { arg: str4, expected: expected4 },
27 | ];
28 |
29 | testCases.forEach(({ arg, expected }, i) => {
30 | describe(`when given "${arg}"`, () => {
31 | it("should return the length of the longest substring (without dupes) from the given string.", () => {
32 | expect(testFn(arg)).toEqual(expected);
33 | });
34 | });
35 | });
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/src/design/BehaviorSubject/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | BehaviorSubject is a design pattern for keeping track of a value that changes
3 | over time where multiple different parts of your app need to know when the
4 | value changes because they need to perform some task when that happens.
5 |
6 | As an analogy, think of multiple researches that are all studying the same
7 | behavior subject (say an animal) to try to understand it's behavior, but each
8 | researcher is studying the behavior for different reasons. That means each
9 | researcher needs to be alerted when the behavior changes so they can study
10 | respond to that behavior event by studying it in their specific way.
11 | */
12 |
13 | class BehaviorSubject {
14 | constructor(startVal) {
15 | this.value = startVal;
16 | this.subscribers = [];
17 | }
18 |
19 | subscribe(callback) {
20 | this.subscribers.push(callback);
21 | this.emit();
22 | }
23 |
24 | emit() {
25 | for (let i = 0; i < this.subscribers.length; i++) {
26 | this.subscribers[i](this.value);
27 | }
28 | }
29 |
30 | getValue() {
31 | return this.value;
32 | }
33 |
34 | /**
35 | * Updates the value and notifies all subscribers.
36 | * @param {any} value The new value.
37 | */
38 | next(value) {
39 | this.value = value;
40 | this.emit();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/recursion/greatestCommonFactor/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const a1 = 5;
6 | const b1 = 5;
7 | const expected1 = 5;
8 |
9 | const a2 = 6;
10 | const b2 = 20;
11 | const expected2 = 2;
12 |
13 | const a3 = 54;
14 | const b3 = 12;
15 | const expected3 = 6;
16 |
17 | const a4 = 12;
18 | const b4 = 54;
19 | const expected4 = 6;
20 |
21 | const a5 = 65;
22 | const b5 = 25;
23 | const expected5 = 5;
24 |
25 | const a6 = 123456;
26 | const b6 = 987654;
27 | const expected6 = 6;
28 |
29 | const testCases = [
30 | { args: [a1, b1], expected: expected1 },
31 | { args: [a2, b2], expected: expected2 },
32 | { args: [a3, b3], expected: expected3 },
33 | { args: [a4, b4], expected: expected4 },
34 | { args: [a5, b5], expected: expected5 },
35 | // { args: [a6, b6], expected: expected6 },
36 | ];
37 |
38 | testCases.forEach(({ args: [a, b], expected }, i) => {
39 | describe(`when given (${a}, ${b})`, () => {
40 | it("should return the greatest common factor of the two given numbers.", () => {
41 | expect(testFn(a, b)).toEqual(expected);
42 | });
43 | });
44 | });
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/src/strings/canBuildS1FromS2/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const strA1 = "Hello World";
6 | const strB1 = "lloeh wordl";
7 | const expected1 = true;
8 |
9 | const strA2 = "Hey";
10 | const strB2 = "hello";
11 | const expected2 = false;
12 | // Explanation: second string is missing a "y"
13 |
14 | const strA3 = "hello";
15 | const strB3 = "helo";
16 | const expected3 = false;
17 | // Explanation: second string doesn't have enough "l" letters
18 |
19 | const strA4 = "hello";
20 | const strB4 = "lllheo";
21 | const expected4 = true;
22 |
23 | const testCases = [
24 | { args: [strA1, strB1], expected: expected1 },
25 | { args: [strA2, strB2], expected: expected2 },
26 | { args: [strA3, strB3], expected: expected3 },
27 | { args: [strA4, strB4], expected: expected4 },
28 | ];
29 |
30 | testCases.forEach(({ args, expected }, i) => {
31 | describe(`when given testCases[${i}]`, () => {
32 | it("should return whether or not the first given string can be built using the characters from the second given string.", () => {
33 | expect(testFn(...args)).toEqual(expected);
34 | });
35 | });
36 | });
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/src/sorts/bubbleSort/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const numsOrdered = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
6 | const numsRandomOrder = [9, 2, 5, 6, 4, 3, 7, 10, 1, 8];
7 | const numsReversed = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
8 | const expected = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
9 |
10 | const testCases = [
11 | {
12 | arg: numsOrdered,
13 | expected: expected,
14 | description: "an already sorted array",
15 | },
16 | {
17 | arg: numsRandomOrder,
18 | expected: expected,
19 | description: "a randomly ordered array",
20 | },
21 | {
22 | arg: numsReversed,
23 | expected: expected,
24 | description: "a reverse-ordered array",
25 | },
26 | ];
27 |
28 | testCases.forEach(({ arg, expected, description }, i) => {
29 | describe(`when given ${description}`, () => {
30 | const actual = testFn(arg);
31 |
32 | it("should return a sorted array.", () => {
33 | expect(actual).toEqual(expected);
34 | });
35 |
36 | it("should have returned the same array after mutating it.", () => {
37 | expect(actual).toBe(arg);
38 | });
39 | });
40 | });
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/src/sorts/quickSort/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const numsOrdered = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
6 | const numsRandomOrder = [9, 2, 5, 6, 4, 3, 7, 10, 1, 8];
7 | const numsReversed = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
8 | const expected = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
9 |
10 | const testCases = [
11 | {
12 | arg: numsOrdered,
13 | expected: expected,
14 | description: "an already sorted array",
15 | },
16 | {
17 | arg: numsRandomOrder,
18 | expected: expected,
19 | description: "a randomly ordered array",
20 | },
21 | {
22 | arg: numsReversed,
23 | expected: expected,
24 | description: "a reverse-ordered array",
25 | },
26 | ];
27 |
28 | testCases.forEach(({ arg, expected, description }, i) => {
29 | describe(`when given ${description}`, () => {
30 | const actual = testFn(arg);
31 |
32 | it("should return a sorted array.", () => {
33 | expect(actual).toEqual(expected);
34 | });
35 |
36 | it("should have returned the same array after mutating it.", () => {
37 | expect(actual).toBe(arg);
38 | });
39 | });
40 | });
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/src/strings/canStringBecomePalindrome/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1 = "";
6 | const expected1 = false;
7 |
8 | const str2 = "a";
9 | const expected2 = true;
10 |
11 | const str3 = "ddaa";
12 | const expected3 = true;
13 | // Explanation: "daad" or "adda"
14 |
15 | const str4 = "dda";
16 | const expected4 = true;
17 | // Explanation: "dad"
18 |
19 | const str5 = "aaadd";
20 | const expected5 = true;
21 | // Explanation: "daaad"
22 |
23 | const str6 = "abc";
24 | const expected6 = false;
25 |
26 | const testCases = [
27 | { args: [str1], expected: expected1 },
28 | { args: [str2], expected: expected2 },
29 | { args: [str3], expected: expected3 },
30 | { args: [str4], expected: expected4 },
31 | { args: [str5], expected: expected5 },
32 | { args: [str6], expected: expected6 },
33 | ];
34 |
35 | testCases.forEach(({ args, expected }, i) => {
36 | describe(`when given testCases[${i}]`, () => {
37 | it("should return whether or not the given string could be rearranged into a palindrome.", () => {
38 | expect(testFn(...args)).toEqual(expected);
39 | });
40 | });
41 | });
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/src/sorts/insertionSort/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const numsOrdered = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
6 | const numsRandomOrder = [9, 2, 5, 6, 4, 3, 7, 10, 1, 8];
7 | const numsReversed = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
8 | const expected = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
9 |
10 | const testCases = [
11 | {
12 | arg: numsOrdered,
13 | expected: expected,
14 | description: "an already sorted array",
15 | },
16 | {
17 | arg: numsRandomOrder,
18 | expected: expected,
19 | description: "a randomly ordered array",
20 | },
21 | {
22 | arg: numsReversed,
23 | expected: expected,
24 | description: "a reverse-ordered array",
25 | },
26 | ];
27 |
28 | testCases.forEach(({ arg, expected, description }, i) => {
29 | describe(`when given ${description}`, () => {
30 | const actual = testFn(arg);
31 |
32 | it("should return a sorted array.", () => {
33 | expect(actual).toEqual(expected);
34 | });
35 |
36 | it("should have returned the same array after mutating it.", () => {
37 | expect(actual).toBe(arg);
38 | });
39 | });
40 | });
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/src/sorts/selectionSort/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const numsOrdered = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
6 | const numsRandomOrder = [9, 2, 5, 6, 4, 3, 7, 10, 1, 8];
7 | const numsReversed = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
8 | const expected = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
9 |
10 | const testCases = [
11 | {
12 | arg: numsOrdered,
13 | expected: expected,
14 | description: "an already sorted array",
15 | },
16 | {
17 | arg: numsRandomOrder,
18 | expected: expected,
19 | description: "a randomly ordered array",
20 | },
21 | {
22 | arg: numsReversed,
23 | expected: expected,
24 | description: "a reverse-ordered array",
25 | },
26 | ];
27 |
28 | testCases.forEach(({ arg, expected, description }, i) => {
29 | describe(`when given ${description}`, () => {
30 | const actual = testFn(arg);
31 |
32 | it("should return a sorted array.", () => {
33 | expect(actual).toEqual(expected);
34 | });
35 |
36 | it("should have returned the same array after mutating it.", () => {
37 | expect(actual).toBe(arg);
38 | });
39 | });
40 | });
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/src/objects/insert/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const table1 = "users";
6 | const insertData1 = { first_name: "John", last_name: "Doe" };
7 | const expected1 =
8 | "INSERT INTO users (first_name, last_name) VALUES ('John', 'Doe');";
9 |
10 | // Bonus:
11 | const insertData2 = {
12 | first_name: "John",
13 | last_name: "Doe",
14 | age: 30,
15 | is_admin: false,
16 | };
17 | const expected2 =
18 | "INSERT INTO users (first_name, last_name, age, is_admin) VALUES ('John', 'Doe', 30, false);";
19 | // Explanation: no quotes areount the int or the bool, technically in SQL the bool would become a 0 or 1, but don't worry about that here.
20 |
21 | const testCases = [
22 | { args: [table1, insertData1], expected: expected1 },
23 | { args: [table1, insertData2], expected: expected2, type: "bonus" },
24 | ];
25 |
26 | testCases.forEach(({ args, expected }, i) => {
27 | describe(`when given testCases[${i}]`, () => {
28 | it("should return a SQL insert command as a string where the given objects key value pairs are the columns and values.", () => {
29 | expect(testFn(...args)).toEqual(expected);
30 | });
31 | });
32 | });
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/src/arrays/diagonalDifference/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const squareMatrix1 = [
6 | [1, 2, 3],
7 | [4, 5, 6],
8 | [9, 8, 9],
9 | ];
10 | const expected1 = 2;
11 | /*
12 | left to right diagonal: 1 + 5 + 9 = 15
13 | right to left diagonal: 3 + 5 + 9 = 17
14 | absolute difference = 2
15 | */
16 |
17 | const squareMatrix2 = [
18 | [1, 2, 3, 4, 5],
19 | [1, 2, 3, 4, 5],
20 | [1, 2, 3, 4, 5],
21 | [1, 2, 3, 4, 5],
22 | [1, 2, 3, 4, 5],
23 | ];
24 | const expected2 = 0;
25 |
26 | const testCases = [
27 | {
28 | args: [squareMatrix1],
29 | expected: expected1,
30 | description: "a 3x3 matrix",
31 | },
32 | {
33 | args: [squareMatrix2],
34 | expected: expected2,
35 | description: "a 5x5 matrix with equal diagonals",
36 | },
37 | ];
38 |
39 | testCases.forEach(({ args, expected, description }) => {
40 | describe("when given " + description, () => {
41 | it("should return the absolute difference between the sums of the diagonals of a given square matrix.", () => {
42 | expect(testFn(...args)).toEqual(expected);
43 | });
44 | });
45 | });
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/src/strings/outputToJson/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Alumni interview question in 2021.
3 |
4 | Given the output text from an executable file, convert it into JSON.
5 |
6 | The result should be a JSON array of two objects.
7 | */
8 |
9 | const fs = require("fs");
10 |
11 | // Open VSCode to the folder this file is in for it to find the output.txt
12 | function outputToJson(filePath = "./output.txt") {
13 | try {
14 | const jsonStr = fs
15 | .readFileSync(filePath, "utf-8")
16 | .split("\n")
17 | .reduce((str, row, i, arr) => {
18 | if (i === arr.length - 1) {
19 | return str + "}]";
20 | }
21 |
22 | // end of object
23 | if (row == "\r") {
24 | return str + "},{";
25 | }
26 |
27 | // Comma before new KVP unless it's the first KVP.
28 | str[str.length - 1] !== "{" && (str += ",");
29 |
30 | let [key, val] = row.split(":");
31 | const trimmedVal = val.trim();
32 | val =
33 | trimmedVal !== "true" && trimmedVal !== "false" && isNaN(+trimmedVal)
34 | ? `"${trimmedVal}"`
35 | : trimmedVal;
36 |
37 | return str + `"${key.trim()}": ${val}`;
38 | }, "[{");
39 | return JSON.parse(jsonStr);
40 | } catch (error) {
41 | console.log(error);
42 | return [];
43 | }
44 | }
45 |
46 | module.exports = { outputToJson };
47 |
--------------------------------------------------------------------------------
/src/sorts/mergeSort/index.spec.js:
--------------------------------------------------------------------------------
1 | const { mergeSort } = require(".");
2 |
3 | describe(mergeSort.name, () => {
4 | const numsOrdered = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
5 | const numsRandomOrder = [9, 2, 5, 6, 4, 3, 7, 10, 1, 8];
6 | const numsReversed = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
7 | const expected = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
8 |
9 | const testCases = [
10 | {
11 | arg: numsOrdered,
12 | expected: expected,
13 | description: "an already sorted array",
14 | },
15 | {
16 | arg: numsRandomOrder,
17 | expected: expected,
18 | description: "a randomly ordered array",
19 | },
20 | {
21 | arg: numsReversed,
22 | expected: expected,
23 | description: "a reverse-ordered array",
24 | },
25 | ];
26 |
27 | testCases.forEach(({ arg, expected, description }, i) => {
28 | describe(`when given ${description}`, () => {
29 | const arrCopy = [...arg];
30 | const actual = mergeSort(arg);
31 |
32 | it("should return a sorted array.", () => {
33 | expect(actual).toEqual(expected);
34 | });
35 |
36 | it("should have returned a new array.", () => {
37 | expect(actual).not.toBe(arg);
38 | });
39 |
40 | it("should not have mutated the given array.", () => {
41 | expect(arrCopy).toEqual(arg);
42 | });
43 | });
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/src/recreated_methods/Array/unshift/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arr1 = [1, 2, 3];
6 | const newItem1 = 0;
7 | const expected1 = 4;
8 | // after function is called, arr1 should be:
9 | const expectedArr1 = [0, 1, 2, 3];
10 |
11 | const arr2 = [];
12 | const newItem2 = "a";
13 | const expected2 = 1;
14 | // after function is called, arr2 should be:
15 | const expectedArr2 = ["a"];
16 |
17 | const testCases = [
18 | {
19 | args: [arr1, newItem1],
20 | expectedRet: expected1,
21 | expectedArr: expectedArr1,
22 | },
23 | {
24 | args: [arr2, newItem2],
25 | expectedRet: expected2,
26 | expectedArr: expectedArr2,
27 | },
28 | ];
29 |
30 | testCases.forEach(
31 | ({ args: [inputArr, newItem], expectedRet, expectedArr }, i) => {
32 | describe(`when given testCases[${i}]`, () => {
33 | it(`should return the new length after adding the new item.`, () => {
34 | expect(testFn(inputArr, newItem)).toBe(expectedRet);
35 | });
36 |
37 | it("should added the new item to the given array.", () => {
38 | expect(inputArr).toEqual(expectedArr);
39 | });
40 | });
41 | }
42 | );
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/src/strings/largestCommonSubstring/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const str1A = "aaa";
6 | const str1B = "aa";
7 | const expected1 = "aa";
8 |
9 | const str2A = "aaba";
10 | const str2B = "aa";
11 | const expected2 = "aa";
12 |
13 | const str3A = "aeff";
14 | const str3B = "abcdef";
15 | // Expected chars can be in any order.
16 | const expected3 = "aef";
17 |
18 | const str4A = "z this hurts my head x";
19 | const str4B = "my head, this hurts";
20 | // Expected chars can be in any order.
21 | const expected4 = "this hurts my head";
22 |
23 | const testCases = [
24 | { args: [str1A, str1B], expected: expected1 },
25 | { args: [str2A, str2B], expected: expected2 },
26 | { args: [str3A, str3B], expected: expected3 },
27 | { args: [str4A, str4B], expected: expected4 },
28 | ];
29 |
30 | testCases.forEach(({ args, expected }, i) => {
31 | describe(`when given testCases[${i}]`, () => {
32 | it("finds the longest longest string that can be built from characters that both of the given strings share.", () => {
33 | expect(testFn(...args).split("")).toEqual(
34 | jasmine.arrayContaining(expected.split(""))
35 | );
36 | });
37 | });
38 | });
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # README
2 |
3 | ## CURRENT STUDENT WARNING
4 |
5 | - If you get in the habit of looking up answers before putting in a real effort to solve them yourself, you are setting yourself up for failure in interviews.
6 |
7 | ## Internal Links
8 |
9 | - [Algo Schedules](/schedules)
10 | - [Lecture Outlines](https://github.com/TheCodingDojo/lecture-outlines)
11 |
12 | ## Student Resources
13 |
14 | - [RIOTWalk Interview Method](./RIOTWalk-interview-method.md)
15 | - [Interviewing Notes](https://docs.google.com/document/d/1jG6C70MRBqH_yP-GKfT2TVZ9tZeHPoRpPCbqkzXuAqE/edit#)
16 | - [Big O Notation Cheat Sheet](https://cooervo.github.io/Algorithms-DataStructures-BigONotation/big-O-notation.html)
17 | - [neetcode - interview algos with solution videos](https://neetcode.io/)
18 | - [Tech Interview Handbook](https://techinterviewhandbook.org/introduction/)
19 | - [Extra Student Resources - Shared Drive Folder](https://drive.google.com/drive/folders/11zE6KbvIdgr6_KtYGtMRNMja6Q41IAuo?usp=sharing)
20 |
21 | ## Clone Instructions & Source Control
22 |
23 | - `git clone https://github.com/TheCodingDojo/algorithms.git`
24 | - `cd algorithms`
25 | - `npm i` to install dependencies.
26 | - `git pull` whenever you want to check for new changes.
27 | - To avoid merge conflicts if you want to take your own notes or add your own solutions, create a new file for whatever algo you are working on.
28 | - [jasmine notes](jasmine.md)
29 |
--------------------------------------------------------------------------------
/src/strings/trim/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Given a string that may have extra spaces at the start and the end,
3 | return a new string that has the extra spaces at the start and the end trimmed (removed)
4 | do not remove any other spaces.
5 | */
6 |
7 | const str1 = " hello world ";
8 | const expected1 = "hello world";
9 |
10 | /**
11 | * Trims any leading or trailing white space from the given str.
12 | * - Time: O(?).
13 | * - Space: O(?).
14 | * @param {string} str
15 | * @returns {string} The given string with any leading or trailing white space
16 | * stripped.
17 | */
18 | function trim(str) {}
19 |
20 | /*****************************************************************************/
21 |
22 | /**
23 | * - Time: O(n) linear, both while loops plus the .slice loop all add up to
24 | * str.length.
25 | * - Space: O(n) linear, .slice creates a new string, at most it will be as
26 | * long as input str.
27 | * @param {string} str
28 | * @returns {string}
29 | */
30 | function trim(str = "") {
31 | let startIdx = 0;
32 | let endIdx = str.length - 1;
33 |
34 | // loose comparison to false works for spaces
35 | // and other space-like characters (tabs, etc.)
36 | while (str[startIdx] == false) {
37 | startIdx++;
38 | }
39 |
40 | while (str[endIdx] == false) {
41 | endIdx--;
42 | }
43 |
44 | return str.slice(startIdx, endIdx + 1);
45 | }
46 |
47 | module.exports = { trim };
48 |
--------------------------------------------------------------------------------
/src/arrays/concatSelf/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arr1 = ["a", "b", "c"];
6 | const expected1 = ["a", "b", "c", "a", "b", "c"];
7 |
8 | const arr2 = ["a"];
9 | const expected2 = ["a", "a"];
10 |
11 | const arr3 = [];
12 | const expected3 = [];
13 |
14 | const testCases = [
15 | { args: [arr1], expected: expected1, description: "three items" },
16 | { args: [arr2], expected: expected2, description: "one item" },
17 | { args: [arr3], expected: expected3, description: "empty array" },
18 | ];
19 |
20 | testCases.forEach(({ args, expected, description }) => {
21 | describe("when given " + description, () => {
22 | const inputArr = args[0];
23 | const inputArrCopy = [...inputArr];
24 | const outputArr = testFn(...args);
25 |
26 | it("should return a new array that contains all the given arrays items, and then all the same items repeated at the end.", () => {
27 | expect(outputArr).toEqual(expected);
28 | });
29 |
30 | it("should have returned a new array, not the given array.", () => {
31 | expect(outputArr).not.toBe(inputArr);
32 | });
33 |
34 | it("should not have mutated the given array.", () => {
35 | expect(inputArr).toEqual(inputArrCopy);
36 | });
37 | });
38 | });
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/src/recreated_methods/Array/push/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arr1 = ["a", "b", "c"];
6 | const newItem1 = "d";
7 | const expected1 = 4;
8 | // what arr1 should be after running push function
9 | const expectedArr1 = ["a", "b", "c", "d"];
10 |
11 | const arr2 = [];
12 | const newItem2 = "a";
13 | const expected2 = 1;
14 | const expectedArr2 = ["a"];
15 |
16 | const testCases = [
17 | {
18 | args: [arr1, newItem1],
19 | expectedRet: expected1,
20 | expectedArr: expectedArr1,
21 | description: "a non empty array",
22 | },
23 | {
24 | args: [arr2, newItem2],
25 | expectedRet: expected2,
26 | expectedArr: expectedArr2,
27 | description: "an empty array",
28 | },
29 | ];
30 |
31 | testCases.forEach(
32 | ({ args: [arr, newItem], expectedRet, expectedArr }, i) => {
33 | describe(`when given testCases[${i}]`, () => {
34 | it("should return the new length after pushing the new item to the back of the array.", () => {
35 | expect(testFn(arr, newItem)).toBe(expectedRet);
36 | });
37 |
38 | it("should have added the new item to the back of the array.", () => {
39 | expect(arr).toEqual(expectedArr);
40 | });
41 | });
42 | }
43 | );
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/src/arrays/indexOfMinVal/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [5, 2, 3];
6 | const expected1 = 1;
7 |
8 | const nums2 = [5, 2, 2, 3];
9 | const expected2 = 1;
10 |
11 | const nums3 = [];
12 | const expected3 = -1;
13 |
14 | const nums4 = [5, 15, 11, 20];
15 | const expected4 = 0;
16 |
17 | const nums5 = [15, 11, 20, 5];
18 | const expected5 = 3;
19 |
20 | const testCases = [
21 | {
22 | args: [nums1],
23 | expected: expected1,
24 | description: "a small array with the min centered",
25 | },
26 | {
27 | args: [nums2],
28 | expected: expected2,
29 | description: "a small array with the minimum duplicated",
30 | },
31 | { args: [nums3], expected: expected3, description: "an empty array" },
32 | {
33 | args: [nums4],
34 | expected: expected4,
35 | description: "the min at the front",
36 | },
37 | { args: [nums5], expected: expected5, description: "the min at the end" },
38 | ];
39 |
40 | testCases.forEach(({ args, expected, description }) => {
41 | describe("when given " + description, () => {
42 | it("should return the index of the minimum value from the given array.", () => {
43 | expect(testFn(...args)).toEqual(expected);
44 | });
45 | });
46 | });
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/src/objects/findObjects/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const items1 = [
6 | { firstName: "Bob", lastName: "Bobbert", age: 31 },
7 | { firstName: "John", lastName: "Smith", age: 25 },
8 | { firstName: "Bob", lastName: "Smith", age: 27 },
9 | { firstName: "Bob", lastName: "White", age: 31 },
10 | ];
11 |
12 | const searchCriteria1 = {
13 | firstName: "Bob",
14 | age: 31,
15 | };
16 | const expected1 = [
17 | { firstName: "Bob", lastName: "Bobbert", age: 31 },
18 | { firstName: "Bob", lastName: "White", age: 31 },
19 | ];
20 |
21 | const searchCriteria2 = {
22 | lastName: "Smith",
23 | };
24 | const expected2 = [
25 | { firstName: "John", lastName: "Smith", age: 25 },
26 | { firstName: "Bob", lastName: "Smith", age: 27 },
27 | ];
28 |
29 | const testCases = [
30 | { args: [searchCriteria1, items1], expected: expected1 },
31 | { args: [searchCriteria2, items1], expected: expected2 },
32 | ];
33 |
34 | testCases.forEach(({ args, expected }, i) => {
35 | describe(`when given testCases[${i}]`, () => {
36 | it("should return an array of the objects from the given array that match the key value pairs of the given object.", () => {
37 | expect(testFn(...args)).toEqual(expected);
38 | });
39 | });
40 | });
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/src/arrays/firstNonRepeated/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [3, 5, 4, 3, 4, 6, 5];
6 | const expected1 = 6;
7 |
8 | const nums2 = [3, 5, 5];
9 | const expected2 = 3;
10 |
11 | const nums3 = [3, 3, 5];
12 | const expected3 = 5;
13 |
14 | const nums4 = [5];
15 | const expected4 = 5;
16 |
17 | const nums5 = [];
18 | const expected5 = null;
19 |
20 | const testCases = [
21 | {
22 | args: [nums1],
23 | expected: expected1,
24 | description: "first unique near the end",
25 | },
26 | {
27 | args: [nums2],
28 | expected: expected2,
29 | description: "first unique at the start",
30 | },
31 | {
32 | args: [nums3],
33 | expected: expected3,
34 | description: "first unique at the end",
35 | },
36 | { args: [nums4], expected: expected4, description: "one number only" },
37 | { args: [nums5], expected: expected5, description: "an empty array" },
38 | ];
39 |
40 | testCases.forEach(({ args, expected, description }) => {
41 | describe("when given " + description, () => {
42 | it("should return the integer that appears earliest that has no duplicate anywhere else in the array.", () => {
43 | expect(testFn(...args)).toEqual(expected);
44 | });
45 | });
46 | });
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/src/recreated_methods/Object/entries/index.test.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const obj1 = {
6 | name: "Pizza",
7 | calories: 9001,
8 | };
9 |
10 | const expected1 = [
11 | ["name", "Pizza"],
12 | ["calories", 9001],
13 | ];
14 |
15 | const proto = {
16 | inheritance: "inherited key",
17 | keyOnProto: "val from proto",
18 | };
19 |
20 | // This object contains inherited key value pairs from the above proto obj.
21 | const obj2 = Object.assign(Object.create(proto), {
22 | firstName: "Foo",
23 | lastName: "Bar",
24 | age: 13,
25 | });
26 |
27 | const expected2 = [
28 | ["firstName", "Foo"],
29 | ["lastName", "Bar"],
30 | ["age", 13],
31 | ];
32 |
33 | const testCases = [
34 | {
35 | args: [obj1],
36 | expected: expected1,
37 | description: "an object with no inherited keys",
38 | },
39 | {
40 | args: [obj2],
41 | expected: expected2,
42 | description: "an object with inherited keys",
43 | },
44 | ];
45 |
46 | testCases.forEach(({ args, expected }, i) => {
47 | describe(`when given testCases[${i}]`, () => {
48 | it("should return a 2d array of the given object's key value pairs.", () => {
49 | expect(testFn(...args)).toEqual(expected);
50 | });
51 | });
52 | });
53 | });
54 | });
55 |
--------------------------------------------------------------------------------
/src/strings/kaprekarsConstant/index.js:
--------------------------------------------------------------------------------
1 | const number1 = 3524;
2 | /*
3 | Explanation:
4 | 1. 5432 - 2345 = 3087
5 | 2. 8730 - 0378 = 8352
6 | 3. 8532 - 2358 = 6174
7 | */
8 | const expected1 = 3;
9 |
10 | const number2 = 2111;
11 | const expected2 = 5;
12 |
13 | const number3 = 9831;
14 | const expected3 = 7;
15 |
16 | /**
17 | * Determines how many digit-summing steps are required to reach kaprekars
18 | * constant from the given number.
19 | * 1. Arrange digits in descending order.
20 | * 2. Sum the sorted digits.
21 | * 3. Repeat until reaching 6174.
22 | * @param {number} num
23 | * @returns {number} The number of summing operations required to reach
24 | * kaprekars constant.
25 | */
26 | function kaprekarsConstant(num) {}
27 |
28 | /*****************************************************************************/
29 |
30 | function kaprekarsConstant(num) {
31 | let count = 0;
32 | if (num === 6174) {
33 | return count;
34 | }
35 |
36 | let numStr = num.toString();
37 |
38 | while (numStr != 6174) {
39 | if (numStr.length < 4) numStr += "0";
40 |
41 | const strDigits = numStr.split("");
42 |
43 | const asc = strDigits
44 | .slice()
45 | .sort((a, b) => a - b)
46 | .join("");
47 |
48 | const desc = strDigits
49 | .slice()
50 | .sort((a, b) => b - a)
51 | .join("");
52 |
53 | numStr = (desc - asc).toString();
54 | count++;
55 | }
56 | return count;
57 | }
58 |
59 | module.exports = {
60 | kaprekarsConstant,
61 | };
62 |
--------------------------------------------------------------------------------
/src/recursion/reverseStr/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Recursively reverse a string
3 | helpful methods:
4 |
5 | str.slice(beginIndex[, endIndex])
6 | returns a new string from beginIndex to endIndex exclusive
7 | */
8 |
9 | const str1 = "abc";
10 | const expected1 = "cba";
11 |
12 | const str2 = "";
13 | const expected2 = "";
14 |
15 | /**
16 | * Recursively reverses a string.
17 | * - Time: O(?).
18 | * - Space: O(?).
19 | * @param {string} str
20 | * @returns {string} The given str reversed.
21 | */
22 | function reverseStr(str) {}
23 |
24 | /*****************************************************************************/
25 |
26 | /**
27 | * input: abc
28 | * output: cba
29 | * return: fn + a
30 | * return: fn + b
31 | * return fn + c
32 | * return ''
33 | * '' + c + b + a
34 | *
35 | * - Time: O(n) linear, n = str.length
36 | * - Space: O(2n) -> O(n) linear. Every char of the string is copied into a new
37 | * string and one function call added to the stack for each char.
38 | */
39 | function reverseStr(str = "") {
40 | if (str === "") {
41 | return "";
42 | }
43 | const strWithoutFirstChar = str.slice(1);
44 | const firstChar = str[0];
45 | return reverseStr(strWithoutFirstChar) + firstChar;
46 | }
47 |
48 | function reverseStr2(str = "", i = str.length - 1) {
49 | if (str === "") {
50 | return "";
51 | }
52 |
53 | if (i === 0) {
54 | return str[i];
55 | }
56 |
57 | return str[i] + reverseStr2(str, i - 1);
58 | }
59 |
60 | module.exports = { reverseStr, reverseStr2 };
61 |
--------------------------------------------------------------------------------
/src/recreated_methods/Array/shift/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arr1 = [1, 2, 3];
6 | const expected1 = 1;
7 | // after running function arr1 should now be:
8 | const expectedArr1 = [2, 3];
9 |
10 | const arr2 = ["a", "b", "c", "d"];
11 | const expected2 = "a";
12 | // after running function arr2 should now be:
13 | const expectedArr2 = ["b", "c", "d"];
14 |
15 | const arr3 = [];
16 | const expected3 = undefined;
17 | const expectedArr3 = [];
18 |
19 | const testCases = [
20 | {
21 | arg: arr1,
22 | expectedRet: expected1,
23 | expectedArr: expectedArr1,
24 | },
25 | {
26 | arg: arr2,
27 | expectedRet: expected2,
28 | expectedArr: expectedArr2,
29 | },
30 | {
31 | arg: arr3,
32 | expectedRet: expected3,
33 | expectedArr: expectedArr3,
34 | },
35 | ];
36 |
37 | testCases.forEach(({ arg, expectedRet, expectedArr }, i) => {
38 | describe(`when given testCases[${i}] containing ${arg.length} items`, () => {
39 | it(`should return the first item from the given array.`, () => {
40 | expect(testFn(arg)).toBe(expectedRet);
41 | });
42 |
43 | it("should remove the first item and shift the remaining items down.", () => {
44 | expect(arg).toEqual(expectedArr);
45 | });
46 | });
47 | });
48 | });
49 | });
50 |
--------------------------------------------------------------------------------
/src/recreated_methods/Array/indexOf/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arr1 = ["a", "b", "c"];
6 | const searchItem1 = "c";
7 | const expected1 = 2;
8 |
9 | const arr2 = ["a", "b", "c"];
10 | const searchItem2 = 5;
11 | const expected2 = -1;
12 |
13 | const arr3 = ["c", "a", "b", "c"];
14 | const searchItem3 = "c";
15 | const expected3 = 0;
16 |
17 | const arr4 = [];
18 | const searchItem4 = 5;
19 | const expected4 = -1;
20 |
21 | const testCases = [
22 | {
23 | args: [arr1, searchItem1],
24 | expected: expected1,
25 | description: "the search item at the end",
26 | },
27 | {
28 | args: [arr2, searchItem2],
29 | expected: expected2,
30 | description: "a search item that doesn't exist",
31 | },
32 | {
33 | args: [arr3, searchItem3],
34 | expected: expected3,
35 | description: "a search item that appears twice",
36 | },
37 | {
38 | args: [arr4, searchItem4],
39 | expected: expected4,
40 | description: "an empty array",
41 | },
42 | ];
43 |
44 | testCases.forEach(({ args, expected }, i) => {
45 | describe(`when given testCases[${i}]`, () => {
46 | it("should return the index of the given element in the given array.", () =>
47 | expect(testFn(...args)).toEqual(expected));
48 | });
49 | });
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/src/arrays/socialDistancingEnforcer/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const queue1 = [0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1];
6 | const expected1 = false;
7 |
8 | const queue2 = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1];
9 | const expected2 = true;
10 |
11 | const queue3 = [1, 0, 0, 0, 0, 0, 0, 0, 1];
12 | const expected3 = true;
13 |
14 | const queue4 = [];
15 | const expected4 = true;
16 |
17 | const testCases = [
18 | {
19 | args: [queue1],
20 | expected: expected1,
21 | description:
22 | "the first two people socially distancing but the next is not.",
23 | },
24 | {
25 | args: [queue2],
26 | expected: expected2,
27 | description: "all people socially distancing",
28 | },
29 | {
30 | args: [queue3],
31 | expected: expected3,
32 | description:
33 | "a person at the start and the end with enough distance between",
34 | },
35 | { args: [queue4], expected: expected4, description: "an empty array" },
36 | ];
37 |
38 | testCases.forEach(({ args, expected, description }) => {
39 | describe("when given " + description, () => {
40 | it("should return a boolean representing if every person is separated by at least 6 empty spaces.", () => {
41 | expect(testFn(...args)).toEqual(expected);
42 | });
43 | });
44 | });
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/src/arrays/containerWithMostWater/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const heights1 = [1, 8, 6, 2, 5, 4, 8, 3, 7];
6 | const expected1 = 49;
7 | // Explanation: heights1[1] and heights1[8] as container edges.
8 | // Length = 8 - 1. Height = 7
9 |
10 | const heights2 = [1, 1];
11 | const expected2 = 1;
12 |
13 | const heights3 = [4, 3, 2, 1, 4];
14 | const expected3 = 16;
15 |
16 | const heights4 = [1, 2, 1];
17 | const expected4 = 2;
18 |
19 | const testCases = [
20 | {
21 | args: [heights1],
22 | expected: expected1,
23 | description: "a wide container solution ignoring first",
24 | },
25 | {
26 | args: [heights2],
27 | expected: expected2,
28 | description: "two same heights",
29 | },
30 | {
31 | args: [heights3],
32 | expected: expected3,
33 | description: "a whole container solution",
34 | },
35 | {
36 | args: [heights4],
37 | expected: expected4,
38 | description: "a whole container solution with short sides",
39 | },
40 | ];
41 |
42 | testCases.forEach(({ args, expected, description }) => {
43 | describe("when given " + description, () => {
44 | it("should return the area of the container that can hold the most water.", () => {
45 | expect(testFn(...args)).toEqual(expected);
46 | });
47 | });
48 | });
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/jasmine.md:
--------------------------------------------------------------------------------
1 | # [Jasmine](https://www.npmjs.com/package/jasmine)
2 |
3 | - Jasmine is a unit testing framework. We will be using it to pass test cases to our algorithms to see if your algorithms return the expected result.
4 |
5 | ## Setup
6 |
7 | - you must have [Node.js](https://nodejs.org/en/download/) installed
8 |
9 | ### Clone a repo that already has jasmine initialized
10 |
11 | 1. `git clone URL/TO/REPO.git` (url can be found on the repos GitHub page by clicking the top right code button)
12 | - this will create a new folder at the location your terminal is open to, the folder will be named after the repository
13 | 2. `cd repo_name`
14 | 3. `npm i` to install the dependencies (jasmine) listed in the `package.json` that came the cloned project.
15 |
16 | ### Initialize a new project and install jasmine
17 |
18 | 1. If you haven't already, run: `npm init` in your algos project folder
19 | 2. `npm i jasmine`
20 | - this should have created a `package.json` file that has `jasmine` and version number listed in it.
21 | 3. copy over the spec folder, or to create your own
22 |
23 | ## Run Jasmine
24 |
25 | - add the following to `package.json`
26 |
27 | - ```json
28 | "scripts": {
29 | "test": "node_modules/.bin/jasmine"
30 | },
31 | ```
32 |
33 | - this allows you to run `npm test` in the terminal open to your project folder
34 | - alternatively, to test a single `Spec` file: `npm test path/to/fileNameSpec.js`
35 | - you can type `npm test` with a space after `test`, then drag and drop the file after the space to auto fill the path
36 |
--------------------------------------------------------------------------------
/src/recursion/generateAnagrams/index.js:
--------------------------------------------------------------------------------
1 | // http://algorithms.dojo.news/static/Algorithms/index.html#LinkTarget_2129
2 | /*
3 | String Anagrams
4 |
5 | Given a string,
6 | return array where each element is a string representing a different anagram (a different sequence of the letters in that string).
7 |
8 | Ok to use built in methods
9 | */
10 |
11 | const str1 = "lim";
12 | const expected1 = ["ilm", "iml", "lim", "lmi", "mil", "mli"];
13 | // Order of the output array does not matter
14 |
15 | /**
16 | * Add params if needed for recursion.
17 | * Generates all anagrams of the given str.
18 | * - Time: O(?).
19 | * - Space: O(?).
20 | * @param {string} str
21 | * @returns {Array} All anagrams of the given str.
22 | */
23 | function generateAnagrams(str) {}
24 |
25 | /*****************************************************************************/
26 |
27 | /**
28 | * Generates all anagrams (permutations) for the given string
29 | * @see https://www.geeksforgeeks.org/time-complexity-permutations-string/
30 | * - Time: O(n^2 * n!)
31 | * - Space: O(n!) factorial due to the call stack.
32 | */
33 | function generateAnagrams(str, solutions = [], partial = "") {
34 | if (!str) {
35 | solutions.push(partial);
36 | }
37 |
38 | for (let i = 0; i < str.length; i++) {
39 | const leftSlice = str.slice(0, i);
40 | const rightSlice = str.slice(i + 1); // skips current letter
41 | generateAnagrams(leftSlice + rightSlice, solutions, partial + str[i]);
42 | }
43 | return solutions;
44 | }
45 |
46 | module.exports = { generateAnagrams };
47 |
--------------------------------------------------------------------------------
/src/arrays/oddOccurrencesInArray/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [1];
6 | const expected1 = 1;
7 |
8 | const nums2 = [5, 4, 5];
9 | const expected2 = 4;
10 |
11 | const nums3 = [5, 4, 3, 4, 3, 4, 5];
12 | const expected3 = 4; // there is a pair of 4s but one 4 has no pair.
13 |
14 | const nums4 = [5, 2, 6, 2, 3, 1, 6, 3, 2, 5, 2];
15 | const expected4 = 1;
16 |
17 | const testCases = [
18 | {
19 | args: [nums1],
20 | expected: expected1,
21 | description: "an array with a length of one",
22 | },
23 | {
24 | args: [nums2],
25 | expected: expected2,
26 | description: "three numbers with one duplicated",
27 | },
28 | {
29 | args: [nums3],
30 | expected: expected3,
31 | description:
32 | "multiple duplicates with the odd frequency greater than 1",
33 | },
34 | {
35 | args: [nums4],
36 | expected: expected4,
37 | description:
38 | "even frequencies that exceed 2 and a single non-duplicated number",
39 | },
40 | ];
41 |
42 | testCases.forEach(({ args, expected, description }) => {
43 | describe("when given " + description, () => {
44 | it("should return the only number that occurs and odd number of times from a non empty array.", () => {
45 | expect(testFn(...args)).toEqual(expected);
46 | });
47 | });
48 | });
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/src/arrays/matrixSearch/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Matrix Search
3 |
4 | Mike digs image recognition and wants to create a JavaScript Imaging Library, just like PIL for Python. He is given 2 different two-dimensional arrays, containing integers between 0 and 65535. Each two-dimensional array represents a gray-scale image, where each integer value is a pixel. The second image might be found somewhere within the larger one. Return whether it is.
5 |
6 | Given array: [[12,34,45,56], and array: [[67,78], return true . [98,87,76,65],[43,32] ] [56, 67 , 78 ,89] , [54, 43 , 32 ,21] ]
7 |
8 | Second: Return location of first match found ( [-1,-1] if no match). In example above, return [2,1] .
9 | */
10 |
11 | function matrixSearch(matrix, image) {
12 | const first = image[0][0];
13 | const imageHeight = image.length;
14 | const imageWidth = image[0].length;
15 | const relevantHeight = matrix.length - imageHeight + 1;
16 | const relevantWidth = matrix[0].length - imageWidth + 1;
17 |
18 | for (let i = 0; i < relevantHeight; i++) {
19 | for (let j = 0; j < relevantWidth; j++) {
20 | if (matrix[i][j] !== first) continue;
21 |
22 | // move in unison until broken
23 | for (var k = 0, matching = true; k < imageHeight && matching; k++) {
24 | for (let l = 0; l < imageWidth && matching; l++) {
25 | if (image[k][l] !== matrix[i + k][j + l]) {
26 | matching = false;
27 | }
28 | }
29 | }
30 |
31 | if (matching) return [i, j];
32 | }
33 | }
34 |
35 | return [-1, -1];
36 | }
37 |
38 | module.exports = { matrixSearch };
39 |
--------------------------------------------------------------------------------
/src/strings/compareVersionNumbers/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const test1V1 = "0.1";
6 | const test1V2 = "1.1";
7 | const expected1 = -1;
8 |
9 | const test2V1 = "1.0.1";
10 | const test2V2 = "1";
11 | const expected2 = 1;
12 |
13 | const test3V1 = "7.5.2.4";
14 | const test3V2 = "7.5.3";
15 | const expected3 = -1;
16 |
17 | const test4V1 = "7.5.2.4";
18 | const test4V2 = "7.5.2";
19 | const expected4 = 1;
20 |
21 | const test5V1 = "1.01";
22 | const test5V2 = "1.001";
23 | const expected5 = 0;
24 | // Explanation: Ignoring leading zeroes, both “01” and “001" represent the same number “1”
25 |
26 | const test6V1 = "1.0.1";
27 | const test6V2 = "1";
28 | const expected6 = 1;
29 |
30 | const testCases = [
31 | { args: [test1V1, test1V2], expected: expected1 },
32 | { args: [test2V1, test2V2], expected: expected2 },
33 | { args: [test3V1, test3V2], expected: expected3 },
34 | { args: [test4V1, test4V2], expected: expected4 },
35 | { args: [test5V1, test5V2], expected: expected5 },
36 | { args: [test6V1, test6V2], expected: expected6 },
37 | ];
38 |
39 | testCases.forEach(({ args, expected }, i) => {
40 | describe(`when given testCases[${i}]`, () => {
41 | it("should return an int representing which version number is larger.", () => {
42 | expect(testFn(...args)).toEqual(expected);
43 | });
44 | });
45 | });
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/src/arrays/missingValue/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [3, 0, 1];
6 | const expected1 = 2;
7 |
8 | const nums2 = [3, 0, 1, 2];
9 | const expected2 = null;
10 | // Explanation: nothing is missing
11 |
12 | /*
13 | Bonus: now the lowest value can now be any integer (including negatives),
14 | instead of always being 0.
15 | */
16 |
17 | const nums3 = [2, -4, 0, -3, -2, 1];
18 | const expected3 = -1;
19 |
20 | const nums4 = [5, 2, 7, 8, 4, 9, 3];
21 | const expected4 = 6;
22 |
23 | const testCases = [
24 | {
25 | args: [nums1],
26 | expected: expected1,
27 | description: "an unordered sequence 0-3",
28 | },
29 | { args: [nums2], expected: expected2, description: "no missing value" },
30 | {
31 | args: [nums3],
32 | expected: expected3,
33 | description: "a BONUS with the sequence -4-2",
34 | },
35 | {
36 | args: [nums4],
37 | expected: expected4,
38 | description: "a BONUS with the sequence 2-9",
39 | },
40 | ];
41 |
42 | testCases.forEach(({ args, expected, description }) => {
43 | describe("when given " + description, () => {
44 | it("should return the missing value from an array containing a consecutive sequence of ints that is unordered but with one missing.", () => {
45 | expect(testFn(...args)).toEqual(expected);
46 | });
47 | });
48 | });
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/src/strings/stringToWordArray/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Helpful notes:
3 |
4 | '\n' == true
5 | => false
6 |
7 | if ('\n') { console.log(true) }
8 | => true
9 |
10 | if ('\n' == false) { console.log(true) }
11 | => true
12 | */
13 |
14 | const str1 = "Life is not a drill!";
15 | const expected1 = ["Life", "is", "not", "a", "drill!"];
16 |
17 | /**
18 | * Converts a string of space separated words into an array of words.
19 | * - Time: O(?).
20 | * - Space: O(?).
21 | * @param {string} wordsStr Space separated words.
22 | * @returns {string} An array of words.
23 | */
24 | function stringToWordArr(wordsStr) {}
25 |
26 | /*****************************************************************************/
27 |
28 | /**
29 | * Converts a string of space separated words into an array of words.
30 | * - Time: O(n) linear.
31 | * - Space: O(n) linear.
32 | * @param {string} wordsStr Space separated words.
33 | * @returns {string} An array of words.
34 | */
35 | function stringToWordArr(wordsStr) {
36 | const words = [];
37 | let currWord = "";
38 |
39 | for (const char of wordsStr) {
40 | // space characters are falsy
41 | if (char == false) {
42 | // in case of multiple spaces, word might still be empty
43 | if (currWord.length > 0) {
44 | words.push(currWord);
45 | currWord = "";
46 | }
47 | } else {
48 | currWord += char;
49 | }
50 | }
51 | // when no space at end, need to include last word
52 | if (currWord.length > 0) {
53 | words.push(currWord);
54 | }
55 | return words;
56 | }
57 |
58 | module.exports = { stringToWordArr };
59 |
--------------------------------------------------------------------------------
/src/fromJob/flattenObjectOfArrays/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const object1 = {
6 | closedCreditMemos: [],
7 | closedDeliveryOrders: [],
8 | closedPickupOrders: [
9 | { id: 112, type: "pickup" },
10 | { id: 117, type: "pickup" },
11 | ],
12 | openCreditMemos: [],
13 | openDeliveryOrders: [
14 | {
15 | id: 123,
16 | type: "delivery",
17 | gateCode: "#2552",
18 | },
19 | {
20 | id: 153,
21 | type: "delivery",
22 | instructions: "Place in secure delivery box.",
23 | },
24 | ],
25 | openPickupOrders: [
26 | {
27 | id: 123,
28 | type: "pickup",
29 | },
30 | ],
31 | returnPickupOrders: [],
32 | };
33 |
34 | const expected1 = [
35 | { id: 112, type: "pickup" },
36 | { id: 117, type: "pickup" },
37 | { id: 123, type: "delivery" },
38 | { id: 153, type: "delivery" },
39 | { id: 123, type: "pickup" },
40 | ];
41 |
42 | const testCases = [
43 | {
44 | arg: object1,
45 | expected: expected1,
46 | },
47 | ];
48 |
49 | testCases.forEach(({ arg, expected }, i) => {
50 | describe(`when given testCases[${i}]`, () => {
51 | it("return a one-dim array of all the objects inside the arrays that are in the given object.", () =>
52 | expect(testFn(arg)).toEqual(expected));
53 | });
54 | });
55 | });
56 | });
57 |
--------------------------------------------------------------------------------
/src/recursion/factorial/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Recursive Factorial
3 |
4 | Input: integer
5 | Output: integer, product of ints from 1 up to given integer
6 |
7 | If less than zero, treat as zero.
8 | Bonus: If not integer, truncate (remove decimals).
9 |
10 | Experts tell us 0! is 1.
11 |
12 | rFact(3) = 6 (1*2*3)
13 | rFact(6.8) = 720 (1*2*3*4*5*6)
14 | */
15 |
16 | const num1 = 3;
17 | const expected1 = 6;
18 | // Explanation: 1*2*3 = 6
19 |
20 | const num2 = 6.8;
21 | const expected2 = 720;
22 | // Explanation: 1*2*3*4*5*6 = 720
23 |
24 | const num3 = 0;
25 | const expected3 = 1;
26 |
27 | /**
28 | * Recursively multiples 1 to the given int.
29 | * - Time: O(?).
30 | * - Space: O(?).
31 | * @param {number} n The int to factorial. Treat negatives as zero and
32 | * floor decimals.
33 | * @returns {number} The result of !n.
34 | */
35 | function factorial(n) {}
36 |
37 | /*****************************************************************************/
38 |
39 | /**
40 | * Recursively multiples 1 to the given int.
41 | * - Time: O(n) linear.
42 | * - Space: O(n) linear due to the call stack.
43 | * @param {number} n The int to factorial. Treat negatives as zero and
44 | * floor decimals.
45 | * @returns {number} The result of !n.
46 | */
47 | function factorial(n) {
48 | // Termination Condition if it's bad data (not a number)
49 | if (isNaN(parseInt(n))) {
50 | return null;
51 | }
52 |
53 | n = Math.floor(n);
54 |
55 | // Base case
56 | if (n <= 0) {
57 | return 1;
58 | }
59 | return n * factorial(n - 1);
60 | }
61 |
62 | module.exports = { factorial };
63 |
--------------------------------------------------------------------------------
/src/arrays/mode/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [];
6 | const expected1 = [];
7 |
8 | const nums2 = [1];
9 | const expected2 = [1];
10 |
11 | const nums3 = [5, 1, 4];
12 | const expected3 = [];
13 |
14 | const nums4 = [5, 1, 4, 1];
15 | const expected4 = [1];
16 |
17 | const nums5 = [5, 1, 4, 1, 5];
18 | const expected5 = [5, 1];
19 | // - order doesn't matter
20 |
21 | const testCases = [
22 | { args: [nums1], expected: expected1, description: "an empty array" },
23 | { args: [nums2], expected: expected2, description: "a single number" },
24 | { args: [nums3], expected: expected3, description: "no duplicates" },
25 | {
26 | args: [nums4],
27 | expected: expected4,
28 | description: "a small array with one duplicate",
29 | },
30 | {
31 | args: [nums5],
32 | expected: expected5,
33 | description:
34 | "a small array with two of the numbers having the same frequency",
35 | },
36 | ];
37 |
38 | testCases.forEach(({ args, expected, description }) => {
39 | describe("when given " + description, () => {
40 | it("should return an array of the integers that occur most frequently in the given array (more than one only if some have the same frequency).", () => {
41 | expect(testFn(...args)).toEqual(
42 | jasmine.arrayWithExactContents(expected)
43 | );
44 | });
45 | });
46 | });
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/src/objects/lens/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const user1 = {
6 | id: 101,
7 | email: "jack@dev.com",
8 | personalInfo: {
9 | name: "Jack",
10 | address: {
11 | street: "Westwish st",
12 | city: "wallas",
13 | state: "WX",
14 | },
15 | },
16 | favorites: {
17 | number: 0,
18 | },
19 | };
20 |
21 | const keys1 = ["personalInfo", "address", "city"];
22 | const expected1 = "wallas";
23 |
24 | const keys2 = ["personalInfo", "address", "country"];
25 | const expected2 = null;
26 |
27 | const keys3 = ["personalInfo", "mainHobby", "yearsActive"];
28 | const expected3 = null;
29 |
30 | const keys4 = ["favorites", "number"];
31 | const expected4 = 0;
32 |
33 | const keys5 = [];
34 | const expected5 = user1;
35 |
36 | const testCases = [
37 | { args: [user1, keys1], expected: expected1 },
38 | { args: [user1, keys2], expected: expected2 },
39 | { args: [user1, keys3], expected: expected3 },
40 | { args: [user1, keys4], expected: expected4 },
41 | { args: [user1, keys5], expected: expected5 },
42 | ];
43 | testCases.forEach(({ args, expected }, i) => {
44 | describe(`when given testCases[${i}]`, () => {
45 | it("should return the value at the end of the given path of keys, or null if it doesn't exist.", () => {
46 | expect(testFn(...args)).toEqual(expected);
47 | });
48 | });
49 | });
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/src/sets/intro.md:
--------------------------------------------------------------------------------
1 | # Sets
2 |
3 | - A set is a mathematical term for a collection of values
4 | - We will mostly use arrays when doing `set` based operations because, although a `Set` datatype exists and can be useful, JS doesn't natively have a multi-set data type.
5 |
6 | ---
7 |
8 | ## `Set` Type in JS
9 |
10 | - `new Set(val1, val2, valn)`
11 | - can pass in an array and when converted to a set it will be auto deduped
12 | - iterate
13 | - `.size`
14 | - `.add(val)`
15 | - `.has(val)`
16 | - `.delete(val)`
17 | - returns `true` if value found & deleted
18 |
19 | ---
20 |
21 | ## Types of Sets
22 |
23 | ### Normal Set
24 |
25 | - No dupes allowed, attempting to add a dupe will result in nothing being added. Creating a set from an array or string with dupes will remove the dupes.
26 | - does not track count of values b/c no dupes
27 |
28 | ---
29 |
30 | ### Multiset (contains dupes)
31 |
32 | - tracks count of values because there are dupes
33 |
34 | ---
35 |
36 | ### Ordered Set / Multiset
37 |
38 | ---
39 |
40 | ### Unordered Set / Multiset
41 |
42 | ---
43 |
44 | ### Intersection
45 |
46 | - only values that are shared between the sets deduped
47 |
48 | ---
49 |
50 | ### Union
51 |
52 | - [Union Example](https://i.ytimg.com/vi/WqYQ3OakKP0/maxresdefault.jpg)
53 | - all values from both sets included but deduped
54 | - 
55 |
56 | ---
57 |
58 | ### Union Multiset
59 |
60 | - the higher count of duped values are kept
61 | - if there are 3 number ones in one set and 2 number ones in the other set, 3 number ones would be kept
62 |
--------------------------------------------------------------------------------
/src/strings/rot13/index.js:
--------------------------------------------------------------------------------
1 | // https://www.codewars.com/kata/530e15517bc88ac656000716/train/javascript
2 |
3 | /*
4 | ROT13 is a simple letter substitution cipher that replaces
5 | a letter with the letter 13 letters after it in the alphabet.
6 | ROT13 is an example of the Caesar cipher.
7 |
8 | Create a function that takes a string and returns the string
9 | ciphered with Rot13. If there are numbers or special characters
10 | included in the string, they should be returned as they are.
11 | Only letters from the latin/english alphabet should be shifted,
12 | like in the original Rot13 "implementation".
13 | */
14 |
15 | /*****************************************************************************/
16 |
17 | const alphabet = [
18 | "a",
19 | "b",
20 | "c",
21 | "d",
22 | "e",
23 | "f",
24 | "g",
25 | "h",
26 | "i",
27 | "j",
28 | "k",
29 | "l",
30 | "m",
31 | "n",
32 | "o",
33 | "p",
34 | "q",
35 | "r",
36 | "s",
37 | "t",
38 | "u",
39 | "v",
40 | "w",
41 | "x",
42 | "y",
43 | "z",
44 | ];
45 |
46 | function rot13(s) {
47 | const chars = s.split("");
48 |
49 | for (let i = 0; i < chars.length; i++) {
50 | let alphabetIdx = alphabet.indexOf(chars[i]);
51 |
52 | if (alphabetIdx > -1) {
53 | let newAlphabetIdx = alphabetIdx + 13;
54 | if (newAlphabetIdx > alphabet.length - 1)
55 | // get the remainder and start indexing again from the beginning
56 | newAlphabetIdx = newAlphabetIdx - alphabet.length - 1;
57 |
58 | chars[i] = [alphabet[newAlphabetIdx]];
59 | }
60 | }
61 | return chars.join("");
62 | }
63 |
64 | module.exports = { rot13 };
65 |
--------------------------------------------------------------------------------
/src/arrays/interleaveArrays/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arrA1 = [1, 2, 3];
6 | const arrB1 = ["a", "b", "c"];
7 | const expected1 = [1, "a", 2, "b", 3, "c"];
8 |
9 | const arrA2 = [1, 3];
10 | const arrB2 = [2, 4, 6, 8];
11 | const expected2 = [1, 2, 3, 4, 6, 8];
12 |
13 | const arrA3 = [1, 3, 5, 7];
14 | const arrB3 = [2, 4];
15 | const expected3 = [1, 2, 3, 4, 5, 7];
16 |
17 | const arrA4 = [];
18 | const arrB4 = [42, 0, 6];
19 | const expected4 = [42, 0, 6];
20 |
21 | const testCases = [
22 | {
23 | args: [arrA1, arrB1],
24 | expected: expected1,
25 | description: "three numbers and three letters",
26 | },
27 | {
28 | args: [arrA2, arrB2],
29 | expected: expected2,
30 | description: "a first array half the size of the second array",
31 | },
32 | {
33 | args: [arrA3, arrB3],
34 | expected: expected3,
35 | description: "a second array half the size of the first array",
36 | },
37 | {
38 | args: [arrA4, arrB4],
39 | expected: expected4,
40 | description: "the first array empty",
41 | },
42 | ];
43 |
44 | testCases.forEach(({ args, expected, description }) => {
45 | describe("when given " + description, () => {
46 | it("should return a new array that contains the items of the given arrays interleaved (alternated).", () => {
47 | expect(testFn(...args)).toEqual(expected);
48 | });
49 | });
50 | });
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/src/callbacks/dropIt/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [1, 4, 3, 6, 9, 15];
6 |
7 | const callback1 = (elem) => {
8 | return elem > 5;
9 | };
10 | const expected1 = [6, 9, 15];
11 |
12 | const callback2 = (elem) => {
13 | return elem > 2;
14 | };
15 | const expected2 = [4, 3, 6, 9, 15];
16 |
17 | const callback3 = (elem) => false;
18 | const expected3 = [];
19 |
20 | const testCases = [
21 | {
22 | args: [nums1, callback1],
23 | expected: expected1,
24 | description: "a callback that checks for greater than 5",
25 | },
26 | {
27 | args: [nums1, callback2],
28 | expected: expected2,
29 | description: "a callback that checks for greater than 2",
30 | },
31 | {
32 | args: [nums1, callback3],
33 | expected: expected3,
34 | description: "a callback that always returns false",
35 | },
36 | ];
37 |
38 | testCases.forEach(({ args: [nums, cb], expected, description }) => {
39 | describe("when given " + description, () => {
40 | const numsCopy = [...nums];
41 | const actual = testFn(numsCopy, cb);
42 |
43 | it("should return the given array after removing every item from index 0 until the callback returns true.", () => {
44 | expect(actual).toEqual(expected);
45 | });
46 |
47 | it("should have mutated and returned the given array.", () => {
48 | expect(actual).toBe(numsCopy);
49 | });
50 | });
51 | });
52 | });
53 | });
54 |
--------------------------------------------------------------------------------
/src/objects/coronaVirusAtRisk/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const friend1 = {
6 | firstName: "Friend",
7 | lastName: "One",
8 | isSocialDistancing: false,
9 | hasCovid: true,
10 | };
11 |
12 | const friend2 = {
13 | firstName: "Friend",
14 | lastName: "Two",
15 | isSocialDistancing: false,
16 | hasCovid: true,
17 | };
18 |
19 | const friend3 = {
20 | firstName: "Friend",
21 | lastName: "Three",
22 | isSocialDistancing: false,
23 | hasCovid: false,
24 | };
25 |
26 | const people1 = [
27 | {
28 | firstName: "Person",
29 | lastName: "One",
30 | isSocialDistancing: false,
31 | friends: [friend2, friend3],
32 | },
33 | {
34 | firstName: "Person",
35 | lastName: "Two",
36 | isSocialDistancing: true,
37 | friends: [friend2, friend1],
38 | },
39 | {
40 | firstName: "Person",
41 | lastName: "Three",
42 | isSocialDistancing: false,
43 | friends: [friend2, friend1],
44 | },
45 | ];
46 |
47 | const expected1 = ["Person One", "Person Three"];
48 |
49 | const testCases = [{ args: [people1], expected: expected1 }];
50 |
51 | testCases.forEach(({ args, expected }, i) => {
52 | describe(`when given testCases[${i}]`, () => {
53 | it("should return an array of the names of people who are at risk of contracting corona virus.", () =>
54 | expect(testFn(...args)).toEqual(expected));
55 | });
56 | });
57 | });
58 | });
59 |
--------------------------------------------------------------------------------
/src/arrays/nthLast/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | // Last element:
6 | const arr1 = ["a", "b", "c", "d"];
7 | const nthLast1 = 1;
8 | const expected1 = "d";
9 |
10 | // Second to last element:
11 | const arr2 = ["a", "b", "c", "d"];
12 | const nthLast2 = 2;
13 | const expected2 = "c";
14 |
15 | const arr3 = ["a", "b", "c", "d"];
16 | const nthLast3 = 0;
17 | const expected3 = null;
18 |
19 | const arr4 = ["a", "b", "c", "d"];
20 | const nthLast4 = -1;
21 | const expected4 = null;
22 |
23 | const arr5 = [];
24 | const nthLast5 = 2;
25 | const expected5 = null;
26 |
27 | const testCases = [
28 | {
29 | args: [arr1, nthLast1],
30 | expected: expected1,
31 | },
32 | { args: [arr2, nthLast2], expected: expected2 },
33 | { args: [arr3, nthLast3], expected: expected3 },
34 | { args: [arr4, nthLast4], expected: expected4 },
35 | {
36 | args: [arr5, nthLast5],
37 | expected: expected5,
38 | description: `an empty array and nthToLast=${nthLast5}`,
39 | },
40 | ];
41 |
42 | testCases.forEach(
43 | ({
44 | args: [arr, nthLast],
45 | expected,
46 | description = `a non-empty array and nthToLast=${nthLast}`,
47 | }) => {
48 | describe("when given " + description, () => {
49 | it("should return the nth item from the back of the given array.", () => {
50 | expect(testFn(arr, nthLast)).toEqual(expected);
51 | });
52 | });
53 | }
54 | );
55 | });
56 | });
57 |
--------------------------------------------------------------------------------
/src/arrays/checkTicTacToeWinner/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const grid1 = [
6 | ["x", "x", ""],
7 | ["x", "x", "o"],
8 | ["", "o", ""],
9 | ];
10 | const expected1 = false;
11 |
12 | const grid2 = [
13 | ["", "o", "x"],
14 | ["o", "x", ""],
15 | ["x", "", ""],
16 | ];
17 | const expected2 = true;
18 |
19 | const grid3 = [
20 | ["x", "", "o"],
21 | ["x", "x", "o"],
22 | ["", "", "o"],
23 | ];
24 | const expected3 = true;
25 |
26 | const grid4 = [
27 | ["", "", ""],
28 | ["o", "o", ""],
29 | ["x", "x", "x"],
30 | ];
31 | const expected4 = true;
32 |
33 | const testCases = [
34 | {
35 | args: [grid1],
36 | expected: expected1,
37 | description: "multiple two in a row",
38 | },
39 | {
40 | args: [grid2],
41 | expected: expected2,
42 | description: "a bottom left to top right win for 'x'",
43 | },
44 | {
45 | args: [grid3],
46 | expected: expected3,
47 | description: "a right column win for 'o'",
48 | },
49 | {
50 | args: [grid4],
51 | expected: expected4,
52 | description: "a bottom row win for 'x'",
53 | },
54 | ];
55 |
56 | testCases.forEach(({ args, expected, description }) => {
57 | describe("when given " + description, () => {
58 | it("should determine if a tic tac toe winner exists.", () => {
59 | expect(testFn(...args)).toEqual(expected);
60 | });
61 | });
62 | });
63 | });
64 | });
65 |
--------------------------------------------------------------------------------
/src/recursion/generateCoinChange/index.js:
--------------------------------------------------------------------------------
1 | // http://algorithms.dojo.news/static/Algorithms/index.html#LinkTarget_2129
2 |
3 | /*
4 | Generate All Possible Coin Change
5 |
6 | Create generate All CoinChange(cents) . Given a number of American cents, compute and return an array enumerating all possible ways to represent it, with pennies (1 cent), nickels (5 cents), dimes (10 cents), quarters (25 cents). For 5 , return [{dimes:0,nickels:1,pennies:0,quarters:0}, {dimes:0,nickels:0,pennies:5,quarters:0}{}] . Do not return duplicate results.
7 | */
8 |
9 | function generateCoinChange(
10 | cents,
11 | solutions = [],
12 | partial = { quarters: 0, dimes: 0, nickels: 0, pennies: 0 }
13 | ) {
14 | solutions.push({
15 | ...partial,
16 | pennies: cents,
17 | });
18 |
19 | if (!partial.quarters) {
20 | const maxQuarters = Math.floor(cents / 25);
21 |
22 | for (let i = 1; i <= maxQuarters; i++) {
23 | generateCoinChange(cents - i * 25, solutions, {
24 | ...partial,
25 | quarters: i,
26 | });
27 | }
28 | }
29 |
30 | if (!partial.dimes) {
31 | const maxDimes = Math.floor(cents / 10);
32 |
33 | for (let i = 1; i <= maxDimes; i++) {
34 | generateCoinChange(cents - i * 10, solutions, {
35 | ...partial,
36 | dimes: i,
37 | });
38 | }
39 | }
40 |
41 | if (!partial.nickels) {
42 | const maxNickels = Math.floor(cents / 5);
43 |
44 | for (let i = 1; i <= maxNickels; i++) {
45 | generateCoinChange(cents - i * 5, solutions, {
46 | ...partial,
47 | nickels: i,
48 | });
49 | }
50 | }
51 |
52 | return solutions;
53 | }
54 |
55 | module.exports = {
56 | generateCoinChange,
57 | };
58 |
--------------------------------------------------------------------------------
/src/intervals/mergeSortedIntervals/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const intervals1 = [
6 | [1, 3],
7 | [2, 6],
8 | [8, 10],
9 | [15, 18],
10 | ];
11 | const expected1 = [
12 | [1, 6],
13 | [8, 10],
14 | [15, 18],
15 | ];
16 | // Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
17 |
18 | const intervals2 = [
19 | [1, 4],
20 | [4, 5],
21 | ];
22 | const expected2 = [[1, 5]];
23 | // Explanation: Intervals [1,4] and [4,5] are considered overlapping.
24 |
25 | const intervals3 = [
26 | [2, 4],
27 | [8, 10],
28 | [15, 20],
29 | ];
30 | const expected3 = [
31 | [2, 4],
32 | [8, 10],
33 | [15, 20],
34 | ];
35 |
36 | const testCases = [
37 | {
38 | args: [intervals1],
39 | expected: expected1,
40 | description: "the first two intervals overlapping",
41 | },
42 | {
43 | args: [intervals2],
44 | expected: expected2,
45 | description: "only two intervals that overlap",
46 | },
47 | {
48 | args: [intervals3],
49 | expected: expected3,
50 | description: "no overlapping intervals",
51 | },
52 | ];
53 |
54 | testCases.forEach(({ args, expected, description }) => {
55 | describe("when given " + description, () => {
56 | it("should merge overlapping intervals into a new array from a given array of sorted intervals.", () =>
57 | expect(testFn(...args)).toEqual(expected));
58 | });
59 | });
60 | });
61 | });
62 |
--------------------------------------------------------------------------------
/src/objects/makeFrequencyTable/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arr1 = ["a", "a", "a"];
6 | const expected1 = {
7 | a: 3,
8 | };
9 |
10 | const arr2 = ["a", "b", "a", "c", "B", "c", "c", "d"];
11 | const expected2 = {
12 | a: 2,
13 | b: 1,
14 | c: 3,
15 | B: 1,
16 | d: 1,
17 | };
18 |
19 | const arr3 = [];
20 | const expected3 = {};
21 |
22 | const testCases = [
23 | {
24 | args: [arr1],
25 | expected: expected1,
26 | description: "an array of 'a' repeated three times",
27 | },
28 | {
29 | args: [arr2],
30 | expected: expected2,
31 | description:
32 | "an array of letters a-d with some dupes and different casing",
33 | },
34 | { args: [arr3], expected: expected3, description: "an empty array" },
35 | ];
36 |
37 | testCases.forEach(({ args, expected }, i) => {
38 | describe(`when given testCases[${i}]`, () => {
39 | it("should return an object that has keys corresponding to the given array's items and values that are a count of the item's frequency.", () => {
40 | const actual = testFn(...args);
41 |
42 | if (actual instanceof Map) {
43 | const pojo = [...actual.entries()].reduce((obj, [key, value]) => {
44 | obj[key] = value;
45 | return obj;
46 | }, {});
47 | expect(pojo).toEqual(expected);
48 | } else {
49 | expect(actual).toEqual(expected);
50 | }
51 | });
52 | });
53 | });
54 | });
55 | });
56 |
--------------------------------------------------------------------------------
/src/DOM/iterativelyRenderTree/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Iteratively renders HTML lists with nested lists for the children matching
3 | the given parent-child-relationships based on the ids.
4 |
5 | Display the id as the innerHTML.
6 | */
7 |
8 | const data1 = [
9 | { parent: null, id: "A" },
10 | { parent: "A", id: "B" },
11 | { parent: "A", id: "C" },
12 | { parent: "A", id: "D" },
13 | { parent: "B", id: "E" },
14 | { parent: "C", id: "F" },
15 | { parent: "D", id: "G" },
16 | ];
17 |
18 | /*
19 | Expected1:
20 |
21 | -
22 | A
23 |
24 | -
25 | B
26 |
29 |
30 | -
31 | C
32 |
35 |
36 | -
37 | D
38 |
41 |
42 |
43 |
44 |
45 | */
46 |
47 | /** TODO
48 | * Iteratively renders an HTML list containing child lists corresponding to
49 | * the parent-child-relationship based on the given ids and displays the id.
50 | * @param {{parent: string, id: string}[]} data
51 | */
52 | function iterativelyRenderTree(data) {
53 | let rootId = null;
54 | const idToChildrenMap = new Map();
55 |
56 | for (const elem of data) {
57 | if (elem.parent === null) {
58 | rootId = elem.id;
59 | }
60 |
61 | if (idToChildrenMap.has(elem.id) === false) {
62 | idToChildrenMap.set(elem.id, []);
63 | }
64 |
65 | idToChildrenMap.get(elem.id).push(elem);
66 | }
67 |
68 | const stack = [];
69 | for (const [id, children] of idToChildrenMap.entries()) {
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/arrays/kMostFrequent/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [2, 1, 1, 3, 1, 2];
6 | const k1 = 2;
7 | const expected1 = [1, 2];
8 | // Explanation: return the two most frequent elements, 1 and 2 are the two most frequent elements
9 |
10 | const nums2 = [0, 2, 0, 3, 2, 0];
11 | const k2 = 1;
12 | const expected2 = [0];
13 | // Explanation: k being 1 means return the single most frequent element
14 |
15 | // 6 occurs 6 times, 3 occurs 3 times, 2 occurs 2 times, 1 occurs 1 time.
16 | const nums3 = [1, 6, 3, 3, 6, 6, 3, 6, 2, 2, 6, 6];
17 | const k3 = 3;
18 | const expected3 = [6, 3, 2];
19 |
20 | const testCases = [
21 | {
22 | args: [nums1, k1],
23 | expected: expected1,
24 | description: `an array of 3 numbers with each duplicated a few times and k=${k1}`,
25 | },
26 | {
27 | args: [nums2, k2],
28 | expected: expected2,
29 | description: `an array of 3 numbers with one that occurs more than the rest and k=${k2}`,
30 | },
31 | {
32 | args: [nums3, k3],
33 | expected: expected3,
34 | description: `an array of 3 numbers each duplicated and k=${k3}`,
35 | },
36 | ];
37 |
38 | testCases.forEach(({ args, expected, description }) => {
39 | describe("when given " + description, () => {
40 | it("should return the k most frequently occurring integers from the array in any order.", () => {
41 | expect(testFn(...args)).toEqual(
42 | jasmine.arrayWithExactContents(expected)
43 | );
44 | });
45 | });
46 | });
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/src/recursion/greatestCommonFactor/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Greatest Common Factor / Denominator
3 |
4 | Input: two integers
5 | Output: greatest common factor (the largest integer that can be evenly divided into both given ints)
6 |
7 | Greek mathematician Euclid demonstrated these facts:
8 |
9 | 1) gcf(a,b) == a , if a == b;
10 |
11 | 2) gcf(a,b) == gcf(a-b,b) , if a>b;
12 |
13 | 3) gcf(a,b) == gcf(a,b-a) , if b>a.
14 |
15 | Second: rework facts #2 and #3 to reduce stack consumption and expand rGCF ’s reach. You should be able to compute rGCF(123456,987654)
16 | */
17 |
18 | const a1 = 5;
19 | const b1 = 5;
20 | const expected1 = 5;
21 |
22 | const a2 = 6;
23 | const b2 = 20;
24 | const expected2 = 2;
25 |
26 | const a3 = 54;
27 | const b3 = 12;
28 | const expected3 = 6;
29 |
30 | const a4 = 12;
31 | const b4 = 54;
32 | const expected4 = 6;
33 |
34 | const a5 = 65;
35 | const b5 = 25;
36 | const expected5 = 5;
37 |
38 | const a6 = 123456;
39 | const b6 = 987654;
40 | const expected6 = 6;
41 |
42 | /**
43 | * Returns the greatest common factor of the two given numbers.
44 | * @param {number} a
45 | * @param {number} b
46 | * @returns {number} The greatest common factor.
47 | */
48 | function rGCF(a, b) {}
49 |
50 | /*****************************************************************************/
51 |
52 | // Maximum call stack exceeded for large inputs.
53 | function rGCF(a, b) {
54 | if (a === b) {
55 | return a;
56 | }
57 |
58 | if (a > b) {
59 | return rGCF(a - b, b);
60 | }
61 |
62 | if (a < b) {
63 | return rGCF(a, b - a);
64 | }
65 | }
66 |
67 | function rGCF2(a, b) {
68 | if (!b) {
69 | return a;
70 | }
71 |
72 | return rGCF2(b, a % b);
73 | }
74 |
75 | module.exports = { /* rGCF, */ rGCF2 };
76 |
--------------------------------------------------------------------------------
/src/arrays/removeAt/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arr1 = ["a", "b", "c"];
6 | const removeIdx1 = 1;
7 | const expected1 = "b";
8 | // after function call, arr1 should be:
9 | const arr1Expected = ["a", "c"];
10 |
11 | const arr2 = ["a", "b", "c"];
12 | const removeIdx2 = 3;
13 | const expected2 = null;
14 | const arr2Expected = ["a", "b", "c"];
15 |
16 | const arr3 = ["a", "b", "c"];
17 | const removeIdx3 = -3;
18 | const expected3 = null;
19 | const arr3Expected = ["a", "b", "c"];
20 |
21 | const testCases = [
22 | {
23 | args: [arr1, removeIdx1],
24 | expectedRet: expected1,
25 | expectedArr: arr1Expected,
26 | },
27 | {
28 | args: [arr2, removeIdx2],
29 | expectedRet: expected2,
30 | expectedArr: arr2Expected,
31 | },
32 | {
33 | args: [arr3, removeIdx3],
34 | expectedRet: expected3,
35 | expectedArr: arr3Expected,
36 | },
37 | ];
38 |
39 | testCases.forEach(
40 | ({
41 | args: [givenArr, removeIdx],
42 | expectedRet,
43 | expectedArr,
44 | description,
45 | }) => {
46 | describe("when given " + description, () => {
47 | it("should remove and return the item at the specified index", () => {
48 | expect(testFn(givenArr, removeIdx)).toEqual(expectedRet);
49 | });
50 |
51 | it("should have removed the item at the given index from the given array.", () => {
52 | expect(givenArr).toEqual(expectedArr);
53 | });
54 | });
55 | }
56 | );
57 | });
58 | });
59 |
--------------------------------------------------------------------------------
/src/recursion/sumToOneDigit/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Sum To One Digit
3 | Implement a function sumToOne(num) that,
4 | given a number, sums that number’s digits
5 | repeatedly until the sum is only one digit. Return
6 | that final one digit result.
7 |
8 | Tips:
9 | to access digits from a number, need to convert it .toString() to access each digit via index
10 | parseInt(arg) returns arg parsed as an integer, or NaN if it couldn't be converted to an int
11 | isNaN(arg) used to check if something is NaN
12 | */
13 |
14 | const num1 = 5;
15 | const expected1 = 5;
16 |
17 | const num2 = 10;
18 | const expected2 = 1;
19 |
20 | const num3 = 25;
21 | const expected3 = 7;
22 |
23 | /**
24 | * Sums the given number's digits until the number becomes one digit.
25 | * @param {number} num The number to sum to one digit.
26 | * @returns {number} One digit.
27 | */
28 | function sumToOneDigit(num) {}
29 |
30 | /*****************************************************************************/
31 |
32 | function sumToOneDigit(n) {
33 | // Termination Condition if it's bad data (not a number)
34 | if (isNaN(parseInt(n))) {
35 | return null;
36 | }
37 |
38 | // base case: return solution
39 | if (n < 10) {
40 | return n;
41 | }
42 |
43 | const strNum = n.toString();
44 | let sum = 0;
45 |
46 | for (const strDigit of strNum) {
47 | sum += parseInt(strDigit);
48 | }
49 |
50 | return sumToOneDigit(sum);
51 | }
52 |
53 | function sumToOneDigit2(num) {
54 | if (num < 10) {
55 | return num;
56 | }
57 |
58 | let sum = 0;
59 |
60 | while (num > 0) {
61 | sum += num % 10;
62 | num = Math.floor(num / 10);
63 | }
64 | return sumToOneDigit2(sum);
65 | }
66 |
67 | module.exports = { sumToOneDigit, sumToOneDigit2 };
68 |
--------------------------------------------------------------------------------
/src/arrays/countEvenNegatives/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Given an array of numbers,
3 | return a count of how many are both even and negative.
4 | */
5 |
6 | const nums1 = [1, 5, -1, 2, -4, 9, -10, 0, -3, -2];
7 | const expected1 = 3;
8 |
9 | const nums2 = [];
10 | const expected2 = 0;
11 |
12 | const nums3 = [-4, -2, -6];
13 | const expected3 = 3;
14 |
15 | /**
16 | * Counts how many numbers are both even and negative.
17 | * - Time: O(?).
18 | * - Space: O(?).
19 | * @param {number} nums
20 | * @returns {number} The count.
21 | */
22 | function countEvenNegatives(nums) {}
23 |
24 | /*****************************************************************************/
25 |
26 | /**
27 | * Counts how many numbers are both even and negative.
28 | * - Time: O(n) linear, n = nums.length. We have to loop over the whole array.
29 | * - Space: O(1) constant. The amount of extra space taken up by our algo
30 | * remains constant even as the given array grows in length because we are
31 | * not storing more items if the array is larger since we are just storing
32 | * a single count.
33 | * @param {number} nums
34 | * @returns {number} The count.
35 | */
36 | function countEvenNegatives(nums = []) {
37 | let count = 0;
38 |
39 | for (let i = 0; i < nums.length; i++) {
40 | if (nums[i] < 0 && nums[i] % 2 === 0) {
41 | count++;
42 | }
43 | }
44 | return count;
45 | }
46 |
47 | /**
48 | * - Time: O(n) linear, n = nums.length. We have to loop over the whole array.
49 | * - Space: O(n) linear. The filter method is creating a new array.
50 | */
51 | const functionalCountEvenNegatives = (nums = []) =>
52 | nums.filter((n) => n < 0 && n % 2 === 0).length;
53 |
54 | module.exports = {
55 | countEvenNegatives,
56 | functionalCountEvenNegatives,
57 | };
58 |
--------------------------------------------------------------------------------
/src/objects/santasNaughtyList/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const students = [
6 | {
7 | firstName: "FN1",
8 | lastName: "LN1",
9 | habits: [
10 | "doesn't wash dishes",
11 | "falls asleep in lecture",
12 | "shows up early",
13 | ],
14 | },
15 | {
16 | firstName: "FN2",
17 | lastName: "LN2",
18 | habits: ["shows up late", "washes dishes", "helps peers"],
19 | },
20 | {
21 | firstName: "FN3",
22 | lastName: "LN3",
23 | habits: ["doesn't wash dishes", "hoards snacks", "shows up late"],
24 | },
25 | {
26 | firstName: "FN4",
27 | lastName: "LN4",
28 | habits: ["shows up early", "helps peers", "washes dishes"],
29 | },
30 | ];
31 |
32 | const badHabit1 = "doesn't wash dishes";
33 | const expected1 = ["FN1 LN1", "FN3 LN3"];
34 |
35 | const badHabit2 = "shows up late";
36 | const expected2 = ["FN2 LN2", "FN3 LN3"];
37 |
38 | const badHabit3 = "vapes too much";
39 | const expected3 = [];
40 |
41 | const testCases = [
42 | { args: [students, badHabit1], expected: expected1 },
43 | { args: [students, badHabit2], expected: expected2 },
44 | { args: [students, badHabit3], expected: expected3 },
45 | ];
46 |
47 | testCases.forEach(({ args, expected }, i) => {
48 | describe(`when given testCases[${i}]`, () => {
49 | it("should an array of all the student objects that have a matching given bad habit.", () => {
50 | expect(testFn(...args)).toEqual(expected);
51 | });
52 | });
53 | });
54 | });
55 | });
56 |
--------------------------------------------------------------------------------
/src/strings/isPalindrome/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | String: Is Palindrome
3 |
4 | Create a function that returns a boolean whether the string is a strict palindrome.
5 | - palindrome = string that is same forwards and backwards
6 |
7 | Do not ignore spaces, punctuation and capitalization
8 | */
9 |
10 | const str1 = "a x a";
11 | const expected1 = true;
12 |
13 | const str2 = "racecar";
14 | const expected2 = true;
15 |
16 | const str3 = "Dud";
17 | const expected3 = false;
18 |
19 | const str4 = "oho!";
20 | const expected4 = false;
21 |
22 | /**
23 | * Determines if the given str is a palindrome (same forwards and backwards).
24 | * - Time: O(?).
25 | * - Space: O(?).
26 | * @param {string} str
27 | * @returns {boolean} Whether the given str is a palindrome or not.
28 | */
29 | function isPalindrome(str) {}
30 |
31 | /*****************************************************************************/
32 |
33 | /**
34 | * - Time: O(n/2) -> O(n) linear.
35 | * - Space: O(1) constant.
36 | * @param {string} str
37 | * @returns {boolean}
38 | */
39 | function isPalindrome(str = "") {
40 | for (let i = 0; i < Math.floor(str.length / 2); i++) {
41 | // Looping inwards from both sides.
42 | const leftChar = str[i];
43 | const rightChar = str[str.length - 1 - i];
44 |
45 | if (leftChar !== rightChar) {
46 | return false; // early exit
47 | }
48 | }
49 | return true;
50 | }
51 |
52 | /**
53 | * - Time: O(3n) -> O(n) linear. Each method used is looping.
54 | * - Space: O(2n) linear. Split and join both create a copy.
55 | * @param {string} str
56 | * @returns {boolean}
57 | */
58 | const functionIsPalindrome = (str = "") =>
59 | str === str.split("").reverse().join("");
60 |
61 | module.exports = { isPalindrome, functionIsPalindrome };
62 |
--------------------------------------------------------------------------------
/src/objects/getMaxServings/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const recipe1 = {
6 | "organic fat": 99,
7 | "broccoli seeds": 1,
8 | okra: 1,
9 | potato: 1,
10 | spicy: 5,
11 | "gourmet memes": 4200,
12 | };
13 |
14 | const available1 = {
15 | "organic fat": 990,
16 | "broccoli seeds": 1,
17 | okra: 10,
18 | potato: 10,
19 | spicy: 50,
20 | "gourmet memes": 42000,
21 | sugar: 9001,
22 | spice: 5,
23 | "everything nice": 1,
24 | "triple point water": 5,
25 | };
26 | const expected1 = 1;
27 | // because only 1 broccoli seeds is available and that is the limiting ingredient
28 |
29 | // same as available1, except broccoli seeds has 10.
30 | const available2 = { ...available1, ["broccoli seeds"]: 10 };
31 | const expected2 = 10;
32 |
33 | // same as available1 except broccoli seeds key is deleted.
34 | const available3 = { ...available1 };
35 | delete available3["broccoli seeds"];
36 | const expected3 = 0; // broccoli seeds key doesn't exist in available ingredients
37 |
38 | const testCases = [
39 | { args: [recipe1, available1], expected: expected1 },
40 | { args: [recipe1, available2], expected: expected2 },
41 | { args: [recipe1, available3], expected: expected3 },
42 | ];
43 |
44 | testCases.forEach(({ args, expected }, i) => {
45 | describe(`when given testCases[${i}]`, () => {
46 | it("should return maximum amount of servings that can be made from the given recipe and available ingredients.", () =>
47 | expect(testFn(...args)).toEqual(expected));
48 | });
49 | });
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/src/strings/reverseString/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | String: Reverse
3 |
4 | Given a string,
5 | return a new string that is the given string reversed
6 | */
7 |
8 | const str1 = "creature";
9 | const expected1 = "erutaerc";
10 |
11 | const str2 = "dog";
12 | const expected2 = "god";
13 |
14 | const str3 = "hello";
15 | const expected3 = "olleh";
16 |
17 | const str4 = "";
18 | const expected4 = "";
19 |
20 | /**
21 | * Reverses the given str.
22 | * - Time: O(?).
23 | * - Space: O(?).
24 | * @param {string} str String to be reversed.
25 | * @returns {string} The given str reversed.
26 | */
27 | function reverseString(str) {}
28 |
29 | /*****************************************************************************/
30 |
31 | /**
32 | * - Time: O(n) linear.
33 | * - Space: O(n) linear.
34 | * @param {string} str
35 | * @returns {string}
36 | */
37 | function reverseString(str = "") {
38 | let reversed = "";
39 |
40 | for (let i = str.length - 1; i >= 0; i--) {
41 | reversed += str[i];
42 | }
43 |
44 | return reversed;
45 | }
46 |
47 | /**
48 | * - Time: O(n) linear.
49 | * - Space: O(n) linear.
50 | * @param {string} str
51 | * @returns {string}
52 | */
53 | function reverseString2(str = "") {
54 | let reversed = "";
55 |
56 | for (let i = 0; i < str.length; i++) {
57 | // prepend instead of append since we aren't looping backwards.
58 | reversed = str[i] + reversed;
59 | }
60 |
61 | return reversed;
62 | }
63 |
64 | /**
65 | * - Time: O(3n) -> O(n) linear.
66 | * - Space: O(2n) -> O(n) linear. Split and join are both duplicating data.
67 | * @param {string} str
68 | * @returns {string}
69 | */
70 | const functionalReverseStr = (str = "") => str.split("").reverse().join("");
71 |
72 | module.exports = { reverseString, reverseString2, functionalReverseStr };
73 |
--------------------------------------------------------------------------------
/src/strings/outputToJson/output.txt:
--------------------------------------------------------------------------------
1 | ID : 0
2 | Status : Ok
3 | Name : OS
4 | State : Ready
5 | Hot Spare Policy violated : Not Assigned
6 | Encrypted : Not Applicable
7 | Layout : RAID-5
8 | Size : 200.00 GB (214748364800 bytes)
9 | T10 Protection Information Status : No
10 | Associated Fluid Cache State : Not Applicable
11 | Device Name : Windows Disk 0
12 | Bus Protocol : SATA
13 | Media : HDD
14 | Read Policy : No Read Ahead
15 | Write Policy : Write Back
16 | Cache Policy : Not Applicable
17 | Stripe Element Size : 64 KB
18 | Disk Cache Policy : Enabled
19 |
20 | ID : 1
21 | Status : Ok
22 | Name : DATA
23 | State : Ready
24 | Hot Spare Policy violated : Not Assigned
25 | Encrypted : Not Applicable
26 | Layout : RAID-5
27 | Size : 7,250.00 GB (7784628224000 bytes)
28 | T10 Protection Information Status : No
29 | Associated Fluid Cache State : Not Applicable
30 | Device Name : Windows Disk 1
31 | Bus Protocol : SATA
32 | Media : HDD
33 | Read Policy : No Read Ahead
34 | Write Policy : Write Back
35 | Cache Policy : Not Applicable
36 | Stripe Element Size : 64 KB
37 | Disk Cache Policy : Enable
--------------------------------------------------------------------------------
/src/data_structures/Trie/intro.md:
--------------------------------------------------------------------------------
1 | # Trie
2 |
3 | ## Intro
4 |
5 | - best known use case is auto-complete text.
6 | - also called digital tree or prefix tree, is a kind of search tree—an ordered tree data structure used to store a dynamic set or associative array where the keys are usually strings
7 | - The trie data structure (initially pronounced “tree” as in the middle syllable of re*trie*val, but now universally pronounced “try” to avoid confusion) is useful in scenarios usually reserved for a hash.
8 | - auto-complete saves additional info on the nodes about how frequently it is used as a word to improve predictive power
9 | - Each node's value will be a letter to represent a letter in a word
10 | - each node has children (arry of nodes alphabetized) to represent the next possible letters in the word (empty array if the word has ended), but there could be a node that has children while still being a full word already, for words contained in other words, e.g., geek in geeks, geek is a full word alread but has 's' as a child.
11 | - [diagram](https://4.bp.blogspot.com/-GNWc5KUMGYc/WAskP-EHFKI/AAAAAAAAEz4/8yikxc2niYgyqH0FWFafq5UTp_kUK6O5ACLcB/s1600/TrieDataStructureImpl.png)
12 |
13 | ## Starter Code
14 |
15 | ```js
16 | class TrieNode {
17 | constructor(val = null) {
18 | this.val = val;
19 | this.children = [];
20 | }
21 | }
22 |
23 | class TrieSet {
24 | constructor() {
25 | this.root = new TrieNode("");
26 | }
27 |
28 | method1(params) {
29 | // 'this' keyword will refer to the
30 | // HashMap instance that method1 was called on
31 | }
32 | }
33 |
34 | // Alternate way to add method to class after it has been declared
35 | TrieSet.prototype.newMethodName = function (params) {
36 | // 'this' keyword will refer to the
37 | // TrieSet instance that method1 was called on
38 | };
39 | ```
40 |
--------------------------------------------------------------------------------
/src/data_structures/Graphs/travelingSalesman/travelingSalesman.js:
--------------------------------------------------------------------------------
1 | /*
2 | Given a list of cities and the distances between each pair of cities, what is
3 | the shortest possible route that visits each city exactly once and returns to
4 | the origin city?
5 |
6 | In Technical Terms:
7 | Given a complete graph with weighted edges (as an adjacency map) what is the
8 | Hamiltonian cycle (path that visits every node once) of minimum cost?
9 |
10 | Time Complexity:
11 | Brute Force - O(n!) - Factorial, checks every possible path.
12 | Dynamic Programming: O(n^2 * 2^n)
13 |
14 | n n! n^2 * 2^n
15 | ------------------------------------------------------
16 | 1 1 2
17 | ------------------------------------------------------
18 | 2 2 16
19 | ------------------------------------------------------
20 | 3 6 72
21 | ------------------------------------------------------
22 | 4 24 256
23 | ------------------------------------------------------
24 | 5 120 800
25 | ------------------------------------------------------
26 | 6 720 2304
27 | ------------------------------------------------------
28 | ... ... ...
29 | ------------------------------------------------------
30 | 15 1307674368000 7372800
31 | ------------------------------------------------------
32 | 16 20922789888000 16777216
33 | ------------------------------------------------------
34 | 17 355687428096000 37879808
35 | ------------------------------------------------------
36 |
37 | DP Idea: compute the optimal solution for all the subpaths of length N while
38 | using information from the already known optimal partial tours of length N-1.
39 |
40 | Pick starting node "S" whose index is 0 <= S < N (including 0 to N exclusive)
41 | */
42 |
--------------------------------------------------------------------------------
/src/amazon/musicRuntime/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const busDuration1 = 300;
6 | const songDurations1 = [70, 120, 200, 45, 210, 40, 60, 50];
7 | const expected1 = [4, 6]; // 210, 60
8 | /* Explanation:
9 | There are multiple pairs that add up to 30 seconds before the bus duration.
10 | The pair at indexes 4 and 6 is the pair with the longest song that is chosen.
11 | */
12 |
13 | const busDuration2 = 300;
14 | const songDurations2 = [70, 120, 200, 230, 45, 210, 40, 60, 50];
15 | const expected2 = [3, 6]; // 230, 40
16 | /* Explanation:
17 | This is the pair with the longest song.
18 | */
19 |
20 | const busDuration3 = 300;
21 | const songDurations3 = [70, 120, 20, 23, 45, 21, 40, 60, 50];
22 | const expected3 = [-1, -1]; // not found.
23 |
24 | const testCases = [
25 | {
26 | args: [busDuration1, songDurations1],
27 | expected: expected1,
28 | description: "two possible solutions",
29 | },
30 | {
31 | args: [busDuration2, songDurations2],
32 | expected: expected2,
33 | description: "two possible neighboring solutions",
34 | },
35 | {
36 | args: [busDuration3, songDurations3],
37 | expected: expected3,
38 | description: "no solution",
39 | },
40 | ];
41 |
42 | testCases.forEach(({ args, expected, description }) => {
43 | describe("when given " + description, () => {
44 | it("should return the pair of songs that is 30 seconds less than the given bus duration or [-1, -1].", () => {
45 | expect(testFn(...args)).toEqual(
46 | jasmine.arrayWithExactContents(expected)
47 | );
48 | });
49 | });
50 | });
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/src/arrays/socialDistancingEnforcer/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Given an array of ints representing a line of people where the space between
3 | indexes is 1 foot, with 0 meaning no one is there and 1 meaning someone is in
4 | that space,
5 |
6 | return whether or not there is at least 6 feet separating every person.
7 |
8 | Bonus: O(n) linear time (avoid nested loops that cause re-visiting indexes).
9 | */
10 |
11 | const queue1 = [0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1];
12 | const expected1 = false;
13 |
14 | const queue2 = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1];
15 | const expected2 = true;
16 |
17 | const queue3 = [1, 0, 0, 0, 0, 0, 0, 0, 1];
18 | const expected3 = true;
19 |
20 | const queue4 = [];
21 | const expected4 = true;
22 |
23 | /**
24 | * Determines whether each occupied space in the line of people is separated by
25 | * 6 empty spaces.
26 | * - Time: O(?).
27 | * - Space: O(?).
28 | * @param {Array<0|1>} queue
29 | * @returns {Boolean}
30 | */
31 | function socialDistancingEnforcer(queue) {}
32 |
33 | /*****************************************************************************/
34 |
35 | /**
36 | * Determines whether each occupied space in the line of people is separated by
37 | * 6 empty spaces.
38 | * - Time: O(n) linear.
39 | * - Space: O(1) constant.
40 | * @param {Array<0|1>} queue
41 | * @returns {Boolean}
42 | */
43 | function socialDistancingEnforcer(queue = []) {
44 | let distance = 0;
45 | let firstPersonSeen = false;
46 |
47 | // Use the existing i value
48 | for (let i = 0; i < queue.length; i++) {
49 | if (queue[i] === 0) {
50 | distance += 1;
51 | } else {
52 | if (firstPersonSeen && distance < 6) {
53 | return false;
54 | }
55 |
56 | firstPersonSeen = true;
57 | distance = 0;
58 | }
59 | }
60 | return true;
61 | }
62 |
63 | module.exports = { socialDistancingEnforcer };
64 |
--------------------------------------------------------------------------------
/src/arrays/twoSum/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const nums1 = [2, 11, 7, 15];
6 | const targetSum1 = 9;
7 | const expected1 = [0, 2];
8 | // Explanation: nums[0] + nums[2] = 2 + 7 = 9
9 |
10 | const nums2 = [10, 3, 2, 5, 4, -1];
11 | const targetSum2 = 6;
12 | const expected2 = [2, 4];
13 |
14 | const nums3 = [3, 8, 4, 1, 9, 0, -2];
15 | const targetSum3 = 6;
16 | const expected3 = [1, 6];
17 |
18 | const nums4 = [3, 8, 4, 1, 9, 0, -2];
19 | const targetSum4 = 8;
20 | const expected4 = [1, 5];
21 |
22 | const testCases = [
23 | {
24 | args: [nums1, targetSum1],
25 | expected: expected1,
26 | description: "an array with the first number as part of the solution",
27 | },
28 | {
29 | args: [nums2, targetSum2],
30 | expected: expected2,
31 | description:
32 | "an array where the solution numbers are separated by one index",
33 | },
34 | {
35 | args: [nums3, targetSum3],
36 | expected: expected3,
37 | description:
38 | "an array where a negative number at the end is part of the solution",
39 | },
40 | {
41 | args: [nums4, targetSum4],
42 | expected: expected4,
43 | description: "an array where 0 is part of the solution",
44 | },
45 | ];
46 |
47 | testCases.forEach(({ args, expected, description }) => {
48 | describe("when given " + description, () => {
49 | it("should find the two ints in the given array that add up to the given sum and return their indexes.", () => {
50 | expect(testFn(...args)).toEqual(
51 | jasmine.arrayWithExactContents(expected)
52 | );
53 | });
54 | });
55 | });
56 | });
57 | });
58 |
--------------------------------------------------------------------------------
/src/recreated_methods/Array/join/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arr1 = [1, 2, 3];
6 | const separator1 = ", ";
7 | const expected1 = "1, 2, 3";
8 |
9 | const arr2 = [1, 2, 3];
10 | const separator2 = "-";
11 | const expected2 = "1-2-3";
12 |
13 | const arr3 = [1, 2, 3];
14 | const separator3 = " - ";
15 | const expected3 = "1 - 2 - 3";
16 |
17 | const arr4 = [1];
18 | const separator4 = ", ";
19 | const expected4 = "1";
20 |
21 | const arr5 = [];
22 | const separator5 = ", ";
23 | const expected5 = "";
24 |
25 | const testCases = [
26 | {
27 | args: [arr1, separator1],
28 | expected: expected1,
29 | description: "three items to join with comma and a space",
30 | },
31 | {
32 | args: [arr2, separator2],
33 | expected: expected2,
34 | description: "three items to join with a hyphen",
35 | },
36 | {
37 | args: [arr3, separator3],
38 | expected: expected3,
39 | description:
40 | "three items to join with a hyphen and a space on both sides",
41 | },
42 | {
43 | args: [arr4, separator4],
44 | expected: expected4,
45 | description: "one item only",
46 | },
47 | {
48 | args: [arr5, separator5],
49 | expected: expected5,
50 | description: "an empty array ",
51 | },
52 | ];
53 |
54 | testCases.forEach(({ args, expected }, i) => {
55 | describe(`when given testCases[${i}]`, () => {
56 | it("should return a string that contains the items of the given array joined and separated by the given separator.", () => {
57 | expect(testFn(...args)).toEqual(expected);
58 | });
59 | });
60 | });
61 | });
62 | });
63 |
--------------------------------------------------------------------------------
/src/recreated_methods/Array/pop/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const arr1 = [1, 2, 3];
6 | const expected1 = 3;
7 | // what arr1 should be after running pop function
8 | const expectedArr1 = [1, 2];
9 |
10 | const arr2 = ["hello"];
11 | const expected2 = "hello";
12 | const expectedArr2 = []; // the only item was removed
13 |
14 | const arr3 = ["hello", "world"];
15 | const expected3 = "world";
16 | const expectedArr3 = ["hello"]; // the last item was removed
17 |
18 | const arr4 = [];
19 | const expected4 = undefined;
20 | const expectedArr4 = [];
21 |
22 | const testCases = [
23 | {
24 | args: [arr1],
25 | expectedRet: expected1,
26 | expectedArr: expectedArr1,
27 | description: "three numbers",
28 | },
29 | {
30 | args: [arr2],
31 | expectedRet: expected2,
32 | expectedArr: expectedArr2,
33 | description: "one word",
34 | },
35 | {
36 | args: [arr3],
37 | expectedRet: expected3,
38 | expectedArr: expectedArr3,
39 | description: "two words",
40 | },
41 | {
42 | args: [arr4],
43 | expectedRet: expected4,
44 | expectedArr: expectedArr4,
45 | description: "an empty array",
46 | },
47 | ];
48 |
49 | testCases.forEach(({ args: [arr], expectedRet, expectedArr }, i) => {
50 | describe(`when given testCases[${i}]`, () => {
51 | it("should return the last item from the given array.", () => {
52 | expect(testFn(arr)).toBe(expectedRet);
53 | });
54 |
55 | it("should have removed the last item from the given array.", () => {
56 | expect(arr).toEqual(expectedArr);
57 | });
58 | });
59 | });
60 | });
61 | });
62 |
--------------------------------------------------------------------------------
/src/sets/orderedIntersection/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const numsA1 = [0, 1, 2, 2, 2, 7];
6 | const numsB1 = [2, 2, 6, 6, 7];
7 | const expected1 = [2, 7];
8 |
9 | const numsA2 = [0, 1, 2, 2, 2, 7];
10 | const numsB2 = [2, 2];
11 | const expected2 = [2];
12 |
13 | const numsA3 = [0, 1, 2, 2, 2, 7];
14 | const numsB3 = [10];
15 | const expected3 = [];
16 |
17 | const testCases = [
18 | {
19 | args: [numsA1, numsB1],
20 | expected: expected1,
21 | description: "a first array longer by one than the second array",
22 | },
23 | {
24 | args: [numsA2, numsB2],
25 | expected: expected2,
26 | description:
27 | "a first array more than double the size of the second array",
28 | },
29 | {
30 | args: [numsA3, numsB3],
31 | expected: expected3,
32 | description:
33 | "a second array with only one number that is larger than all the first array numbers",
34 | },
35 | ];
36 |
37 | testCases.forEach(({ args: [numsA, numsB], expected, description }) => {
38 | describe("when given " + description, () => {
39 | const copyOfNumsA = [...numsA];
40 | const copyOfNumsB = [...numsB];
41 | const actual = testFn(numsA, numsB);
42 |
43 | it("should return the ordered deduped intersection of two given sorted arrays.", () => {
44 | expect(actual).toEqual(expected);
45 | });
46 |
47 | it("should not mutate the first given array", () => {
48 | expect(numsA).toEqual(copyOfNumsA);
49 | });
50 |
51 | it("should not mutate the second given array", () => {
52 | expect(numsB).toEqual(copyOfNumsB);
53 | });
54 | });
55 | });
56 | });
57 | });
58 |
--------------------------------------------------------------------------------
/src/strings/isRotation/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Create the function isRotation(str1,str2) that
3 | returns whether the second string is a rotation of the first.
4 | */
5 |
6 | const strA1 = "ABCD";
7 | const strB1 = "CDAB";
8 | // Explanation: if you start from A in the 2nd string, the letters are in the same order, just rotated
9 | const expected1 = true;
10 |
11 | const strA2 = "ABCD";
12 | const strB2 = "CDBA";
13 | // Explanation: all same letters in 2nd string, but out of order
14 | const expected2 = false;
15 |
16 | const strA3 = "ABCD";
17 | const strB3 = "BCDAB";
18 | // Explanation: same letters in correct order but there is an extra letter.
19 | const expected3 = false;
20 |
21 | /**
22 | * Determines whether the second string is a rotated version of the first.
23 | * - Time: O(?).
24 | * - Space: O(?).
25 | * @param {string} s1
26 | * @param {string} s2
27 | * @returns {boolean} Whether the second string is a rotated version of the 1st.
28 | */
29 | function isRotation(s1, s2) {}
30 |
31 | /*****************************************************************************/
32 |
33 | /**
34 | * Solution approach:
35 | * All rotated versions of s2 are included in s1 + s1.
36 | * s1: "ABCD".
37 | * s1 + s1: "ABCDABCD".
38 | *
39 | * s2 Rotation variations:
40 | * s2: "CDAB".
41 | * s2: "DABC".
42 | * s2: "BCDA".
43 | * - Time: O(4n) -> O(n) linear. Concatenating s1 + s1 requires the characters
44 | * of s1 to be copied into a new string twice (2n). The .includes is then
45 | * looping over the string that is twice the length of s1 (2n) again. Add
46 | * up both 2n to get 4n.
47 | * - Space: O(2n) -> O(n) linear, where n is s1.length, 2n from s1 + s1.
48 | */
49 | function isRotation(s1 = "", s2 = "") {
50 | if (s1.length !== s2.length || s1 === s2) {
51 | return false;
52 | }
53 | return (s1 + s1).includes(s2);
54 | }
55 |
56 | module.exports = { isRotation };
57 |
--------------------------------------------------------------------------------
/src/objects/updateInventory/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const newInv1 = [
6 | { name: "Grain of Rice", quantity: 9000 },
7 | { name: "Peanut Butter", quantity: 50 },
8 | { name: "Royal Jelly", quantity: 20 },
9 | ];
10 | const currInv1 = [
11 | { name: "Peanut Butter", quantity: 20 },
12 | { name: "Grain of Rice", quantity: 1 },
13 | ];
14 | const expected1 = [
15 | { name: "Peanut Butter", quantity: 70 },
16 | { name: "Grain of Rice", quantity: 9001 },
17 | { name: "Royal Jelly", quantity: 20 },
18 | ];
19 |
20 | const newInv2 = [];
21 | const currInv2 = [{ name: "Peanut Butter", quantity: 20 }];
22 | const expected2 = [{ name: "Peanut Butter", quantity: 20 }];
23 |
24 | const newInv3 = [{ name: "Peanut Butter", quantity: 20 }];
25 | const currInv3 = [];
26 | const expected3 = [{ name: "Peanut Butter", quantity: 20 }];
27 |
28 | const testCases = [
29 | {
30 | args: [newInv1, currInv1],
31 | expected: expected1,
32 | description: "one two inventory item and two existing items",
33 | },
34 | {
35 | args: [newInv2, currInv2],
36 | expected: expected2,
37 | description: "an empty array of new inventory",
38 | },
39 | {
40 | args: [newInv3, currInv3],
41 | expected: expected3,
42 | description: "one new inventory item and empty current inventory",
43 | },
44 | ];
45 |
46 | testCases.forEach(({ args, expected }, i) => {
47 | describe(`when given testCases[${i}]`, () => {
48 | it("should return whether or not the 1st given string is a rotation of the 2nd given string.", () => {
49 | expect(testFn(...args)).toEqual(expected);
50 | });
51 | });
52 | });
53 | });
54 | });
55 |
--------------------------------------------------------------------------------
/src/strings/getQuoteFromCaret/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a str and an in-bounds idx that represents the position of the caret
3 | * return the substr that is enclosed by double quotes that the caret is within
4 | * or an empty string if the caret is not within double quotes.
5 | */
6 |
7 | const str1 = `wow "jabascript cool" lol "foo"`;
8 | const idx1 = 10;
9 | const expected1 = "jabascript cool";
10 |
11 | const str2 = `hello "world", good morning.`;
12 | const idx2 = 2;
13 | const expected2 = "";
14 |
15 | /**
16 | * Finds the double quote enclosed substr that the caret is within.
17 | * @param {string} str
18 | * @param {number} caretIdx Represents the location of the caret.
19 | * @returns {string} The double quote enclosed substr.
20 | */
21 | function getQuoteFromCaret(str, caretIdx) {}
22 |
23 | /*****************************************************************************/
24 |
25 | /**
26 | * Finds the double quote enclosed substr that the caret is within.
27 | * @param {string} str
28 | * @param {number} caretIdx Represents the location of the caret.
29 | * @returns {string} The double quote enclosed substr.
30 | */
31 | function getQuoteFromCaret(str, caretIdx) {
32 | let quote = "";
33 |
34 | let leftQuoteFound = false;
35 | let leftIdx = caretIdx;
36 |
37 | while (leftIdx >= 0) {
38 | if (str[leftIdx] === `"`) {
39 | leftQuoteFound = true;
40 | break;
41 | }
42 |
43 | quote = str[leftIdx] + quote;
44 | leftIdx--;
45 | }
46 |
47 | let rightIdx = caretIdx + 1;
48 | let rightQuoteFound = false;
49 |
50 | while (rightIdx < str.length) {
51 | if (str[rightIdx] === `"`) {
52 | rightQuoteFound = true;
53 | break;
54 | }
55 |
56 | quote += str[rightIdx];
57 | rightIdx++;
58 | }
59 |
60 | if (leftQuoteFound && rightQuoteFound) {
61 | return quote;
62 | }
63 |
64 | return "";
65 | }
66 |
67 | module.exports = { getQuoteFromCaret };
68 |
--------------------------------------------------------------------------------
/src/arrays/sumArrColumns/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Input: Two arrays of equal length containing integers
3 | Output: A new array where each item is the sum of
4 | the items in arr1 and arr2 at that same index
5 | */
6 |
7 | const numbersA1 = [20, 10, 30];
8 | const numbersB1 = [10, 30, 20];
9 | const expected1 = [30, 40, 50];
10 |
11 | /**
12 | * Returns a new array that is the sum of the columns of the two given arrays
13 | * of equal lengths.
14 | * - Time: O(?).
15 | * - Space: O(?).
16 | * @param {Array} nums1
17 | * @param {Array} nums2
18 | * @returns {Array} The column sums.
19 | */
20 | function sumArrColumns(nums1, nums2) {
21 | // code here
22 | }
23 |
24 | // Tests
25 | const result1 = sumArrColumns(numbersA1, numbersB1);
26 | console.log(result1, "should equal", expected1);
27 |
28 | /*****************************************************************************/
29 |
30 | /**
31 | * Returns a new array that is the sum of the columns of the two given arrays
32 | * of equal lengths.
33 | * - Time: O(n) linear, n = length of either nums1 or nums2 since they will
34 | * have the same length.
35 | * - Space: O(n) linear. The new array created will have the same length.
36 | * @param {Array} nums1
37 | * @param {Array} nums2
38 | * @returns {Array} The column sums.
39 | */
40 | function sumArrColumns(nums1 = [], nums2 = []) {
41 | const summedCols = [];
42 |
43 | for (let i = 0; i < nums1.length; i++) {
44 | summedCols.push(nums1[i] + nums2[i]);
45 | }
46 | return summedCols;
47 | }
48 |
49 | /**
50 | * - Time: O(n) linear.
51 | * - Space: O(n) linear. `.map` creates a new array.
52 | * @param {Array} nums1
53 | * @param {Array} nums2
54 | * @returns {Array}
55 | */
56 | const functionalSumArrColumns = (nums1 = [], nums2 = []) =>
57 | nums1.map((n1, i) => n1 + nums2[i]);
58 |
59 | module.exports = {
60 | sumArrColumns,
61 | functionalSumArrColumns,
62 | };
63 |
--------------------------------------------------------------------------------
/schedules/web_fund.md:
--------------------------------------------------------------------------------
1 | # Web Fund Algo Schedule
2 |
3 | - [Pair Programming](../pair-programming.md)
4 | - **NOTE: A new set of web fund algos were added to web fund 2021 curriculum so these are no longer used, but they are a great fundamental set if more algos are desired and the platform doesn't cover the recreation of some of the fundamental array methods that are covered here.**
5 | - [Printable Basic 13](https://docs.google.com/document/d/1Vw-8ZzZy_kfkcK-6MUkXJNfNQ7qX9_nkxnIBNoVNdbM/edit#heading=h.wr6t3eu5n64f)
6 |
7 | ---
8 |
9 | ## Week 1 - Intro
10 |
11 | 1. Mon
12 | - Orientation
13 | - basics review: variables, arrays, loops, functions
14 | - [Functions Intro](../src/intro/basicAlgos/intro.md)
15 | 2. Tue
16 | - [basicAlgos](../src/intro/basicAlgos/index.js)
17 | 3. Wed
18 | - [indexOf](../src/recreated_methods/Array/indexOf/index.js)
19 | - unfinished [basicAlgos](../src/intro/basicAlgos/index.js)
20 | 4. Thur
21 | - [nthLast](../src/arrays/nthLast/index.js)
22 | - [countEvenNegatives](../src/arrays/countEvenNegatives/index.js)
23 | 5. Fri
24 | - [slice](../src/recreated_methods/Array/slice/index.js)
25 | - [capitalization](../src/strings/capitalization/index.js)
26 |
27 | ---
28 |
29 | ## Week 2 - Arrays
30 |
31 | 1. Mon
32 | - [concat](../src/recreated_methods/Array/concat/index.js)
33 | - [concatSelf](../src/arrays/concatSelf/index.js)
34 | 2. Tue
35 | - [indexOfMinVal](../src/arrays/indexOfMinVal/index.js)
36 | - [reverseArr](../src/arrays/reverseArr/index.js)
37 | 3. Wed
38 | - [unshift](../src/recreated_methods/Array/unshift/index.js)
39 | - [shift](../src/recreated_methods/Array/shift/index.js)
40 | 4. Thur
41 | - [removeAt](../src/arrays/removeAt/index.js)
42 | - [minToFront](../src/arrays/minToFront/index.js)
43 | 5. Fri
44 | - [flatten2dArray](../src/arrays/flatten2dArray/index.js)
45 | - [secondLargest](../src/arrays/secondLargest/index.js)
46 | - [sumArrColumns](../src/arrays/sumArrColumns/index.js)
47 |
--------------------------------------------------------------------------------
/src/data_structures/Trie/index.js:
--------------------------------------------------------------------------------
1 | class TrieNode {
2 | constructor(val = null) {
3 | this.val = val;
4 | // children will be TrieNodes as well
5 | this.children = [];
6 | }
7 | }
8 |
9 | class TrieSet {
10 | constructor() {
11 | this.root = new TrieNode("");
12 | }
13 |
14 | add(val, node = this.root, partial = "") {
15 | // when val str has been sliced all the way it will be empty str
16 | if (val === "") {
17 | if (node.val === partial) {
18 | return false;
19 | }
20 |
21 | node.val = partial;
22 | return true;
23 | }
24 |
25 | const index = val[0].toLowerCase().charCodeAt(0) - 97;
26 | let nextNode = node.children[index];
27 |
28 | if (nextNode === undefined) {
29 | nextNode = node.children[index] = new TrieNode();
30 | }
31 | return this.add(val.slice(1), nextNode, partial + val[0]);
32 | }
33 |
34 | contains(val, node = this.root, partial = "") {
35 | if (node === undefined) {
36 | return false;
37 | }
38 |
39 | if (val === "") {
40 | return node.val === partial;
41 | }
42 |
43 | const index = val[0].toLowerCase().charCodeAt(0) - 97;
44 | return this.contains(val.slice(1), node.children[index], partial + val[0]);
45 | }
46 |
47 | autoComplete(val, node = this.root, completions = []) {
48 | if (node === undefined) return completions;
49 |
50 | if (val === "") {
51 | if (node.val !== null) {
52 | completions.push(node.val);
53 | }
54 |
55 | for (let i = 0; i < node.children.length; i++) {
56 | if (node.children[i] !== undefined) {
57 | this.autoComplete("", node.children[i], completions);
58 | }
59 | }
60 | } else {
61 | const index = val[0].toLowerCase().charCodeAt(0) - 97;
62 | this.autoComplete(val.slice(1), node.children[index], completions);
63 | }
64 | return completions;
65 | }
66 | }
67 |
68 | module.exports = {
69 | TrieSet,
70 | TrieNode,
71 | };
72 |
--------------------------------------------------------------------------------
/src/objects/groupObjects/index.spec.js:
--------------------------------------------------------------------------------
1 | const functions = require(".");
2 |
3 | Object.values(functions).forEach((testFn) => {
4 | describe(testFn.name, () => {
5 | const objects1 = [
6 | {
7 | name: "Baby Yoda",
8 | category: "cute",
9 | },
10 | {
11 | name: "Cricket Protein",
12 | category: "food",
13 | },
14 | {
15 | name: "Shibe",
16 | category: "Cute",
17 | },
18 | {
19 | name: "Ancient India",
20 | category: "Cradle of Civilization",
21 | },
22 | {
23 | name: "Wasp Crackers",
24 | category: "Food",
25 | },
26 | {
27 | name: "The Fertile Crescent",
28 | category: "Cradle of Civilization",
29 | },
30 | ];
31 |
32 | const expected1 = {
33 | cute: [
34 | {
35 | name: "Baby Yoda",
36 | category: "cute",
37 | },
38 | {
39 | name: "Shibe",
40 | category: "Cute",
41 | },
42 | ],
43 | food: [
44 | {
45 | name: "Cricket Protein",
46 | category: "food",
47 | },
48 | {
49 | name: "Wasp Crackers",
50 | category: "Food",
51 | },
52 | ],
53 | "cradle of civilization": [
54 | {
55 | name: "Ancient India",
56 | category: "Cradle of Civilization",
57 | },
58 | {
59 | name: "The Fertile Crescent",
60 | category: "Cradle of Civilization",
61 | },
62 | ],
63 | };
64 |
65 | const testCases = [{ args: [objects1], expected: expected1 }];
66 | testCases.forEach(({ args, expected }, i) => {
67 | describe(`when given testCases[${i}]`, () => {
68 | it("should return a new array of only the objects from the given array that match the provided search criteria.", () => {
69 | expect(testFn(...args)).toEqual(expected);
70 | });
71 | });
72 | });
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/src/objects/invertObj/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Invert Hash
3 |
4 | A hash table / hash map is an obj / dictionary
5 |
6 | Given an object / dict,
7 | return a new object / dict that has the keys and the values swapped so that the keys become the values and the values become the keys
8 | */
9 |
10 | const obj1 = { name: "Zaphod", charm: "high", morals: "dicey" };
11 | const expected1 = { Zaphod: "name", high: "charm", dicey: "morals" };
12 |
13 | /**
14 | * Inverts the given object's key value pairs so that the original values
15 | * become the keys and the original keys become the values.
16 | * - Time: O(?).
17 | * - Space: O(?).
18 | * @param {Object} obj
19 | * @return The given object with key value pairs inverted.
20 | */
21 | function invertObj(obj) {}
22 |
23 | /*****************************************************************************/
24 |
25 | /**
26 | * Inverts the given object's key value pairs so that the original values
27 | * become the keys and the original keys become the values.
28 | * - Time: O(n) linear, where n is amount of keys in obj.
29 | * - Space: O(n).
30 | * @param {Object} obj
31 | * @return The given object with key value pairs inverted.
32 | */
33 | function invertObj(obj = {}) {
34 | const inverted = {};
35 |
36 | for (let key in obj) {
37 | const value = obj[key];
38 |
39 | inverted[value] = key;
40 | }
41 | return inverted;
42 | }
43 |
44 | /**
45 | * Inverts the given object's key value pairs so that the original values
46 | * become the keys and the original keys become the values.
47 | * - Time: O(2n) -> O(n) linear, where n is amount of keys in obj.
48 | * - Space: O(n).
49 | * @param {Object} obj
50 | * @return The given object with key value pairs inverted.
51 | */
52 | const functionalInvertObj = (obj = {}) =>
53 | Object.entries(obj).reduce((inverted, [key, value]) => {
54 | inverted[value] = key;
55 | return inverted;
56 | }, {});
57 |
58 | module.exports = { invertObj, functionalInvertObj };
59 |
--------------------------------------------------------------------------------