• Sudoku Solver

    This solution uses DFS (Depth First Search) Algorithm and looks for a unique solution to the given Sudoku Puzzle.

    DFS Solution

    /**
     * @param {character[][]} board
     * @return {void} Do not return anything, modify board in-place instead.
     */
    const solveSudoku = function(board) {
      canSolveCheck(board, 0, 0);
    };
    
    // sudoku solver (backtracking) Time complexity = O(9^m)  m = number of spaces to be filled.
    
    const canSolveCheck = (board, x, y) => {
      if (x === 9) {
        return true;
      } else if (y === 9) {
        return canSolveCheck(board, x + 1, 0);
      }
      if (board[x][y] !== '.') {
        return canSolveCheck(board, x, y + 1);
      } else {
        for (let i = 1; i <= 9; i++) {
          board[x][y] = i + '';
          if (valid(board, x, y) && canSolveCheck(board, x, y + 1)) {
            return true;
          }
          board[x][y] = '.';
        }
        return false;
      }
    };
    
    const valid = (board, x, y) => {
      const i = board[x][y];
      for (let k = 0; k < 9; k++) {
        if (k !== y && board[x][k] === i) {
          return false;
        }
        if (k !== x && board[k][y] === i) {
          return false;
        }
        const row = Math.floor(x / 3) * 3 + Math.floor(k / 3);
        const col = Math.floor(y / 3) * 3 + (k % 3);
        if (!(row === x && col === y) && board[row][col] === i) {
          return false;
        }
      }
      return true;
    };

    Using a Map

    Instead of running valid() for all possible values, we can pre-compute and check if the current value is valid.

    
    const solveSudoku = function(board) {
      canSolveCheckMemoryOptimized(board, 0, 0);
    };
    
    const canSolveCheckMemoryOptimized = (board, x, y) => {
      if (x === 9) {
        return true;
      } else if (y === 9) {
        return canSolveCheck(board, x + 1, 0);
      }
      if (board[x][y] !== '.') {
        return canSolveCheck(board, x, y + 1);
      } else {
        const obj = {};
        buildObj(board, x, y, obj);
        for (let i = 1; i <= 9; i++) {
          board[x][y] = i + '';
          if (!(board[x][y] in obj) && canSolveCheck(board, x, y + 1)) {
            return true;
          }
          board[x][y] = '.';
        }
        return false;
      }
    };
    
    const buildObj = (board, x, y, obj) => {
      for (let k = 0; k < 9; k++) {
       obj[board[x][k]] = true;
       obj[board[k][y]] =true;
       const row = Math.floor(x / 3) * 3 + Math.floor(k / 3);
       const col = Math.floor(y / 3) * 3 + (k % 3);
       obj[board[row][col]] = true;
      }
    };

    Demo

    Another alternate solution would be to precompute these values into lists of Maps.

    Java

    This solution uses DFS (Depth First Search) Algorithm and looks for a unique solution to the given Sudoku Puzzle.

    (more…)
  • Group API calls with callbacks (asynchronous)

    Write a class with a method getKey(key, callback) that invokes an API with the provided key. The method should also invoke a callback with the corresponding value returned by the API . Calls that are made within a given interval should be grouped.

    Input:
    getKey(v1/get?key=foo , () => console.log(x));
    
    Output:
    Let us assume the API returns the following
    {foo: 50} 
    Then the callback is going to be invoked with corresponding value 50
    // 50

    API call with grouped keys, is used when the the subsequent calls are made within a 20 ms delay for example,

    Input:
    getKey(v1/get?key=foo , () => console.log(x)); // at t = 0
    getKey(v1/get?key=bar , () => console.log(x)); // at t = 10
    getKey(v1/get?key=foo , () => console.log(x)); // at t =20
    
    Output:
    Let us assume the API (domain/get?key=foo,bar,foo) returns the following
    {foo: 50, bar: 100} 
    Then the callbacks are going to be invoked with the corresponding values 50, 100 and 50.
    // 50
    // 100
    // 50
    class Api {
      constructor(url, delay) {
        this.url = `${url}?key=`;
        this.delay = delay;
        this.queue = [];
        this.blocked = false;
      }
    
      getkey = (key, cb) => {
        this.queue.push([key, cb]);
        if (!this.blocked) {
          this.blocked = true;
          setTimeout(() => this.callApi(), this.delay);
        }
      };
    
      callApi = async () => {
        if (this.queue.length) {
          const keyMap = {};
          while (this.queue.length) {
            const [key, cb] = this.queue.shift();
            (keyMap[key] || (keyMap[key] = [])).push(cb);
          }
          try {
            const response = await fetch(this.url + Object.keys(keyMap).join(','));
            if (!response.ok) {
              throw 'Status: ' + response.status;
            }
            const data = await response.json();
            console.log(data)
            /*
            Testing for httpbin response.
                    const data = {
                      args: {
                        key: "foo"
                      }
                    };
            */
            data[data.args.key] = 12;
            for (const [key, val] of Object.entries(data)) {
              (keyMap[key] || []).forEach(cb => cb(val));
            }
          } catch (error) {
            throw error;
          }
          this.callApi();
        } else {
          this.blocked = false;
        }
      };
    }
    
    /* Test case */
    const api = new Api('https://httpbin.org/get', 3000);
    const test = (x) => console.log(x);
    api.getkey('foo', test);
    

    Demo

  • Find the City With the Smallest Number of Neighbors at a Threshold Distance

    For a given bidirectional weighted graph, find the node (city) with the least number of nodes reachable within a given threshold.

    Note: If there are multiple such nodes, then return the node with the highest value among them.

    Time Complexity: O(n^3)

    const findtheCity = (n, edges, threshold) => {
      const adjMatrix = Array(n);
    
      for (let i = 0; i < n; i++) {
        adjMatrix[i] = [];
        for (let j = 0; j < n; j++) {
          adjMatrix[i][j] = (i === j) ? 0 : Number.MAX_VALUE;
        }
      }
    
      for (const val of edges) {
        adjMatrix[val[0]][val[1]] = val[2];
        adjMatrix[val[1]][val[0]] = val[2];
      }
    
      fw(adjMatrix);
    
      let minNeighbours = Number.MAX_VALUE;
      let neighbour;
      for (let i = 0; i < n; i++) {
        let currNeighbours = 0;
    
        for (let j = 0; j < n; j++) {
          if (adjMatrix[i][j] <= threshold) {
            currNeighbours++;
          }
        }
    
        if (currNeighbours <= minNeighbours) {
          minNeighbours = currNeighbours;
          neighbour = i;
        }
      }
    
      return neighbour;
    };
    
    
    const fw = (adjMatrix) => {
      const n = adjMatrix.length;
      for (let k = 0; k < n; k++) {
        for (let i = 0; i < n; i++) {
          for (let j = 0; j < n; j++) {
            adjMatrix[i][j] = Math.min(adjMatrix[i][j],
            adjMatrix[i][k] + adjMatrix[k][j]);
          }
        }
    
      }
    };
    
    console.log(findtheCity(4, [
      [0, 1, 3],
      [1, 2, 1],
      [1, 3, 4],
      [2, 3, 1]
    ], 4)); // 3
    

    Demo

  • Window.location object

    Javascript can access the URL of the current page with window.location object. This object contains various properties of the URL such as protocol, host, pathname, search and more.

    • window.location.href returns the href (URL) of the current page
    • window.location.hostname returns the domain name of the web host
    • window.location.pathname returns the path and filename of the current page
    • window.location.protocol returns the web protocol used (http: or https:)
    • window.location.assign() loads a new document
    <button class="newDocument">
       New Document
    </button>
    console.log(window.location.href); //"https://fiddle.jshell.net/_display/?editor_console=true"
    
    console.log(window.location.hostname); //"fiddle.jshell.net"
    
    console.log(window.location.pathname); //"/_display/"
    
    console.log(window.location.protocol); //"https:"
    
    //Window.location.assign - click on the "New Document" button to load a new document.
    
    function newDocument() {
      window.location.assign("https://www.collegestash.com/")
    }
    
    const newDocButton = document.querySelector(".newDocument");
    
    newDocButton.addEventListener('click', newDocument);

    Demo

  • Find the winner

    Lets say you want to find the winner of a game where the participants pick up stones (n). If ‘A’ and ‘B’ are the 2 players, then the rules of the game are as follows:

    • Player ‘A’ always starts first.
    • Player ‘A’ always picks 1 stone.
    • Player ‘B’ always picks 2 stones.
    • Player ‘A’ and Player ‘B’ take alternate turns.
    • The player to pick up the last stone is the loser.

    Write a method that returns the winner. There can be 3 possible outcomes “A | B | null”.

    /** 
     * @param {number} n
     * @return {'A' | 'B' | null}
     */
    function findWinner(n) {
      // A : true
      // B : false
      if (!n || n <= 0)
        return null;
      return whoWins(n - 1, true) ? 'A' : 'B';
    }
    
    function whoWins(n, player) {
      if (n <= 0)
        return !player;
      return whoWins(n - (player ? 2 : 1), !player);
    }
    
    /** Test cases **/
    console.log(findWinner(1)); // B
    console.log(findWinner(2)); // A
    console.log(findWinner(3)); // A
    console.log(findWinner(4)); // B
    console.log(findWinner(0)); // null
    console.log(findWinner(null)); // null
    
    

    Demo

    A shorter version of the above code in ES6.

    const findWinner = (n) => (!n || n <= 0) ? null : whoWins(n - 1, true) ? 'A' : 'B';
    const whoWins = (n, player) => (n <= 0) ? !player : whoWins(n - (player ? 2 : 1), !player);
    
    /** Test cases **/
    console.log(findWinner(1)); // B
    console.log(findWinner(2)); // A
    console.log(findWinner(3)); // A
    console.log(findWinner(4)); // B
    console.log(findWinner(0)); // null
    console.log(findWinner(null)); // null

    Demo

    Iterative Solution

    const findWinner = (n) => {
      if (!n || n < 1) {
        return null;
      }
      let totalStones = 0;
      let player = 1; // A
      while (totalStones < n) {
        totalStones += player ? 1 : 2;
        player = !player;
      }
      return player ? 'A' : 'B';
    };

    Demo

    Using for loop

    const findWinner = (n) => {
      if (!n || n < 1) {
        return null;
      }
      let player = 1; // A
      for (let totalStones = 0; totalStones < n; totalStones += player ? 1 : 2) {
        player = !player;
      }
      return player ? 'A' : 'B';
    };
    
    /** Test cases **/
    console.log(findWinner(1));      // B
    console.log(findWinner(2));      // A
    console.log(findWinner(3));      // A
    console.log(findWinner(4));      // B
    console.log(findWinner(0));      // null
    console.log(findWinner(null));   // null

    Demo

  • 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

  • Items in Container

    An inventory management system represents items and compartment walls as a string s:

    • * represents an item.
    • ​| represents a compartment wall (pipe).​

    An item is considered enclosed (inside a valid compartment) only if it lies between two compartment walls (|…|). Items outside the outermost walls within a specified substring range are excluded.​ Given a string s and two integer arrays startIndices and endIndices, determine the number of enclosed items for each range [startIndices[i], endIndices[i]].​

    Complete the function getItems:

    function getItems(
      s: string,
      startIndices: number[],
      endIndices: number[]
    ): number[]

    Solution

    const getItems = (str, startIndices, endIndices) => {
      const n = str.length;
      const prefix = new Array(n).fill(0);
      const leftPipe = new Array(n).fill(-1);
      const rightPipe = new Array(n).fill(-1);
    
      // 1. Compute prefix sum of '*' and nearest left pipe
      let count = 0;
      let lastLeftPipe = -1;
      for (let i = 0; i < n; i++) {
        if (str[i] === '*') {
          count++;
        } else {
          lastLeftPipe = i;
        }
        prefix[i] = count;
        leftPipe[i] = lastLeftPipe;
      }
    
      // 2. Compute nearest right pipe
      let lastRightPipe = -1;
      for (let i = n - 1; i >= 0; i--) {
        if (str[i] === '|') {
          lastRightPipe = i;
        }
        rightPipe[i] = lastRightPipe;
      }
    
      // 3. Process 1-indexed queries
      const result = [];
      for (let i = 0; i < startIndices.length; i++) {
        const start = startIndices[i] - 1;
        const end = endIndices[i] - 1;
    
        const firstPipe = rightPipe[start];
        const lastPipe = leftPipe[end];
    
        // Valid container requires two distinct pipes where firstPipe < lastPipe
        if (firstPipe !== -1 && lastPipe !== -1 && firstPipe < lastPipe) {
          result.push(prefix[lastPipe] - prefix[firstPipe]);
        } else {
          result.push(0);
        }
      }
    
      return result;
    };
    
    // Test Case
    console.log(getItems('|**|*|*', [1, 1], [5, 6])); // Output: [2, 3]
    

    Complexity

    • ​Time Complexity: O(N + Q) — O(N) preprocessing across the string of length N, followed by O(1) per query for Q queries.​
    • Space Complexity: O(N) for the lookup tables.
  • 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

  • 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

  • Create Array of size in Js

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

    Demo