Javascript run length encoding algorithm

General Tech Learning Aids/Tools 2 years ago

0 2 0 0 0 tuteeHUB earn credit +10 pts

5 Star Rating 1 Rating

Posted on 16 Aug 2022, this text provides information on Learning Aids/Tools related to General Tech. Please note that while accuracy is prioritized, the data presented might not be entirely correct or up-to-date. This information is offered for general knowledge and informational purposes only, and should not be considered as a substitute for professional advice.

Take Quiz To Earn Credits!

Turn Your Knowledge into Earnings.

tuteehub_quiz

Answers (2)

Post Answer
profilepic.png
manpreet Tuteehub forum best answer Best Answer 2 years ago

 

I have implemented a custom run length encoding algorithm that converts an m x n array into an p x (n+1) array. The extra column is to record counts. Probably easier to show through examples:

 

encode = (array) => {
  // crude array equality function
  arrayEquals = (...arr) => {
    return arr[0].map(x => {
      return JSON.stringify(x);
    }).every((x, _, a) => {
      return x === a[0];
    });
  };

  let result = [],
    count = -1,
    len = array.length;

  array.reduce((acc, val, i) => {
    if (!arrayEquals([acc, val])) {
      // if current value differs from last
      if (i !== len - 1) {
        // push the count and data to the result
        result.push([++count, acc]);
        count = 0; // reset the count
      } else { // last iteration
        // push the (n - 1)th  value
        result.push([++count, acc]);
        // now push the nth value
        result.push([1, val]);
      }
    } else {
      // if current value equals the last, increment counter and continue
      count++;
      if (i === len - 1) { // last iteration
        // push regardless 
        count === 1 ? result.push([++count, val]) : result.push([count, val]);
      }
    }
    return val;
  }, array[0]);

  return result;
};

console.log(encode([1, 1, 2, 2, 3, 3, 4]));
console.log(encode([
  [1, 2, 3],
  [4, 5, 6],
  [7
                                                
                                                
0 views
0 shares
profilepic.png
manpreet 2 years ago

Separation of concerns

The problem has two distinct, independent components:

  • Compute run length
  • Decide if two values are equal

I agree that using reduce makes sense here to compute the run length. If you separate this computation from the equality decision, the logic of the reducer can become a lot simpler:

  const reducer = (acc, val) => {
    if (acc.length > 0 && equals(acc[acc.length - 1][1], val)) {
      acc[acc.length - 1][0]++;
      return acc;
    }
    acc.push([1, val]);
    return acc;
  };
  return arr.reduce(reducer, []);

That is:

  • When the accumulator is not empty, and the last element has matching value, then increment the count of the last element, and return the accumulator.

  • Append [1, val] to the accumulator.

  • The accumulator starts empty.

The equality condition is to be implemented. You can even require the implementation to be passed in as parameter.

As @radarbob suggests, it's good to get the run-length computation working without worrying about mixed value types. The implementation of the equals function here is not interesting at all for run-length computation. You can start with a simple const equals = (a, b) => a === b. Having mixed values in the input doesn't affect at all the run-length computation logic.

The converse is also true: it should be possible to implement the equality logic independently from run-length. This reduces your mental burden and helps you think clearly, focusing on one problem at a time. I came up with this:

  const equals = (a, b) => {
    if (a === b) {
      return true;
    }
    if (typeof(a) !== typeof(b)) {
      return false;
    }
    if (Array.isArray(a)) {
      return arrayEquals([a, b]);
    }
    return false;
  };

This implementation handles some easy basic cases, and delegates some non-trivial ones, such as comparing arrays. Your arrayEquals will work nicely for the purpose. Looking at this implementation, it's also quite clear what kind of values are supported: primitive and arrays only. (As far as we can trust the externalized arrayEquals implementation...)


0 views   0 shares

No matter what stage you're at in your education or career, TuteeHub will help you reach the next level that you're aiming for. Simply,Choose a subject/topic and get started in self-paced practice sessions to improve your knowledge and scores.