After learning about the requirements for the Sudoku App, model the Sudoku table.
- [Instructor] After the introduction of LoDash in the preview section, we will now write an application, beyond demonstrating the usage of the LoDash library. We will put the principles of mostly functional programming into practice. We will now develop a fully client-side web application. Therefore, expect no API communication, and expect no server-side code. LoDash can equally be used on client-side, and on server-side though, so for this reason, there's not much difference between client-side, and full-stack development using LoDash.
The application we will write is a Sudoku App. As you can see on screen, as Sudoku table is nine times nine table where in each cell the value of a cell can either be empty, or a number between one, and nine. Every row, every column, and the two diagonals have to contain each digit once. Further more, the nine areas bounded by the thick borders also have to contain the nine distinct digits once.
In this application, the user should be able to select a cell, and change its value. Whenever the value is invalid, the Sudoku table should be marked as invalid. The value of a cell can be changed to become one to nine, or the value can also be cleared. At the bottom of the screen, you can see a timer starting from zero seconds, measuring how much time it takes us to solve the Sudoku puzzle. We will write the application in five steps.
In the first video, we will model the Sudoku table followed by the modeling of the field constraints that will check whether the Sudoku table is valid, or invalid. In the third video, we will render the Sudoku table. Then comes event handling, making sure that the user can select cells, and change their values by using the keyboard. In the fifth, and final video we will validate the table, and test our application. So let's start with the modeling of the Sudoku table.
Let's review the requirements for the application once more. We have to implement the nine times nine Sudoku grid with validation. Whenever the table is invalid, the Sudoku table has to be rendered as red with the red background. We should be able to change the value of each and every cell from one to nine, and we should also provide the ability to clear the value of a field by pressing space. In addition we have to implement a timer.
We will now use Bottom-Up design for modeling the table. We will just start with playing around with some functions, and the developer tools of the browser. So let's start writing some code. First of all, we should be able to create rows, and tables. The createRow function is rather very simple. We will use the _.times function so it creates an area with a constant null nine times. The _.times can either repeat at constant, or a function.
So let's use _.times once more in the createTable where we will repeat the application of the createRow function nine times as well. In this way, we create a matrix of nine null arrays. If the console.table the result, you can see the nine times nine null matrix created. So so far we can create an empty table quite easily. Let's create our test table, and let's also add some test data, so we can render some values.
If the console.table the new (t) constant you can see that the corresponding values are entered on the top left of the Sudoku table. Now this is not going to be easy for testing, and for this purpose, I will provide you with a second way of creating a row, and creating a table. In the createRow, we will use the _.map function which is very similar to the regular map function by the way, except that _.map accepts the array that the map as the first argument, and the second argument is a function that transforms each value inside the array to a new value.
We could've just used the regular map function as well. It is not mandatory to use Underscore's map function anymore, but now that we are using LoDash, we're going to put the LoDash map function into practice. _.range( 9 ) creates an array with nine values, ranging from zero to eight, with an increment of one. Let's stop for a moment with this _.range( 9 ), you can see that with the map, and the range, we just create an alternative for a 4loop basically.
So even though we are not doing looping in LoDash, with the _.range, we can easily create a loop-like structure, which looks somewhat functional as well. Oh, and by the way, in the previous description I used Underscore, and I will use Underscore often times in the LoDash, but the principles apply for both libraries. We're exploring LoDash now, LoDash has more functions than Underscore in general, but I will use the Underscore name as synonym sometimes, because I am use to naming the LoDash symbol as Underscore.
So let's test the creatRow2( 4 ), we can see that the array of strings is created with the values 4-0 to 4-8. This will make it very easy to test our application, because we will exactly know which cells are placed in our results. Let's continue with a createTable2 function which is going to use the createRow2 function as well. The createTable2 function has no arguments, and it maps a range of nine, which is basically executing a loop once more to the createRow2 function.
This similar to the first createTable function we we're just executing a different function. You can see that the corresponding pairs are printed out in a matrix. The second value in the pair is always the column. The first value is always the row. Let's create our test table t2, we will use it in the future. So once more, t2 is printed on screen with a column row of pairs. Now let's move on, and let's write a function to select a row from the table.
It accept two arguments, a table, and a row. And it returns just a table, row. This is straightforward, this is just syntactic sugars so that we think in higher abstraction levels, not just array selections. getRow( t2, 4 ) for instance creates a vector with values for the first value in the pairs is always four. The second value corresponds with the row number. Now let's write a getColumn function as well with a table, columnIndex input values. We have to map the table using a function which selects the corresponding element, denoted by columnIndex from each row.
We can put getColumn into action as well, and you can see that the corresponding vectors are created. Now that we know how to retrieve rows, and columns, it is important to know that we also have to retrieve areas. Now we can see that there are nine areas in the Sudoku table. Let's denote them by X, and Y coordinates ranging from zero to two each. You can the mapping on screen. We will retrieve a function where the input arguments are going to be the table reference, and the corresponding X, and Y values.
And we are looking for the retrieval of the nine values inside an area in a simple one-dimensional array. So for instance you can see that x = 2, y = 1 equals one area on screen. The columns are denoted by 3x, 3x+1, and 3x+2, and the rows are denoted by 3y, 3y+1, 3y+2. This is what we're going to retrieve by using LoDash. Let's console.table our test table.
You can see it on screen. Now let's create a x = 2; y = 1; variable pair, and let's describe the selectedRows in an array of arrays. You can see that the selectedRows contain the area that we are looking for. Starting with the element 3-6 on the top left, and 5-8 on the bottom right. So let's print the selected area once more, and our task is going to be to find the proper elements. We're gonna use the map function to map each row to its corresponding slice from 3*x to 3*x + 2.
We got an array of arrays. Now if you console.table the array of arrays, you can see that we just got the right elements. The elements that we're interested in from 3-6 to 5-8. But the problem is this is an array of arrays, and we are looking for a simple one dimensional array. But no problem, we learned about the flatMap function in the section of functors, and monads. We learned there that flatMap flattens the result of the mapping, and just returns the one-dimensional array.
So by applying flat map, we've got the corresponding elements in a simple one-dimensional array. Let's continue by writing a generic getArea function. As discussed before the input arguments are table X, and Y. We will get the rows in the same way as before by retrieving the rows 3y, 3y + 1, and 3y + 2. We will then return a flatMap of these rows transformed by the function row, row, row.slice.
3*x to 3*x + 3. The first value 3*x is the first value that we are interested in. And the second value 3*x + 3 is the first value we are not interested in from the row. Let's exercise the getArea function, you can see that the corresponding elements are retrieved. We will also test the 1-0, and 0-1 pair, and these values are also working perfectly. Now we have retrieved rows, columns, and areas, we just have to solve the retrieval of diagonals.
We have two diagonals, the mainDiagonal, and the backwardDiagonal. The retrieval of the mainDiagonal is a simple mapping where we just retrieve the nth-element from the nth-row. That's straightforward. Retrieval of the backDiagonal is almost the same as the retrieval of the mainDiagonal, the only exception is that the return value of the map transformer function is not row idex, but row[ 8 - Index ]. Let's test this too, functions, the mainDiagonal, you can see that the row, and column number is the same, and the backDiagonal, it starts from 0-8 to 8-0.
So as a summary, you can see all the functions that we created in this video. First we figured out how to create rows, and tables. Then we wrote a getRow, and a getColumn function. getRow was super easy because we just returned the row element of the table, and getColumn was simple mapping. We have to perform some exercises to compute the getArea of the function first. And we put the flatMap function of LoDash into practice. We learned that flatMap flattens an array of arrays into a one-dimensional array.
We concluded this video with the retrieval of the mainDiagonal, and the backwardsDiagonal. In the next video, we will put all these functions into practice, and we will assemble an array of constraint arrays, and we will also implement the validation of the Sudoku table.
- Bridging functional programming theory and practice
- Working with Underscore.js, Lazy.js, Ramda.js, and Immutable.js
- Creating a web application with Lodash
- Foundations of reactive programming
- Writing a simple application in RxJS