diff --git a/.eslintrc b/.eslintrc index b3aa6db..f6c16e1 100644 --- a/.eslintrc +++ b/.eslintrc @@ -16,7 +16,8 @@ 2, "always" ], - "eqeqeq": 2 + "eqeqeq": 2, + "no-console": 0 }, "env": { "es6": true, @@ -28,4 +29,4 @@ "modules": true }, "extends": "eslint:recommended" -} +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4bc1dbf --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,23 @@ +{ + // Use IntelliSense to learn about possible Node.js debug attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "mocha", + "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", + "stopOnEntry": false, + "args": [ + "--no-timeouts", + "--colors" + ], //you can specify paths to specific tests here + "cwd": "${workspaceRoot}", + "env": { + "NODE_ENV": "testing" + } + } + ] +} \ No newline at end of file diff --git a/src/chapter10/q01.js b/src/chapter10/q01.js new file mode 100644 index 0000000..274e667 --- /dev/null +++ b/src/chapter10/q01.js @@ -0,0 +1,9 @@ +export function merge(A, B) { + for (let aIndex = 0; aIndex < A.length && 0 < B.length; aIndex++) { + if (A[aIndex] > B[0]) { + A.splice(aIndex, 0, B.shift()); + A.pop(); + } + } + return A; +} \ No newline at end of file diff --git a/src/chapter10/q01.spec.js b/src/chapter10/q01.spec.js new file mode 100644 index 0000000..172db4c --- /dev/null +++ b/src/chapter10/q01.spec.js @@ -0,0 +1,11 @@ +import { expect } from 'chai'; +import { merge } from './q01'; + +describe('ch10-q01', function () { + const A = [1, 3, 5, 6, 7, undefined, undefined]; + const B = [2, 4]; + const result = merge(A, B); + it('merges arrays into one ordered', function () { + expect(result).to.be.eql([1, 2, 3, 4, 5, 6, 7]); + }); +}); \ No newline at end of file diff --git a/src/chapter10/q02.js b/src/chapter10/q02.js new file mode 100644 index 0000000..1776578 --- /dev/null +++ b/src/chapter10/q02.js @@ -0,0 +1,28 @@ +//10.2 Group Anagrams: Write a method to sort an array of strings so that all the anagrams are next to each other. + +export function groupAnagrams(A) { + let buckets = []; + for (let i = 0, len = A.length; i < len; i++) { + const elementSorted = sortLetters(A[i]); + const bucket = buckets.find((element) => { + return elementSorted === element.sortedWord; + }); + if (bucket) { + bucket.elements.push(A[i]); + } + else { + buckets.push({ sortedWord: elementSorted, elements: [A[i]] }); + } + } + + let result = []; + for (let i = 0, len = buckets.length; i < len; i++) { + result = result.concat(buckets[i].elements); + } + + return result; +} + +function sortLetters(word) { + return word.toLowerCase().split('').sort().join(''); +} \ No newline at end of file diff --git a/src/chapter10/q02.spec.js b/src/chapter10/q02.spec.js new file mode 100644 index 0000000..3586797 --- /dev/null +++ b/src/chapter10/q02.spec.js @@ -0,0 +1,11 @@ +import { expect } from 'chai'; +import { groupAnagrams } from './q02'; + + +describe('ch10-q02', function () { + const A = ['asd', 'as', 'sAd', 'sA', 'Das']; + const result = groupAnagrams(A); + it('Sorting an array of strings so that all the anagrams are next to each other.', function () { + expect(result).to.be.eql(['asd', 'sAd', 'Das', 'as', 'sA']); + }); +}); \ No newline at end of file diff --git a/src/chapter10/q04.js b/src/chapter10/q04.js new file mode 100644 index 0000000..469c25a --- /dev/null +++ b/src/chapter10/q04.js @@ -0,0 +1,51 @@ +/*10.4 Sorted Search, No Size: You are given an array-like data structure Listy +which lacks a size method.It does, however, have an elementAt(i) method that +returns the element at index i in 0(1) time. If i is beyond the bounds of the +data structure, it returns -1. (For this reason, the data structure only supports +positive integers.) Given a Listy which contains sorted, positive integers, find the +index at which an element x occurs. If x occurs multiple times, you may return any index.*/ + +export function Listy(array) { + this._array = array; +} + +Listy.prototype.elementAt = function (index) { + if (index >= this._array.length) { + return -1; + } + + return this._array[index]; +}; + +export function findIndex(listy, x) { + //looking for borders of binary search + let left = 0; + let right = 3 * left + 1; + while (listy.elementAt(right) !== -1 && listy.elementAt(right) < x) { + left = right; + right = 3 * left + 1; + } + + //doing search + while (right !== left) { + if (x === listy.elementAt(right)) { + return right; + } + if (x === listy.elementAt(left)) { + return left; + } + if (-1 === listy.elementAt(left) && -1 === listy.elementAt(right)) { + return -1; + } + + const middle = Math.floor(left + (right - left) / 2); + if (x <= listy.elementAt(middle) || middle === left || -1 === listy.elementAt(middle)) { + right = middle; + } + else { + left = middle; + } + } + + return -1; +} \ No newline at end of file diff --git a/src/chapter10/q04.spec.js b/src/chapter10/q04.spec.js new file mode 100644 index 0000000..440d402 --- /dev/null +++ b/src/chapter10/q04.spec.js @@ -0,0 +1,26 @@ +import { expect } from 'chai'; +import { findIndex, Listy } from './q04'; + + +describe('ch10-q04: find index in listy', function () { + const listy = new Listy([2, 4, 5, 6, 19, 20, 50, 100]); + const result = findIndex(listy, 80); + it('Item between the existing items range but doesn\'t exist in listy', function () { + expect(result).to.be.eql(-1); + }); + + const result1 = findIndex(listy, 120); + it('Item bigger then any element in listy', function () { + expect(result1).to.be.eql(-1); + }); + + const result2 = findIndex(listy, 50); + it('Item 50 exists in listy', function () { + expect(result2).to.be.eql(6); + }); + + const result3 = findIndex(listy, 19); + it('Item 19 exists in listy', function () { + expect(result3).to.be.eql(4); + }); +}); \ No newline at end of file diff --git a/src/chapter10/q05.js b/src/chapter10/q05.js new file mode 100644 index 0000000..b25bacf --- /dev/null +++ b/src/chapter10/q05.js @@ -0,0 +1,34 @@ +/*10.5 Sparse Search: Given a sorted array of strings that is interspersed +with empty strings, write a method to find the location of a given string.*/ + +export function findIndex(stringArray, word) { + //saving word indexes in separate array + let wordIndexes = []; + for (let i = 0, len = stringArray.length; i < len; i++) { + if (stringArray[i] !== '') { + wordIndexes.push(i); + } + } + + //doing binary search only with indexes of words + let left = 0; + let right = wordIndexes.length - 1; + while (left !== right) { + if (word === stringArray[wordIndexes[left]]) { + return wordIndexes[left]; + } + if (word === stringArray[wordIndexes[right]]) { + return wordIndexes[right]; + } + + + const middle = Math.floor(left + (right - left) / 2); + if (word <= stringArray[wordIndexes[middle]] || middle === left) { + right = middle; + } + else { + left = middle; + } + } + return -1; +} \ No newline at end of file diff --git a/src/chapter10/q05.spec.js b/src/chapter10/q05.spec.js new file mode 100644 index 0000000..79e1edb --- /dev/null +++ b/src/chapter10/q05.spec.js @@ -0,0 +1,32 @@ +import { expect } from 'chai'; +import { findIndex } from './q05'; + + +describe('ch10-q05: find index of item in string array with empty strings. ', function () { + const array = ['at', '', '', '', 'ball', '', '', 'car', '', '', 'dad', '', '']; + + it('Index of "ball"', function () { + let result = findIndex(array, 'ball'); + expect(result).to.be.eq(4); + }); + + it('Index of "at"', function () { + let result = findIndex(array, 'at'); + expect(result).to.be.eq(0); + }); + + it('Index of "car"', function () { + let result = findIndex(array, 'car'); + expect(result).to.be.eq(7); + }); + + it('Index of "dad"', function () { + let result = findIndex(array, 'dad'); + expect(result).to.be.eq(10); + }); + + it('Index of item that doen\'t exist in array', function () { + let result = findIndex(array, 'trololo'); + expect(result).to.be.eq(-1); + }); +}); \ No newline at end of file diff --git a/src/chapter10/q08.js b/src/chapter10/q08.js new file mode 100644 index 0000000..8376007 --- /dev/null +++ b/src/chapter10/q08.js @@ -0,0 +1,23 @@ +/*10.8 Find Duplicates: You have an array with all the numbers from 1to N, +where Nis at most 32,000.The array may have duplicate entries and you do not +know what N is. With only 4 kilobytes of memory available, how would you print +all duplicate elements in the array? +*/ + +export function getDuplicates(intArray) { + const vector = {}; + const duplicates = []; + for (var i = 0; i < intArray.length; i++) { + var element = intArray[i]; + if (vector[element]) { + if (-1 === duplicates.indexOf(element)) { + duplicates.push(element); + } + } + else { + vector[element] = 1; + } + } + + return duplicates; +} \ No newline at end of file diff --git a/src/chapter10/q08.spec.js b/src/chapter10/q08.spec.js new file mode 100644 index 0000000..5e5963d --- /dev/null +++ b/src/chapter10/q08.spec.js @@ -0,0 +1,12 @@ +import { expect } from 'chai'; +import { getDuplicates } from './q08'; + + +describe('ch10-q08: find duplicates in int array', function () { + const array = [1, 2, 3, 4, 1, 6, 3]; + + it('Index of "ball"', function () { + let result = getDuplicates(array, 'ball'); + expect(result).to.be.eql([1, 3]); + }); +}); \ No newline at end of file diff --git a/src/chapter10/q11.js b/src/chapter10/q11.js new file mode 100644 index 0000000..661889c --- /dev/null +++ b/src/chapter10/q11.js @@ -0,0 +1,26 @@ +/*10.11 Peaks and Valleys: In an array of integers, a "peak" is an element which +is greater than or equal to the adjacent integers and a "valley" is an element which +is less than or equal to the adjacent inte- gers. For example, in the array +{5, 8, 6, 2, 3, 4, 6}, {8, 6} are peaks and {S, 2} are valleys. Given an array of +integers, sort the array into an alternating sequence of peaks and valleys. +EXAMPLE +Input: {5, 3, 1, 2, 3} +Output: {5, 1, 3, 2, 3}.*/ + +export function sort(intArray) { + intArray.sort(); + + let ind = 0; + while (ind < Math.floor(intArray.length / 2)) { + swap(intArray, ind, intArray.length - ind - 1); + ind += 2; + } + + return intArray; +} + +function swap(array, a, b) { + const buffer = array[a]; + array[a] = array[b]; + array[b] = buffer; +} \ No newline at end of file diff --git a/src/chapter10/q11.spec.js b/src/chapter10/q11.spec.js new file mode 100644 index 0000000..9ae57f1 --- /dev/null +++ b/src/chapter10/q11.spec.js @@ -0,0 +1,26 @@ +import { expect } from 'chai'; +import { sort } from './q11'; + +describe('ch10-q11: sort array to peeks and valleys. ', function () { + const array = [5, 3, 1, 2, 3]; + + it('Should return correctly sorted array with only peaks and valleys.', function () { + let result = sort(array); + let isCorrectSort = result.every((value, index, arr) => { + return isValleyOrPeek(arr, index); + }); + expect(isCorrectSort).to.be.eq(true, JSON.stringify(result)); + }); +}); + +function isValleyOrPeek(array, index) { + + if (index === 0 || index === array.length - 1) { + return true; + } + if (array[index - 1] <= array[index] && array[index + 1] <= array[index] + || array[index - 1] >= array[index] && array[index + 1] >= array[index]) { + return true; + } + return false; +} \ No newline at end of file