Categories
interview

Multi List Iterator – Javascript

Print a list of lists vertically using an Iterator.

For example:

// Usage
const node = new MultiIterator([[1, 2], [], [4], [5]]);

while (node.hasNext()) {
  console.log(node.next());
}

Input:

[[1, 2], [], [4], [5]]

Output:

1

4

5

2
class MultiIterator {
  constructor(inp) {
    this.inp = inp;
    this.x = -1;
    this.inpLen = inp.length;
    this.levelProgress = Array(inp.length).fill(0);
    this.nextX = 0;
  }

  hasNext() {
    var count = 0;
    var listIndex = this.x;
    var elemIndex;
    do {
      listIndex++;
      listIndex %= this.inpLen;
      elemIndex = this.levelProgress[listIndex]; // index = size - 1
      count++;
    } while (count < this.inpLen && elemIndex === this.inp[listIndex].length)
    if (elemIndex === this.inp[listIndex].length) {
      return false;
    }
    this.nextX = listIndex;
    return true;
  }

  next() {
    if (this.hasNext()) {
      this.x = this.nextX;
      this.levelProgress[this.x]++;
      return this.inp[this.x][this.levelProgress[this.x] - 1];
    }
    return null;
  }
}

// Test Code
const node = new MultiIterator([
  [1, 2],
  [],
  [4],
  [5],
]);

while (node.hasNext()) {
  console.log(node.next());
}

Demo

You can print this list horizontally as well.

For example:

Input:

[[1, 2], [], [4], [5]]

Output:

1

2

4

5
class MultiIterator {
  constructor(inp) {
    this.inp = inp;
    this.x = 0;
    this.y = -1;
    this.inpLen = inp.length;
    this.nextX = 0;
    this.nextY = 0;
  }

  hasNext() {
    var listIndex = this.x;
    var elemIndex = this.y + 1;
    while (listIndex < this.inpLen && elemIndex === this.inp[listIndex].length) {
      listIndex++;
      elemIndex = 0;
    }
    if (listIndex === this.inpLen) {
      return false;
    }
    this.nextX = listIndex;
    this.nextY = elemIndex;
    return true;
  }

  next() {
    if (this.hasNext()) {
      this.x = this.nextX;
      this.y = this.nextY;
      return this.inp[this.nextX][this.nextY];
    }
    return null;
  }
}

// Test Code
const node = new MultiIterator([
  [1, 2],
  [],
  [4],
  [5],
]);

while (node.hasNext()) {
  console.log(node.next());
}

Demo

Categories
interview

Items in Container

const getItems = (str, startIndices, endIndices) => {
  let count = 0;
  const arr = Array(str.length);
  arr[0] = 0;
  for (let i = 1; i < str.length; i++) {
    if (str[i] === '*') {
      count++;
      arr[i] = arr[i - 1];
    } else {
      arr[i] = count;
    }
  }
  const ret = Array(startIndices.length);
  for (let i = 0; i < startIndices.length; i++) {
    ret[i] = arr[endIndices[i] - 1] - arr[startIndices[i] - 1];
  }
  return ret;
}

console.log(getItems('|**|*|*', [1, 1], [5, 6])); // [2,3]

Demo

Categories
interview

In-Flight Media

// In-Flight Media

const getMovies = (flightDuration, movieDurations) => {
  const movieTargetDuration = flightDuration - 30;
  const requiredDurations = {};
  var ret = [];
  for (let [key, movieDuration] of Object.entries(movieDurations)) {
    if (movieDuration in requiredDurations) {
      // Found a pair.
      ret.push([requiredDurations[movieDuration], parseInt(key)]);
    }
    requiredDurations[movieTargetDuration - movieDuration] = parseInt(key);
  }

  // Find the pair with the maximum duration movie.
  var maxDuration = -1;
  var maxLoc = -1;
  for (let [key, value] of Object.entries(ret)) {
    var currMax = Math.max(movieDurations[value[0]], movieDurations[value[1]]);
    if (currMax > maxDuration) {
      maxDuration = currMax;
      maxLoc = key;
    }
  }
 
  // If no pair found then return [-1, 1].
  return maxLoc > -1 ? ret[maxLoc] : [-1, 1];
};

console.log(getMovies(90, [1, 10, 25, 35, 60])); // [2,3]

Demo

Categories
interview

Implement Array.prototype.map()

Array.prototype.map = function(mapper, thisArg) {
  const arr = [];

  for (const [key] of Object.entries(this)) {
    arr[key] = mapper.call(thisArg, this[key], key >>> 0, this);
  }

  return arr;
}

const arr = [];
arr[0] = 0;
arr[2] = 2;
arr[3] = 3;
console.log(arr); // [0, undefined, 2, 3]
console.log(arr.map(x => 2 * x)); // [0, undefined, 4, 6]

Demo

Categories
interview

Create Array of size in Js

const arr = Array(3).fill(5);
console.log(arr); // [5, 5, 5]

Demo

Categories
interview

Uglify CSS Class names



/**
 * @returns {string}
 */
function getUniqueClassName() {
  getUniqueClassName.count = getUniqueClassName.count || 1;

  var helper = () => {
    var count = getUniqueClassName.count++;
    var ret = '';
    while (count > 0) {
      var curr = (count - 1) % 52;
      ret = String.fromCharCode((curr < 26) ? 97 /* a */ + curr : 65      /* A */ + (curr - 26)) + ret;
      count = Math.floor((count - 1) / 52);
    }
    return ret;
  }

  return helper();
}

getUniqueClassName.reset = function() {
  getUniqueClassName.count = 0;
}

console.log(getUniqueClassName()); // a
console.log(getUniqueClassName()); // b


Demo

Categories
interview

HTMLElement to Virtual DOM and back

/**
 * @param {HTMLElement} 
 * @return {object} object literal presentation
 */
function virtualize(element) {
  if (element.nodeType === 3)
    return element.textContent;
  const ret = {
    type: element.tagName.toLowerCase(),
    props: {
      children: []
    }
  };
  element.childNodes.forEach(child => ret.props.children.push(virtualize(child)));
  if (ret.props.children.length === 1)
    ret.props.children = ret.props.children[0];
  for (const {
      name,
      value
    } of element.attributes)
    ret.props[name === 'class' ? 'className' : name] = value;
  return ret;
}

/**
 * @param {object} valid object literal presentation
 * @return {HTMLElement} 
 */
function render(obj) {
  if (typeof obj === 'string') return document.createTextNode(obj);
  const {
    type,
    props: {
      children,
      ...attributes
    }
  } = obj;
  const ret = document.createElement(type);
  const childNodes = typeof children === 'string' ? [children] : children;
  childNodes.forEach(childNode => ret.append(render(childNode)));
  for (const [key, val] of Object.entries(attributes)) {
    ret.setAttribute(key === 'className' ? 'class' : key, val)
  }
  return ret;
}

Demo

Categories
interview

Is Element in View

<body onscroll="onscroll()">

  <div style="width: 400px; height:800px; border:1px solid #222;">Scroll Down</div>

  <div id="demo">
    Demo
  </div>

</body>
const isInView = (element) => {
  const {
    top,
    right,
    bottom,
    left
  } = element.getBoundingClientRect();

  return top >= 0 &&
    left >= 0 &&
    right <= (window.innerWidth || document.documentElement.clientWidth) &&
    bottom <= (window.innerHeight || document.documentElemetn.clientHeight);
};

const demo = document.getElementById('demo');

const onscroll = function() {
  console.log(isInView(demo));
};

Demo

Categories
interview

accessKey

<div>Test</div>
const demo = document.getElementById('demo');

 demo.onclick = (e) => {
   console.log(e.target.textContent);
 };
 demo.accessKey = 'w';

 // Alt + W for Windows + Chrome
 // [Control] [Option] + accesskey for Mac
 // Alt + W for Linux + Chrome

Demo

Categories
interview

Staircase using repeat()

Runtime Complexity: O(n^2)

/*Create a staircase based on user input n.

steps(5) should return the below output:
"#    "
"##   "
"###  "
"#### "
"#####" 
*/

const steps = (n) => {
if( n > 0){
  for (let row = 0; row < n; row++) {
      let step = '';

      for (let col = 0; col < n; col++) {
        col <= row ? step += '#' : step += ' ';
      }
       console.log(step);
   }
   return
}
console.log(`please give a number greater than 0`)
}

steps(5);
/* Output
"#    "
"##   "
"###  "
"#### "
"#####" */

Demo

String.prototype.repeat()

Introduced in ES2015+, the repeat() method constructs and returns a new string which contains the specified number of copies of the string on which it was called, concatenated together.

Syntax: str.repeat(count)
count is an integer between 0 and infinity(positive) indicating the number of times to repeat the string.

CodeOutput
‘abc’.repeat(-1)RangeError
‘abc’.repeat(0)
‘abc’.repeat(1)‘abc’
‘abc’.repeat(2)‘abcabc’
‘abc’.repeat(3.5)‘abcabcabc’ // Uses floor
‘abc’.repeat(1/0)Range Error

Note: If the total length of the string to be returned equals or exceeds (1 << 28, i.e., 2^28) then, this method throws a RangeError as most modern browsers can’t handle strings longer than that.

if((str.length * count) >= 1 << 28) // This 
/* A simplified solution using String.prototype.repeat
 */
 
 const steps = (n) => {
  for(let i = 1; i <= n; i++) {
    let step = '#'.repeat(i) + ' '.repeat(n-i);
    console.log(step);
  }
}

steps(5);
/* Output
"#    "
"##   "
"###  "
"#### "
"#####" */

Demo