├── .babelrc ├── 00_other ├── compareRandom.js ├── randomSequence.js ├── max.js └── sequence.js ├── 06_bfs ├── src │ ├── personIsSeller.js │ ├── addToQueue.js │ └── findMangoSeller.js └── app │ └── findMangoSellerScript.js ├── 03_recursion ├── src │ ├── countdown.js │ ├── sum.js │ ├── count.js │ └── factorial.js └── app │ └── countdownScript.js ├── 05_hash ├── src │ └── vote.js └── app │ └── voteScript.js ├── 04_quickSort ├── app │ └── quickSortScript.js └── src │ └── quickSort.js ├── 02_selectionSort ├── app │ ├── selectionSortScript.js │ └── findSmallestScript.js └── src │ ├── findSmallest.js │ └── selectionSort.js ├── 01_binarySearch ├── app │ └── binarySearchScript.js └── src │ └── binarySearch.js ├── 07_dijkstrasAlg ├── src │ ├── findLowestCostNode.js │ └── findLowestCostWay.js └── app │ └── findLowestCostWayScript.js ├── 08_greedyAlg ├── app │ └── statesScript.js └── src │ └── states.js └── README.md /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env"] 3 | } 4 | -------------------------------------------------------------------------------- /00_other/compareRandom.js: -------------------------------------------------------------------------------- 1 | export default (a, b) => Math.random() - 0.5; 2 | -------------------------------------------------------------------------------- /06_bfs/src/personIsSeller.js: -------------------------------------------------------------------------------- 1 | export default (name) => name.slice(-1) === 'm'; 2 | -------------------------------------------------------------------------------- /03_recursion/src/countdown.js: -------------------------------------------------------------------------------- 1 | const countdown = (num) => { 2 | console.log(num); 3 | return num <= 1 ? null : countdown(num - 1); 4 | } 5 | 6 | export default countdown; 7 | -------------------------------------------------------------------------------- /06_bfs/src/addToQueue.js: -------------------------------------------------------------------------------- 1 | export default (list, queue) => { 2 | for (let i = 0; i < list.length; i += 1) { 3 | queue.push(list[i]); 4 | } 5 | return queue; 6 | } 7 | -------------------------------------------------------------------------------- /03_recursion/src/sum.js: -------------------------------------------------------------------------------- 1 | const sum = (array) => { 2 | if (array.length <= 1) { 3 | return array[0]; 4 | } 5 | 6 | return array.shift() + sum(array); 7 | } 8 | 9 | export default sum; 10 | -------------------------------------------------------------------------------- /00_other/randomSequence.js: -------------------------------------------------------------------------------- 1 | import compareRandom from './compareRandom'; 2 | import sequence from './sequence'; 3 | 4 | export default (start, end) => { 5 | return sequence(start, end).sort(compareRandom); 6 | } 7 | -------------------------------------------------------------------------------- /03_recursion/src/count.js: -------------------------------------------------------------------------------- 1 | const count = (list) => { 2 | if (list.length === 0) { 3 | return 0; 4 | } 5 | list.shift(); 6 | return 1 + count(list); 7 | } 8 | 9 | export default count; 10 | -------------------------------------------------------------------------------- /03_recursion/src/factorial.js: -------------------------------------------------------------------------------- 1 | const factorial = (num) => { 2 | if (num === 0 || num === 1) { 3 | return 1; 4 | } 5 | 6 | return num * factorial(num - 1); 7 | } 8 | 9 | export default factorial; 10 | -------------------------------------------------------------------------------- /05_hash/src/vote.js: -------------------------------------------------------------------------------- 1 | export default (name, voted) => { 2 | if (name in voted) { 3 | console.log("kick them out!"); 4 | } else { 5 | voted[name] = true; 6 | console.log("let them vote!"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /00_other/max.js: -------------------------------------------------------------------------------- 1 | const max = (list) => { 2 | if (list.length === 1) { 3 | return list[0]; 4 | } 5 | const head = list.shift(); 6 | const tail = max(list); 7 | return head >= tail ? head : tail; 8 | } 9 | 10 | export default max; 11 | -------------------------------------------------------------------------------- /05_hash/app/voteScript.js: -------------------------------------------------------------------------------- 1 | import checkVoter from '../src/vote'; 2 | 3 | let voted = {}; 4 | 5 | checkVoter("Mike", voted); 6 | console.log(voted); 7 | checkVoter("John", voted); 8 | console.log(voted); 9 | checkVoter("Mike", voted); 10 | console.log(voted); 11 | -------------------------------------------------------------------------------- /04_quickSort/app/quickSortScript.js: -------------------------------------------------------------------------------- 1 | import quickSort from '../src/quickSort'; 2 | import randomSequence from '../../00_other/randomSequence'; 3 | 4 | const array = randomSequence(1, 10); 5 | console.log("Sequence: " + array); 6 | console.log("Sorted: " + quickSort(array)); 7 | -------------------------------------------------------------------------------- /00_other/sequence.js: -------------------------------------------------------------------------------- 1 | export default (start, end) => { 2 | if (start > end) { 3 | return []; 4 | } 5 | 6 | let result = []; 7 | for (let i = start; i <= end; i += 1) { 8 | result.push(i); 9 | } 10 | 11 | return result; 12 | } 13 | -------------------------------------------------------------------------------- /02_selectionSort/app/selectionSortScript.js: -------------------------------------------------------------------------------- 1 | import selectionSort from '../src/selectionSort'; 2 | import randomSequence from '../src/randomSequence'; 3 | 4 | const array = randomSequence(1, 10); 5 | console.log("Sequence: " + array); 6 | console.log("Sorted: " + selectionSort(array)); 7 | -------------------------------------------------------------------------------- /02_selectionSort/app/findSmallestScript.js: -------------------------------------------------------------------------------- 1 | import randomSequence from '../src/randomSequence'; 2 | import findSmallest from '../src/findSmallest'; 3 | 4 | const array = randomSequence(1, 10); 5 | console.log("Sequence: " + array); 6 | console.log("Index of smallest: " + findSmallest(array)); 7 | -------------------------------------------------------------------------------- /01_binarySearch/app/binarySearchScript.js: -------------------------------------------------------------------------------- 1 | import sequence from '../src/sequence'; 2 | import binarySearch from '../src/binarySearch'; 3 | 4 | const list = sequence(1, 10); 5 | const item = 3; 6 | 7 | console.log("Item: " + item); 8 | console.log("Sequence: " + list); 9 | console.log("Index of item: " + binarySearch(list, item)); 10 | -------------------------------------------------------------------------------- /02_selectionSort/src/findSmallest.js: -------------------------------------------------------------------------------- 1 | export default (arr) => { 2 | let smallest = arr[0]; 3 | let smallestIndex = 0; 4 | 5 | for (let i = 0; i < arr.length; i += 1) { 6 | if (arr[i] < smallest) { 7 | smallest = arr[i]; 8 | smallestIndex = i; 9 | } 10 | } 11 | 12 | return smallestIndex; 13 | } 14 | -------------------------------------------------------------------------------- /02_selectionSort/src/selectionSort.js: -------------------------------------------------------------------------------- 1 | import findSmallest from '../../00_other/findSmallest'; 2 | 3 | export default (array) => { 4 | let size = array.length; 5 | let newArr = []; 6 | for (let i = 0; i < size; i += 1) { 7 | let smallest = findSmallest(array); 8 | newArr.push(array[smallest]); 9 | array.splice(smallest, 1); 10 | } 11 | 12 | return newArr; 13 | } 14 | -------------------------------------------------------------------------------- /07_dijkstrasAlg/src/findLowestCostNode.js: -------------------------------------------------------------------------------- 1 | export default (costs, processed) => { 2 | let lowestCost = Infinity; 3 | let lowestCostIndex = null; 4 | for (let node in costs) { 5 | let cost = costs[node]; 6 | if (cost < lowestCost && processed.indexOf(node) === -1) { 7 | lowestCost = costs[node]; 8 | lowestCostIndex = node; 9 | } 10 | } 11 | return lowestCostIndex; 12 | } 13 | -------------------------------------------------------------------------------- /03_recursion/app/countdownScript.js: -------------------------------------------------------------------------------- 1 | //import countdown from '../source/countdown'; 2 | //import factorial from '../source/factorial'; 3 | //import sum from '../source/sum'; 4 | //import count from '../source/count'; 5 | 6 | const list = [4, 6, 2]; 7 | console.log(max(list)); 8 | 9 | //const list = [2, 4, 6]; 10 | //console.log(count(list)); 11 | 12 | //const array = [2, 4 ,6]; 13 | //console.log(sum(array)); 14 | 15 | //console.log(factorial(5)); 16 | //countdown(10); 17 | -------------------------------------------------------------------------------- /08_greedyAlg/app/statesScript.js: -------------------------------------------------------------------------------- 1 | import states from '../src/states'; 2 | 3 | let statesNeeded = new Set(["mt", "wa", "or", "id", "nv", "ut", "ca", "az"]); 4 | 5 | let stations = new Map([ 6 | ["kone", new Set(["id", "nv", "ut"])], 7 | ["ktwo", new Set(["wa", "id", "mt"])], 8 | ["kthree", new Set(["or", "nv", "са"])], 9 | ["kfour", new Set(["nv", "ut"])], 10 | ["kfive", new Set(["ca", "az"])] 11 | ]); 12 | 13 | console.log(states(statesNeeded, stations)); 14 | -------------------------------------------------------------------------------- /01_binarySearch/src/binarySearch.js: -------------------------------------------------------------------------------- 1 | export default (list, item) => { 2 | let low = 0; 3 | let high = list.length - 1; 4 | 5 | while (low <= high){ 6 | let mid = Math.floor((low + high) / 2); 7 | let guess = list[mid]; 8 | if (guess === item) { 9 | return mid; 10 | } 11 | if (guess > item) { 12 | high = mid - 1; 13 | } 14 | if (guess < item) { 15 | low = mid + 1; 16 | } 17 | } 18 | 19 | return null; 20 | } 21 | -------------------------------------------------------------------------------- /04_quickSort/src/quickSort.js: -------------------------------------------------------------------------------- 1 | const quickSort = (array) => { 2 | if (array.length < 2) { 3 | return array; 4 | } 5 | 6 | const pivot = array[0]; 7 | let less = []; 8 | let greater = []; 9 | 10 | for (let i = 1; i < array.length; i += 1) { 11 | if (array[i] <= pivot) { 12 | less.push(array[i]); 13 | } else { 14 | greater.push(array[i]); 15 | } 16 | } 17 | 18 | return quickSort(less).concat(pivot, quickSort(greater)); 19 | } 20 | 21 | export default quickSort; 22 | -------------------------------------------------------------------------------- /06_bfs/app/findMangoSellerScript.js: -------------------------------------------------------------------------------- 1 | import findMangoSeller from '../src/findMangoSeller'; 2 | 3 | /* 4 | let graph = {}; 5 | graph["you"] = ["alice", "bob", "claire"]; 6 | graph["bob"] = ["anuj", "peggy"]; 7 | graph["alice"] = ["peggy"]; 8 | graph["claire"] = ["thom", "jonny"]; 9 | graph["anuj"] = []; 10 | graph["peggy"] = []; 11 | graph["thom"] = []; 12 | graph["jonny"] = []; 13 | */ 14 | 15 | let graph = {}; 16 | graph["you"] = ["alice"]; 17 | graph["alice"] = ["you"]; 18 | 19 | let searchQueue = []; 20 | 21 | console.log(findMangoSeller(searchQueue, graph, "you")); 22 | -------------------------------------------------------------------------------- /07_dijkstrasAlg/app/findLowestCostWayScript.js: -------------------------------------------------------------------------------- 1 | import findLowestCostWay from '../src/findLowestCostWay'; 2 | 3 | let graph = {}; 4 | graph["start"] = {}; 5 | graph["start"]["a"] = 6; 6 | graph["start"]["b"] = 2; 7 | graph["a"] = {}; 8 | graph["a"]["fin"] = 1; 9 | graph["b"] = {}; 10 | graph["b"]["a"] = 3; 11 | graph["b"]["fin"] = 5; 12 | graph["fin"] = {}; 13 | 14 | let costs = {}; 15 | costs["a"] = 6; 16 | costs["b"] = 2; 17 | costs["fin"] = Infinity; 18 | 19 | let parents = {}; 20 | parents["a"] = "start"; 21 | parents["b"] = "start"; 22 | parents["fin"] = null; 23 | 24 | findLowestCostWay(graph, costs, parents); 25 | -------------------------------------------------------------------------------- /06_bfs/src/findMangoSeller.js: -------------------------------------------------------------------------------- 1 | import addToQueue from './addToQueue'; 2 | import personIsSeller from './personIsSeller'; 3 | 4 | export default (searchQueue, graph, startPoint) => { 5 | searchQueue = addToQueue(graph[startPoint], searchQueue); 6 | let searched = []; 7 | 8 | while(searchQueue.length !== 0) { 9 | let person = searchQueue.shift(); 10 | if (searched.indexOf(person) === -1) { 11 | if (personIsSeller(person)) { 12 | return person + " is a mango seller"; 13 | } else { 14 | searchQueue = addToQueue(graph[person], searchQueue); 15 | searched.push(person); 16 | } 17 | } 18 | } 19 | 20 | return "nobody is a mango seller"; 21 | } 22 | -------------------------------------------------------------------------------- /07_dijkstrasAlg/src/findLowestCostWay.js: -------------------------------------------------------------------------------- 1 | import findLowestCostNode from './findLowestCostNode'; 2 | 3 | export default (graph, costs, parents) => { 4 | let processed = []; 5 | 6 | let node = findLowestCostNode(costs, processed); 7 | 8 | while (node !== null) { 9 | let cost = costs[node]; 10 | let neighbors = graph[node]; 11 | for (let n in neighbors) { 12 | let newCost = cost + neighbors[n]; 13 | if (newCost < costs[n]) { 14 | costs[n] = newCost; 15 | parents[n] = node; 16 | } 17 | } 18 | processed.push(node); 19 | node = findLowestCostNode(costs, processed); 20 | } 21 | 22 | console.log(costs); 23 | console.log(parents); 24 | console.log(processed); 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Грокаем Алгоритмы 2 | 3 | ## О коде 4 | 5 | Реализация примеров и задач из книги *Грокаем Алгоритмы* на **Javascript** 6 | 7 | ## О книге 8 | 9 | > Алгоритмы — это всего лишь пошаговые алгоритмы решения задач, и большинство таких задач уже были кем-то решены, протестированы и проверены. Можно, конечно, погрузиться в глубокую философию гениального Кнута, изучить многостраничные фолианты с доказательствами и обоснованиями, но хотите ли вы тратить на это свое время? 10 | 11 | >Откройте великолепно иллюстрированную книгу, и вы сразу поймете, что алгоритмы — это просто. А грокать алгоритмы — это веселое и увлекательное занятие. 12 | 13 | ## Содержание 14 | 15 | * [**Бинарный поиск**](01_binarySearch) 16 | * [**Сортировка выбором**](02_selectionSort) 17 | * [**Быстрая сортировка**](04_quickSort) 18 | * [**Поиск в ширину**](06_bfs) 19 | * [**Алгоритм Дейкстры**](07_dijkstrasAlg) 20 | * [**Жадный алгоритм**](08_greedyAlg) 21 | -------------------------------------------------------------------------------- /08_greedyAlg/src/states.js: -------------------------------------------------------------------------------- 1 | /* 2 | Имплементация базовых операций над множествами взята отсюда: 3 | https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set 4 | */ 5 | 6 | Set.prototype.isSuperset = function(subset) { 7 | for (var elem of subset) { 8 | if (!this.has(elem)) { 9 | return false; 10 | } 11 | } 12 | return true; 13 | } 14 | 15 | Set.prototype.union = function(setB) { 16 | var union = new Set(this); 17 | for (var elem of setB) { 18 | union.add(elem); 19 | } 20 | return union; 21 | } 22 | 23 | Set.prototype.intersection = function(setB) { 24 | var intersection = new Set(); 25 | for (var elem of setB) { 26 | if (this.has(elem)) { 27 | intersection.add(elem); 28 | } 29 | } 30 | return intersection; 31 | } 32 | 33 | Set.prototype.difference = function(setB) { 34 | var difference = new Set(this); 35 | for (var elem of setB) { 36 | difference.delete(elem); 37 | } 38 | return difference; 39 | } 40 | 41 | export default (statesNeeded, stations) => { 42 | let finalStations = new Set(); 43 | 44 | while (statesNeeded.size !== 0) { 45 | let bestStation = null; 46 | let statesCovered = new Set(); 47 | 48 | for (let [station, statesForStation] of stations) { 49 | let covered = statesNeeded.intersection(statesForStation); 50 | if (covered.size > statesCovered.size) { 51 | bestStation = station; 52 | statesCovered = covered; 53 | } 54 | } 55 | 56 | finalStations.add(bestStation); 57 | statesNeeded = statesNeeded.difference(statesCovered); 58 | } 59 | 60 | return finalStations; 61 | } 62 | --------------------------------------------------------------------------------