Guest User

Untitled

a guest
Oct 17th, 2017
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.07 KB | None | 0 0
  1. const NOT_FOUND = "not found"
  2.  
  3. // Plain binary search implementation
  4. // BTW: this one contains a bug, try finding it =)
  5. function binarySearch(ar, el) {
  6. let m = 0, n = ar.length - 1
  7. while (m <= n) {
  8. const k = (n + m) >> 1
  9. if (el > ar[k])
  10. m = k + 1
  11. else if(el < ar[k])
  12. n = k - 1
  13. else
  14. return k
  15. }
  16. return -m - 1
  17. }
  18.  
  19. // Matrix view class, allows working with rectangular matrix subsets
  20. class MatrixView {
  21. constructor(source, left = 0, top = 0, right = undefined, bottom = undefined) {
  22. this.source = source
  23. this.left = left
  24. this.top = top
  25. this.bottom = bottom || source.length
  26. this.right = right || (source.length > 0 ? source[0].length : 0)
  27. }
  28.  
  29. // Extracts diagonal from current subset
  30. * extractDiagonal() {
  31. for (let [i, j] = [this.top, this.left]; i < this.bottom && j < this.right; i++, j++)
  32. yield this.source[i][j]
  33. }
  34.  
  35. // Extracts row at given index and inner start
  36. * extractRow(rowIndex = 0, startIndex = 0) {
  37. for (let i = this.left + startIndex; i < this.right; i++)
  38. yield this.source[this.top + rowIndex][i]
  39. }
  40.  
  41. // Extracts column at given index and inner start
  42. * extractColumn(columnIndex = 0, startIndex = 0) {
  43. for (let i = this.top + startIndex; i < this.bottom; i++)
  44. yield this.source[i][this.left + columnIndex]
  45. }
  46.  
  47. // Converts local coordinates to global
  48. toSourceCoordinates([x, y]) {
  49. return [this.top + x, this.left + y];
  50. }
  51.  
  52. // Performs matrix binary search
  53. binarySearchMatrix(el) {
  54.  
  55. // Our view is empty => not found
  56. if (this.top >= this.bottom || this.left >= this.right)
  57. return NOT_FOUND;
  58.  
  59. // Our view is a row => do a binary search
  60. if (this.top + 1 === this.bottom) {
  61. const rowIndex = binarySearch([...this.extractRow()], el)
  62. return rowIndex >= 0 ? this.toSourceCoordinates([0, rowIndex]) : NOT_FOUND
  63. }
  64.  
  65. // Our view is a column => do a binary search
  66. if (this.left + 1 === this.right) {
  67. const columnIndex = binarySearch([...this.extractColumn()], el)
  68. return columnIndex >= 0 ? this.toSourceCoordinates([columnIndex, 0]) : NOT_FOUND
  69. }
  70.  
  71. // Search for the elment on a diagonal
  72. let diagonalIndex = binarySearch([...this.extractDiagonal()], el)
  73.  
  74. // Return if it's found
  75. if (diagonalIndex >= 0)
  76. return this.toSourceCoordinates([diagonalIndex, diagonalIndex])
  77.  
  78. // Pick on a diagonal, after which our element should be
  79. diagonalIndex = -diagonalIndex - 2
  80.  
  81. // If element could be outside diagonal => it's outside matrix => not found
  82. if (diagonalIndex === -1 || diagonalIndex === this.right || diagonalIndex == this.bottom)
  83. return NOT_FOUND
  84.  
  85. const diagonalCoords = this.toSourceCoordinates([diagonalIndex, diagonalIndex])
  86.  
  87. // Search for element in upper-right matrix subset
  88. let t = new MatrixView(this.source, diagonalCoords[1] + 1, this.top, this.right, diagonalCoords[0] + 1)
  89. let result = t.binarySearchMatrix(el);
  90. if (result !== NOT_FOUND) return result;
  91.  
  92. // Search for element in bottom-left matrix subset
  93. t = new MatrixView(this.source, this.left, diagonalCoords[0] + 1, diagonalCoords[1] + 1, this.bottom)
  94. result = t.binarySearchMatrix(el);
  95. if (result !== NOT_FOUND) return result;
  96.  
  97. // Otherwise
  98. return NOT_FOUND;
  99. }
  100. }
  101.  
  102. function binarySearchMatrix(ar, el) {
  103. return new MatrixView(ar).binarySearchMatrix(el)
  104. }
  105.  
  106. const sortedMatrix = [
  107. [ 0, 1, 2, 3, 4, 5],
  108. [ 10, 10, 20, 21, 22, 23],
  109. [ 20, 21, 30, 31, 32, 33],
  110. [ 30, 31, 40, 41, 42, 43],
  111. [ 40, 41, 50, 51, 52, 55],
  112. [ 50, 51, 60, 61, 62, 63],
  113. ]
  114.  
  115. const n = sortedMatrix.length
  116.  
  117. // Search for all elements in matrix
  118. for (let i = 0; i < n; i++)
  119. for (let j = 0; j < n; j++) {
  120. let result = binarySearchMatrix(sortedMatrix, sortedMatrix[i][j])
  121. if (sortedMatrix[i][j] !== sortedMatrix[result[0]][result[1]])
  122. console.log(`ERROR searchin for ${sortedMatrix[i][j]}, returned ${result}`)
  123. }
  124.  
  125. // Search for elements outside matrix
  126. for (let i = -10; i <= 70; i++) {
  127. let result = binarySearchMatrix(sortedMatrix, i)
  128. console.log(`Searched for ${i} returns ${result}`)
  129. }
Add Comment
Please, Sign In to add comment