Code challenge Max Product Finder: Only 4 of 5 tests pass

Max Product Finder

code-challenge-max-product-finder-javascript

I can’t find out why the last test doesn’t pass. I think I have tested all possible cases and get the correct results. Does anyone have an idea?

function maxProductFinderK(numbers, size) {
  // Write your code here
  if(size===0) return 0;

  numbers.sort((a,b) => b-a);
  if(size===1) return numbers[0];

  let product = 1;
  const getProduct = arr => arr.reduce((acc,el) => acc * el, 1);

  /**
 * Returns an array with max 2 items with largest product size
 * @param {number} len - max length of the returned array
 */
  function getMax(len) {
    const start = numbers.slice(0, len);
    const end = numbers.slice(numbers.length-len);
    if(getProduct(start) < 0 && getProduct(end) < 0) return [];
    return getProduct(start) > getProduct(end) ? numbers.splice(0, len) : numbers.splice(numbers.length-len, len);
  }

  while(size > 0) {
    let len = Math.min(2, Math.max(0, size));
    product *= getProduct(getMax(len));
    size-=len;
  }
  return product;
}

console.log(maxProductFinderK([-8, 6, -7, 3, 2, 1, -9], 7)) // returns 2592
console.log(maxProductFinderK([-8, 6, -7, 3, 2, 1, -9], 3)) // returns 432
console.log(maxProductFinderK([-8, 6, -7, 3, 2, 1, -9], 2)) // returns 72
console.log(maxProductFinderK([-3,-2,-4], 3)) // returns 12
console.log(maxProductFinderK([-3,-2,-4], 1)) // returns -2
console.log(maxProductFinderK([-3,-2,-4], 0)) // returns 0

Same issue here. My solution attempt for reference:

function maxProductFinderK(nums, k, n = nums.length) {
  nums.sort((a, b) => a - b);

  if (nums[n - 1] === 0 && k % 2 !== 0) return 0
  if (nums[n - 1] <= 0 && k % 2 !== 0) return getProduct(nums.slice(n - 1 - k))

  let maxProduct = 1;
  let left = 0;
  let right = n - 1;

  if (k % 2 !== 0) {
      maxProduct *= nums[right];
      right--;
      k--;
  }

  k /= 2;

  for (let itr = 0; itr < k; itr++) {
      let left_product = nums[left] * nums[left + 1];
      let right_product = nums[right] * nums[right - 1];
      if (left_product > right_product) {
          maxProduct *= left_product;
          left += 2;
      } else {
          maxProduct *= right_product;
          right -= 2;
      }
  }
  return maxProduct;
}

var getProduct = (array) => array.reduce((acc, curr) => acc * curr, 1)

I tried a maxHeap solution too, but that still gave me 4/5. I wonder if there’s a way of doing it without a heap and without sorting. Otherwise, the best possible time is O(n*log(n)).

1 Like

I noticed one case that may be a problem.
maxProductFinderK([-3,-2,-4], 3) should return −24 since −3 × −2 × −4 = −24

Maybe there’s an issue when the length of the array is the same as the size parameter.

1 Like

I tried both approaches: Return the max product that can be achieved with max k factors → my current approach. If I am to return the max product that can be obtained with exactly k factors, even if the product is smaller than what can be obtained with one factor less, I just have to comment out one line in my code:

if(getProduct(start) < 0 && getProduct(end) < 0) return [];
console.log(maxProductFinderK([-8, 6, -7, 3, 2, 1, -9], 7)) // returns -18144
console.log(maxProductFinderK([-8, 6, -7, 3, 2, 1, -9], 3)) // returns 432
console.log(maxProductFinderK([-8, 6, -7, 3, 2, 1, -9], 2)) // returns 72
console.log(maxProductFinderK([-3,-2,-4], 3)) // returns -24
console.log(maxProductFinderK([-3,-2,-4], 1)) // returns -2
console.log(maxProductFinderK([-3,-2,-4], 0)) // returns 0

That doesn’t seem to have an effect on the test, though. Still only 4/5 tests pass.
Yet your understanding of the task must be correct since your code passes all tests with the same results as mine with the line commented out. With one exception:

console.log(maxProductFinderK([-3,-2,-4], 0)) // returns NaN with your code

But returning NaN or undefined for a size === 0 doesn’t help either. So there must be one test case I still don’t see.

Not subscribed, so can’t run tests.

How about implementing the above approach. But when k is 0 or array is empty [], then instead of returning 0, try returning 1.

@javaace96747
Your issue may be different than mirja_t. Consider the tests

console.log(maxProductFinderK([-3,-2,-4], 3)) 
// Your code returns -2 which isn't correct

console.log(maxProductFinderK([-3,-2,-4], 1)) 
// Your code returns 6 which isn't correct
1 Like

Unfortunately, that also doesn’t work :frowning:

function maxProductFinderK(numbers, size) {
  if(size===0 || !numbers.length) { return 1; }

I tried to return 0, 1, undefined, NaN – to no avail. Still 4/5.
They probably don’t test with an empty array as the instructions read:

You may presume that the length of the list of integers is greater than or equal to k

Funnily enough, writing code that only solves those two edge cases doesn’t work, so those two edge cases weren’t a factor in getting 4/5.

Could it be because of mutation?

numbers.sort((a,b) => b-a);
let x = [-8, 6, -7, 3, 2, 1, -9];
console.log(x);   // [-8, 6, -7, 3, 2, 1, -9]
console.log(maxProductFinderK(x, 4)); // 1296
console.log(x); // [2, 1, -7]
1 Like

No, I considered that, too, and also tried a variant with a copy of the input array. Same result…

1 Like

Ok. Last idea for the time being.

Combine all three suggestions in a single run:
Suggestion 1: Comment out if(getProduct(start) < 0 && getProduct(end) < 0) return []; to implement the exactly k factors approach
Suggestion 2: Return 1 when k is 0
Suggestion 3: Don’t mutate the original array.

It’s a long shot, but no harm in trying.

1 Like

Bildschirmfoto 2023-01-20 um 18.07.39
:woman_shrugging:

function maxProductFinderK(numbers, size) {
  // Write your code here
  if(size===0) return 1;

  let numbersCopy = [...numbers];
  numbersCopy.sort((a,b) => b-a);
  if(size===1) return numbersCopy[0];

  let product = 1;
  const getProduct = arr => arr.reduce((acc,el) => acc * el, 1);
  
  function getMax(len) {
    const start = numbersCopy.slice(0, len);
    const end = numbersCopy.slice(numbersCopy.length-len);
    return getProduct(start) > getProduct(end) ? numbersCopy.splice(0, len) : numbersCopy.splice(numbersCopy.length-len, len);
  }

  while(size > 0) {
    let len = Math.min(2, Math.max(0, size));
    product *= getProduct(getMax(len));
    size-=len;
  }
  return product;
}

But thanks for your ideas anyway :slight_smile:

1 Like