Skip to content
Open
5 changes: 3 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
2,
"always"
],
"eqeqeq": 2
"eqeqeq": 2,
"no-console": 0
},
"env": {
"es6": true,
Expand All @@ -28,4 +29,4 @@
"modules": true
},
"extends": "eslint:recommended"
}
}
23 changes: 23 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
]
}
9 changes: 9 additions & 0 deletions src/chapter10/q01.js
Original file line number Diff line number Diff line change
@@ -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;
}
11 changes: 11 additions & 0 deletions src/chapter10/q01.spec.js
Original file line number Diff line number Diff line change
@@ -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]);
});
});
28 changes: 28 additions & 0 deletions src/chapter10/q02.js
Original file line number Diff line number Diff line change
@@ -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('');
}
11 changes: 11 additions & 0 deletions src/chapter10/q02.spec.js
Original file line number Diff line number Diff line change
@@ -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']);
});
});
51 changes: 51 additions & 0 deletions src/chapter10/q04.js
Original file line number Diff line number Diff line change
@@ -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;
}
26 changes: 26 additions & 0 deletions src/chapter10/q04.spec.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
34 changes: 34 additions & 0 deletions src/chapter10/q05.js
Original file line number Diff line number Diff line change
@@ -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;
}
32 changes: 32 additions & 0 deletions src/chapter10/q05.spec.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
23 changes: 23 additions & 0 deletions src/chapter10/q08.js
Original file line number Diff line number Diff line change
@@ -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;
}
12 changes: 12 additions & 0 deletions src/chapter10/q08.spec.js
Original file line number Diff line number Diff line change
@@ -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]);
});
});
26 changes: 26 additions & 0 deletions src/chapter10/q11.js
Original file line number Diff line number Diff line change
@@ -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;
}
26 changes: 26 additions & 0 deletions src/chapter10/q11.spec.js
Original file line number Diff line number Diff line change
@@ -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;
}