commit 8c3ca7a910dde41faa6795c5018297c21490b3f9 Author: Sergey Krylov Date: Thu Jan 23 08:40:17 2025 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/01/binarySearch.js b/01/binarySearch.js new file mode 100644 index 0000000..ac35aff --- /dev/null +++ b/01/binarySearch.js @@ -0,0 +1,27 @@ +const binarySearch = (list, item) => { + let startIndex = 0; + let endIndex = list.length - 1; + + while (startIndex <= endIndex) { + let midIndex = Math.floor((startIndex + endIndex) / 2); + const candidate = list[midIndex]; + + if (candidate === item) { + console.log(`Item ${item} found at index ${midIndex}`); + return midIndex; + } + + if (candidate > item) { + endIndex = midIndex - 1; + } else { + startIndex = midIndex + 1; + } + }; + + console.log(`Not found "${item}"`); + return null; +}; + +const list = [10, 20, 30, 50, 80, 100, 500]; +binarySearch(list, 20); // 1 +binarySearch(list, 40); // null \ No newline at end of file diff --git a/01/simpleSearch.js b/01/simpleSearch.js new file mode 100644 index 0000000..1fab58f --- /dev/null +++ b/01/simpleSearch.js @@ -0,0 +1,18 @@ +const simpleSearch = (list, item) => { + for (let i = 0; i <= list.length; i++) { + const candidate = list[i]; + if (candidate === item) { + console.log(`Item ${item} found at index ${i}`); + return i; + } + } + + console.log(`Not found "${item}"`); + return null; +}; + + +const list = [10, 20, 30, 50, 80, 100, 500]; + +simpleSearch(list, 20); // 1 +simpleSearch(list, 40); // null diff --git a/02/selectionSort.js b/02/selectionSort.js new file mode 100644 index 0000000..7273bf3 --- /dev/null +++ b/02/selectionSort.js @@ -0,0 +1,47 @@ +const findSmallestIndex = (arr) => { + let smallestValue = arr[0]; + let smallestIndex = 0; + + for (let i = 1; i < arr.length; i++) { + const candidate = arr[i]; + if (candidate < smallestValue) { + smallestIndex = i; + smallestValue = candidate + } + } + + return smallestIndex; +} + +const selectionSort = (arr) => { + const result = []; + const copyArr = [...arr]; + + for (let i = 0; i < arr.length; i++) { + const smallestIndex = findSmallestIndex(copyArr); + const smallestValue = copyArr.splice(smallestIndex, 1)[0]; + result.push(smallestValue); + } + + return result; +} + +const recursiveSelectionSort = array => { + if (!array.length) return []; + + const copyArr = [...array]; + const smallestIndex = findSmallestIndex(copyArr); + + return [ + ...copyArr.splice(smallestIndex, 1), + ...recursiveSelectionSort(copyArr), + ]; +}; + +const array = [2, 4, 5, 1, 6, 3]; +const sorted = selectionSort(array); +const sorted2 = recursiveSelectionSort(array); + +console.log('array', array); +console.log('sorted array', sorted); +console.log('recursive sorted array', sorted2); \ No newline at end of file diff --git a/03/counter.js b/03/counter.js new file mode 100644 index 0000000..10076bc --- /dev/null +++ b/03/counter.js @@ -0,0 +1,10 @@ +const counter = (val) => { + if (val < 1) { + return; + } + + console.log(val); + counter(val - 1); +} + +counter(5); \ No newline at end of file diff --git a/04/max_item.js b/04/max_item.js new file mode 100644 index 0000000..9f50be9 --- /dev/null +++ b/04/max_item.js @@ -0,0 +1,11 @@ +const max_item = (arr) => { + if (arr.length < 2) { + return arr[0]; + } + + + return Math.max(arr[0], max_item(arr.slice(1))); +} + +const res = max_item([999, 1, 2, 8, 3, 4, 5]); +console.log('res', res); \ No newline at end of file diff --git a/04/quick_sort.js b/04/quick_sort.js new file mode 100644 index 0000000..6b601b2 --- /dev/null +++ b/04/quick_sort.js @@ -0,0 +1,23 @@ +const quick_sort = (arr) => { + if (arr.length < 2) { + return arr; + } + + const pivot = arr[0]; + const less = []; + const greater = []; + + for (let i = 1; i < arr.length; i++) { + const candidate = arr[i]; + if (candidate < pivot) { + less.push(candidate) + } else { + greater.push(candidate); + } + } + + return [quick_sort(less), pivot, quick_sort(greater)].flat(); +} + +const res = quick_sort([1, 234, 21, 4, 211, 4, 63, 12, 84, 2]) +console.log('res', res); \ No newline at end of file diff --git a/04/sum.js b/04/sum.js new file mode 100644 index 0000000..0293d21 --- /dev/null +++ b/04/sum.js @@ -0,0 +1,10 @@ +const sum = (arr) => { + if (arr.length < 2) { + return arr[0] || 0; + } + + return arr[0] + sum(arr.slice(1)); +} + +const res = sum([1, 2, 3, 4, 5, 6, 8]) +console.log('res', res); \ No newline at end of file diff --git a/05/check_voter.js b/05/check_voter.js new file mode 100644 index 0000000..67de2cb --- /dev/null +++ b/05/check_voter.js @@ -0,0 +1,17 @@ +const voter = {}; +const checkVoter = (vote) => { + if (voter[vote]) { + console.log('Duplicate', vote); + return false; + } + + voter[vote] = true; + console.log('Success Vote', vote); + return true; +} + + +checkVoter('Mike'); +checkVoter('Jack'); +checkVoter('John'); +checkVoter('Mike'); \ No newline at end of file diff --git a/06/bfs.js b/06/bfs.js new file mode 100644 index 0000000..4c9379e --- /dev/null +++ b/06/bfs.js @@ -0,0 +1,39 @@ +const breadthFirstSearch = (graph, start, end) => { + const queue = graph[start]; + const checked = []; + + let lastLevelElement = queue[queue.length - 1]; + let level = 1; + + + while (queue.length) { + const candidate = queue.shift(); + + if (candidate === end) { + return level; + } + + if (checked.includes(candidate)) { + continue; + } + + queue.push(...(graph[candidate] || [])); + if (candidate === lastLevelElement) { + lastLevelElement = queue[queue.length - 1]; + level += 1; + } + } + + return -1; +} + +const graph = { + a: ['b', 'c', 'd'], + b: ['e', 'f'], + d: ['e', 'g'], + c: ['j', 'k'], + e: ['l'] +} + +const res = breadthFirstSearch(graph, 'a', 'l'); +console.log('res', res); \ No newline at end of file diff --git a/09/dijkstra.js b/09/dijkstra.js new file mode 100644 index 0000000..c7002f7 --- /dev/null +++ b/09/dijkstra.js @@ -0,0 +1,97 @@ +// 1) Найти самый дешевый узел из необработанных +// 2) Проверить минимальный путь до его соседей и обновить стоимость и родителя +// 3) Пометить узел как обработанный +// 4) Продолжать пока все узлы не будут обработаны +// 5) Вернуть итоговую стоимость и путь + +const findLowestCostNode = (costs, processed) => { + let lowestCost = Infinity; + let lowestCostNode = null; + + Object.entries(costs).forEach(([node, cost]) => { + if (!processed.includes(node) && cost < lowestCost) { + lowestCost = cost; + lowestCostNode = node; + } + }); + + return lowestCostNode; +}; + +const dejsktra = (graph, [from, to]) => { + const costs = { + [to]: Infinity, + ...graph[from], + }; + + const parents = {}; + Object.keys(graph[from]).forEach(key => parents[key] = from); + + const processed = []; + + let lowestCostNode = from; + while(lowestCostNode) { + const neighbours = graph[lowestCostNode] || {}; + Object.keys(neighbours).forEach(neighbour => { + let cost = costs[lowestCostNode] + neighbours[neighbour]; + + if (!costs[neighbour]) { + costs[neighbour] = Infinity; + } + + if (cost < costs[neighbour]) { + costs[neighbour] = cost; + parents[neighbour] = lowestCostNode; + } + }) + + processed.push(lowestCostNode); + lowestCostNode = findLowestCostNode(costs, processed); + } + + const path = [to]; + let parent = parents[to]; + + while (parent) { + path.push(parent); + parent = parents[parent]; + } + + return { + value: costs[to], + path: path.reverse() + } +}; + + +const testGraph = { + a: { b: 2, f: 6 }, + b: { c: 4 }, + c: { d: 8, g: 6 }, + d: { h: 3 }, + e: { b: 1, g: 5, }, + f: { e: 1, g: 7 }, + g: { d: 2, h: 4, j: 2,}, + h: { j: 1 }, +}; + +const complexGraph = { + a: { b: 4, c: 2, d: 7 }, + b: { e: 3, f: 1, g: 5 }, + c: { f: 4, h: 2 }, + d: { h: 6, i: 3 }, + e: { j: 2, k: 4 }, + f: { j: 5, l: 2 }, + g: { k: 3, m: 4 }, + h: { l: 5, n: 2 }, + i: { n: 4, o: 3 }, + j: { m: 1, n: 6 }, + k: { n: 2, o: 5 }, + l: { o: 4 }, + m: { o: 3 }, + n: { o: 2 }, + o: {} +}; + +console.log(dejsktra(testGraph, ['a', 'j'])); // { value: 14, path: [ 'a', 'b', 'c', 'g', 'j' ] } +console.log(dejsktra(complexGraph, ['a', 'o'])); // { value: 8, path: [ 'a', 'c', 'h', 'n', 'o' ] } \ No newline at end of file diff --git a/10/greedy.js b/10/greedy.js new file mode 100644 index 0000000..0eac0ec --- /dev/null +++ b/10/greedy.js @@ -0,0 +1,37 @@ +// Найти непокрытые штаты +// Выбрать странцию покрывающую больше всех штатов из непокрытых + +const findStations = (allStationLst, needStateList) => { + let needed = new Set([...needStateList]); + let result = new Set(); + + while (needed.size > 0) { + let statesCovered = new Set(); + let stationCandidate; + + Object.keys(allStationLst).forEach((station) => { + const stationStateCovered = new Set([...allStationLst[station]].filter(item => needed.has(item))); + if (stationStateCovered.size > statesCovered.size) { + statesCovered = stationStateCovered; + stationCandidate = station; + } + }) + + result.add(stationCandidate); + needed = new Set([...needed].filter(item => !statesCovered.has(item))); + } + + return result +}; + +const needStateList = new Set(["mt", "wa", "or", "id", "nv", "ut", "ca", "az"]); +const stations = { + kone: new Set(["id", "nv", "ut"]), + ktwo: new Set(["wa", "id", "mt"]), + kthree: new Set(["or", "nv", "ca"]), + kfour: new Set(["nv", "ut"]), + kfive: new Set(["ca", "az"]), +}; + + +console.log(findStations(stations, needStateList)); diff --git a/11/dynamic.js b/11/dynamic.js new file mode 100644 index 0000000..2e93887 --- /dev/null +++ b/11/dynamic.js @@ -0,0 +1,63 @@ +// 1) составить матрицу из 0 +// 2) если буква на i месте не совпадают, то 0 +// 3) если совпадают, то берется значение из предыдущей ячейки и увеличивается на 1 +// 4) обновляется максимальная подстрока + + +const createMatrix = (row, col) => { + const arr = Array(row).fill(Array(col).fill(0)); + return JSON.parse(JSON.stringify(arr)); +} + +const maxCommonSubstring = (str1, str2) => { + const matrix = createMatrix(str1.length, str2.length); + + let maxSize = 0; + let endIndex = 0; + + for (let i = 0; i < str1.length; i++) { + for (let j = 0; j < str2.length; j++) { + if (str1[i] !== str2[j]) { + continue + } + + matrix[i][j] = (i && j) > 0 ? matrix[i - 1][j - 1] + 1 : 1; + + if (matrix[i][j] >= maxSize) { + maxSize = matrix[i][j]; + endIndex = j + 1; + } + } + } + + return str1.slice(endIndex - maxSize, endIndex); +} + + +maxCommonSubstring('fish', 'hish'); // 'ish' +maxCommonSubstring('fish', 'fista'); // 'fis' +maxCommonSubstring('fish', 'fista'); // 'is' + + +const maxCommonSubsequence = (str1, str2) => { + const matrix = createMatrix(str1.length, str2.length); + + for (let i = 0; i < str1.length; i++) { + for (let j = 0; j < str2.length; j++) { + if (str1[i] === str2[j]) { + matrix[i][j] = (i && j) > 0 ? matrix[i - 1][j - 1] + 1 : 1; + } else { + const left = i > 0 ? matrix[i - 1][j] : 0; + const up = j > 0 ? matrix[i][j - 1] : 0 + + matrix[i][j] = Math.max(left, up); + } + } + } + + + return matrix[str1.length - 1][str2.length - 1] +} + +maxCommonSubsequence('fort', 'fosh'); // 2 +maxCommonSubsequence('fish', 'fosh'); // 3