Saturday, October 2, 2010

List of Combinations in C#

In Mathematics, Combination is the number of different ways of selecting 'r' elements from a set of 'n' elements where r <= n. The mathematical notation for combination is "nCr". As far as I have searched, I couldn't find such a functionality in .net framework. Therefore, I decided to create my own program that will generate the different combinations given the values of n and r. Calculating the number of combinations is straightforward. You need to calculate the factorials of n,n-r and r. This can be done by calling the factorial method thrice and then using the formula n!/((n-r)!r!) to compute the number of different combinations.

The real challenge was to be able to generate all possible combinations. First of all, I tried using 'while' loop, breaking out of the loop once all the combinations are listed. But it was missing out some of the combinations. Then, I decided to solve the problem using recursion.

I had used the exhaustive approach to ensure that every combination is traversed. The methodology is that you create a tree by selecting one of the numbers of an array as a root and add the remaining numbers of an array as its child. For each child, the index values that have not occurred when traversing the path from the root to that child are added as its children. This process is repeated for every child until the depth of this tree is equal to r-1. Each array value gets selected as a root, so there will be n trees with depths r-1.

For example, if there is an array of 4 indices with values 1,2,3 and 4, and you want to find out combinations of 3 in it, then, you will get the following trees:









If we keep track of all paths traversed from root to leaf for each of the trees obtained, then we will get all the permutations in which order is important. But, the task is to have list of combinations. Hence, we would check each path elements and compare it with the elements of the paths already traversed. This path is stored only if its elements do not exactly match with the elements of the previous paths. Thus, we will get list of combinations in which order does not matter.

In my implementation, there is a loop that goes through a single iteration of an integer array. In each iteration, I consider the index value to be a root element and then build a tree with the remaining index values. This is done by calling the method "GetCombinations()" that does the main job. This method is recursively called to build a tree.

After building a tree, all the paths from root to leaf are traversed and stored in the global list object "Combinations" only if they are unique,i.e., their elements do not match with a path already in the list. This process of building a tree and traversing and storage of paths is repeated for each iteration. At first, I created a method which manually checks the elements of each of the paths of "Combinations" list, but the execution became tremendously slow even for small numbers as this method was called very often. Therefore, I used hashtable to store the paths along with "Combinations" so that checking could be done faster.

The method guarantees retrieval of all possible combinations. However, it became notably slower as 'n' is increased (typically above 100). Here is the code for combinations:

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace CombinationGenerator
{
class Program
{
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; //predefined numbers. n=20 in this case
int UsingNum;
int r = 2;
List values; // holds the values of 'arr' array
List dummy; // temporary storage of values
List combinations = new List(); //contains the combinations
Hashtable ht = new Hashtable();


public void Combinations()
{
values = new List();


for (int i = 0; i < arr.Length; i++)
{
values.Add(arr[i]);
}


dummy = new List(values);


for (int index = 0; index < values.Count; index++)
{
UsingNum = dummy[0]; // it contains the index value that is the root in particular iteration
dummy.RemoveAt(0);
GetCombinations(new List(), new List(dummy), r - 1);
}


for (int i = 0; i < combinations.Count; i++)
{
int[] p = combinations[i];
foreach (int a in p)
Console.Write(a.ToString() + " ");
Console.Write("\n");
}

Console.WriteLine("No. of combinations =" + combinations.Count);
}



public void GetCombinations(List hold, List temp, int diff) //Method for building trees and generating combinations
{
string str = "";
for (int i = 0; i < temp.Count; i++)
{
if (diff > 1) // Checking the depth of tree which has to be equal to 'r-1'
{
int num = temp[i];
List a = new List(hold);
a.Add(num);
List b = new List(temp);
b.RemoveAt(i);
GetCombinations(a, b, r - (a.Count + 1));
}

else if (diff == 1)
{
str = "";
if (hold.Count == 0)
{
int[] comb = { UsingNum, temp[i] };
Array.Sort(comb);

for (int j = 0; j < comb.Length; j++)
{
str = str + comb[j] + ",";
}

str.Remove(str.Length - 1);
if (!ExistInCombinationSet(str))
{
combinations.Add((int[])comb.Clone());
ht.Add(str, (int[])comb.Clone());
}

}

else
{

int[] comb = new int[hold.Count + 2];
comb[0] = UsingNum;


for (int j = 0; j < hold.Count; j++)
{
comb[j + 1] = hold[j];
}

comb[hold.Count + 1] = temp[i];
Array.Sort(comb);

for (int j = 0; j < comb.Length; j++)
{
str = str + comb[j] + ",";
}

str.Remove(str.Length - 1);

if (!ExistInCombinationSet(str))
{
combinations.Add((int[])comb.Clone());
ht.Add(str, (int[])comb.Clone());
str = "";
}


}
}
}
}


public bool ExistInCombinationSet(string str) // Method to check whether the traversed path is unique
{

if (ht.ContainsKey(str))
return true;
else
return false;

}

static void Main(string[] args)
{
Program prg = new Program();
prg.Combinations();
Console.ReadLine();
}
}
}

Suggestions for improving the code are most welcome. The code can be downloaded from here.

Saturday, June 19, 2010

5 and 3 gallon water containers riddle

It is a problem that is often asked by interviewers to examine the analytical skills of the interviewee. So the problem is that you are provided with 2 water containers with capacity of 5 and 3 gallons. You are asked to come up with 4 gallons of water using only these 2 containers. Nothing else is provided except water which is assumed to be present in large quantity.

When I was asked this question by the interviewer, I quickly thought about dividing both the quantities by 2 and adding them up. Half of 3 is equal to 1.5 and half of 5 is equal to 2.5. Adding these 2 integers gives 4. BINGO!! I was so excited that I figured out the solution in less than 30 seconds. I told the interviewer that you fill both the containers to their maximum capacity and then empty them by half the size of the corresponding containers. Pour the remaining half of water left in 3 gallons containers into the other one and you will have the 4 gallons of water. On that the interviewer replied, "I'm not asking about the approximation, I want exactly 4 gallons of water using the 2 containers". I thought about it for a while and then was finally able to solve the riddle with a small hint from interviewer in the middle.

Here are the steps of solving this riddle:

1)Fill the 5 gallon container completely with water.
2)Pour the water from 5 gallon container into 3 gallon container until it is completely filled. Hence, you are left with 2 gallons in the former container.
3)Empty the 3 gallon water container.
4)Pour the 2 gallon water from 5 gallon container into this one.
5)Again fill the 5 gallon container with water completely.
6)Pour the water into 3 gallon water container until its filled completely.

Since, the 3 gallon container already had 2 gallons of water before, so only 1 gallon of water is being added into it. This means 5 gallon container lost 1 gallon of water. Hence, we are left with 4 gallons of water in the 5 gallon container.

Saturday, January 30, 2010

Semantic Analyzer

This post is continuation of my previous blog post regarding Compiler construction in which I had discussed "Lexical" and "Syntax" analyzer. In this post, I will discuss the Semantic Analyzer which gave me a really hard time during the semester. It was tougher than the previous 2 phases. For this phase, we were alloted one month (The whole of March).

The job of the Semantic Analyzer is to ensure that the code is semantically correct. In this phase, the compiler associates semantic information to the parse tree built during the Syntax Analysis phase and constructs Symbol Table. A Symbol Table holds information about identifiers in the source code regarding their declaration and location in the code. At this point, the code is syntactically correct and being checked for semantic errors such as type checking, object binding, assignment of local variables before use, etc.

Click here to download Semantic Analyser.zip file. Run JFlex tool over Scanner.txt file to generate a lexer file. Use 'byaccj' tool over CS-540Assignment_3.txt file to generate a parser file. Byaccj is a YACC-compatible parser generator tool that takes an input source file and produces one or more Java files. For detailed information about byaccj and its use, click here. The zip file also contains a README.txt file that contains step-by-step instructions for the user. You will need to download and install "byaccj1.15_win32" before proceeding with the third instruction. The test.txt file is a test file for testing the functionality of the Semantic Analyzer.

Saturday, January 16, 2010

Compiler in Java

In my second semester at George Mason University, I took a course "CS-540 Language Processors". In this course, we had to do 4 projects. Guess what were these 4 projects? They were the 4 phases of compiler construction:
1) Lexical Analyzer
2) Syntax Analyzer
3) Semantic Analyzer
4) Code Generator

The compiler was developed for the subset of Tiger language. Tiger language is a small, imperative language with integer and string variables, arrays, records, and nested functions. Its syntax resembles some functional languages.

In this post, I'm going to discuss about the Lexical and Syntax Analyzer. Both of these phases were part of the second project. They were developed using JFlex tool. JFlex is a lexical analyzer generator for Java that is designed to work together with the LALR parser generator CUP by Scott Hudson, and the Java modification of Berkeley Yacc known as BYacc/J by Bob Jamison. For detailed information about JFlex and its specification, click here.

The reason I'm not discussing the first project is that it was a small one whose aim was to facilitate students in getting familiar with JFlex. In order to work with JFlex, one has to provide lexical specification of the language in a format acceptable by JFlex. This specification, as mentioned in the link above, consists of three parts, divided by %%:
a) usercode
b) options and declarations
c) lexical rules.

From this specification JFlex generates a .java file with one class that contains code for the scanner. The class has a constructor that reads standard input and contains a function yylex() that runs the scanner and used by parser to get the next token from the input.

Click here to download my second project which is a text file. Download JFlex and run it over this text file which will generate a .java file. Create a new Java Application project and include the newly created file in it. This file reads input from a file. Therefore, you should provide full path of the test file along with filename as parameter when running this project.

Wednesday, January 6, 2010

Checkers code

Click here to download the source code for checkers game mentioned in my previous post. It was developed in Visual C#.NET 2005.

The heuristic function is used to get the best possible move for computer at each of its turns. It works as follows:
- For each of the computer's pieces, there are 2 diagonally forward moves available if its a non-king piece and 2 diagonally forward moves and 2 diagonally backward moves are available if its a king piece.
- For each of these available moves, the diagonal distance to the nearest human piece is calculated using the function "EvaluateMove()".
- The diagonal distance value and coordinates of the move with the greatest diagonal distance is stored for the piece which is currently its best move.
- The previous steps are repeated for each of the computer's pieces.
- Finally, the best move of all the pieces are compared and the move with the highest distance is chosen by computer.

Here is the code that carry out these tasks:

public PlayerMove GetBestMove (Player pl)
{
int distance = 0;
int x = pl.X_Coordinate;
int y = pl.Y_Coordinate;
int []x_pos = new int[4];
int []y_pos = new int[4];
bool CanJump, MoveAvailable, HasAtleastOneMove = false;
int DiagDist = 0,MinDist = -10;

PlayerMove move = new PlayerMove();
move.player = pl;

x_pos[0] = x + 1; y_pos[0] = y + 1;
MoveAvailable = CheckMoveAvailability(x_pos [0], y_pos[0]);
CanJump = IsJumpAvailable(x_pos[0], y_pos[0], x_pos[0] + 1, y_pos[0] + 1, pl);

if (MoveAvailable||CanJump)
{
HasAtleastOneMove = true;

if (CanJump)
{
move.player = pl;
move.New_X_Coordinate = x_pos [0] + 1;
move.New_Y_Coordinate = y_pos[0] + 1;
move.CapturedMove = true;
return move ;
}

DiagDist = EvaluateMove(x_pos[0],y_pos[0],x,y);
MinDist = DiagDist;
move.New_X_Coordinate = x_pos [0];
move.New_Y_Coordinate = y_pos[0];
move.Heuristic = MinDist;
move.CapturedMove = false;

}

x_pos[1] = x - 1; y_pos[1] = y + 1;
MoveAvailable = CheckMoveAvailability(x_pos[1], y_pos[1]);
CanJump = IsJumpAvailable(x_pos[1], y_pos[1], x_pos[1] - 1, y_pos[1] + 1, pl);
if (MoveAvailable||CanJump)
{
HasAtleastOneMove = true;

if (CanJump)
{
move.player = pl;
move.New_X_Coordinate = x_pos[1] - 1;
move.New_Y_Coordinate = y_pos[1] + 1;
move.CapturedMove = true;
return move;
}

DiagDist = EvaluateMove(x_pos[1],y_pos[1],x,y);

if (MinDist < DiagDist) // Use of Heuristics
{
MinDist = DiagDist;
move.New_X_Coordinate = x_pos[1];
move.Heuristic = MinDist;
move.New_Y_Coordinate = y_pos[1];
move.CapturedMove = false;
}

}

if (pl.IsKing)
{
x_pos[2] = x + 1; y_pos[2] = y - 1;
MoveAvailable = CheckMoveAvailability(x_pos[2], y_pos[2]);
CanJump = IsJumpAvailable(x_pos[2], y_pos[2], x_pos[2] + 1, y_pos[2] - 1, pl);
if (MoveAvailable||CanJump)
{
HasAtleastOneMove = true;

if (CanJump)
{
move.player = pl;
move.New_X_Coordinate = x_pos[2] + 1;
move.New_Y_Coordinate = y_pos[2] - 1;
move.CapturedMove = true;
return move;
}

DiagDist = EvaluateMove(x_pos[2], y_pos[2], x, y);

if (MinDist < DiagDist)
{
MinDist = DiagDist;
move.New_X_Coordinate = x_pos[2];
move.New_Y_Coordinate = y_pos[2];
move.Heuristic = MinDist;
move.CapturedMove = false;
}

}

x_pos[3] = x - 1; y_pos[3] = y - 1;
MoveAvailable = CheckMoveAvailability(x_pos[3], y_pos[3]);
CanJump = IsJumpAvailable(x_pos[3], y_pos[3], x_pos[3] - 1, y_pos[3] - 1, pl);

if (MoveAvailable||CanJump)
{
HasAtleastOneMove = true;

if (CanJump)
{
move.player = pl;
move.New_X_Coordinate = x_pos[3] - 1;
move.New_Y_Coordinate = y_pos[3] - 1;
move.CapturedMove = true;
return move;
}

DiagDist = EvaluateMove(x_pos[3], y_pos[3], x, y);

if (MinDist < DiagDist)
{
MinDist = DiagDist;
move.New_X_Coordinate = x_pos[3];
move.Heuristic = MinDist;
move.New_Y_Coordinate = y_pos[3];
move.CapturedMove = false;
}

}
}
if (HasAtleastOneMove)
return move;
else
return null;

}


private int EvaluateMove(int x, int y, int Current_X, int Current_Y)
{
int MinDistToOpponent = 0, temp = 0, distance = 0,temp_x, temp_y;
temp_x = x;
temp_y = y;

while (true)
{
if (temp_x + 1 == Current_X && temp_y + 1 == Current_Y)
{
temp = -1;
break;
}

if ((temp_x > 8) || (temp_y > 8))
{
distance = 100;
break;
}

else if (IsCellOccupiedByOpponent(temp_x, temp_y))
{
distance = temp;
break;
}

else
{
temp = temp + 1;
temp_x = temp_x + 1;
temp_y = temp_y + 1;
}
}

temp = 0;
temp_x = x;
temp_y = y;

while (true)
{
if (temp_x - 1 == Current_X && temp_y + 1 == Current_Y)
{
temp = -1;
break;
}


if ((temp_x < 1) || (temp_y > 8)) // No opponents in this path
{
temp = 100;
break;
}

else if (IsCellOccupiedByOpponent(temp_x, temp_y))
{
break;
}

else
{
temp = temp + 1;
temp_x = temp_x - 1;
temp_y = temp_y + 1;
}
}

if (distance > temp && temp != -1)
distance = temp;

temp = 0;
temp_x = x;
temp_y = y;

while (true)
{
if (temp_x + 1 == Current_X && temp_y - 1 == Current_Y)
{
temp = -1;
break;
}

if ((temp_x > 8 ) || (temp_y < 1)) // No opponents in this path
{
temp = 100;
break;
}

else if (IsCellOccupiedByOpponent(temp_x, temp_y))
{
break;
}

else
{
temp = temp + 1;
temp_x = temp_x + 1;
temp_y = temp_y - 1;
}
}

if (distance > temp && temp != -1)
distance = temp;

temp = 0;
temp_x = x;
temp_y = y;

while (true)
{
if (temp_x - 1 == Current_X && temp_y - 1 == Current_Y)
{
temp = -1;
break;
}

if ((temp_x < 1) || (temp_y < 1)) // No opponents in this path
{
temp = 100;
break;
}

else if (IsCellOccupiedByOpponent(temp_x, temp_y))
{
break;
}

else
{
temp = temp + 1;
temp_x = temp_x - 1;
temp_y = temp_y - 1;
}
}

if (distance > temp && temp != -1)
distance = temp;

return distance;
}

Monday, December 28, 2009

Game of Checkers

It was my second semester at George Mason University and I took "Artificial Intelligence" course. As usual, the tedious part of any course is deciding the project. Finally, I decided to make "Checkers" game. I gathered complete information about the game and its rules. Thinking about the interface, designing game strategy, implementation (using C#) and testing was all done in 1.5 weeks.

Given the time limitation, I had to come up with a sufficiently intelligent game. Therefore, I decided to use defensive strategy.

Heuristic
The heuristic function is the diagonal distance from the square, onto which a computer can move its piece in its turn, to the nearest human piece. Hence, this distance is calculated for each of the possible moves available for computer. The move with the highest distance is chosen. If there is a jump move available, it is given the priority over all other possible moves regardless of the heuristic function.

The Game
Click here to download and play Checkers.

How to Play
At first, it is human's turn. The player should select his piece by clicking on it once. Then the player should select an empty square onto which he desires to move the selected piece. If the player makes an illegal move, he will be prompted with a message and will be required to make a legal move in order to proceed with the game. When the player has made a legal move, the computer will make its move and in this way both players would alternate among their turns. This will go on until one of the players is wiped off the board.

Any suggestions for refinement, especially the intelligence part, are most welcome.