A Javascript challenge from Google

Claudia
5 min readOct 13, 2021

I found a Youtube video where a developer was sharing some challenges she had received from Google during a first-round interview. Her name is Kris, AKA acodingnomad .

One of the questions she had received was to dynamically generate a table with x number of rows and columns, initial values of 4 rows and 5 columns.

To make things more interesting, she had to also populate the table with some data in this format;

Pattern for automatically generating a table and its contents.

As you can see it fills the columns in a snake pattern starting from 1, going down then across and up and so forth.

At this point, I decided to stop listening to the video/looking at the code. I wanted to see what my solution would be instead.

For Kris’s solution, visit her github

My Solution on Codepen.io

The Markup

I kept the markup and CSS simple as I was more concerned with the Javascript functionality.

We have a form, I make sure to preventDefault() so that the form doesn’t try and refresh. I have 2 inputs with the number type, 1 for rows, 1 for columns and a button.

<form id="tableForm" onsubmit="event.preventDefault();">
<label for="rows">Number of rows <input type="number" id="rows" value="4" /></label>
<label for="columns">Number of Columns <input type="number" id="columns" value="5" /></label>
<button>Make Table</button>
</form>

The Javascript

We need to get the values from the inputs for rows and columns and we also multiply these values together to find out the maximum number of items we need.

const rows = document.querySelector("#rows").value;
const columns = document.querySelector("#columns").value;
const maxNumbers = rows * columns;

We then create an array and fill it with the maxNumbers+1 (as the keys are 0 indexed) and splice the first value out as we do not need 0 in our array.

const arr = [...Array(maxNumbers + 1).keys()].splice(1);

We now have an array of numbers from 1 to maxNumbers.

My next step was to split the array into separate arrays of columns. Given the original example, it would mean I needed 5 arrays of 4 items.

let newArr = [];
for (i = 1; i <= columns; i++) {
newArr.push(arr.splice(0, rows));
}

If you log newArr at this point you should see something that looks like this:

[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16],[17,18.19,20]]

The way I was thinking to implement the solution, I wanted to have a nested for loop where I would take the first index of every array for the first row, then the next and so forth. Looking at the above example if we did this, it would not match our pattern. It would look like this:

That is not the pattern we want. We need the even columns to be reversed. Remembering that arrays are 0 indexed, we will reverse all items where the index is odd.

To do this I map through my newly created array of arrays and if the index is odd (using modulus to check), I reverse the array otherwise I keep it as is.

const fixedArr = newArr.map((col, i) => {
if (i % 2 !== 0) {
return col.reverse();
}
return col;
});

Finally, I have my data in the order I want. Now I need to generate the actual rows and tables.

Given the number of rows in the input, we will generate a row at a time using a for-loop.

let newRow = "";
for (let i = 0; i < rows; i++) {
}

Within this loop, we need another for-loop that keeps track of the column indexes. It will create a new <td> and within the td set the content to be what is in newArr and within newArr at thej index and when it finds that inner array to iterate using the i from the outer loop. (brain dump and I will come back and try and fix this paragraph to be more readable. Sorry!)

let rowItems = "";for (let j = 0; j < columns; j++) {
rowItems += `<td>${newArr[j][i]}</td>`;
}

So in the first inner loop, we should see something like this;

newArr[0][0] (which would be 1)
newArr[0][1] (which would be 2)
newArr[0][2] (which would be 3)
newArr[0][3] (which would be 4)

and to give an example of the second, our second array was reversed. We should see something like this.

newArr[1][0] (which would be 8)
newArr[1][1] (which would be 7)
newArr[1][2] (which would be 6)
newArr[1][3] (which would be 5)

Finally, we can put the <td> items within a <tr> and then append this row to the newRow variable.

const theRow = `<tr>${rowItems}</tr>`;
newRow += theRow;

Once this is all done, we need to add the markup and content within the table div that has been created and added to the DOM

const theTable = document.getElementById("table");
theTable.innerHTML = newRow;

This is the logic of the nested for-loop and adding it to the table.

let newRow = "";

for (let i = 0; i < rows; i++) {
let rowItems = "";
for (let j = 0; j < columns; j++) {
rowItems += `<td>${newArr[j][i]}</td>`;
}
const theRow = `<tr>${rowItems}</tr>`;
newRow += theRow;
}
const theTable = document.getElementById("table");
theTable.innerHTML = newRow;

Of course, we will need to create an event listener that wait’s for the button to be pressed to run our function.

form.addEventListener("submit", () => {
createTable();
});

Here is the entire JS code:

const form = document.querySelector("form");function createTable() {
const rows = document.querySelector("#rows").value;
const columns = document.querySelector("#columns").value;
const body = document.body;
const maxNumbers = rows * columns;//creating an array of the max numbers of items we can have starting from 1;
const arr = [...Array(maxNumbers + 1).keys()].splice(1);
let newArr = [];
// given the number of columns, we will split the array into new arrays.
for (i = 1; i <= columns; i++) {
newArr.push(arr.splice(0, rows));
}
//we want to reverse the order of all the even columns. Arrays are 0 indexed as we know
//so we are reversing the odd indexes.
const fixedArr = newArr.map((col, i) => {
if (i % 2 !== 0) {
return col.reverse();
}
return col;
});
// create a table and append it to the dom.
const table = document.createElement("table");
table.setAttribute("id", "table");
body.appendChild(table);
let newRow = "";
//given the number of rows, we will generate a row at a time;
for (let i = 0; i < rows; i++) {
let rowItems = "";
// however we have our arrays as columns so we need to get the items from each column
// at the same index
for (let j = 0; j < columns; j++) {
rowItems += `<td>${newArr[j][i]}</td>`;
}
//we set each row's td's to be bound by actual table rows
const theRow = `<tr>${rowItems}</tr>`;
newRow += theRow;
}
//we need to find the table in the dom
const theTable = document.getElementById("table");
//and set the innerhtml to what we have generated
theTable.innerHTML = newRow;
}
//event listener for submit runs the function
form.addEventListener("submit", () => {
createTable();
});

--

--