Related
This question already has an answer here:
Java - Two-Dimensional Arrays - Plotting Points
(1 answer)
Closed 6 years ago.
I have an assignment for a JAVA class I am taking. We are discussing two-dimensional arrays, however on this particular assignment, I can not figure out how to return back specific points and set those points with a specific value. Here is the assignment:
Write a method called create2DArray that will fill, create, and return a 10 x 10 2d array with random numbers in the range of 1 to 100. Write a method called print2DArray that will print a 10 x 10 2D array in row column fashion. Write a method called createCoords that will search the 2D array looking for any value that is evenly divisible by 3. Once you have found a number you should log the row, column location. This means when your method finishes it should produce a list of coordinates that I can use to plot my graph. This method must also return the number of coordinates that are divisible by 3 so that I know how many points there are to plot. I am not particular as to how the coordinates are returned back as long as I get a list of the row, column locations. So, I will leave it to you to work out a mechanism for returning the values. To test that you have logged the coordinates create another function called fillLocations that will fill the locations in the array you have logged with -1. So, your program should flow in this order 1.create2DArray 2.print2DArray 3.createCoords 4.fillLocations 5.print2DArray
I understand and have completed create2DArray and print2DArray, but I can not figure out createCoords and fillLocations. Here is what I have so far, but it does not work and there are errors present:
public int createCoords(int row1, int col1){
int[][] coords = new int[row1][col1];
int[][] count = new int[0][0];
int co = 0;
for(int row = 0; row < 10; row++)
{
for(int col = 0; col < 10; col++)
{
if(coords[row][col] % 3 == 0)
co++;
return count[row][col];
}
}
return co;}
public int fillLocations(int[][] count){
int x = 0;
int y = 0;
for(int row = 0; row < 10; row++)
{
for(int col = 0; col < 10; col++)
{
if(count[row][col] % 3 == 0)
x = row;
y = col;
break;
}
}
return (x, y);}
I'm not going to write the code, but pretty much how I would go about doing this is:
I would have a separate 2d boolean array the same size as the 2d int array, auto filled with false. This would go in createCoords.
use nested for loop to cycle through all addresses of the 2d int array, and when i find a number that's divisible by three, i mark the corresponding point on the boolean array as 'true'. This would also go in createCoords.
after the for loops finish, I then look at the original 2d int array and boolean array. i would use the nested for loops again, and when i find a true value on the boolean array, i would mark the corresponding location on the int array as -1. This would go in fillLocations. You should also pass the 2d boolean array to fillLocation along with the 2d int array.
Good luck!
EDIT: this is assuming that the FillLocation function REPLACES values in the 10x10 int array with -1. That's what I interpreted your question to be. Please correct me if i'm wrong. I also added a short description at the end of each paragraph where each segment of code would go.
There are couple of problems with your code. Firstly, for the fillLocations method, you are expected to return the NUMBER of cells ([row][column]) where the value is divisible by 3. This means that for each value that passes the test:
if(coords[row][col] %3 === 0)
Then you should increment the counter by 1.
So for this part, your code would look like:
int [][] your2DArray = new int[10][10];
...
private int getNumberOfValuesDivisibleByThree(){
int numberOfValuesDivisibleByThree = 0;
for (int row=0; row < your2DArray.length; row++){
for(int col = 0; col < your2DArray[0].length; col++){
if(your2DArray[row][col] % 3 === 0){
//value at this coordinate or in this cell is divisible by 3
//here you can 'log' the coordinates as required -
System.out.println(row+","+col);
//increment the count
numberOfValuesDivisibleByThree +=1;
}
}
}
//return the final count
return numberOfValuesDivisibleByThree;
}
Please see how to create and manipulate a 2D array in Java. Syntax for creating a two-dimensional array
To this question:
The superqueen is a chess piece that can move like a queen, but also like a knight. What is the maximal number of superqueens on an 8X8 chessboard such that no one can capture an other?
I want to write a brute force algorithm to find the maximum. Here's what I wrote:
public class Main {
public static boolean chess[][];
public static void main(String[] args) throws java.lang.Exception {
chess = new boolean[8][8];
chess[0][0] = true;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
/*Loop to check various possibilities*/
if (!checkrow(i) && !checkcolumn(j) && !checkdiagonals(i, j) && !checkknight(i, j)) {
if (i != 0 || j != 0) {
chess[i][j] = true;
}
}
}
}/*printing the array*/
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
System.out.print(((chess[i][j]) ? "T" : "x") + "|");
}
System.out.println();
}
}
/*All working fine here*/
public static boolean checkrow(int a) {
for (int i = 0; i < 8; i++) {
if (chess[a][i]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkcolumn(int a) {
for (int i = 0; i < 8; i++) {
if (chess[i][a]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkdiagonals(int pi, int pj) {
int i = pi - Math.min(pi, pj);
int j = pj - Math.min(pi, pj);
for (int k = i, l = j; k < 8 && l < 8; k++, l++) {
if (chess[k][l]) {
return true;
}
}
int i_2 = pi - Math.min(pi, pj);
int j_2 = pj + Math.min(pi, pj);
for (int k = i_2, l = j_2; k < 8 && l > 1; k++, l--) {
if (chess[k][l]) {
return true;
}
}
return false;
}
/*Not All working fine here try commenting out this method above so that that it doesn't run during the check*/
public static boolean checkknight(int pi, int pj) {
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (0 <= pi + 2 * i && pi + 2 * i <= 8 && 0 <= pj + j && pj + j <= 8) {
if (chess[pi + 2 * i][pj + j]) {
return true;
}
}
if (0 <= pi + i && pi + i <= 8 && 0 <= pj + 2 * j && pj + 2 * j <= 8) {
if (chess[pi + i][pj + 2 * i]) {
return true;
}
}
}
}
return false;
}
}
I have two questions:
My algorithm for checkknight looks for all knight positions, is it wrong? or there is some coding error.Everything is working fine when I comment out it and I get a nice solution.
Secondly it'll result only in one solution.For other solutions I have to offset(or change position) of other pieces bit by bit after each mega-loop of this, I am confused about implementing it. My instincts guide me that I need to change whole of the code. Is there a modification or a way to do it?
Additional Thoughts: I think we would add to a counter each time we place a piece and add to a long array and output the maximum and array after storing the relevant data.
Code Location: You may view/edit/fork/download it at http://ideone.com/gChD8a
This a rough brute-force method starting from the opposite direction, i.e. from the solved eight-queens puzzle. This will allow us to find a bunch of viable solutions.
The brute-force technique for going from a single superqueen to potentially 8 seems to be especially complex due to the knight's traversal. Based on the runs, about 60% of the viable paths for normal queens are invalid with superqueens. So if we were to instead brute force normal queens, and then work backwards, that is potential time saved for finding a solution, and we can better determine the run-time. Because we know normal queens is easier.
We start off with the 12 fundamental solutions, we would then use these as inputs. Solving normal queens is outside this, but the wiki page has a fantastic article describing everything.
In my case, I stored them as Strings representing the coordinate of the queen (the rows are indices).
So: "17468253" = A1, B7, C4, D6, E8, F2, G5, H3
By brute-forcing the opposite direction from solved queens, we only have to test at most 12 x 8! possible solutions. Because order doesn't matter, additional optimization could occur by eliminating duplicate boards and solutions for processing.
First up, checkKnight, which appears to be your source of confusion. Using absolute values, you can reasonably determine whether or not a piece is within knight's range by checking whether the X offset is 2 and Y offset is 1, or vice versa. You've made a complex checkKnight function to check each individual location and whether or not a piece is on the border. Working the other way by hitscanning each queen to each other queen is logically simpler and less of a nightmare to debug.
Queen class
public class Queen {
int i, j;
public Queen(int i, int j) {
this.i = i;
this.j = j;
}
public boolean checkKnight(Queen queen) { // if any queen meets another
// queen at 2 and 1 offset, we
// eliminate it.
return (Math.abs(i - queen.i) == 2 && Math.abs(j - queen.j) == 1)
|| (Math.abs(i - queen.i) == 1 && Math.abs(j - queen.j) == 2);
}
}
This board has been modified since I originally posted. It takes a String input and converts it to a full chessboard. It has some minor work towards the potential any-size board, but right now it handles child board creation. When a child board is created, the queens are passed by reference rather than making a whole new set of queens. A total of 96 queens are stored in memory, 1 for each one on the original 12-board solution. Not perfectly optimized, but better than 96 -> 672 -> 4032 -> ...
Board class
public class Board {
static int boardSize = 8;
ArrayList<Queen> queens = new ArrayList<Queen>();
public Board(String s) {
for (int i = 0; i < s.length(); i++) {
queens.add(new Queen(i, s.charAt(i) - 49)); // you could implement
// base 16 here, for
// example, for a 15x15
// board
}
}
public Board(Board b) { // duplicates the board, but keeps references to
// queens to conserve memory, only 96 total queens
// in existence through search!
for (Queen q : b.queens) {
queens.add(q);
}
}
public boolean checkForImpact() {
for (int i = 0; i < queens.size(); i++) {
for (int j = i + 1; j < queens.size(); j++) {
if (queens.get(i).checkKnight(queens.get(j))) { // just check
// for any
// queens
// intersecting,
// one hit is
// enough
return true;
}
}
}
return false;
}
public ArrayList<Board> getChildBoards() { // create child boards with a
// single queen removed
ArrayList<Board> boards = new ArrayList<Board>();
for (int i = 0; i < queens.size(); i++) {
boards.add(new Board(this));
}
int i = 0;
for (Board b : boards) {
b.queens.remove(i);
i++;
}
return boards;
}
public String drawBoard() {
String s = "";
char[][] printableBoard = new char[boardSize][boardSize];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
printableBoard[i][j] = '_';
}
}
for (Queen q : queens) {
printableBoard[q.i][q.j] = 'Q';
}
s += " A B C D E F G H\n";
for (int i = 0; i < 8; i++) {
s += (8 - i) + "|";
for (int j = 0; j < boardSize; j++) {
s += printableBoard[i][j];
s += "|";
}
s += "\n";
}
return s;
}
}
Test class
import java.util.ArrayList;
public class Test {
static String[] boards = { "24683175", "17468253", "17582463", "41582736",
"51842736", "31758246", "51468273", "71386425", "51863724",
"57142863", "63184275", "53172864" }; // all 12 solutions for the 8
// queens problem
static ArrayList<Board> boardObjects = new ArrayList<Board>();
public static void main(String[] args) {
for (String queens : boards) { // create starter boards
boardObjects.add(new Board(queens));
}
int i;
ArrayList<Board> foundBoards = null;
for (i = 8; i > 0; i--) {
ArrayList<Board> newBoards = new ArrayList<Board>();
foundBoards = new ArrayList<Board>();
for (Board b : boardObjects) {
if (b.checkForImpact()) { // if any queen intercepts we get
// children
ArrayList<Board> boardsToBeAdded = b.getChildBoards(); // pass
// all
// permutations
// of
// queens
// once
// removed
for (Board bo : boardsToBeAdded) {
newBoards.add(bo); // add it in to the next list
}
} else {
foundBoards.add(b); // if we have no impact, we have a
// solution
}
}
if (!foundBoards.isEmpty())
break;
boardObjects.clear();
boardObjects = newBoards;
}
System.out.println("The maximum number of super-queens is: " + i);
ArrayList<String> winningCombinations = new ArrayList<String>();
for (Board board : foundBoards) {
String createdBoard = board.drawBoard();
boolean found = false;
for (String storedBoard : winningCombinations) {
if (storedBoard.equals(createdBoard))
found = true;
}
if (!found)
winningCombinations.add(createdBoard);
}
for (String board : winningCombinations) {
System.out.println(board);
}
}
}
The end output is:
The maximum number of super-queens is: 6
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|Q|_|
6|_|_|_|Q|_|_|_|_|
5|_|_|_|_|_|_|_|_|
4|_|_|_|_|_|_|_|Q|
3|_|Q|_|_|_|_|_|_|
2|_|_|_|_|Q|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|_|_|
6|_|_|_|_|Q|_|_|_|
5|_|_|_|_|_|_|_|Q|
4|_|Q|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|_|_|_|Q|_|_|
1|_|_|Q|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|Q|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|_|_|_|_|_|
4|_|_|Q|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|_|_|_|_|_|_|
1|_|_|_|Q|_|_|_|_|
I've removed the duplicates and made a nice board printing method. don't remember the exact math, but this highlights 40 possible locations. There are others, just by looking, but we've found a fair chunk of them already! From here, we can gently shift individual queens around. From a cursory look, each board has a single piece that can be moved to 3 additional spaces, so now we know there are probably about 160 solutions.
Conclusions
With this application, the run-time on my machine was less than a second, meaning that if we attached this to a standard queens application, the additional knight's brute-forcing would have no impact on that process and have almost the same run-time. In addition, because only 6-piece puzzles are possible, we know that your eventual application run will finish its finding at the 6th piece being placed, as no more solutions are possible, since there are no viable 7-piece and 8-piece solutions.
In other words, finding the maximum super-queen layout is likely actually shorter than the maximum queen layout due to the additional restrictions!
Trying to brute-force such a question is a good way to get a feel for it. So I won't suggest looking up pre-cooked solutions at first.
One little remark though: I don't see the reason for the condition if (i != 0 || j != 0) { that you have there. You are working on Java arrays. Instead of 1 through 8, they go 0 through 7, but the 0 is the first column, you should not eliminate it, otherwise it's only a 7x7 board.
First, let me address your technical question: how to calculate the knight positions.
Take a sheet of quad paper, put a queen somewhere not less than two squares away from the edge. Then mark the end positions of a knight-move from it.
You'll end up with just 8 squares that need to be considered. There is no point in doing a 3x3 loop to find them. A better idea would be to prepare a static array with the relative coordinates of the knight moves - an array of 8 pairs of numbers - and loop on that. So you have only an 8-step loop. In each step of the loop, check for bounds (0 ≤ X + Xoffset < 8, 0 ≤ Y + Yoffset < 8 ), and you have the knight coordinates.
Second, there is no point checking the part of the board that's ahead of you. Since you have not covered the next row and those below it, there is no point in looking for queens there. The implications of this:
You'll never put another queen in the same row where you have just marked a queen position (because you threaten it horizontally). This means that if you mark a queen, you should use continue to break out of the inner loop to the next row.
You don't need checkrow(). When you start a row, there is no queen ahead of you. And if you followed the above bullet point, there is no queen on your back, either.
When you use checkcolumn, you start at row 0, but you can finish at the row before the one you are on (i-1). There are still no queens in the rows below you! The same is true for the diagonal checks.
Earlier I said that you need to prepare and check 8 knight positions. But now you know there is no queen at the knight positions ahead of you. So you only need to prepare an array with four knight positions - the ones above your position.
But most importantly... once you have finished and you have your queens in positions and print the board: you have a single solved board. You have proved that this number of queens is possible. But is it the highest number possible? You have not checked what happens if you don't put a queen on the first square of the first row, but on the second. Perhaps this will allow you to put in an extra queen later. And what about the queen in the second row? Maybe if you moved that, you would be able to put a queen somewhere below where you couldn't before?
So, now you have to actually do the same thing over again, changing one decision every time and working from there. In effect, you have many potential boards. Why? Because there may be more than one valid position on each row where you put that row's queen. So you have decided to put it in the first valid position. But what if you decide to put it in the second valid position? Or leave that row empty? Each such decision is followed by another set of decisions on the next row.
The different boards created by different decisions form a decision tree. The problem for you to consider, therefore, is how to work such a tree out. How to write your decision trail and then backtrack, change, fill another board and count the queens at each level. People here suggested recursion, because it lends itself nicely to such problems. Or you can keep a stack of decisions if you want. You can eliminate some of the potential boards based on symmetries.
I suggest you first make sure you understand your single board well, and then consider how to represent your decision tree and how to traverse it.
There are several questions here.
The first is: how many knight-queens can be placed on an nxn chessboard? Since a k-piece solution can trivially be reduced to a k-1 piece solution, it makes sense to start from the upper bound. That is, look for an n-piece solution, if that fails look for an n-1 piece solution, and so forth.
The second question is: how should I look for a k-piece solution? There are two classic strategies: depth-first and breadth-first. In the former, you consider one vertex of the search tree at a time and use backtracking on failure. In the latter, you consider one complete level of the search tree at a time.
Something that can make a great deal of difference to your search is to account for symmetry (in this case, rotations and reflections).
The third (implicit) question is: what is a good representation here? If your chess-boards are less than 8x8 in size then a 64-bit bit-pattern will do very nicely!
In practical terms, try to separate the three levels of your problem as far as you can. If you don't, you'll find that a choice in one level will severely limit your options at another level.
This is a method for a Sudoku game.
Could someone explain their thought processes for this? :( I'm having a lot of difficulty figuring this out. I know for the first method, we're supposed to use a for loop or something.
I know my iteration for my method is wrong...Sorry :(
private int countOccurrencesInCol(int col, int d){
for (int i = 0; i < grid.length; i++;){
for(int j = col; j = col; j++;){
if (grid[i][j] == d){
count++;
}
}
}
return count;
}
This method returns the number of times a digit occurs in a given column in a 9 X 9 matrix.
private int countPossiblePlacementsInCol (int col, int d){
This method is supposed to determine the number of spots in a given column where a given digit can be placed, and returns the number of spots where a digit can be placed in a spot for a given column. If the digit already occurs, then the method returns 0.
Here is some code with explainations to help you understand the approach required:
private int countOccurrencesInCol(int col, int d) {
// counter variable to count the number of occurrences
int counter = 0;
// matrix is the 2D array, the first index is the row, second is the column
// loop through each index of the given column, checking for the digit, d
for(int row = 0; row < matrix.length; row++) {
// if a match is found...
if(matrix[row][col] == d) {
// increment the counter by one
counter++;
}
}
// return the final count
return counter;
}
The next method is a bit trickier, because I am not clear on what is required. Is this method supposed to just return the number of empty cells in the given column? Or should it take into account all the rules of sudoku and check if those empty cells are valid moves for that digit? If it is the former, then the solution is simple:
private int countPossiblePlacementsInCol(int col, int d) {
// I am assuming an empty cell is indicated by 0. In that case,
// we can reuse the previous method to find the number of occurrences of d,
// and the occurences of 0
// first, find out if the digit already occurs in the row, return 0
// if it does:
if(countOccurrencesInCol(col, d) > 0) {
return 0;
}
// next, return the number of times 0 occurs (the number of empty cells):
return countOccurrencesInCol(col, 0);
}
However, if you must count only VALID moves, this gets a lot trickier. The last line in the previous method would turn into something more like this:
private int countPossiblePlacementsInCol(int col, int d) {
//start the same as the previous method:
if(countOccurrencesInCol(col, d) > 0) {
return 0;
}
int counter = 0;
// this time, for each cell in the column, you must check that it is a valid move:
for(int row = 0; row < matrix.length; row++) {
if(countOccurrencesInRow(row, d) == 0 &&
countOccurencesInSquare(row, col, d) == 0) {
counter++
}
}
}
The two methods I used this time, countOccurrencesInRow and countOccurencesInSquare are going to do something similar to countOccurrencesInCol. The Row one is basically the same as the Col one, but it checks a row instead of a column. The Square one is a bit trickier. Assuming you know the rules of sudoku, you should know that a square is a 3x3 section of the 9x9 game board (in which there are 9 3x3 sections). The Square method will use the row and col to figure out which square the given cell is in, and then loop through the rows and columns of just that square, counting occurrences of the given digit. For this, you will need to use two for loops, one nested inside the other. If you have trouble understanding how to properly use for loops, and loop through arrays, then I suggest you talk to your teacher/professor for additional help on the topic.
I hope these explanations and examples help. Good luck.
You do not need a second for loop.
Count of occurrence of number in a column can be found by
private int countOccurrencesInCol(int col, int d){
for (int i = 0; i < grid.length; i++){
if (grid[i][col] == d){
count++;
}
}
return count;
}
Hope this helps!
Good luck!
I need to make a simple(standart) minesweeper for my project.
I want to check the surrounding elements of a random(or specific) element of a 2d array.
lets say I have an array like that
boolean board[5][5]
I want to check the surrounding elements of
board[0][0]
I wrote that:
public int numberChecker(int h, int w) {
int checker = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int he = h - 1 + i;
int wi = w - 1 + i; <---- this i should be j that was the issue
if (board.getHeight() > he && he >= 0
&& wi >= 0 && board.getWidth() > wi) {
if (boomChecker(he, wi)) {
if (w != (wi) && h != (he)) {
checker++;
}
}
}
}
}
return checker;
}
the problem is I think it only checks " \ " way (do not know how to put it in words)
ex:
(output # means uncovered numbers mean surrounding mines)
uncover 4-2
######
######
0#####
#0####
##0### <-- unlocking this one
###0##
or
uncover 0-0
0#####
#0####
##0###
###### <-- there is a mine at check spot
######
######
the code itself is not important (I know I made it a bit complicated to explain myself)
all I need is a working surrounding checking for loop (or anything)
thanks in advance
Problem solved
simple stupid mistake
int he = h - 1 + i;
int wi = w - 1 + i; <--- i should be j
thanks
I think your mistake is in this 2 lines:
int he = h - 1 + i;
int wi = w - 1 + i;
you add to the height AND to the width the value of i.
So you just check every of the 3 diagonal fields 3 times.
I think it should be
int he = h - 1 + i;
int wi = w - 1 + j;
so you really iterate through all 9 possible fields and not just through the diagonale.
Hope that helps!
I'm going to write my answer as though answering a homework question
now what you really ought to do is, for each cell in your array, there are 8 other cells to check. so something like:
count += board[i-1][j-1] ? 1 : 0;
count += board[i-1][j] ? 1 : 0;
count += board[i-1][j+1] ? 1 : 0;
count += board[i][j-1] ? 1 : 0;
etc.
be sure to include some mechanism to prevent you from accessing elements outside the bounds of the array.
also, if you were wondering what the ? and : mean, look up the Ternary Operator It's useful in all sorts of situations.
By the way, you might be better off explicitly checking each of the 8 possible surrounding cells. It's entirely possible that the JVM might automatically unroll your loop, but I don't see why you wouldn't just check them explicitly. It will be faster, and easier to understand.
boolean upleft = board[row-1][column-1];
boolean up = board[row-1][column];
boolean upright = board[row-1][column+1];
boolean left = board[row][column-1];
boolean right = board[row][column+1];
boolean downleft = board[row+1][column-1];
boolean dow = board[row+1][column];
boolean downright = board[row+1][column+1];
You'll of course have to do bounds checking if your on the edge of the board, but it makes more sense as to what is going on.
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);
}