I need to create a random maze of 1s and 0s, and it does not have to be possible to solve. The program I am writing needs to be able to search through this maze and tell me whether not it is possible to get from the beginning to end. 0s are fine to go through, but 1s are like walls. Currently I am just trying to create the random array, and what I have so far compiles, but it returns this: [[I#4ea20232. So far I have this:
import java.util.Random;
public class SearchMaze{
public static void main(String [] args){
int n = 8;
int m = 7;
int[][] maze = new int[n][m];
Random rand = new Random();
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
maze[i][j] = rand.nextInt(2);
System.out.println(maze);
}
}
I am trying to get something like this:
1000000
1111100
0000001
1110111
1010101
1010101
0000110
1110000
I can't seem to find why something like this wouldn't work.
The problem is that the toString of an array returns useless information. Using a list will not help much because it will print everything on one line with commas. Try to use nested loops to output the data.
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
System.out.print(maze[i][j]);
}
System.out.print('\n');
}
When you print an object like System.out.println(a);, you're really calling the toString() method of that object. Thus you're really calling System.out.println(a.toString());.
The toString() method of Arrays isn't particularly useful, so by doing System.out.println(maze) you're not going to see anything informative.
Fortunately, the Arrays class has helper methods that can reduce your problem to a single line. Try using:
System.out.println(Arrays.deepToString(maze));
Given that your maze is 2d, you can use some replaceAll calls to format it like your post:
System.out.println(Arrays.deepToString(maze)
.replaceAll("],\\s\\[", "\n")
.replaceAll(",\\s|]|\\[", "")
);
Instead filling the maze with random values, you need to start will all 1s and fill it with random paths e.g. going north or east for a given length.
Just like the loops you have you need to print them this way too.
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
System.out.print(maze[i][j]);
}
System.out.println();
}
Not the answer to your problem, as it has already been answered, but how do you know where to begin and where to end?
Anyway, I came here to steer you towards the A* algorithm - it's a path finding algorithm that would be great for this type of application.
I think a better solution would be to create an object for the maze:
public class Maze {
public Maze(final int[][] maze) {
this.maze = maze;
}
#Override
public String toString() {
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < maze.length; i++) {
for (int j = 0; j < maze[i].length; j++) {
builder.append(maze[i][j]);
}
builder.append("\r\n");
}
return builder.toString();
}
private final int[][] maze;
}
Related
I need to have the columns organized in increasing order. Right now I have the following done but, it is sorting the rows and not columns.Any help would be nice, ive been working on this all day. Thanks.
public static double[][] sortColumns(double[][] m) {
double[][] sortedArray = new double[m.length][m.length];
for (int i = 0; i < m.length; i++) {
double[] temp = new double[m.length];
for (int j = 0; j < m.length; j++) {
temp[j] = m[j][i];
}
Arrays.sort(temp);
for (int j = 0; j < temp.length; j++) {
sortedArray[j][i] = temp[j];
}
}
return sortedArray;
}
If you change
temp[j] = m[j][i];
to
temp[j] = m[i][j];
and
sortedArray[j][i] = temp[j];
to
sortedArray[i][j] = temp[j];
then your existing algorithm will work fine. It just means you'll be copying columns to your "temporary sorting area" instead of rows.
In your current solution, you are just mistaking on indexes, just like David Wallace tells you in his answer. I propose you a different answer, enumerating the possible solutions of this problem.
You have at least 4 solutions :
instead of storing your data like you are currently doing it, use the transponate of your matrix
implement yourself an efficient sorting algorithm that takes a bi-dimensional array and the index of a column in argument
at each turn of you loop, fill an array with the current column, sort it, and copy it back (if you don't care about using some additional memory, do it). That is what you are currently trying to do
transponate your matrix, sort its lines, transponate it back (if you don't want to use too much memory, use this)
I prefer the last solution, which code is :
public static double[][] sortColumns(double[][] m) {
double[][] sortedArray = new double[m.length][m.length];
// compute the transponate of m
for (int i=0 ; i<m.length ; i++)
for (int j=0 ; j<m[i].length ; j++)
sortedArray[j][i] = m[i][j];
// sort the lines of the transponate
for (int i=0; i<sortedArray.length; i++)
Arrays.sort(sortedArray[i]);
// transponate back the result of the sorting
for (int i=0 ; i<sortedArray.length ; i++)
for (int j=i+1 ; j<sortedArray[i].length ; j++) {
double tmp = sortedArray[i][j];
sortedArray[i][j] = sortedArray[j][i];
sortedArray[j][i] = tmp;
}
return sortedArray;
}
When I look at your code I see the following line:
double[][] sortedArray = new double[m.length][m.length];
it doesn't look right to me.
you need to find length and breath of the array so i would do something like this:
length = m.length;
breath = m[0].length;
if i m not sure of all rows have same no of elements i may do that check by a for loop and initialize with the max.. wud lead to memory wastage but thats another demon to tame :)
next when we write m[x][y] x represents the rows and y represents the columns so when ur doing :
for (int j = 0; j < m.length; j++) {
temp[j] = m[j][i];
}
Arrays.sort(temp);
you are fetching all the values from a column i, assigning it to temp array and sorting the column.
hope that helps
public static void main{
String [][] book = new String[100][6];
for(int i = 0; i < 1; i++) {
for(int j = 0; j < 5; j++) {
book[i][j] = i;
}
}
arrayMethod(book);
}
public static void arrayMethod(String[][] array){
System.out.println(Arrays.asList(array));
}
arrayMethod method output is [[Ljava.lang.String;#639facbc, [Ljava.lang.String;#8059dbd, [Ljava.lang.String;#28b6e768, [Ljava.lang.String;#1271ba, ....
Problem is that in arrayMethod I can't acces 2 dimension array data, where can be problem?
It's doing exactly what you want: you're pretending the (first-level) array is a List (of Array) and then printing the toString() of those, which looks something like [Ljava.lang.String#pointer. You probably want this instead:
System.out.println(Arrays.deepToString(array));
as Alya'a Gamal said, if you want to put an int inside an array of String you need to parse it : book[i][j] = Integer.toString(i);.
Then if you want to display your array, you need to run thought it, like this for example :
public static void arrayMethod(String[][] array){
for(int i = 0; i < array.length;i++) {
for(int j = 0; j < array[i].length;j++)
System.out.println(array[i][j]); // a stringBuilder would be better than to print inside the loop
}
}
You can use Arrays.toString to print 1-D string array, but you CANNOT use Arrays.toString to print the 2-D array directly.
There are 2 ways for you to print the 2D string array in console.
Way#1 ==>
System.out.println(Arrays.deepToString(array));
Way#2 ==>
for(String[] arr: array)
{
System.out.println(Arrays.toString(arr));
}
I see three issues here :
(1). The signature of the main method looks odd. It would raise a compile issue.
public static void main(String args[])
{
// Your code here
}
(2). In the following code :
for(int i = 0; i < 1; i++) {
for(int j = 0; j < 5; j++) {
book[i][j] = i;
}
}
book[i][j] =i; // Here you are trying to insert an int in place where a String is required.
This will again lead to a compile time issue.
You can correct it as follows:
book[i][j] = Integer.toString(i);
(3).
Use the following static method in the Arrays class to print the elements of 2D array on the console.
System.out.println(Arrays.deepToString(array));
Hope this helps.
+1 for isolating the problem.
I'm trying to create a 2D array of lists for a Sudoku. Essentially 81 lists each containing possible solutions to that box in the Sudoku grid. I've tried multiple declarations so far, but whenever I try to add values to a list it returns a null pointer exception. Here is an example, simply populating each of the lists with the numbers 1-9.
List<Integer>[][] sudoku = (List<Integer>[][]) new List[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
for (int k = 1; k < 10; ) {
sudoku[i][j].add(k);
}
}
}
I'm not even positive a 2D array of lists is the optimal way to go about this, but I've done everything from scratch (with a relatively low knowledge of java) so far so I'd like to follow through with this method. The original code looked as follows:
List[][] sudoku = new List[9][9];
Research quickly revealed that this wouldn't cut it.
Thank you in advanced for any help!
Try this one. The general idea, create a master list and while you loop through it, create one inner list.
/* Declare your intended size. */
int mainGridSize = 81;
int innerGridSize = 9;
/* Your master grid. */
List<List<Integer>> mainList = new ArrayList<List<Integer>>(mainGridSize);
/* Your inner grid */
List<Integer> innerList = null;
/* Loop around the mastergrid */
for (int i=0; i<mainGridSize; i++) {
/* create one inner grid for each iteration of the main grid */
innerList = new ArrayList<Integer>(innerGridSize);
/* populate your inner grid */
for (int j=0; j<innerGridSize; j++)
innerList.add(j);
/* add it to your main list */
mainList.add(innerList);
}
Illustrated:
If you need to vary your grid, just change the values of the gridSize.
You cannot create array of generic lists.
You can create List of Lists:
List<List<List<Integer>>> soduko = new ArrayList<>();
And then populate it as you wish.
or use casting:
List[][] soduko = (List<IntegerNode>[][]) new LinkedList[9][9];
You have create the array of Lists but you did not initialize it. Insert this in the second line an the problem should be solved.
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++){
sudoku[i][j]=new ArrayList<Integer>();
}
}
Or to do it all in one go do it like this:
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
sudoku[i][j]= new ArrayList<Integer>();
for (int k = 1; k < 10; ) {
sudoku[i][j].add(k);
}
}
}
If you know that you need exactly 81 2D arrays, you can create 3D array:
int[][][] sudoku = new int[81][9][9];
The way you did it now would produce compilation error.
I was looking through some old contest questions, and I found this one, it looked fun, http://dwite.ca/old/Problem5Jan2006.pdf , I tried using the floyd warshall algorithm to get the shortest path from any node to any other node, can you guys see what I did wrong? it does not give the desired output set out on the contest question page
import java.io.*;
import java.util.*;
public class DistanceBetween {
public static void main(String[] args) throws FileNotFoundException {
Scanner s = new Scanner(new File("DATA5.txt"));
int n = Integer.parseInt(s.nextLine());
int[][] dist = new int[60][60];
for(int y=0;y<60;++y)for(int x=0;x<60;++x)dist[y][x]=10000000;
Map<Character, Integer> map = new TreeMap<Character, Integer>();
for (int i = 0; i < n; ++i) {
String text[] = s.nextLine().split(" ");
int c = 0;
if (!map.containsKey(text[0].charAt(0))) {
map.put(text[0].charAt(0), c);
c++;
}
if (!map.containsKey(text[0].charAt(1))) {
map.put(text[0].charAt(1), c);
c++;
}
dist[map.get(text[0].charAt(0))][map.get(text[0].charAt(1))] = Integer.parseInt(text[1]);
}
for (int k = 0; k < map.size(); ++k) {
for (int i = 0; i < map.size(); ++i) {
for (int j = 0; j < map.size(); ++j) {
dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}
for (int i = 0; i < 5; ++i) {
String text = s.nextLine();
System.out.println(dist[map.get(text.charAt(0))][map.get(text.charAt(1))]);
}
}}
There are several problems in your code:
Overwritten mapping
Your int c is local variable of the for cycle which means the highest used mapping index doesn't survive to the next iteration, so the reading in next iteration overrides the previous one. So the distance matrix is not properly filled after data loading.
Solution: move the int c = 0; outside from the for loop.
Unidirectional roads
The roads are bidirectional in the instructions, but you register them only as unidirectional. As the consequence of that are higher on non-existent connections between towns.
Solution: add dist[map.get(text[0].charAt(1))][map.get(text[0].charAt(0))] = Integer.parseInt(text[1]); right after the similar one.
Besides these hard issues I have also couple hints for you. You do not have follow them but as if you want to improve your programming skills then you should think about them.
Messy code
Your code is hard to read, there are multiple restated information such as indicies, the solving process is in the single method etc. Such code is not only hard to read but also extremely hard to debug and fix. For your own good I recommend you to write it cleaner.
Algorithm efficiency
Floyd-Warshall's algorithm has a O(n^3) complexity. The size of problem (amount of towns) is A-M = 13. In this complexity it makes 13^3 = 2197 iterations. I know, it might not seem to be a lot, but consider the amount of tasks to solve in a given time limit.
I would recommend you to use Dijkstra's algorithm which has complexity O(|E| + |V|log|V|). In this task the worst case with some simplification is |E| = (|V|^2)/2, |V|=13. It means, that the final number of iterations is 5 (|V|^2 / 2 + |V|log|V|) = 5 (13^2 / 2 + 13 * log13) ~ 5 * 132 = 660. If I am not wrong and made any mistake, this is significantly less, especially when we consider the total amount of tasks.
Input reading
I might be wrong but I attended multiple programming contests and competitions and it never forced attendees to work with files. An input was always redirected from files to a standard input. I guess, that the main reason for this is a security, but the simplification is probably also highly beneficial.
Well that question I got, I am starting to do SPOJ now, and I gotta admit it is pretty difficult later on, but I came across the same kind of question http://www.spoj.com/problems/SHPATH/ , I also used Floyd Warshall
import java.util.*;
public class Floydwarshall {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String q = s.nextLine();
for(int t=0;t<Integer.parseInt(q);++t){
int n = Integer.parseInt(s.nextLine());
int[][] cost = new int[n][n];
for (int y = 0; y < n; ++y) {
for (int x = 0; x < n; ++x) {
cost[x][y] = 10000;
}
}
Map<String, Integer> map = new TreeMap<String, Integer>();
int c = 0;
for (int i = 0; i < n; ++i) {
String a = s.nextLine();
if (!map.containsKey(a)) {
map.put(a, c);
c++;
}
int f = Integer.parseInt(s.nextLine());
for (int j = 0; j < f; ++j) {
String text[] = s.nextLine().split(" ");
cost[map.get(a)][Integer.parseInt(text[0]) - 1] =
cost[Integer.parseInt(text[0]) - 1][map.get(a)] = Integer.parseInt(text[1]);
}
}
for (int k = 0; k < map.size(); ++k) {
for (int i = 0; i < map.size(); ++i) {
for (int j = 0; j < map.size(); ++j) {
cost[i][j] = Math.min(cost[i][j], cost[i][k] + cost[k][j]);
}
}
}
int num = Integer.parseInt(s.nextLine());
for (int i = 0; i < num; ++i) {
String text[] = s.nextLine().split(" ");
System.out.println(cost[map.get(text[0])][map.get(text[1])]);
}
}
}}
now it runs alright for the sample input, but when I hand it in, it gives me this
NZEC (non-zero exit code) - this message means that the program exited returning a value different from 0 to the shell. For languages such as C, this probably means you forgot to add "return 0" at the end of the program. For interpreted languages (including JAVA) NZEC will usually mean that your program either crashed or raised an uncaught exception.
Problem is I cannot kind where it crashes or raises an uncaught exception since it
works with the sample input
Here's the code:
public class Deck {
private Card[] cards;
public Deck() {
cards = new Card[52];
String[] ranks = {"ace","two","three","four","five","six","seven","eight","nine","ten","jack","queen","king"};
String[] suits = {"hearts","diamonds","clubs","spades"};
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++) {
cards[cards.length] = new Card(ranks[i],suits[n]);
}
}
}
}
As you can see, this loops though the two given arrays and generates a card for every combination. There are 13 ranks x 4 suits = 52 cards. I expected that on the 52nd iteration, cards.length would be 51, but the compiler says
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 52
at com.cards.Deck.<init>(Deck.java:14)
Why is that?
The issue is that cards.length is not the total number of elements used in the array; it's the total number of elements in the array, regardless of what you've stored in the array so far. Consequently, as soon as you execute the inner loop, this will try accessing the 52nd element of the array, causing the exception you've seen.
To fix this, consider instead storing a counter that will keep track of the next free index, or use some simple math to derive the position that the card should go in from its suit and value. For example, since on each iteration of the outer loop you will write ranks.length elements to the array, on iteration (i, n) you will write to array index i * ranks.length + n. Using this, you could rewrite the inner loop as
// Careful... still buggy!
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++) {
cards[i * ranks.length + n] = new Card(ranks[i],suits[n]);
}
}
Additionally, note that your access into the arrays is wrong. Right now, you're writing
new Card(ranks[i],suits[n]);
However, i ranges over suits, not values. The proper code would be
new Card(ranks[n],suits[i]);
Which gives this final implementation:
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++) {
cards[i * ranks.length + n] = new Card(ranks[n],suits[i]);
}
}
More generally, though, don't use the .length field of an array to track how many used elements there are. You'll need to store that separately. Alternatively, consider using an ArrayList, which wraps an array and tracks this for you.
Hope this helps!
cards[cards.length]
Because you're trying to use an index that doesn't exist. cards.length is 52, your array is 0 - 51.
I suspect you're trying to insert each card into that array, which means you need another counter ;)
int cardIndex = 0;
for(int i = 0; i < suits.length; i++) {
for(int n = 0; n < ranks.length; n++, cardIndex++) {
cards[cardIndex] = new Card(ranks[n],suits[i]);
}
}
EDIT: What I didn't catch is what others have mentioned - you also have the counters for ranks/suits switched in the Card constructor - fixed that too.
The index variables for ranks ranks and suits are exchanged.
(Don't damage your head with your palm.)
Consider it with renamed variables:
for(int SUIT = 0; SUIT < suits.length; SUIT++) {
for(int RANK = 0; RANK < ranks.length; RANK++) {
cards[cards.length] = new Card(ranks[SUIT],suits[RANK]);
}
}
It isn't always best to use i and n. (I would have used s and r.)
Also, consider:
Card[] cards = new Card[X];
cards[X] // will never be "in bounds", indices from [0, X-1]
Happy coding.