function removeDuplicateChar(str) {
let char;
const charCount = {};
const newStr = [];
for(let i =0; i < str.length; i++) {
char = str[i];
if(charCount[char]) {
charCount[char]++;
} else charCount[char] = 1;
}
for (let char in charCount) {
if (charCount[char]==1) newStr.push(char);
}
return newStr.join('');
}
removeDuplicateChar('Learn more javascript dude'); // "Lnmojvsciptu"const a = 100;
Math.floor(Math.random() * a);
Math.floor(0.9999999999 * a); // 99const a = 100;
Math.floor(Math.random() * (a + 1));
Math.floor(0.9999999999 * (a + 1)); // 100const a = 10;
Math.floor(Math.random() * 100) + a; // [a, (100 + a))
// lower limit:
Math.floor(0.0000000 * 100) + a; // 10
// upper limit:
Math.floor(0.9999999 * 100) + a; // 109function randomExc(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}function randomInc(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}In this example the task is: how to get a random number between 5 to 7 if we have a random function to get 1 to 5
function rand5() {
return 1 + Math.random() * 4;
}
function rand7() {
return 5 + rand5() / 5 * 2;
}For this there is a math formula to get a sum of a sequence of n characters. For example: find a sum of consequtive numbers between 5 and 62, altogether there are 20 numbers.
What the above task means is that the difference between 2 neighboring numbers is not 1
but perhaps 4 or something. It's OK, the formula works so long as the numbers are uniformly distributed.
Let 5 be a1 and 62 be a2 and let n be the number of numbers in the sequence (thus n = 20). The
formula looks as follows:
SUM = (n * (a1 + a2)) / 2
Let's calculate: SUM = (20 * (5 + 62)) / 2 = 670
Similarly we can calculate the sum for the sequence of numbers: 1-10 is SUM = 10*(1+10)/2 = 55
Let's use this formula to solve our problem:
function missingNumber(arr) {
const n = arr.length + 1;
const expectedSum = n * (1 + n) / 2;
const sum = arr.reduce((t,v) => t + v);
return expectedSum - sum;
}
missingNumber([5, 2, 6, 1, 3]); // 4Question: From a unsorted array, check whether there are any two numbers that will sum up to a given number?
Answer: Simplest thing in the world: double loop:
function sumFinder(arr, sum) {
const len = arr.length;
for(let i = 0; i < len - 1; i++) {
for(let j = i + 1; j < len; j++) {
if (arr[i] + arr[j] === sum) return true;
}
}
return false;
}
sumFinder([6,4,3,2,1,7], 9); // true
sumFinder([6,4,3,2,1,7], 2); // falseInterviewer: What is the time complexity of this function
You: O(n^2)
Interviewer: Can you make this better
You: Let me see. I can have an object where I will store the difference of sum and element. And then when i get to a new element and if i find the difference in the object, then i have a pair that sums up to the desired sum.
function sumFinder(arr, sum) {
const len = arr.length;
const differences = {};
let num;
for(let i = 0; i < len; i++) {
num = arr[i];
if(differences[num]) {
return true;
} else differences[sum-num] = true;
}
return false;
}
sumFinder([6,4,3,2,1,7], 9); // true
sumFinder([6,4,3,2,1,7], 2); // false
console.log(sumFinder([6,4,3,2,1,7], 9)); // true
console.log(sumFinder([6,4,3,2,1,7], 2)); // falseQuestion: How would you find the largest sum of any two elements?
Answer: this is actually very simple and straight forward. Just find the two largest number and return sum of them
function topSum(arr) {
let biggest = arr[0];
let second = arr[1];
const len = arr.length;
let i = 2;
if (len < 2) return null;
if (biggest < second) [biggest, second] = [second, biggest];
while(i < len) {
if(arr[i] > biggest) {
second = biggest;
biggest = arr[i];
} else if (arr[i] > second) second = arr[i];
i++;
}
return biggest + second;
}
topSum([1,2,3,4,2,3,1,2]); // 7Question: Count Total number of zeros from 1 upto n?
Answer: If n = 50. number of 0 would be 11 (0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100). Please note that 100 has two 0. This one looks simple but little tricky
Explanation: So the tick here is. If you have a number 1 to 50 the value is 5. just 50 divided by 10. However, if the value is 100. the value is 11. You will get by 100/10 = 10 and 10/10. Thats how you will get in the more zeros in one number like (100, 200, 1000)
function countZero(n) {
let count = 0;
while(n > 0) {
count += Math.floor(n / 10);
n /= 10;
}
return count;
}
countZero(2014); // 223function solveSudoku(matrix) {
function isInRow(row, num) {
for(let i = 0; i < 9; i++) {
if(matrix[row][i] === num) return true;
}
}
function isInCol(col, num) {
for(let i = 0; i < 9; i++) {
if(matrix[i][col] === num) return true;
}
}
function isInBox(row, col, num) {
const r = Math.floor(row / 3) * 3;
const c = Math.floor(col / 3) * 3;
for(let i = r; i < r + 3; i++) {
for(let j = c; j < c + 3; j++) {
if(matrix[i][j] === num) return true;
}
}
}
function isSafe(row, col, num) {
return (!isInRow(row, num) && !isInCol(col, num) && !isInBox(row, col, num));
}
function solve() {
for(let row = 0; row < 9; row++) {
for(let col = 0; col < 9; col++) {
if(!matrix[row][col]) {
for(let num = 1; num <= 9; num++) {
if(isSafe(row, col, num)) {
matrix[row][col] = num;
if(solve()) {
return true;
} else {
matrix[row][col] = 0;
}
}
}
return false;
}
}
}
return true;
}
if(solve()) {
return matrix;
} else throw new Error('unsolvable');
}This task is for Recursive Backtracking
Explanation:
Idea: Idea is very simple. We will convert the string to an array. from the array we will pick one character and then permute rest of it. After getting the permutation of the rest of the characters, we will concatenate each of them with the character we have picked.
step-1 First copy original array to avoid changing it while picking elements
step-2 Use splice to removed element from the copied array. We copied the array because splice will remove the item from the array. We will need the picked item in the next iteration.
step-3 [1,2,3,4].splice(2,1) will return [3] and remaining array = [1,2,4]
step-4 Use recursive method to get the permutation of the rest of the elements by passing array as string
step-5 Finally, concat like a + permute(bc) for each
function permutations(str) {
const arr = str.split('');
const perms = [];
let rest;
let picked;
let restPerms;
let next;
if (arr.length === 1) return [str];
for (let i = 0; i < arr.length; i++) {
rest = [...arr];
picked = rest.splice(i, 1);
restPerms = permutations(rest.join(''));
for (let j = 0; j < restPerms.length; j++) {
next = [...picked, ...restPerms[j]]
perms.push(next.join(''));
}
}
return perms;
}
permutations('boat'); // 24 permutationsHere is a real life example of this task asked on the interview:
Given an array of words like this:
[
['1', '2', '3'],
['true', 'false'],
['NaN', 'undefined', 'null'],
]write a function that will print all the possible variations of the words inside inner arrays so that the result looks like this:
1,true,NaN
1,true,undefined
1,true,null
1,false,NaN
1,false,undefined
1,false,null
2,true,NaN
2,true,undefined
2,true,null
2,false,NaN
2,false,undefined
2,false,null
3,true,NaN
3,true,undefined
3,true,null
3,false,NaN
3,false,undefined
3,false,null
Here is the implementation:
function wordsPuzzle(words) {
function getPermutations(words, iterableIndex) {
const lastIndex = words.length - 1;
if (iterableIndex === lastIndex) {
return words[lastIndex].map((word) => [word]);
}
const permutations = getPermutations(words, iterableIndex + 1);
const result = [];
const iterable = words[iterableIndex];
for (let i = 0; i < iterable.length; i += 1) {
const currentWord = iterable[i];
for (let j = 0; j < permutations.length; j += 1) {
result.push([currentWord, ...permutations[j]]);
}
}
return result;
}
return getPermutations(words, 0);
}Implement a function which pushes all 0s to the right while keeping the non-zero values in order, use of push
or splice is forbidden:
const arr = [0, 10, 0, 1, 2, 3, 0, 0, 4, 0, 0, 0];
shiftZeros(arr); // [10, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0];
function shiftZeros(arr) {
// first count non-zeros:
let nonZeroCount = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] !== 0) nonZeroCount++;
}
// then loop until all the non-zero
// elements have been moved to the beginning
let count = 0;
let i = 0;
while (count < nonZeroCount) {
if (arr[i] !== 0) {
[arr[i], arr[count]] = [arr[count], arr[i]];
count++;
}
i++;
}
return arr;
}Find the greatest 3 elements of the array without using sort of any kind or mutating the source array:
function threeBiggest(arr) {
let maxOne = -Infinity;
let maxTwo = -Infinity;
let maxThree = -Infinity;
let elem;
for (let i = 0; i < arr.length; i += 1) {
elem = arr[i];
if (elem > maxOne) {
maxThree = maxTwo;
maxTwo = maxOne;
maxOne = elem;
} else if (elem > maxTwo) {
maxThree = maxTwo;
maxTwo = elem;
} else if (elem > maxThree) {
maxThree = elem;
}
}
return `first - ${maxOne}, second - ${maxTwo}, third - ${maxThree}`;
}
threeBiggest([5,4,3,6,7,8,9,10,1,2]); // "first - 10, second - 9, third - 8"Write a function that works like so:
serialProcess([1,2,3,4,5], (el, index, list, done) => {
setTimeout(() => { done(el + el); });
}).then(console.log); // [1,4,9,16,25]Takes in an array and a callback ( which modifies each array item in a certain way ). Beware that the callback
only calls its last parameter ( another callback ) in setTimeout. The return value should be a Promise with
an array of modified items as seen above. Here is the solution:
function serialProcess(arr, cb) {
return Promise.all(
arr.map((value, index, array) => {
return new Promise((resolve) => {
cb(value, index, array, resolve);
})
})
);
}Write bind that can be chained like so fun.bind().bind().bind(). Each new call to bind should replace
the context and all but beware as the source function should remain the same ( or else Maximum Call
Stack exceeded ):
Function.prototype.bind = (function() {
let fun = null;
let context = null;
let firstParams = null;
return function() {
context = arguments[0];
firstParams = Array.prototype.slice.call(arguments, 1);
if (!fun) {
fun = this;
}
return function() {
const secondParams = Array.prototype.slice.call(arguments);
const funToCall = fun;
fun = null;
return funToCall.apply(context, firstParams.concat(secondParams));
}
}
}());
class Cat {
constructor(name) {
this.name = name;
this.x = 12;
this.y = 11;
}
danceAround(param1, param2) {
this.name += this.x + this.y + param1;
this.param2 = param2;
}
}
const cat = new Cat('Tom');
const rightObject = { name: 'Holmes', x: 'node', y: 'Nose' };
cat.danceAround
.bind({ name: 'Cool', x: 'wow', y: 0 }, ':)', '>0')
.bind({ name: 'Another dide', x: 'what', y: 'where' }, '--)')
.bind(rightObject, 'coolFirstPar')('coolSecond Par');
rightObject; // { name: 'HolmesnodeNosecoolFirstPar, x: 'node', y: 'Nose', param2: 'coolSecond Par' }Here is a task I come up with: we have n number of requests, make JS fetch them one after another:
const urlCount = 30;
const baseURI = 'https://jsonplaceholder.typicode.com/todos/';
const urls = [];
let i = 0;
while (i < urlCount) {
urls[i] = `${baseURI}${i}`;
i += 1;
}
function getRandom() {
Promise.all(urls.map((url, i) => fetch(url).then(res => {
// console.log(`Getting: ${i}`);
return res.json();
}))).then(console.log);
}
function getOrdered() {
urls.reduce((t, url, i) => {
return t.then(() => {
return fetch(url).then(res => {
// console.log(`Getting ${i}`);
return res.json();
}).then(console.log);
});
}, Promise.resolve());
}
function getOrderedToo() {
urls.reduce((t, url, i) => {
return t.then(() => fetch(url)).then(res => {
// console.log(`Getting ${i}`);
return res.json();
}).then(console.log);
}, Promise.resolve());
}Now let's make it harder. Imagine that our server can handle only m number of requests at a time, thus you should
fetch m out of n urls, and only after they have arrived, fetch another m urls and so on until we are done.
Here is the solution:
const n = 30;
const m = 4;
const baseURI = 'https://jsonplaceholder.typicode.com/todos/';
const urls = [];
fillURLs();
doStuff();
function fillURLs() {
let i = 0;
while (i < n) {
urls[i] = `${baseURI}${i}`;
i += 1;
}
}
function doStuff() {
let promise = Promise.resolve();
for (let i = 0; i < n; i += m) {
const urlsToFetchAtATime = urls.slice(i, Math.min(i + m, n));
promise = promise.then(() => {
return Promise.all(urlsToFetchAtATime.map(url => {
return fetch(url).then(res => res.json());
})).then(responses => {
console.log('I have fetched:', responses);
});
});
}
}It is awesome!
CSS Parser is a great thing. It may be too complicated to ask at the interview but I need to keep it somewhere:
function parseCss(text) {
let tokenizer = /([\s\S]+?)\{([\s\S]*?)\}/gi,
rules = [],
rule, token;
text = text.replace(/\/\*[\s\S]*?\*\//g, '');
while ( (token = tokenizer.exec(text)) ) {
const style = parseRule( token[2].trim() );
style.cssText = stringifyRule(style);
rule = {
selectorText : token[1].trim().replace(/\s*\,\s*/, ', '),
style,
};
rule.cssText = rule.selectorText + ' { ' + rule.style.cssText + ' }';
rules.push(rule);
}
return rules;
}
function parseRule(css) {
let tokenizer = /\s*([a-z\-]+)\s*:\s*((?:[^;]*url\(.*?\)[^;]*|[^;]*)*)\s*(?:;|$)/gi,
obj = {},
token;
while ( (token=tokenizer.exec(css)) ) {
obj[token[1].toLowerCase()] = token[2];
}
return obj;
}
function stringifyRule(style) {
let text = '',
keys = Object.keys(style).sort();
for (let i=0; i<keys.length; i++) {
text += ' ' + keys[i] + ': ' + style[keys[i]] + ';';
}
return text.substring(1);
}
const ast = parseCss(`
body {
color: yellow;
font-size: 14px;
}
.className {
display: flex;
}
`);ast ( Abstract Syntax Tree ) will look like this:
[
{
"selectorText": "body",
"style": {
"color": "yellow",
"font-size": "14px",
"cssText": "color: yellow; font-size: 14px;"
},
"cssText": "body { color: yellow; font-size: 14px; }"
},
{
"selectorText": ".className",
"style": {
"display": "flex",
"cssText": "display: flex;"
},
"cssText": ".className { display: flex; }"
}
]Imagine the situation where we have items:
const items = [
{name: 'Zh', surname: 'Pak', age: 19},
{name: 'Va', surname: 'In', age: 26},
{name: 'An', surname: 'Ik', age: 27},
{name: 'Mi', surname: 'Tr', age: 30},
{name: 'Ma', surname: 'Pv', age: 30},
];And we want to sort them first by name and then by surname. So the logic would look like this:
items.sort((left, right) => {
const firstCharLeft = left.name[0];
const firstCharRight = right.name[0];
// if the first 2 letters are the same then sort by surname
if (firstCharLeft === firstCharRight) {
return sortBySurname(left, right);
}
return firstCharLeft > firstCharRight ? 1 : -1;
});
function sortBySurname(left, right) {
const firstCharLeft = left.surname[0];
const firstCharRight = right.surname[0];
// normally if the callback provided to Array.prototype.sort returns 0, then
// JS will not swap the two elements for whose comparison the callback returned 0
if (firstCharLeft === firstCharRight) return 0;
return firstCharLeft > firstCharRight ? 1 : -1;
}But what if the surnames are the same too? Then we would want to sort by age. Well, it is good but getting the sort for age into our existing code is starting to make our code look like shit. Thus we need to write a composable sort that would look like this:
composeSort(sortByName, sortBySurname, sortByAge);Such a call to composeSort will return a callback we should be able to pass like so:
items.sort(composeSort(sortByName, sortBySurname, sortByAge));to the .sort method. And such a callback returned by composeSort should thus sort all the values
- first by
sortByName - then in case
sortByNameencounters the same 2 first letters, then sort bysortBySurname - and if the same story happens to
sortBySurname, then sort withsortByAge
So we want a utility to make possible our logic that we just now came up with above.
Here is the implementation:
function composeSort(...sortCbs) {
return (left, right) => {
return sortCbs.reduce((t, cb) => t || cb(left, right), 0);
};
}So the resulting callback from composeSort looks at the value ( either -1 or 1 ) returned by the first callback,
then if it is 0 it checks that the next callback returns either 1 or -1 and not 0, yet if it also retruns 0 it looks at
the value returned by the 3rd callback and so on all that by reducing the array of callbacks.
Implement a Transation class that would behave like so:
function Transaction(arr) {
...
}
const arr = [];
const tA = new Transaction(arr);
const tB = new Transaction(arr);
const tC = new Transaction(arr);
tA.push('A1');
tA.push('A2');
tB.push('B1');
tB.push('B2');
tC.unshift('C1');
tC.push('C2');
tB.push('B3');
tA.push('A3');
console.log('1st', arr); // 1st: ['C1', 'A1', 'A2', 'B1', 'B2', 'C2', 'B3', 'A3']
tB.rollback();
console.log('2nd', arr); // 2nd: ['C1', 'A1', 'A2', 'C2', 'A3']
tA.commit();
tA.rollback();
console.log('3rd', arr); // 3rd: ['C1', 'A1', 'A2', 'C2', 'A3']
tC.rollback();
console.log('4th', arr); // 4th: ['A1', 'A2', 'A3']Here is the implementation ( it is one of those tasks that you solve by using 2 arrays ):
function Transaction(arr) {
this.hash = String(Math.random()).slice(2);
if (!Transaction.array) {
Transaction.array = arr;
}
}
Transaction.array = null;
Transaction.hashesArr = [];
Transaction.prototype.push = function (val) {
this.constructor.array.push(val);
this.constructor.hashesArr.push(this.hash);
};
Transaction.prototype.unshift = function (val) {
this.constructor.array.unshift(val);
this.constructor.hashesArr.unshift(this.hash);
};
Transaction.prototype.rollback = function () {
const array = this.constructor.array;
const hashesArray = this.constructor.hashesArr;
for (let i = array.length; i >= 0; i -= 1) {
if (hashesArray[i] === this.hash) {
array.splice(i, 1);
hashesArray.splice(i, 1);
}
}
};
Transaction.prototype.commit = function () {
const hashesArray = this.constructor.hashesArr;
for (let i = hashesArray.length; i >= 0; i -= 1) {
if (hashesArray[i] === this.hash) {
delete hashesArray[i];
}
}
};Imagine we have the following tickets:
[
{ from: 'London', to: 'Moscow' },
{ from: 'NY', to: 'London' },
{ from: 'Moscow', to: 'SPb' },
...
]Out of these tickets we can build a straight route from a to b. Thus we are going to fly from New York to Texas according to the following route:
NY -> London -> Washington -> Texas
We can tell so by looking at the sorted tickets below:
[
{ from: 'NY', to: 'London' },
{ from: 'London', to: 'Moscow' },
{ from: 'Moscow', to: 'SPb' },
...
]We need to implement a function which would order the tickets like above so that we can trace them and get the route from a to b.
Here is the awesome implementation:
function getRoute(tickets = []) {
const result = [];
const length = tickets.length;
const destinationRegistry = {};
const departureRegistry = {};
for (let i = 0; i < length; i += 1) {
const ticket = tickets[i];
destinationRegistry[ticket.to] = ticket;
departureRegistry[ticket.from] = ticket;
}
const currentTicket = tickets[0];
result.push(currentTicket);
let destTicket = departureRegistry[currentTicket.to];
while(destTicket) {
result.push(destTicket);
destTicket = departureRegistry[destTicket.to];
}
let departureTicket = destinationRegistry[currentTicket.from];
while(departureTicket) {
result.unshift(departureTicket);
departureTicket = destinationRegistry[departureTicket.from];
}
return result;
}While the recursive solution might blow up the Call Stack in JS, here is the non recursive alternative:
Naive Approach:
function flattenArrayNonRec(arr) {
const flattenedArray = [];
let iterable = arr;
while (iterable.length) {
const firstElem = iterable.shift();
if (!Array.isArray(firstElem)) {
flattenedArray.push(firstElem);
} else {
iterable = [...firstElem, ...iterable];
}
}
return flattenedArray;
}Something crazy I came up with ( O(n) thou ):
/**
As we go inside inner arrays of the non flattened array, try to think as though we go a level deeper, as though
we go to the depth = prevDepth + 1; but we also have to keep track of which index in the array we were at
before we fell into the inner array, depthIndexesStack is a stack that holds just that sort of information.
For instance in the future it might look something like:
[
7,
4,
2,
11,
]
Thus from the above we can distill that as we were iterating over the source array, at depth 0,
at 7th element we ran into the inner array, then we stepped into the inner array and started iterating
over it, at depth 1 now, when we found, at index 4, yet another inner array and stepped into that whose
2nd element turned out to be still another inner array which we stepped into and now we are there, at depth 3,
at the 11th index element. As we step out of the inner array, we pop the last element of depthIndexesStack
off the stack. The following algorithm is based on just such an iteration.
*/
function flattenArrayNonRec(arr) {
const depthIndexesStack = [];
const flattenedArray = [];
const sourceArray = arr.slice();
depthIndexesStack.push(0);
while (depthIndexesStack.length) {
const depth = depthIndexesStack.length;
let iterable = sourceArray;
let j = 0;
while (j < depth - 1) {
iterable = iterable[depthIndexesStack[j]];
j += 1;
}
const index = depthIndexesStack[depth - 1];
const item = iterable[index];
if (index === iterable.length) {
depthIndexesStack.pop();
const newDepth = depthIndexesStack.length;
const oldIndex = depthIndexesStack[newDepth - 1];
depthIndexesStack[newDepth - 1] = oldIndex + 1;
continue;
}
if (!Array.isArray(item)) {
flattenedArray.push(item);
depthIndexesStack[depth - 1] = index + 1;
} else {
depthIndexesStack.push(0);
}
}
return flattenedArray;
}Since I have the explanation in the awesome video, here is the solution only:
// n queens problem
// board: 1 - there is a queen, 0 - the cell is empty
const BOARD_SIZE = 4;
const board = createBoard(BOARD_SIZE);
// process:
queenBacktrack(board);
console.log(board.map((innerBoard) => innerBoard.join(' ')).join('\n'));
// functions:
function queenBacktrack(board) {
function solve(row = 0) {
const boardSize = board.length;
if (row === boardSize) {
return true;
}
for (let i = 0; i < boardSize; i += 1) {
if (isQueenSafe(row, i, board)) {
board[row][i] = 1;
if (solve(row + 1)) {
return true;
} else {
board[row][i] = 0;
}
}
}
return false;
}
if (solve()) {
return board;
} else {
throw new Error('Unsolvable');
}
}
function isQueenSafe(row, col, board) {
return (
checkRowsAndColums(row, col, board) &&
checkDiagonals(row, col, board)
);
}
// task helpers:
function createBoard(boardSize) {
const arr = [];
let i = 0;
while (i < boardSize) {
arr.push(new Array(boardSize).fill(0));
i += 1;
}
return arr;
}
function checkRowsAndColums(row, col, board) {
const boardSize = board.length;
for (let i = 0; i < boardSize; i += 1) {
if (board[row][i] === 1) {
return false;
}
if (board[i][col] === 1) {
return false;
}
}
return true;
}
function checkDiagonals(row, col, board) {
const NUMBER_OF_BOARD_EDGES = 4;
const boardSize = board.length;
// guide on how for the algorithm to attain the top-left, top-right, bottom-left, bottom-right
// cells relative to the current cell ( which is board[row][col] ); for instance in order to get
// the top left cell relative to the current one, we need to do board[row - 1][col - 1], or -1 -1:
const howToGetDiagnals = [
[-1, -1],
[-1, 1],
[1, -1],
[1, 1],
];
// Note: since we never have any queens *below* the cell we are checking ( we are going top to bottom,
// like in the video ), we can make the algorithm a bit more efficient by commenting out the
// [-1, 1] and [1, -1] instructions above
let offset = 1;
while (true) {
let overflowCount = 0;
let i = 0;
while (i < howToGetDiagnals.length) {
const instruction = howToGetDiagnals[i];
const nextRow = row + offset * instruction[0];
const nextColumn = col + offset * instruction[1];
if (
nextRow >= 0 && nextColumn >= 0 &&
nextRow < boardSize && nextColumn < boardSize
) {
if (board[nextRow][nextColumn] === 1) {
return false;
}
} else {
overflowCount += 1;
}
i += 1;
}
if (overflowCount === NUMBER_OF_BOARD_EDGES) {
break;
} else {
offset += 1;
}
}
return true;
}The log is going to be:
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
Here is a polyfill for bind but done without using apply, call or any other functions:
function bindPolyfill(fn, ctx) {
function createFunctionCall(argsCount) {
var functionCall = '(';
for (var i = 0; i < argsCount; i += 1) {
var isLastElem = i === argsCount - 1;
functionCall += 'arguments[' + i + ']' + (isLastElem ? '' : ',');
}
functionCall += ');';
return functionCall;
}
return function () {
var argsCount = arguments.length;
ctx.__fn__ = fn;
var result = eval('ctx.__fn__' + createFunctionCall(argsCount));
delete ctx.__fn__;
return result;
};
}
const testingFunc = function (first, second) {
console.log('context:', this);
console.log('first', first);
console.log('second', second);
return this.name;
};
const bound = bindPolyfill(testingFunc, { name: 'John' });
console.log(bound('firstVal', true, 'awesome'));The expected output:
context: { name: 'John', __fn__: [Function: testingFunc] }
first firstVal
second true
John