Thursday 28 May 2015

Read files from the root directory of your web application ( webapp/*) - Java

Was thinking about a good way to load internationalized error properties file to the web application, a simple resource bundle.
After a bit of thought, decided to make it simply this way:

Place it in the webapp/*

But how the hell do we read it from the java application which runs from my src/main/java?
Copy that at webapp/WEB_INF/i18n/*.properties and try reading the file at  ../../webapp/WEB-INF/i18n/<locale_name>/*.properties ?

Good luck!
Try that and let me know.

Life it not fair my friend and so are java programs on web apps!

Try this instead:
this.getClass().getClassLoader().getResourceAsStream("../i18n/<locale_name>/*.properties")

The classloader identifies the path starting from webapps\


Thursday 9 April 2015

Carnatic cassandra

Let's talk a bit about NoSQL with carnatic music. ;)

What if one has to represent the melakarta chart as a data model using an expandable schema and improve it for other use-cases? Here we go...

Melakartas define fundamental scales that are used in carnatic music (a classical musical form from southern part of India).

I'll start from defining a schema like this (An image below for our reference)

My primary key is going to be a combination of name of the chakra (the segments of the circle - indu, netra, agni and all) and the melakarta_id.

create table melakarta(chakra text,melakarta_id int,melakarta_name text,notation list<text>,shudhamadhyama boolean,primary key (chakra,melakarta_id));





Get some records in place. 

As a lighter side note, if you observe the names of melakartas like one of my colleagues did, carnatic system gives a lot of prominence to women.

insert into melakarta (chakra,melakarta_id,melakarta_name,notation,shudhamadhyama) values ('veda',19,'Jhamkaradhwani',['S','R2','G2','M1','P','D1','N1','S'], true);
insert into melakarta (chakra,melakarta_id,melakarta_name,notation,shudhamadhyama) values ('veda',20,'Natabhairavi',['S','R2','G2','M1','P','D1','N2','S'], true);
insert into melakarta (chakra,melakarta_id,melakarta_name,notation,shudhamadhyama) values ('veda',21,'Keeravani',['S','R2','G2','M1','P','D1','N3','S'], true);
insert into melakarta (chakra,melakarta_id,melakarta_name,notation,shudhamadhyama) values ('veda',22,'Karaharapriya',['S','R2','G2','M1','P','D2','N2','S'], true);
insert into melakarta (chakra,melakarta_id,melakarta_name,notation,shudhamadhyama) values ('veda',23,'Gowrimanohari',['S','R2','G2','M1','P','D2','N3','S'], true);
insert into melakarta (chakra,melakarta_id,melakarta_name,notation,shudhamadhyama) values ('veda',24,'Varunapriya',['S','R2','G2','M1','P','D3','N3','S'], true);
In such a schema, each super row has 6 column families - as cassandra calls it - each with 6 melakartas.

How do we add ragas to this schema?

Multiple ragas can be derived from same melakarta. How can we store multiple ragas under each melakarta? 
Thanks to the collections (all your sets, lists and maps) in cassandra. We can always add another column in cassandra which has the set of ragas. I know you already noticed the list of notations. I'm just showing off!  

create table melakarta(chakra text,melakarta_id int,melakarta_name text,notation list<text>,shudhamadhyama boolean,ragas set<text>,
primary key (chakra,melakarta_id));

One thing to note about these column entries is that they insert keys in the sorted order automatically. Easy search, folks, easy!

If one were to design the same schema in an RDBMS world, it should probably look like this


create table melakarta(chakra text,melakarta_id int,melakarta_name text,notation list<text>,shudhamadhyama boolean,primary key (melakarta_id));

create table raga(raga_id int,raga_name text,melakarta_id int,primary key (raga_id));


If you were to pick which melakarta a raga belongs to, you would end up doing 2 lookups. Search table: raga and use the key melakarta_id to fetch the melakarta_name again. 

In a noSQL system, we highly encourage duplication.


create table raga(raga_id int,raga_name text,melakarta_name text,primary key (raga_id));
Make your queries less complex by bringing data to the same data model instead of incorporating FK's. This is a fundamental shift from the world of normalization. 

We thus knock some sense into the unstructured world with a little bit of compromise - duplication.

Sunday 15 March 2015

Sudoku Generator Initial thoughts (Incomplete)

Sudoku is a great distraction during a busy day. I somehow manage to stay away from this section at a cozy corner of the sports section on "the Hindu".

What if we were to design a sudoku generator which generates a fully formed sudoku template and simply plucks some numbers away depending on the difficulty level?

There are different ways in which we can generate a filled template. I'm thinking about one such (possibly) brute force way here. Comments are welcome!

1) Start from a random first line

4 7 5 | 3 2 8 | 6 9 1 ||


You can do this in 9! - 9 factorial - ways. (Sigh!)

2)

i)

Construct the next line in such a way that you pick the following 3 from the last 6 in the first row.

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | -  -  - | -  -  - ||  OR 2 6 3 | -  -  -  | - -  - ||

6P3 ways (6 permuted in 3 slots)

ii)
Repeat the same for the second and third slots

Note: When we are doing this, we have to look for repetitions and consistency.  

For example: 

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 5 1 | -  -  - || (This is wrong!)

Picked 4 5 1 from 4 7 5 and 6 9 1. This is clearly wrong.

It's also possible that we go about doing this over and over. While doing this we need to do some cool swaps while doing the validations in the same row.

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 5 9 | 7 2 6 ||  (This is wrong too!)

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||  (This is OK. Upphhh! Let's see...)


3) Pick the next 3 in third row in each 3 x 3 square is pretty much decided. It's only a matter of moving them around. We choose any order. 3 x 3!  

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 || 

With these 3 steps, we can generate the first 3 x 9 section. 

4) Try steps 1 - 3 vertically.

Pick the next 6 from 3 x 2 
7 5
8 1
6 9

Eg., 
4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 ||
5
7
9
1
8
6

5)  Pick the next 6 from 
4 5
3 1
2 9

now with validations, of course

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 ||
5 4
7 1
9 3
1 5
8 2
6 9

6)  We're not left with many choices for the next 6. The remaining 3 of each 3 x 2 square can be permuted. 

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 ||
5 4 2
7 1 8
9 3 6
1 5 4
8 2 7
6 9 3

7) It gets tricky from here on... 
In the second 3 x 3, vertically down, we need to pick 6 from
7 1 8
9 3 6

While placing the 6, we need to consider all the basic validations

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 ||
5 4 2 | 7 8 3 | 9 1 6 ||
7 1 8
9 3 6
1 5 4
8 2 7
6 9 3

8) 
While trying to arrange 
9 3 6 
1 5 4 

We run into this strange issue where we need to find a not-so-straight-forward swap for 6. 

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 ||
5 4 2 | 7 8 3 | 9 1 6 ||
7 1 8 | 5 9 4 | 2 3 6 ||  (This is wrong!)
9 3 6
1 5 4
8 2 7
6 9 3

6 cannot be in the 1 x 3 section  2 3 6 because in the section
9 1 6
2 3 6
We need to have 1 - 9 each only once!  
What do we swap 6 with? 4 in 5 9 4? 
Let's see...

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 ||
5 4 2 | 7 8 3 | 9 1 6 ||
7 1 8 | 5 9 6 | 2 3 4 ||  (This is wrong!)
9 3 6
1 5 4
8 2 7
6 9 3

Oops! How can 4 be there? The vertical
1
5
4
6
4
Has two 4's now. Strict no-no!

Swapping with 3, 

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 ||
5 4 2 | 7 8 3 | 9 1 6 ||
7 1 8 | 5 9 6 | 2 4 3 ||
9 3 6
1 5 4
8 2 7
6 9 3

Good here!

9) 
Fill the next 3 in the 2 sections
7 8 3
5 7 9 
and
9 1 6
2 4 3

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 ||
5 4 2 | 7 8 3 | 9 1 6 ||
7 1 8 | 5 9 6 | 2 4 3 ||
9 3 6 | 2 1 4 | 5 7 8 ||
1 5 4
8 2 7
6 9 3

10) 

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 ||
5 4 2 | 7 8 3 | 9 1 6 ||
7 1 8 | 5 9 6 | 2 4 3 ||
9 3 6 | 2 1 4 | 5 7 8 ||
1 5 4 | 8 3 2 | 7 ----|| (This is a blunder again. 7 can't be here. So swap with 2? )
8 2 7
6 9 3

4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 ||
5 4 2 | 7 8 3 | 9 1 6 ||
7 1 8 | 5 9 6 | 2 4 3 ||
9 3 6 | 2 1 4 | 5 7 8 ||
1 5 4 | 8 7 2 | 3-----|| (Swapped with 3. 3 also has the same problem. So do 6 9 3)
8 2 7
6 9 3


4 7 5 | 3 2 8 | 6 9 1 ||
3 8 1 | 4 6 9 | 7 2 5 ||
2 6 9 | 1 5 7 | 3 8 4 ||
5 4 2 | 7 8 3 | 9 1 6 ||
7 1 8 | 5 9 6 | 2 4 3 ||
9 3 6 | 2 1 4 | 5 7 8 ||
1 5 4 | 8 7 2 | 3-----||
8 2 7
6 9 3

This is where we will have to do more smart swaps. Check-mate!
Time up. 
Will continue a little later.