Advertisement
Guest User

Untitled

a guest
Mar 19th, 2019
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**********************************************************/
  2. /** IMPLEMENTATION OF MY ALGORITHM (DYNAMIC PROGRAMMING) **/
  3. /**********************************************************/
  4. const getTotalMinDist = (a, b) => {
  5.     let count = 0
  6.  
  7.     const m = a.length
  8.     const n = b.length
  9.  
  10.     // Create MinDist table
  11.     let minDist = new Array(n).fill(0).map(() => new Array(m))
  12.  
  13.     // Helper functions so that we can use 1-based indices instead of 0-based indices
  14.     const getMinDist = (i, j) => {
  15.         // Implement the base case here itself instead of filling the table for convenience
  16.         if (j == m + 1)
  17.             return {dist: 0, subseq: []}
  18.         else
  19.             return minDist[i - 1][j - 1]
  20.     }
  21.     const setMinDist = (i, j, dist, subseq) => {minDist[i - 1][j - 1] = {dist: dist, subseq: subseq}}
  22.     const getA = (i) => a[i - 1]
  23.     const getB = (i) => b[i - 1]
  24.  
  25.     // Fill minDist in the correct order using the recurrence relation
  26.     for (let j = m; j >= 1; j--) {
  27.         for (let i = 1; i <= j + n - m; i++) {
  28.             // Keep track of the subsequence that produced the minimum L1 distance
  29.             let min_dist = Infinity
  30.             let min_index = -1
  31.             let min_next_subseq = []
  32.  
  33.             // This for loop iterates through the parameters to the min function in my answer
  34.             for (let next_i_start = i; next_i_start <= j + n - m; next_i_start++) {
  35.                 // Recursive step from my answer
  36.                 let cur_dist = getMinDist(next_i_start + 1, j + 1).dist + Math.abs(getA(j) - getB(next_i_start))
  37.  
  38.                 if (cur_dist < min_dist) {
  39.                     min_dist = cur_dist
  40.                     min_index = next_i_start
  41.                     min_next_subseq = getMinDist(next_i_start + 1, j + 1).subseq
  42.                 }
  43.             }
  44.  
  45.             // Set this entry of the table to the minimum distance found
  46.             //  as well as the value of b at the index chosen + the rest of the optimal subsequence after that point
  47.             setMinDist(i, j, min_dist, [getB(min_index)].concat(min_next_subseq))
  48.         }
  49.     }
  50.  
  51.     return getMinDist(1, 1)
  52. }
  53.  
  54. /*******************************/
  55. /** BRUTEFORCE IMPLEMENTATION **/
  56. /*******************************/
  57. const bruteForceGetTotalMinDist = (a, b) => {
  58.     // Recursively try every combination of a.length indices of b
  59.     //   remaining_indices: number of indices left to determine
  60.     //   indices: an ordered list of indices into b, the function will find the minimum L1 distance to a while
  61.     //            considering only all subsequences of b that contain the values of b at these indices
  62.     const tryCombinations = (remaining_indices, indices) => {
  63.         // If there are no more indices left to pick (we have picked a.length indices into b)
  64.         if (remaining_indices == 0) {
  65.             // Computes the L1 distance between a and the subsequence of b given by the indices array
  66.             let dist = a.map((a_val, a_index) => Math.abs(a_val - b[indices[a_index]])).reduce((x, y) => x + y)
  67.  
  68.             // Return the L1 distance along with the sequence that produced that distance
  69.             return {dist: dist, subseq: indices.map((i) => b[i])}
  70.         }
  71.  
  72.         // Otherwise, add another index to our current selection of indices for the
  73.         //  subsequence of b and recursively find the minimum L1 distance
  74.         let min_dist = {dist: Infinity}
  75.  
  76.         for (let i = 0; i < b.length; i++) {
  77.             // If i is an index that can be inserted into indices array
  78.             //  by virtue of the array being empty, or i being greater than the last element
  79.             if (indices.length == 0 || i > indices[indices.length - 1]) {
  80.                 let new_indices = indices.slice()
  81.                 new_indices.push(i)
  82.  
  83.                 let result = tryCombinations(remaining_indices - 1, new_indices)
  84.                 if (result.dist < min_dist.dist)
  85.                     min_dist = result
  86.             }
  87.         }
  88.  
  89.         return min_dist
  90.     }
  91.  
  92.     return tryCombinations(a.length, [])
  93. }
  94.  
  95. // Run both of them with randomized arrays a lot of times to gain confidence that my answer is correct
  96. let numErrors = 0
  97.  
  98. for (let i = 0; i < 100000; i++) {
  99.     const a = new Array(7).fill(0).map(() => Math.floor(Math.random() * 50))
  100.     const b = new Array(15).fill(0).map(() => Math.floor(Math.random() * 50))
  101.  
  102.     bruteForceSolution = bruteForceGetTotalMinDist(a, b)
  103.     dynamicProgSolution = getTotalMinDist(a, b)
  104.  
  105.     // A lazy way to check for equality of two objects in JS (only works sometimes, this is one of those times)
  106.     if (JSON.stringify(bruteForceSolution) != JSON.stringify(dynamicProgSolution))
  107.         numErrors++
  108. }
  109.  
  110. console.log("Number of errors: " + numErrors)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement