Monday 8 August 2016

Displaying Grids Without Using Inbuilt Layout Managers - Part 1

Using inbuilt layout managers to display information in a grid is quite simple. Consider the examples in the pictures below. Using Groovy language for demonstration, Figure 1 shows code to display buttons in a linear layout while Figure 2 shows how to display the same buttons in a grid by just adding one line of code - p.setLayout(new GridLayout(3, 4)).

Figure 1: Displaying buttons using the default Flow layout


Figure 2: Displaying buttons using the Grid layout


It can be that simple. But what if you are using a platform or language that does not come with inbuilt layout managers? Or perhaps you just want to output plain text to the console but it should be formatted in a grid. Or you just want to have more control on how your data is displayed?

Luckily, it is not too difficult but there are a few points to know that are handy. Consider the following grid with 3 rows and 4 columns:

1      2      3      4
5      6      7      8
9    10    11    12

The number of columns is the width of the grid, in this case 4. 

If we divide each number by the width we get the following, where r means remainder:





  0r1  0r2  0r3  1r0
  1r1  1r2  1r3  2r0
  2r1  2r2  2r3  3r0
  1. Each column shares the same remainder!
  2. The remainder in the last column is zero. 
  3. Except for the last value each number in the same row has the same integer value.


Now suppose we have a similar grid but whose numbering starts from 0


   0   1    2    3
   4   5    6    7
   8   9  10  11

If again we divide each number by the width we get the following, where r means remainder:



 0r0  0r1  0r2  0r3
 1r0  1r1  1r2  1r3
 2r0  2r1  2r2  2r3

Notice that:
  1. Each column shares the same remainder!
  2. The remainder in the last column is 3. 
  3. Each number in the same row has the same integer value.

In the first grid we started counting from 1 whereas in the second grid we started from 0. The difference between 1 and 0 is called the offset. Notice the effect in properties numbered 3 for each case.  With a little experimentation and more observation we can come up with the following method/function to print a grid


 def printGrid(List list, int width){   
   offset = list.first()    
   for(i in list){      
     if((i - offset) % width == 0 && i != start){  
       println ''  
     }  
     print "$i".padLeft(6) //padLeft is just for formatting so the output looks good  
   }  
 }  

Let us test the method, say 10 times:

 random = new Random()  
 10.times{  
   offset = random.nextInt(10)  
   width = random.nextInt(8) + 2  
   r = random.nextInt(5) + 2  
   length = width * r -1  
   list = (offset..length).toList()  
   println "\n" +"-" * 30  
   println "List is=$list, width=$width, r=$r"  
   printGrid(list, width)    
 }  

We get like the following (note that I have used _ for padding instead for space for better display in this html document)

 ----------------------------------------  
 List is = [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47],   
 width = 8, r = 6  
 _____4_____5_____6_____7_____8_____9____10____11  
 ____12____13____14____15____16____17____18____19  
 ____20____21____22____23____24____25____26____27  
 ____28____29____30____31____32____33____34____35  
 ____36____37____38____39____40____41____42____43  
 ____44____45____46____47  
 ----------------------------------------  
 List is = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],   
 width = 8, r = 3  
 _____3_____4_____5_____6_____7_____8_____9____10  
 ____11____12____13____14____15____16____17____18  
 ____19____20____21____22____23  
 ----------------------------------------  
 List is = [9, 10, 11, 12, 13, 14, 15], width = 8, r = 2  
 _____9____10____11____12____13____14____15  
 ----------------------------------------  
 List is = [5], width = 2, r = 3  
 _____5  
 ----------------------------------------  
 List is = [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],   
 width = 4, r = 5  
 _____4_____5_____6_____7  
 _____8_____9____10____11  
 ____12____13____14____15  
 ____16____17____18____19  
 ----------------------------------------  
 List is = [8, 9, 10, 11, 12, 13, 14, 15, 16, 17],   
 width = 9, r = 2  
 _____8_____9____10____11____12____13____14____15____16  
 ____17  
 ----------------------------------------  
 List is = [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34],   
 width = 7, r = 5  
 _____6_____7_____8_____9____10____11____12  
 ____13____14____15____16____17____18____19  
 ____20____21____22____23____24____25____26  
 ____27____28____29____30____31____32____33  
 ____34  
 ----------------------------------------  
 List is = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26],   
 width = 9, r = 3  
 _____2_____3_____4_____5_____6_____7_____8_____9____10  
 ____11____12____13____14____15____16____17____18____19  
 ____20____21____22____23____24____25____26  
 ----------------------------------------  
 List is = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],   
 width = 7, r = 3  
 _____0_____1_____2_____3_____4_____5_____6  
 _____7_____8_____9____10____11____12____13  
 ____14____15____16____17____18____19____20  
 ----------------------------------------  
 List is = [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39],   
 width = 8, r = 5  
 _____6_____7_____8_____9____10____11____12____13  
 ____14____15____16____17____18____19____20____21  
 ____22____23____24____25____26____27____28____29  
 ____30____31____32____33____34____35____36____37  
 ____38____39  

So it looks like our method works. Here is the modified version for our html friendly output above

 def printGrid(List list, int width){   
   offset = list.first()    
   for(i in list){      
     if((i - offset) % width == 0 && i != start){  
       println ''  
     }  
     print "$i".padLeft(6, '_')  
   }  
 }  

More to come in Part 2. Thank you.

Thursday 4 August 2016

Working with Grids - Introduction

Grids are often used to present various types of information. You can think of countless examples including tables, crosswords, soft keyboards, various puzzles and games, etc. Yet all grids possess these two basic properties - they have rows and columns.

Knowing how to represent grids internally (in code) and how to present the information to the user is very import for a programmer. Personally, I often find myself using grids when making Android apps in my 'free' time.


Figure 1: Examples of Grids depicting information

In the next series of posts I shall spend time explaining how to use grids starting from the basics and progressing to complex grids.


Figure 2: Example of Grid depicting a calendar


I hope this will be an exciting journey! Thank you.