From dd66cfd6638cbb33f12f44cec006e4f992e1163d Mon Sep 17 00:00:00 2001 From: gyim1345 Date: Thu, 7 Jan 2021 23:22:17 +0900 Subject: [PATCH] [gyim1345] implement search algorithms dfs bfs jump search brute force rabin karp --- .../DFS_BFS.test.js" | 73 +++++++++++++++++++ .../bruteForceSearch.test.js" | 20 +++++ .../jumpSearch.test.js" | 34 +++++++++ .../rabinKarp.test.js" | 29 ++++++++ 4 files changed, 156 insertions(+) create mode 100644 "\354\236\220\353\243\214\352\265\254\354\241\260/DFS_BFS.test.js" create mode 100644 "\354\236\220\353\243\214\352\265\254\354\241\260/bruteForceSearch.test.js" create mode 100644 "\354\236\220\353\243\214\352\265\254\354\241\260/jumpSearch.test.js" create mode 100644 "\354\236\220\353\243\214\352\265\254\354\241\260/rabinKarp.test.js" diff --git "a/\354\236\220\353\243\214\352\265\254\354\241\260/DFS_BFS.test.js" "b/\354\236\220\353\243\214\352\265\254\354\241\260/DFS_BFS.test.js" new file mode 100644 index 0000000..2e8dd42 --- /dev/null +++ "b/\354\236\220\353\243\214\352\265\254\354\241\260/DFS_BFS.test.js" @@ -0,0 +1,73 @@ + + +class Graph { + constructor() { + this.map = new Map(); + this.root = null; + } + + + addEdge(a,b) { + if(this.root === null) { + this.root = a; + } + const arr = this.map.get(a); + if(arr) { + this.map.set(a,[...this.map.get(a),b ]) + return; + } + this.map.set(a,[b]) + } + + + dfs(currentNumber= this.root, history = []) { + history.push(currentNumber); + const nextNumbers = this.map.get(currentNumber); + if(!nextNumbers || nextNumbers.every(number => history.includes(number))) { + return [currentNumber]; + } + for(let i = 0; i < nextNumbers.length; i += 1){ + if(!history.includes(nextNumbers[i])) { + return [currentNumber, ...this.dfs(nextNumbers[i], history)]; + } + } + } + + bfs() { + let queue = [this.root]; + let answer = [this.root]; + while(queue[0]){ + const currentNumber = queue.shift(); + const numbers = this.map.get(currentNumber) || [] + let filteredNumbers = numbers.filter(number => !answer.includes(number)); + answer = [...answer, ...filteredNumbers]; + queue = [...queue, ...filteredNumbers]; + } + return answer; + } +} + +test('dfs', () => { + const graph = new Graph(); + graph.addEdge(1,2); + graph.addEdge(1,5); + graph.addEdge(2,3); + graph.addEdge(3,4); + graph.addEdge(4,5); + graph.addEdge(5,6); + graph.addEdge(6,1); + console.log(graph) + expect(graph.dfs()).toEqual([1,2,3,4,5,6]); +}); + +test('bfs', () => { + const graph = new Graph(); + graph.addEdge(1,2); + graph.addEdge(1,5); + graph.addEdge(2,3); + graph.addEdge(3,4); + graph.addEdge(4,5); + graph.addEdge(5,6); + graph.addEdge(6,1); + expect(graph.bfs()).toEqual([1,2,5,3,6,4]); +}); \ No newline at end of file diff --git "a/\354\236\220\353\243\214\352\265\254\354\241\260/bruteForceSearch.test.js" "b/\354\236\220\353\243\214\352\265\254\354\241\260/bruteForceSearch.test.js" new file mode 100644 index 0000000..90ef0f8 --- /dev/null +++ "b/\354\236\220\353\243\214\352\265\254\354\241\260/bruteForceSearch.test.js" @@ -0,0 +1,20 @@ +const bruteForce = (string, targetWord) => { + for(let i=0; i < string.length; i += 1) { + let match = true; + for(let j=0; j < targetWord.length; j += 1) { + if(string[i+j] !== targetWord[j]) { + match = false; + break; + } + } + if(match) { + return i; + } + } + return 1; +} + + +test('bruteForce', () => { + expect(bruteForce('abcdefg', 'cde')).toBe(2); +}); \ No newline at end of file diff --git "a/\354\236\220\353\243\214\352\265\254\354\241\260/jumpSearch.test.js" "b/\354\236\220\353\243\214\352\265\254\354\241\260/jumpSearch.test.js" new file mode 100644 index 0000000..7023b1e --- /dev/null +++ "b/\354\236\220\353\243\214\352\265\254\354\241\260/jumpSearch.test.js" @@ -0,0 +1,34 @@ +// 무조건 정렬된 리스트에서 실행 +// 평균 복잡도 O(√n) +// 점프 하면서 interval을 찾는 순간 linear search 실행 + +const jumpSearch = (array, target) => { + + const jumpSize = Math.floor(Math.sqrt(array.length)); + let index = 0; + //점프 + while(target > array[index]) { + index += jumpSize; + } + //반대 방향으로 linear search + for(let i = index; i > index -jumpSize; i -= 1) { + if(target === array[i]) { + return i; + } + } + + return 'Not Found'; +} + +test('jumpSearch', () => { + expect(jumpSearch([0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610 ], 55)).toBe(10); + + expect(jumpSearch([0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610 ], 54)).toBe('Not Found'); + + expect(jumpSearch([0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610 ], 144)).toBe(12); + + expect(jumpSearch([0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610 ], 233)).toBe(13); + + expect(jumpSearch([10, 20, 30,40 ,50,60, 70, 80, 90 ], 90)).toBe(8); +}); + diff --git "a/\354\236\220\353\243\214\352\265\254\354\241\260/rabinKarp.test.js" "b/\354\236\220\353\243\214\352\265\254\354\241\260/rabinKarp.test.js" new file mode 100644 index 0000000..12a5c6b --- /dev/null +++ "b/\354\236\220\353\243\214\352\265\254\354\241\260/rabinKarp.test.js" @@ -0,0 +1,29 @@ +const rabinKarp = (string, targetWord) => { + const targetHash = getHash(targetWord); + const length = targetWord.length; + let currentHash = getHash(string.substring(0,length)); + for(let i = 0; i < string.length - length; i += 1) { + if(targetHash === currentHash){ + return i; + } + currentHash = updateHash(currentHash, string[i], string[i+length], length) + } +} + +const updateHash = (currentHash, first, last = '0', length) => { + return (currentHash - first.charCodeAt(0) * Math.pow(2, length - 1)) * 2 + last.charCodeAt(0); +} + +const getHash = (string) => { + console.log(string); + return string.split('').reduce((acc,cur,i) => { + console.log(acc, cur.charCodeAt(0), cur.charCodeAt(0) * Math.pow(2, string.length - i -1)) + return acc + cur.charCodeAt(0) * Math.pow(2, string.length - i -1); + },0) +} + + + +test('rabinKarp', () => { + expect(rabinKarp('abcdefg', 'cde')).toBe(2); +}); \ No newline at end of file