Adjusting intensity on an image - java

I am trying to increase the intensity of a grayscale image while maintaining the outline of the image.The algorithm I'm creating only looks at values in the left, right, upper and lower neighbors of each cell, effectively only processing the interior cells of the array. Obviously there are lines and lines of code but I am being thrown the ArrayOutOfBoundsException on this one block (I can provide it all if needed). Can someone tell me what my problem is or offer advice on what needs a second look?
public Image getEdgeImage(){
Image edge = new Image(this);
for(int row = 1; row < numRows; row++) {
for(int col = 1 ; col < numColumns; col++) {
double Lx = -.5 * edge.pixels[row -1][col].getRed() + (.5 * edge.pixels[row + 1][col].getRed()) ;
double Ly = -.5 * edge.pixels[row][col -1].getRed() + (.5 * edge.pixels[row][col + 1].getRed());
int L = (int) Math.sqrt((Lx * Lx) + (Ly * Ly));
edge.pixels[row][col] = new Color(L, L, L);
}
}
return edge;
}

If your getting ArrayOutOfBoundException, Please do watch on the area your accessing the Array element by +/- the index.
In your program the line No 5 & 6, your accusing the next elements with out checking the array length.
edge.pixels[row + 1]
edge.pixels[row][col + 1]
Array Index will start from 0 to length-1, Suppose your array has the length of 10, and on the 9th iteration your program will check for the index 10 in line 5&6 the code highlighted above.

Related

How can you find the max rectangular area in histogram recursively?

I need to come up with a recursive solution for the "Maximum rectangular area in a histogram" problem. For those not familiar with it, here´s an explanation:
A histogram is a display of statistical information that uses rectangles to show the frequency of data items. These rectangles are usually vertical.
In the histogram, all the bars are usually different sizes. In the problem, you have to find the maximum rectangular area in the histogram. For example, if the sizes are [4,1,4,5,6] the maximum area is 12 because we take the last 3 bars [4,5,6], take the shortest bar [4], and apply the rectangular area formula (4x3=12).
The only requirements are:
-It has to be done in java.
-Stacks can´t be used.
-It has to be recursive.
In case it helps, i have a non-recursive solution:
public static int MaxHistograma(int[] histograma) {
if (histograma.length == 1) {
return histograma[0];
}
int res = 0;
for (int i = 0; i < histograma.length - 1; i++) {
int min = histograma[i];
for (int j = i + 1; j < histograma.length; j++) {
min = Math.min(min, histograma[j]);
res = Math.max(histograma[j], Math.max(res, min * (j - i + 1)));
res = Math.max(res, histograma[i]);
}
}
return res;
}
If you start with the base case of a histogram with 1 column then the largest area is simply equal to height of the column.
When you add a include the 2nd column, the area may be either be
1) Equal to the max area from the previous histogram
2) Equal to the height of this 2nd column
3) Equal to the area of the new rectangle which has been formed horizontally
When you look at the third column, it's the same. It's either the max area from the previous histogram (2 cols), the height of the new column (red), or the area of the horizontal rectangle (purple).
Here is a code skeleton to achieve this
private int getLargestArea(int[] histogram)
{
if (histogram.length > 1)
{
int horizontalRectangleArea = 0; //TODO
int lastColumnHeight = 0; //TODO
return Math.max(
Math.max(horizontalRectangleArea, lastColumnHeight),
getLargestArea(Arrays.copyOf(histogram, histogram.length - 1)) //copy the array, subtracting 1 column
);
}
else
{
return histogram[0]; // height of single column
}
}

Single array re-indexing for table formatting

I am looking for a more elegant solution to the following scenario (language doesn't matter, Java is fine, but I am currently in C#). Suppose a linear array is coming in and being displayed as a table with X items per row (For instance, 9 items coming in at 3 items per row, so 3 rows of 3). If the array is being indexed 0 through 8, it is currently displayed as such:
6 7 8
3 4 5
0 1 2
So, the elements are displayed left to right, bottom to top. I would like to rearrange this to be displayed top to bottom, like this:
0 1 2
3 4 5
6 7 8
This requires reordering the array so that the new array's indexes are [6,7,8,3,4,5,0,1,2], with respect to the original's indexes. My current (untested) solution is the following: assume the array to be returned is 'array' and a temporary copy is 'temp', and the 'cols' variable is already the number of items per row.
int rows = (array.Length + cols - 1) / cols; //ceiling function to determine rows needed
int pos = array.Length - cols; //starting position in index transfer
int offset = 0; //needed when negative index reached
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (pos + j >= 0)
array[cols * i + j - offset] = temp[pos + j]; //assign values of temp to array
else
++offset; //takes care of negative indeces
}
pos -= cols;
}
return array;
The problem is this code is quite unreadable and possibly inefficient because of the double loop, though I don't expect many more than 9 items to come through. Is there a more elegant solution to this using slicing up the array, reversing, or anything that isn't so difficult to read? It's just a fun little problem I've been thinking about for an issue at work. Anybody's input is appreciated, thanks!
It is worth noting that potentially uneven tables can be created (For instance, 9 elements with 4 items per row creates 2 rows of 4, one row of 1. The 'offset' variable is used to protect negative array indexing if this is the case).
This is what I came up with: it doesn't sort your original array at all, but every inner loop starts at a computed starting-index based on the row you're printing. Let me know if you have any questions. This isn't specific to you, more specific to your situation, but the concept and functionality is there.
int[] array = new int[9] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
int rows = 3;
int cols = 3;
int count = 0;
for (int x = 1; x <= rows; x++)
{
int startingPos = array.Length - (x * rows);
for (int y = cols; y > 0; y--)
{
Console.Write(array[startingPos] +", ");
count++;
startingPos++;
}
Console.WriteLine();
}

Shifting a pixel image left and right

I have a set of arrays (which are "pixels" - RGB representation) for e.g.
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(1,1,1)(1,1,1)(1,1,1)(1,1,1)
(2,2,2)(2,2,2)(2,2,2)(2,2,2)
I want to shift left/right the columns and up/down the rows. for example:
ShiftCol + 2 will yield the output:
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(0,0,0)(0,0,0)(1,1,1)(1,1,1)
(0,0,0)(0,0,0)(2,2,2)(2,2,2)
ShiftRow - 1 will yield the output:(after ShiftCol +2)
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(0,0,0)(0,0,0)(1,1,1)(1,1,1)
(what happend in the above output is: First row move to second row, second row to third row, and first row became black (just zero's), the third row is just replaced with the second row.
ShiftCol- 1 will yield the output:
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(0,0,0)(0,0,0)(0,0,0)(0,0,0)
(0,0,0)(1,1,1)(1,1,1)(0,0,0)
I just need your help to show me how can I "move" every column to the right, that will be enough. What I managed to do is when ShiftCol +2 is called, the first column is moved 2 columns to the right (and is appeared on the third column) and the first two columns are turned to (0,0,0) which is black color. the problem is I don't know how to move EVERY column to the right according the the number it is called to move right, for example - if i call ShiftCol(2) and the pixel image array is 3x4 as you can see in the outputs what should happen is that: first column will be moved twice to the right - to the third column, and first column will become black (0,0,0), second column will be moved to twice to the right too and will become the fourth column. third and fourth columns will just be replaced by first and second columns.
It'll be enough if you just guide me somehow how to manage that, anyhow you can focus on the method "ShiftCol" only in RGBImage class and you'll see what I've accomplished so far within code. Thanks on advance!
*PLEASE, keep the answer simple with code. I learned just for loops, while loops, if statements, arrays.. I don't want to use in this project any other advanced material.
Here's my code:
RGBColor class:
public class RGBColor {
/**
* attributes: red, green and blue component of a color.
*/
private int _red,_green,_blue;
/**
* final variables.
*/
private final int MAX_VALUE = 255,MIN_VALUE = 0;
private final double THIRTY_PERCENT = 0.3,FIFTY_NINE_PERCENT = 0.59,ELEVEN_PERCENT = 0.11;
/**
* Consctructor which gets 3 colors (RGB), we check here if their range is valid (0 - 255), if not we assign black to it.
*
* #param red - The red color component value.
* #param green - The green color component value.
* #param blue - The blue color component value
*/
public RGBColor(int red, int green, int blue)
{
if(isValid(red,green,blue))
{
_red = red;
_green = green;
_blue = blue;
}
else
doBlack();
}
/**
* Construct a black RGBColor. i.e. red = green = blue = 0
*/
public RGBColor()
{
doBlack();
}
/**
* Here we check if the color number was entered correctly.
* It has to be an integer (whole number) between 0-255.
*
* #param nums - a component value, should be the number between 1-4
* #param return - return true if the number is between 1-4, false otherwise.
*/
private boolean isValid(int nums)
{
return ((nums >= MIN_VALUE) && (nums <= MAX_VALUE));
}
/**
* Here we check if the color number was entered correctly.
* It has to be an integer (whole number) between 0-255.
*
* #param red - the red component
* #param green - the green component
* #param blue - the red component
* #param return true if values are correct, false otherwise.
*/
private boolean isValid(int red, int green, int blue)
{
return ((red <= MAX_VALUE && red >= MIN_VALUE &&
green <= MAX_VALUE && green >= MIN_VALUE &&
blue <= MAX_VALUE && blue >= MIN_VALUE));
}
/**
* Returns RGB color string triplet with numbers between 0-255, i.e. (0,127,127)
*/
public String toString()
{
return ("(" + _red + "," + _green + "," + _blue + ")");
}
/**
* RGBColor will become the color Black. (0,0,0)
*/
private void doBlack()
{
_red = _green = _blue = 0;
}
}
RGBImage class:
public class RGBImage
{
private int _rows, _cols;
private RGBColor[][] _pixels;
private int _offset = 0;
public RGBImage(int rows, int cols)
{
_rows = rows;
_cols = cols;
_pixels = new RGBColor[_rows][_cols];
for(int i = 0; i < _rows; i++)
for(int j = 0; j < _cols; j++)
_pixels[i][j] = new RGBColor();
}
public RGBImage(RGBColor[][] pixels)
{
_rows = pixels.length;
_cols = pixels[0].length;
_pixels = new RGBColor[_rows][_cols];
for(int i = 0; i < _rows; i++)
for(int j = 0; j < _cols; j++)
_pixels[i][j] = new RGBColor(pixels[i][j]);
}
public void shiftCol (int offset)
{
if(_offset == 0)
_offset = offset;
else
_offset += offset;
int currentShift = 1;
if( (_offset == _cols) || (-_offset == _cols) ){
makeBlack(_rows,_cols); //make black
}
else if( (_offset < _cols) || (-_offset < _cols) )
{
if(_offset > 0){
for(int j = currentShift; j < _cols && j <= _offset; j++){
for(int i = 0; i < _rows; i++){
setPixel(i,j + 1,this._pixels[i][j]);
setPixel(i,j,this._pixels[i][j] = new RGBColor());
}
}
_offset++;
currentShift++;
}
else if(offset < 0){
offset = -offset;
for(int j = currentShift; j < _cols && j <= offset; j++){
for(int i = 0; i < _rows; i++){
setPixel(i,_cols - 1 - j,this._pixels[i][_cols - j]);
setPixel(i,_cols,this._pixels[i][_cols - j] = new RGBColor());
}
currentShift++;
}
}
}
}
public void setPixel(int row, int col, RGBColor pixel)
{
if ((pixel != null) && (row < _pixels.length) && (col < _pixels[0].length))
_pixels[row][col] = new RGBColor(pixel);
}
public String toString()
{
String pixelSet ="";
for (int i = 0; i < _rows; i++){
for(int j = 0; j < _cols; j++){
pixelSet += this._pixels[i][j].toString();
}
pixelSet += "\n";
}
//pixelSet += tester;
return pixelSet;
}
}
and my Output tester class:
StudentTester class:
public class StudentTester {
public static void main(String[] args) {
System.out.println("Black Image Constructor:");
RGBImage rgbImg0 = new RGBImage(3,4);
System.out.println(rgbImg0);
System.out.println("Constructor with RGBColor[][] Array Parameter:");
RGBColor[][] rgbArray1 = new RGBColor[5][4];
for (int i=0; i<rgbArray1.length;i++)
for (int j=0; j<rgbArray1[0].length;j++)
rgbArray1[i][j] = new RGBColor(i,i,i);
RGBImage rgbImg1 = new RGBImage(rgbArray1);
System.out.println(rgbImg1);
System.out.println("Copy Constructor:");
RGBImage rgbImg2 = new RGBImage(rgbImg1);
System.out.println(rgbImg2);
System.out.println("flipVertical:");
rgbImg1.flipVertical();
System.out.println(rgbImg1);
System.out.println("rotateClockwise:");
rgbImg1.rotateClockwise();
System.out.println(rgbImg1);
System.out.println("shiftCol 2:");
rgbImg1.shiftCol(3);
System.out.println(rgbImg1);
System.out.println("shiftCol 2:");
rgbImg1.shiftCol(-2);
System.out.println(rgbImg1);
System.out.println("shiftCol 2:");
rgbImg1.shiftCol(1);
System.out.println(rgbImg1);
}
}
First, you don't really need the _offset field. The only place you are using it is the shiftCol() method, and it is not really a part of the state of the image as an object. It should therefore be a local variable. But really, the parameter offset is doing the job quite well, you don't need an extra variable. Remember, parameters are passed by value, even if you change the value of offset, it's not going to change anything in the calling code.
Second, you really don't need the variable currentShift, either. You are adding one to it, but the first currentShift++ is not in a loop and there is no further use of it, and the second currentShift++ is in a loop, but it doesn't affect anything in the loop and is not used after it. So - get rid of it.
Now, to your real problem. Let's look at the positive offset first. What you do for each column is:
Put the value of the pixel in the pixel to its right
Change the current value of the pixel to black - twice (first by setting it directly in the _pixels[i][j] and then again by the call to setPixel()).
This has several problems. First, since you run with j from 0 to offset, what happens is this:
The pixel that was in column 0 is placed in column 1, and column 0 is blackened.
The pixel that is in column 1 (which we actually changed in the previous step) is placed in column 2, and column 1 is blackened.
Then the pixel is moved to column 3, and so on.
Why all these moves of one pixel? And the creation of a new pixel object each time you do it.
And you just moved a single column, destroying all the column values along the way. Doing so, you lost all the information in them that should have also been moved!
And then, of course, the double assignment of new objects, one of which goes straight to the garbage.
Now to untangle this knot.
As a rule, when you copy a portion of an array onto itself, it's always important to copy in the right order. Let's look at a simple array of characters:
0 1 2 3 4 5
┌─┬─┬─┬─┬─┬─┐
│A│B│C│D│E│F│
└─┴─┴─┴─┴─┴─┘
Suppose you want to move the "BCD" part two spaces to the right, so that the result would be "ABCBCD" (not caring about erasing the moved part at the moment). Naively, you think that moving:
arr[3] = arr[1];
arr[4] = arr[2];
arr[5] = arr[3];
is going to do the right thing. but in fact, what you get is:
0 1 2 3 4 5
┌─┬─┬─┬─┬─┬─┐
│A│B│C│B│C│B│
└─┴─┴─┴─┴─┴─┘
Why is there a "B" in position 5? Because we have already changed arr[3] in our first assignment. Doing that destroyed the D, so when we come to assign arr[3] to arr[5], it's already "B".
The correct way to copy to the right is therefore to start from the right:
arr[5] = arr[3];
arr[4] = arr[2];
arr[3] = arr[1];
But... if we wanted to shift left, doing it in the reverse order like that would not work. Start again from our original "ABCDEF". Suppose we want to shift the "CDE" 2 positions to the left to get "CDEDEF". If we do it in reverse:
arr[2] = arr[4];
arr[1] = arr[3];
arr[0] = arr[2];
Then again, we get:
0 1 2 3 4 5
┌─┬─┬─┬─┬─┬─┐
│E│D│E│D│E│F│
└─┴─┴─┴─┴─┴─┘
Because arr[2] was already changed when we got to it.
Conclusion:
To shift part of an array to the right, you have to start your loop from the high indexes and go down to the low indexes.
To shift part of an array to the left, you have to start your loop from the low indexes and go up to the high indexes.
Also note that there is no point in moving the block one place and then one more place etc. - it just wastes time (and memory if you create new objects). You should shift it directly to where it is supposed to be. If you are supposed to move it by 2, then its new index is j+2.
Now, let's suppose our array is like the rows in your problem. We want to shift all the contents, not just part, and fill in with blanks.
So if I want to shift this array 2 positions to the right:
0 1 2 3 4 5
┌─┬─┬─┬─┬─┬─┐
│A│B│C│D│E│F│
└─┴─┴─┴─┴─┴─┘
I expect to get:
0 1 2 3 4 5
┌─┬─┬─┬─┬─┬─┐
│ │ │A│B│C│D│
└─┴─┴─┴─┴─┴─┘
I now know I have to start on the right to do it correctly. What I do is look at each position from 5 down to 0, and think: what is the source for this position? It's supposed to be the cell such that I'm currently two positions to the right of. That is, the cell that's two position to my left. Is there such a cell? If so, put its value in the current index. If not (because the source position is negative), then I fill in with a blank:
for ( i = arr.length - 1; i >= 0; i-- ) {
if ( i - offset >= 0 ) {
arr[i] = arr[i-offset];
} else {
arr[i] = ' ';
}
}
If you got the idea, you'll now be able to apply what I did with the array of characters to your row of pixels.
Your next task should be applying the reverse logic to negative offsets (remember, left to right!)
One final note: don't use setPixel() for this copy operation. It creates new pixel objects, and that's really unnecessary (except for the black parts). I suppose setPixel() does that because it's a public method and gives a protective copy of the pixel so that if its contents are changed it won't affect our image. But for an internal operation, that's not necessary.
Try this method:
public void shiftCol (int offset)
{
if(offset > 0){
for(int j = _cols - 1; j >= 0; j--){
for(int i = 0; i < _rows; i++){
if (j - offset >= 0)
_pixels[i][j] = _pixels[i][j-offset];
else
_pixels[i][j] = new RGBColor();
}
}
} else {
for(int j = 0; j <=_cols - 1; j++){
for(int i = 0; i < _rows; i++){
if (j - offset < _cols)
_pixels[i][j] = _pixels[i][j-offset];
else
_pixels[i][j] = new RGBColor();
}
}
}
}

Trouble finding path in a grid

I am trying to find number of paths between top left and bottom right cells on a checker board. i can only move to the adjacent right and adjacent bottom cell. This way i can have a maximum of 2 non intersecting simple paths. I am using a recursive approach.
private void processMatrix()
{
if(matrix[0][0]!=1 || matrix[0][0]!=matrix[ROWS-1][COLUMNS-1])
System.out.println("No Path Exists between bottom right and top left cells");
int row=0;
int col=0;
traverse(row,col);
}
private boolean traverse(int row, int col)
{
path.add(new Point(row,col));
if(row+1<ROWS)
{
if(matrix[row+1][col]==0)
{
return false;
}
if(matrix[row+1][col]==1)
{
traverse(row+1,col);
}
}
if(col+1<COLUMNS)
{
if(matrix[row][col+1]==0)
{
return false;
}
if(matrix[row][col+1]==1)
{
traverse(row,col+1);
}
}
if(col==COLUMNS-1 && row==ROWS-1)
return true;
return false;
}
But with this code i am only able to traverse the lower triangular matrix. And when i reverse the order of if blocks in the traverse() function i am only able to traverse a path in the upper triangular matrix. Unable to figure out what is wrong. I also want to detect intersecting paths. Please help.
EDIT:
The matrix consists of 0s and 1s.
A path exists if it is connected by adjacent cells containing only 1s. In other words the path will be a chain of 1s.
You seem to be overcomplicating things with your code. If your matrix is 0s and 1s, use boolean instead of int. Non-intersecting paths seems a bit silly, since all paths are equally valid in taxicab geometry. Here's the simple solution for finding the number all paths, it will show you how it works with the block of system.out prints:
int rows = 9;
int columns = 8;
boolean[][] matrix = new boolean[rows][columns];
for (boolean[] arr : matrix) {/* Set values of matrix such that true = can pass thru that space, false = space blocked */
Arrays.fill(arr, true);
}
matrix[4][6] = false;
matrix[2][5] = false;
int[][] paths = new int[rows][columns];//number of paths reaching each space in i steps
paths[0][0] = 1; //Starting space
for (int i = 0; i < rows + columns - 2; i++) {//Taxicab distance is always x+y, i = distance travelled so far
int[][] newPaths = new int[rows][columns]; //number of paths reaching each space in i+1 steps
for (int x = i >= columns ? i - columns + 1 : 0; x <= i && x < rows;) { //x is traditionally columns but it doesn't matter
int y = i - x; //if statement is x declaration ensures that this is < columns
int newX = x + 1; //will be used repeatedly
int newY = y + 1; //will be used repeatedly
if (newX < rows && matrix[newX][y]) newPaths[newX][y] += paths[x][y];
if (newY < columns && matrix[x][newY]) newPaths[x][newY] += paths[x][y];
x = newX;
}
paths = newPaths;
for (int x = 0; x < rows; x++) { //optional, show the algorithm at work
for (int y = 0; y < columns; y++) {
int r = paths[x][y];
System.out.print(r);
if (r < 100) System.out.print(" ");
if (r < 10) System.out.print(" ");
}
System.out.println();
}
System.out.println();
}
System.out.println(paths[rows - 1][columns - 1]); //result
If all you want to determine is whether a path exists, replace int[][] paths with boolean[][] paths and change the operations accordingly.
This is a fundamental dynamic programming problem.
Let dp[R][C] be the number of paths from the top-left cell to the cell on row R and column C (1-indexed).
Initial values (when R or C is 1):
dp[R][1] = 1 if matrix[i][1] has value 1 for i = 1..R, otherwise dp[R][1] = 0.
dp[1][C] = 1 if matrix[1][j] has value 1 for j = 1..C, otherwise dp[1][C] = 0.
Then dp[R][C] = dp[R-1][C] + dp[R][C-1] if matrix[R][C] = 1, otherwise dp[R][C] = 0 (for R, C >= 2)
And this is it. The intuition behind this idea is that if we know that we can get to cell on row R-1, column C by N different roads, then if we go down once, we will get N different roads to cell [R, C]. Analogically for going right from cell [R, C-1] to [R, C].
Finally, the answer is in dp[N][M], where N and M are the dimensions of the matrix.

how to traverse though a 2d char array searching for words in java?

I am having trouble with a school assignment and would really appreciate some insight. I am asked to create a wordsearch using a 25x25 2d char array and somehow go through that array by developing an algorithm that will search through it to find 21 pre-defined words.
So far I have been able to create a ragged array of the words that I need to find and the 2d array with the chars placed in each position.
in = new ASCIIDataFile("wordsearch.txt");
display = new ASCIIDisplayer();
int numberWords = in.readInt();
wordlist = new char[numberWords][];
for (int i =0; i<wordlist.length; i++){
wordlist[i] = in.readLine().toUpperCase().toCharArray();
}
for(int i = 0;i<wordlist.length; i++){
display.writeLine(" ");
for(int j = 0;j<wordlist[i].length; j++){
display.writeChar(wordlist[i][j]);
}
}
//done wordlists
int gridLength = in.readInt();
int gridHeight = in.readInt();
grid = new char[gridHeight][gridLength];
for(int i = 0;i<gridLength; i++){
grid[i] = in.readLine().toCharArray();
}
My problem in creating the algorithm to search though the 2d array and match it with a character in the wordlist.
I am supposed to make different methods, for searching forwards, backwards and diagonal.
I have been struggling for days just to do the forward search.
I really how no idea about how to go about this problem, so far all I have is
for(int k = 0; k<wordlist.length; k++){
int p = 0;
for(int row = 0;row<gridLength; row++){
for(int col = 0;col<gridHeight; col++){
while(p<wordlist[k].length){
if(grid[row][col] == wordlist[k][p]){
//do something
}
}
}
}
}
}
Any help or pointers would be greatly appreciated!
The trick is, you don't need to consider all 8 possible directions separately. You can represent each with a vector. E.g., 'forward' direction would be (0, 1) (first row number, then column) - a vector pointing to the right. Diagonal top-left direction would be (-1, -1). Well, you get the idea.
Then, just create a function
boolean findWord(int row, int col, int d_row, int d_col, char[] word);
It can take current matrix position ((row, col), where word is supposed to start), search direction ((d_row, d_col)) and a word to look for. It returns whether the given word is here.
Then you can invoke it for different directions, e.g.
findWord(row, col, -1, 0, word);
findWord(row, col, -1, 1, word);
findWord(row, col, 0, 1, word);
...
(I'm listing them in clock-wise order)
Implementing findWord is just incrementing current position by d_row and d_col, until we find mismatch in characters or word ends. The basic routine is like this
while (row < total_rows && row >= 0 && col < total_columns && col >= 0) {
// check character here
...
row += d_row;
col += d_col;
}
I bet you'll have all processing code (except input-reading) in 40 lines.
You first need to understand how to search a short string inside a bigger string. There are couple of options here: from the simplest algorithm up to more complex (like Knuth Morris Pratt and the family). You can get a list of their descriptions here: http://en.wikipedia.org/wiki/String_searching_algorithm. I strongly recommend you try the naive search first.
Once you can search a string inside another string you will need to abstract the way you access the bigger string and adapt the matrix data to it.
Basically assuming this matrix:
1 2 3 4
-------
1| a b c d
2| b c d a
3| c d a b
4| d a b c
and this string abc
you will first make some code to be able to find abc inside abcd or bcda or cdab etc.
Once you can do that you should build the intermediate step of extracting (for each possible lookup type: horizontal, vertical, diagonal, reverse diagonal) series of chars and apply the previous algorithm on them.
For example if we want to search diagonally we would generate 7 strings from the matrix:
a
bb
ccc
dddd
aaa
bb
c
if you want to search horizontally you would generate those strings:
abcd
bcda
cdab
dabc
and seach inside each string.
Once this is working you should combine the searching with reading the proper chars from the matrix. Hopefully if you follow this path you will be able to figure it out :).
Good luck.
To travel diagonally in any 2D matrix of arbitrary dimensions, hope the below function helps.
public static void prinDiagonalsInGrid(char[][] grid, int rows, int cols)
{
String result = "";
int min = Math.min(rows, cols);
int max = Math.max(rows, cols);
int sameLengthDiagonals = max - min + 1;
int totalDiagonals = (rows + cols) - 1;
for (int p = 0; p < totalDiagonals; p++)
{
int xIndex;
int maxCnt;
if (p < (min - 1)) // First diagonals
{
maxCnt = xIndex = p;
}
// diagonals of equal length in the middle
else if (sameLengthDiagonals != 0 &&
p >= (min - 1) && p < (sameLengthDiagonals + min - 1))
{
if (rows < cols)
xIndex = rows - 1;
else
xIndex = p;
maxCnt = min - 1;
}
else // Last diagonals
{
xIndex = rows - 1;
maxCnt = totalDiagonals - p - 1;
}
for (int cnt = 0; cnt <= maxCnt; cnt++)
{
result += grid[xIndex][p - xIndex] + " ";
--xIndex;
}
result += "\n";
}
System.out.println(result);
}

Categories