Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Does anybody know how to move "on the ones" and change them to 2? I think we need recursion, but I'm not very good at it, so I'm asking you for help.
You can only move up, down, left or right.
Here is an example:
int[][] a = {{ 0, 0, 0},
{1, 1, 0},
{1, 1, 1},
{1, 0, 1} };
recursiveFunction(a, 1, 1); // (<array you're checking>, <x of the group>, <y of the group>
/* int a now contains:
* { 0, 0, 0,
* 2, 2, 0,
* 2, 2, 2,
* 2, 0, 2 } */
int[][] b = {{0, 0, 0, 0, 1},
{1, 1, 0, 0, 1},
{1, 1, 1, 0, 1},
{1, 0, 1, 0, 1} };
recursiveFunction(b, 0, 5);
/* int b now contains:
* { 0, 0, 0, 0, 2
* 1, 1, 0, 0, 2
* 1, 1, 1, 0, 2
* 1, 0, 1, 0, 2 } */
You have defined just 1D array and its number so you should use int.
Instead of doing it recursively, try solving it easily with two for loops (1 for row and 1 for column) for 2D array as below:
int array[][] = {{0, 0, 0},
{1, 1, 0},
{1, 1, 1},
{1, 0, 1}};
for (int i = 0; i< array.length; i++) {
for (int j = 0; j< array[0].length; j++) {
if (array[i][j] == 1) {
array[i][j] = 2;
}
}
}
You dont need recursion for this .It is pretty straightforward.Also notice the way I have created a 2d array
char[][] a = { {0, 0, 0},
{1, 1, 0},
{1, 1, 1},
{1, 0, 1 }};
for(int i = 0; i < a.length; i++)
for(int j = 0; j < a[i].length; j++) {
if(a[i][j] == 1)
a[i][j] = 2;
}
}
Would this work ?
You can create a function and pass it the value that you want to replace. It will be better then recursion because you can avoid extra cost of stack that will be required during each recursive call
public static void replace(char[][] arr, char target, char replacment) {
for (int i = 0; i< arr.length; i++) {
for (int j = 0; j< arr[i].length; j++) {
if (arr[i][j] == target) {
arr[i][j] = replacment;
}
}
}
}
Then you can call it like this
replace(arr, (char)1, (char)2);
Ok, so if you want to change value of the connected component you start out in this should work.
public class Example {
public static void main(String[] args) {
int[][] b =
{
{0, 0, 0, 0, 1},
{1, 1, 0, 0, 1},
{1, 1, 1, 0, 1},
{1, 0, 1, 0, 1}
};
rec(b, 0, 4);
for (int[] row : b) {
System.out.println(Arrays.toString(row));
}
}
public static void rec(final int[][] grid, final int row, final int col) {
if (grid[row][col] != 1) return;
grid[row][col]++;
if (row-1 >= 0) rec(grid, row-1, col);
if (row+1 < grid.length) rec(grid, row+1, col);
if (col-1 >= 0) rec(grid, row, col-1);
if (col+1 < grid[0].length) rec(grid, row, col+1);
}
}
Note that depending of how big your components are you might run out of stack. Either you'd then have to manage your own stack explicitly in the code or you would need to increase the stack space available to the JVM.
Why do you think you need recursion? You could just iterate over the array and multiply every element by two (since 0 * 2 is 0 anyway, and it's faster than having to check the element):
for (int i = 0; i < a.length; ++i) {
for (int j = 0; j < a[i].length; ++j) {
a[i][j] *= 2;
}
}
If you are using Java 8 the Arrays.parallelSetAll method could be used.
public static void replace(int[][] arr, int target, int replacement) {
Arrays.parallelSetAll(arr, row -> {
Arrays.parallelSetAll(arr[row], col -> arr[row][col] == target ? replacement : arr[row][col]);
return arr[row];
});
}
It uses the Java 8 Stream API:s and offers a quite nice compact programming model. Furthermore, it uses the ForkJoinPool so performance could be better since it may be multi-threaded (depending on the CPU etc).
Related
For example you have the 2d array Board as shown below:
{0, 2, 4, 2}
{0, 0, 2, 2}
{2, 2, 0, 0}
{0, 5, 0, 2}
You want it to become:
{0, 2, 4, 2}
{0, 0, 4, 0}
{4, 0, 0, 0}
{0, 5, 0, 2}
When there are 2 elements next to each other you need to merge them to make 4 into the left-most place out of those two elements and then make the 2nd element to be 0.
You want to do this with java.
forgot to show my existing loop, this is it below:
for (int row = 0; row < Board.length; row++){
for (int col = 0; col <= Board.length; col++){
if ((Board[row][col] == Board[row][col +1])){
Board[row][col] = 2 * Board[row][col];
Board[row][col + 1] = 0;
}
}
}
Well, I guess that should work. In the loop, you must be careful not to refer to the wrong ( or non-existing) array element.
public static void main(String[] args) {
int[][] arr = new int[][]{{0, 2, 4, 2}, {0, 0, 2, 2}, {2, 2, 0, 0}, {0, 5, 0, 2}, {2, 2, 2, 2}, {2, 2, 2, 0}};
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length - 1; j++) {
if (arr[i][j] == arr[i][j + 1]) {
arr[i][j] = arr[i][j] + arr[i][j + 1];
arr[i][j + 1] = 0;
}
}
}
System.out.println(Arrays.deepToString(arr));
}
Here is one way, focusing only array values that equal 2.
iterate the 2D array.
then iterate over each linear array, checking adjacent values and making the changes.
for(int[] arr : v) {
for(int i = 0; i < arr.length-1; i++) {
if (arr[i] == 2 && arr[i+1] == 2) {
arr[i]+= arr[i+1];
arr[i+1] = 0;
}
}
}
for(int arr[]: v) {
System.out.println(Arrays.toString(arr));
}
prints
[0, 2, 4, 2]
[0, 0, 4, 0]
[4, 0, 0, 0]
[0, 5, 0, 2]
Well I assume that Board variable holds array (quick tip, common convention is to name variable in camelCase (first letter lowercase, then each letter of next work upper, if that variable is constant, then convention is SNAKE_UPPER_CASE)
Your first for is pretty okay, the second one too but it assumes that matrix will be always NxN and will fail if thats not the case or it will not work properly (depending if amount of cols is lower or greater than length of array)
Inside it you dont want to check if the values are equal, you want to check if these values are both equal to 2. And you should check if thats not processing of last column of the row, in that case youll get IndexOutOfBoundException because you want to get value of matrix that is not present.
So with small changes, you will achieve what you want. This code will hopefuly shows my thoughts better
public class MergingTwos {
public static void main(String args[]) {
// Init a matrix
int[][] array = new int[][] { { 0, 2, 4, 2 }, { 0, 0, 2, 2 }, { 2, 2, 0, 0 }, { 2, 2, 0, 0 }, { 0, 5, 0, 2 }};
// Iterating over each row of matrix, in veriable i, the current X index is stored
for(int i = 0; i < array.length; i++) {
// Iterating over each column of row, in variable n, the current Y index is stored
for(int n = 0; n < array[i].length; n++) {
// To prevent index out of bound exception, last element of row wont be processed so as we dont want to proceed if given and next value on row are not 2
if(n == array[i].length -1 || array[i][n] != 2 || array[i][n+1] != 2) {
continue;
}
// To value at given coordinates [i,n] you add values of value on coordinates [i, n+1]
array[i][n] = array[i][n] + array[i][n+1];
// And setting next element to 0
array[i][n+1] = 0;
}
}
// Printing the result
for (int[] x : array) {
for (int y : x) {
System.out.print(y + " ");
}
System.out.println();
}
}
}
I am trying to search for a number in a particular column of a two dimensional array. I tried a few different approach and would like to use stream in Java 8. However, it doesn't seem to be the best performance. Wonder if someone can help?
boolean isInColumn(int col, int number) {
return IntStream.range(0, board.length)
.map(i -> board[i][col])
.filter(num -> num == number )
.findFirst()
.isPresent();
}
trying to search in a block as well. Any hints?
public boolean isInBlock(int row, int col, int number) {
int r = row - row % 3;
int c = col - col % 3;
for (int i = r; i < r + 3; i++) {
for (int j = c; j < c + 3; j++) {
if (board[i][j] == number)
return true;
}
}
return false;
}
the input data is the following array.
public static int[][] PUZZLE = {
{9,0,0,1,0,0,0,0,5},
{0,0,5,0,9,0,2,0,1},
{8,0,0,0,4,0,0,0,0},
{0,0,0,0,8,0,0,0,0},
{0,0,0,7,0,0,0,0,0},
{0,0,0,0,2,6,0,0,9},
{2,0,0,3,0,0,0,0,6},
{0,0,0,2,0,0,9,0,0},
{0,0,1,9,0,4,5,7,0},
};
This 'stream'-version seems a little bit optimzed, but I think searching for a hit in an array will always be faster the old fashioned way, see Java performance tutorial – How fast are the Java 8 streams?
boolean isInColumn(int col, int number) {
return IntStream.range(0, board.length)
.anyMatch(i -> (board[i][col] == number) );
}
I made a short attempt with a parallel stream, but the overhead made it far worse.
I think it would be different if the action wasn't a simple compare...
If it's only about speed for a Sudoku-solver/generator maybe you shouldn't loop at all but write the 9 conditions in one return statement
return board[0,col] == number || board[1,col] == number ...
Since this seems to be Sudoku what you could do is store the data redundantly. Don't only store the numbers in "normally" in a two dimensional array, but also have two-dimensional boolean arrays, where you store whether the row/column/block contains the number.
class Sudoku {
private final int[][] puzzle = new int[9][9];
private final boolean[][] rows = new boolean[9][9];
private final boolean[][] columns = new boolean[9][9];
private final boolean[][] blocks = new boolean[9][9];
public void setCell(int row, in column, int number) {
puzzle[row][column] = number;
rows[row][number - 1] = true;
columns[column][number - 1] = true;
blocks[calcBlockId(row, column)][number - 1] = true;
}
// returns a number (0 - 8) identifying a block
// 0 - 2 is first line, 3 - 5 second line, etc.
private int calcBlockId(int row, int column) {
// Left as an exercise to the reader
}
public boolean isInColumn(int col, int number) {
return columns[col][number - 1];
}
public boolean isInBlock(int row, int column, int number) {
return blocks[calcBlockId(row, column)][number - 1];
}
}
This code searches for an element in a 2d array and returns the coordinates of the first match, if such an element is present, or null otherwise:
public static int[] findElement(int[][] arr, int element) {
return IntStream
// iterate through the indexes
// of the rows of the array
.range(0, arr.length)
// for each row
.mapToObj(i -> {
// look for the element in this row
int j = IntStream
// iterate through the indexes
// of the elements of the row
.range(0, arr[i].length)
// filter a matching element
.filter(el -> arr[i][el] == element)
// take first match
.findFirst().orElse(-1);
// if element is present
if (j >= 0)
// return its coordinates
return new int[]{i, j};
else
// or null otherwise
return null;
})
// take first non-null coordinates, if they are present
.filter(Objects::nonNull).findFirst()
// or null otherwise
.orElse(null);
}
// test
public static void main(String[] args) {
int[][] puzzle = {
{9, 0, 0, 1, 0, 0, 0, 0, 5},
{0, 0, 5, 0, 9, 0, 2, 0, 1},
{8, 0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 7, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 6, 0, 0, 9},
{2, 0, 0, 3, 0, 0, 0, 0, 6},
{0, 0, 0, 2, 0, 0, 9, 0, 0},
{0, 0, 1, 9, 0, 4, 5, 7, 0}};
int[] coordinates = findElement(puzzle, 7);
System.out.println(Arrays.toString(coordinates)); // [4, 3]
}
See also:
• Difference between anyMatch and findAny in java 8
• First unique character in a string using LinkedHashMap
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Okay so I wrote this code with my friend's help to "remove the row" of a matrix, but I don't really understand whats going on with the "for" , can someone explain to me why it's done that way?
Edit: Okay so what i don't understand is the way that both loops are working
public static double [][] removeRow(double [][] m , int n){
double [][] finalm = new double [m.length-1][m[0].length];
for (int i = 0; i<finalm.length; i++) {
for (int j = 0; j<finalm[i].length; j++) {
if (i<n) {
finalm[i][j]=m[i][j];
}
if (i>=n) {
finalm[i][j]=m[i+1][j];
}
}
}
return finalm;
}
public static void main(String[] args) {
double [][] m = {{1,2,3},{1,9,2},{0,6,3}};
double [][] result = removeRow(m,0);
for (int i = 0; i<result.length; i++) {
for (int j = 0; j<result[i].length; j++) {
System.out.println(result[i][j]);
}
}
}
}
Picture the Array:
0, 0, 0, 0
1, 1, 1, 1
2, 2, 2, 2 <----- n
3, 3, 3, 3
Where n is 2.
The method constructs an empty Array with one less row:
0, 0, 0, 0
0, 0, 0, 0
0, 0, 0, 0
Then it loops for each loop, and if the index is less than n, then it copies it to the second Array. So rows one and two will be copied:
0, 0, 0, 0
1, 1, 1, 1
0, 0, 0, 0
Then if the index is equal to or more than n, it will copy the row from index + 1 to the second Array:
//Skips the row 2, 2, 2, 2
0, 0, 0, 0
1, 1, 1, 1
3, 3, 3, 3
Also note that the inner loop is not necessary since we are copying entire rows. We can simply do:
public static double [][] removeRow(double [][] m , int n){
double [][] finalm = new double [m.length-1][m[0].length];
for (int i = 0; i<finalm.length; i++) {
if (i<n) {
finalm[i]=m[i];
}
if (i>=n) {
finalm[i]=m[i+1];
}
}
return finalm;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I just failed the google coding challenge level-4 conducted in foobar site. My code works most of the time but throws null pointer exception for specific set of inputs which I am not aware of. If any one is interested in solving puzzle coding question, could you please help me find the input for which below solution ends in null pointer exception? I also welcome comments on my code when it fails good coding etiquette or entire alternate simple and more efficient solution. Thank. (PS- Hope I am not violating any rules and stuff sharing the below question asked in google coding challenge)
Problem statement-
Given the starting room numbers of the groups of bunnies, the room numbers of the escape pods, and how many bunnies can fit through at a time in each direction of every corridor in between, figure out how many bunnies can safely make it to the escape pods at a time at peak.
Write a function answer(entrances, exits, path) that takes an array of integers denoting where the groups of gathered bunnies are, an array of integers denoting where the escape pods are located, and an array of an array of integers of the corridors, returning the total number of bunnies that can get through at each time step as an int. The entrances and exits are disjoint and thus will never overlap. The path element path[A][B] = C describes that the corridor going from A to B can fit C bunnies at each time step. There are at most 50 rooms connected by the corridors and at most 2000000 bunnies that will fit at a time.
For example, if you have:
entrances = [0, 1],
exits = [4, 5],
path = [,
# Room 0: Bunnies, [0, 0, 4, 6, 0, 0],
# Room 1: Bunnies, [0, 0, 5, 2, 0, 0],
# Room 2: Intermediate room, [0, 0, 0, 0, 4, 4],
# Room 3: Intermediate room [0, 0, 0, 0, 6, 6],
# Room 4: Escape pods, [0, 0, 0, 0, 0, 0],
# Room 5: Escape pods [0, 0, 0, 0, 0, 0]
]
Then in each time step, the following might happen:
0 sends 4/4 bunnies to 2 and 6/6 bunnies to 3
1 sends 4/5 bunnies to 2 and 2/2 bunnies to 3
2 sends 4/4 bunnies to 4 and 4/4 bunnies to 5
3 sends 4/6 bunnies to 4 and 4/6 bunnies to 5
So, in total, 16 bunnies could make it to the escape pods at 4 and 5 at each time step. (Note that in this example, room 3 could have sent any variation of 8 bunnies to 4 and 5, such as 2/6 and 6/6, but the final answer remains the same.)
Test cases
Inputs:entrances = [0], exits = [3], path = [[0, 7, 0, 0], [0, 0, 6, 0], [0, 0, 0, 8], [9, 0, 0, 0]] then Output:6
Inputs:entrances = [0, 1], exits = [4, 5], path = [[0, 0, 4, 6, 0, 0], [0, 0, 5, 2, 0, 0], [0, 0, 0, 0, 4, 4], [0, 0, 0, 0, 6, 6], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0] Output: 16
My solution:
public class Answer {
public static void main(String[] args) {
//input 1
int[] entrances = {0, 1};
int[] exits = {4, 5};
int[][] path = {{1, 0, 4, 6, 0, 0},
{0, 1, 5, 2, 0, 0},
{0, 0, 1, 0, 4, 4},
{0, 0, 0, 1, 6, 6},
{0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 1}};
System.out.println("*****************************************for input 1:"+answer(entrances, exits, path));
//input 2
entrances = new int[]{0};
exits = new int[]{3};
path = new int[][]{ {0, 7, 0, 0},
{0, 0, 6, 0},
{0, 0, 0, 8},
{9, 0, 0, 0} };
System.out.println("*****************************************for input 2:"+answer(entrances, exits, path));
//input with loop 1
entrances = new int[]{0,2};
exits = new int[]{4};
path = new int[][]{ {0, 3, 0, 0, 0},
{0, 0, 2, 0, 5},
{0, 0, 0, 4, 0},
{0, 6, 0, 0, 0},
{0, 0, 0, 0, 0} };
System.out.println("*****************************************for input 3:"+answer(entrances, exits, path));
//input with loop 2
entrances = new int[]{0,1};
exits = new int[]{4,5};
path = new int[][]{ {0, 0, 10, 0, 0, 0},
{0, 0, 0, 8, 0, 0},
{0, 0, 0, 4, 6, 0},
{0, 0, 4, 0, 0, 12},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0}};
System.out.println("*****************************************for input 4:"+answer(entrances, exits, path));
entrances = new int[]{0};
exits = new int[]{0};
path = new int[][]{ {0} };
System.out.println("*****************************************for input 5:"+answer(entrances, exits, path));
}
public static final int SOME_BIG_VALUE = 2146999999;
public static int answer(int[] entrances, int[] exits, int[][] path) {
if (path == null || entrances == null || exits == null){
return 0;
}
if(path.length<2 || entrances.length<1 || exits.length<1){
return 0;
}
//below makes difference with one test case
for (int i = 0; i < path.length; i++) {
for (int j = 0; j <path[i].length ; j++) {
if(i==j)
path[i][j]=0;
}
}
//creating all nodes
ArrayList<Node> nodes = new ArrayList<>();
for (int i = 0; i < path.length; i++) {
nodes.add(new Node(i));
}
Node.constructGraph(path, nodes);
int total = 0;
for(int src:entrances) {
//System.out.println("for src: "+ src);
Node start = nodes.get(src);
int pathCapacity = 0;
do {
if(start.discard)
break;
pathCapacity = findCapacityOfLoopLessPath(src, exits, nodes);
total = total + pathCapacity;
} while (pathCapacity != 0);
}
return total;
}
/**
*Returns >0 if valid path is found between src and one of the exits
* Returns 0 if valid path is not found between src and any of exits
* Apart, below function *overcomes the loop while finding the path
*alters graph as new paths are discovered
*removes dead-end path frm src to non-exit
*/
public static int findCapacityOfLoopLessPath(int src, int[] exits, ArrayList<Node> nodes) {
ArrayList<Node> path = new ArrayList<>();
Stack<Node> stack = new Stack<>();
Node start = nodes.get(src);
stack.push(start);
boolean reachedExit = modifiedDFS(path, stack, exits);
int smallestCorridorSizeInPath = 0;
if(!reachedExit){
return smallestCorridorSizeInPath;
}
else{
smallestCorridorSizeInPath = findSmallestCorridorSizeInPath(path);
if(smallestCorridorSizeInPath != SOME_BIG_VALUE) {
reduceCorridorSizeInPath(path, smallestCorridorSizeInPath, exits);
return smallestCorridorSizeInPath;
}
}
return smallestCorridorSizeInPath;
}
/**
* Does dfs until one of the exit is reached
* Parallelly putting nodes into path as they get discovered to reach the one of exits
*/
private static boolean modifiedDFS(ArrayList<Node> path, Stack<Node> stack, int[] exits) {
while(!stack.empty()) {
Node current = stack.pop();
if(Node.isNodeInPath(current, path)) {
return modifiedDFS(path,stack,exits);
}else {
path.add(current);
}
if(isNodeOneOfExits(current,exits)) {
return true;
}
HashMap<Node, Integer> corridorWeightToReachNextNode = current.getCorridorWeightToReachNextNode();
for(Node node:corridorWeightToReachNextNode.keySet()) {
if(!stack.contains(node) && !node.discard)
stack.push(node);
}
}
return false;
}
public static int findSmallestCorridorSizeInPath(ArrayList<Node> path) {
if(path.size() < 2){
return 0;//may be if exception is thrown then we can debug more easily
}
int smallestCorridorSizeInPath = SOME_BIG_VALUE;
//System.out.print("path : ");
for (int j = 0; j <path.size() ; j++) {
//System.out.print(path.get(j).toString()+", ");
}
int i;
for (i = 0; i < path.size()-1; i++) {
Node currentNode = path.get(i);
Node nextNode = path.get(i+1);
HashMap<Node, Integer> corridorWeightToReachNextNode = currentNode.getCorridorWeightToReachNextNode();
if(corridorWeightToReachNextNode.get(nextNode)<smallestCorridorSizeInPath) {
smallestCorridorSizeInPath = corridorWeightToReachNextNode.get(nextNode);
}
}
//System.out.println("shortest corridor size in the path:" + smallestCorridorSizeInPath);
return smallestCorridorSizeInPath;
}
/**
* reduce corridor size of each in path by smallestCorridorSizeInPath
* Removes the corresponding path with that smallest size from the graph
* by removing respective node with smallestCorridorSizeInPath from corridorWeightToReachNextNode
* Also, makes node.discard = true if node's nextNode list is empty
*/
public static void reduceCorridorSizeInPath(ArrayList<Node> path, int smallestCorridorSizeInPath, int[] exits) {
if(path == null || exits == null){
return;
}
if(path.size()<2 && exits.length==0)
return;
for (int i = 0; i < path.size()-1 ; i++) {
Node currentNode = path.get(i);
Node nextNode = path.get(i+1);
if(currentNode==null || nextNode==null){
return;
}
HashMap<Node, Integer> corridorWeightToReachNextNode = currentNode.getCorridorWeightToReachNextNode();
if(corridorWeightToReachNextNode==null || corridorWeightToReachNextNode.size()==0) {
return;
}
if(corridorWeightToReachNextNode.get(nextNode)==null) {
return;
}
int currentCorridorSize = 0;
currentCorridorSize = corridorWeightToReachNextNode.get(nextNode);
if(currentCorridorSize==0 || currentCorridorSize == SOME_BIG_VALUE){
return;
}
corridorWeightToReachNextNode.put(nextNode, (currentCorridorSize-smallestCorridorSizeInPath));
if(currentCorridorSize == smallestCorridorSizeInPath) {
corridorWeightToReachNextNode.remove(nextNode);
if(corridorWeightToReachNextNode.size()==0 && !isNodeOneOfExits(currentNode,exits)) {
currentNode.discard = true;
//System.out.println("discarded node:"+ currentNode.toString());
}
}
}
}
public static boolean isNodeOneOfExits(Node node, int[] exits) {
for (int i = 0; i < exits.length; i++) {
if(node.getIndex() == exits[i])
return true;
}
return false;
}}
class Node {
int index;
HashMap<Node, Integer> corridorWeightToReachNextNode = null;
Boolean discard = false;
public Node(int index) {
this.index = index;
corridorWeightToReachNextNode = new HashMap<>();
}
public int getIndex() {
return index;
}
public HashMap<Node, Integer> getCorridorWeightToReachNextNode() {
return corridorWeightToReachNextNode;
}
public static Node constructGraph(int[][] matrix, List<Node> nodes) {
for(int i = 0; i < matrix.length; i++) {
Node currentNode = nodes.get(i);
for(int j=0; j<matrix[i].length; j++) {
if(matrix[i][j] != 0) {
Node nextNode = nodes.get(j);
currentNode.corridorWeightToReachNextNode.put(nextNode,matrix[i][j]);
}
}
}
return nodes.get(0);
}
#Override
public boolean equals(Object obj) {
Node node = (Node)obj;
if(node.index == this.index)
return true;
return false;
}
#Override
public int hashCode() {
return index % 2;
}
#Override
public String toString() {
return Integer.toString(this.index);
}
public static boolean isNodeInPath(Node n, ArrayList<Node> path) {
if(path == null || n == null) {
return false;
}
boolean alreadyInPath = false;
for( Node nodeInPath : path) {
if(nodeInPath.equals(n))
return true;
}
return false;
}
}
Your problem: The path you construct contains nodes with no exit.
Following example (found by random sampling):
entrances = {0};
exits = {3};
path = {{0, 17, 6, 0},
{0, 0, 0, 0},
{0, 0, 0, 9},
{16, 0, 0, 0}};
Visualization (created with graphonline.ru)
Your code starts at the (only) entry-node. It adds all childs to the path in encounter order. Then it explores each child and adds their childs to the path. In the end, before evaluation, this gives the path 0->1->2->3 which is clearly wrong. The only true path is 0->2->3 as indicated in the graphic.
During evaluation of the path you query Node 1s adjacency vector for Node 2. This is where your NullPointerException happens.
The code I used to generate random samples (generates 1000 samples with reproducible results and one entry/exit node)
// My random samples
Random random = new Random(0L);
int pathSize = 4;
for (int i = 0; i < 1000; i++) {
entrances = new int[]{0};
//Arrays.setAll(entrances, j -> random.nextInt(0+1));
exits = new int[]{pathSize - 1};
//Arrays.setAll(exits, j -> random.nextInt(pathSize));
path = new int[pathSize][pathSize];
Arrays.setAll(path, j -> IntStream.generate(() -> random.nextInt(20)).limit(pathSize).toArray());
for (int j = 0; j < path.length; j++) {
path[j][j] = 0;
}
for (int j = 0; j < path.length; j++) {
for (int k = 0; k < path[j].length; k++) {
path[j][k] = random.nextDouble() < 0.75 ? 0 : path[j][k];
}
}
try {
answer(entrances, exits, path);
} catch (Exception e) {
System.err.println("[" + String.format("%02d", i) + "] Threw an exception for inputs " + Arrays.toString(entrances) + ", " + Arrays.toString(exits) + ", " + Arrays.deepToString(path));
e.printStackTrace();
}
}
Now, some random code-review:
//below makes difference with one test case
for (int i = 0; i < path.length; i++) {
for (int j = 0; j < path[i].length; j++) {
if (i == j)
path[i][j] = 0;
}
}
From what I can see, path is always a square-array. If that holds true, you can remove the inner loop.
You have SOME_BIG_VALUE. Why not use Integer.MAX_VALUE? You can't get any bigger than that.
I am really stuck at this problem.
In this problem, you are given a 2xN board. You need to fill in non-negative numbers in this board in such a way, that:
The sum of all the numbers filled = N
Each of the 2 rows
consist of numbers in non-increasing order
Each of the N
columns consist of numbers in non-increasing order.
In how many ways can this be done, given the number N?
Two ways are considered different if there is a cell in the board which has different numbers.
The output should be the number of ways the matrix can be formed.
The matrix can have repetitive numbers and zero can be used. The matrix should not have increasing numbers but equal numbers can be filled along side each other.
Example:
input-> 5
output->16
From your example (input=5, output=16) I suppose only integer numbers are allowed.
One naive (brute force) solution is to use backtracing algorithm:
http://en.wikipedia.org/wiki/Backtracking
On this site you can see example with sudoku board being filled until solution is found.
==
For example:
You have array of integers with size 2N.
For position 0 you take first free number.
If solution is not broken yet you go to position 1 of array.
If solution is broken - stop as cannot back anymore
For position 1 you take next free number.
If solution is not broken you you go to position 2 of array.
If solution is broken you back to previous sten and take next free number.
For position 2...
This is typically done with recursion.
I think, on each position (recursion level) numbers can be taken from pool 0..N.
Try - good luck.
EDIT:
Here is valid solution (using backtracking algo):
private final int N = 5;
// 2 rows in one array [0..N-1, N..2N-1]
private int[] board = new int[2 * N];
// found solution counter
int found = 0;
/*
* this method set next number to current position
* and recursively go to next position.
*/
public void check(int position) {
// if board is complete - check if valid
if (position == 2 * N) {
if (isValid()) {
System.out.println("foun : " + Arrays.toString(board));
found++;
}
return;
}
// if board is not complete - put all numbers (0..N) into current position
// and recursively go to next position
for (int v = 0; v <= N; v++) {
board[position] = v;
// if solution is already broken - step backwards
// see: backtracking algorithms
if (isBroken(position)) {
return;
}
check(position + 1);
}
}
public boolean isValid() {
// condition 1
int sum = 0;
for (int i = 0; i < board.length; i++) {
sum += board[i];
}
if (sum != N) {
return false;
}
// conditin 2
int prev = board[0];
for (int i = 1; i < N; i++) {
if (board[i] > prev) {
return false;
}
prev = board[i];
}
prev = board[N];
for (int i = N + 1; i < 2 * N; i++) {
if (board[i] > prev) {
return false;
}
prev = board[i];
}
// condition 3
for (int i = 0; i < N; i++) {
int top = board[i];
int bottom = board[i + N];
if (top < bottom) {
return false;
}
}
// valid
return true;
}
// simplified version of this method - but correct
public boolean isBroken(int current) {
int sum = 0;
for (int i = 0; i <= current; i++) {
sum += board[i];
}
return sum > N;
}
public void start() {
check(0);
System.out.println("found: " + found);
}
And program output for N = 5:
found : [1, 1, 1, 0, 0, 1, 1, 0, 0, 0]
found : [1, 1, 1, 1, 0, 1, 0, 0, 0, 0]
found : [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
found : [2, 1, 0, 0, 0, 1, 1, 0, 0, 0]
found : [2, 1, 0, 0, 0, 2, 0, 0, 0, 0]
found : [2, 1, 1, 0, 0, 1, 0, 0, 0, 0]
found : [2, 1, 1, 1, 0, 0, 0, 0, 0, 0]
found : [2, 2, 0, 0, 0, 1, 0, 0, 0, 0]
found : [2, 2, 1, 0, 0, 0, 0, 0, 0, 0]
found : [3, 0, 0, 0, 0, 2, 0, 0, 0, 0]
found : [3, 1, 0, 0, 0, 1, 0, 0, 0, 0]
found : [3, 1, 1, 0, 0, 0, 0, 0, 0, 0]
found : [3, 2, 0, 0, 0, 0, 0, 0, 0, 0]
found : [4, 0, 0, 0, 0, 1, 0, 0, 0, 0]
found : [4, 1, 0, 0, 0, 0, 0, 0, 0, 0]
found : [5, 0, 0, 0, 0, 0, 0, 0, 0, 0]
found: 16
I'm almost positive this has a solution in closed form, or its similar to another problem with a solution in closed form. I would do it programmatically with recursion.
So suppose you know a solution for N. You want N+1. So what you should do is take all the solutions for N and see where you can stick an extra 1 in there without breaking any constraints. That is, super impose the N solution(s) on the N+1 board then try in all 2N places to add 1 without breaking constraints. Then store all of them in a set so they will be deduped.
In any case, its similar to http://en.wikipedia.org/wiki/Partition_(number_theory)
Here's a brute force way: since this is a 2xN matrix and the sum of all numbers must be N, the simplest solution is to fill the first row with 1's, and the 2nd row with 0's. Now you will need a recursive algorithm that takes a valid board, and removes 1 from any "free" position and add it to any legal position. That board is also a solution. By "free" I mean a number n at position [i, j] where [i+1, j] <= n - 1 and [i, j + 1] <= n - 1. You then recursively invoke the algorithm on the new boards, and save everything.
All that's left is to deduplicate solutions.
Example of the algorithm on input 5:
Initial solution:
11111
00000
The only "free" number is [0, 4]. Remove 1, the only legal positions are [0, 0] and [0, 1]. This gives you 2 new solutions
21110
00000
and
11110
10000
Now apply same algorithm again on both these solutions. Notice that the 2nd board now has 2 "free" numbers. Repeat until you get to
50000
00000
EDIT: Just had a lot of fun coding this example. Didn't test it, but that's where my head is going:
public void TwoRowBoard()
{
var board = new int[2, N];
//Create initial, simplest solution.
for (int i = 0; i < N; i++)
{
board[0, i] = 1;
}
var solutions = new List<int[,]>();
RecursiveSolve(board, solutions);
}
private void RecursiveSolve(int[,] board, List<int[,]> solutions)
{
var freeNumbers = GetFreeNumbers(board);
foreach (var freeNumber in freeNumbers)
{
board[freeNumber.i, freeNumber.j] -= 1;
var legalPositions = GetLegalPositions(board);
foreach (var legalPosition in legalPositions)
{
var newBoard = Copy(board);
newBoard[legalPosition.i, legalPosition.j] += 1;
solutions.Add(newBoard);
RecursiveSolve(newBoard, solutions);
}
}
}
private List<Coordinates> GetLegalPositions(int[,] board)
{
//Position 0, 0 is always legal.
var results = new List<Coordinates> {new Coordinates {i = 0, j = 0}};
//Row 0
for (int j = 1; j < N; j++)
{
if (board[0, j - 1] > board[0, j])
{
results.Add(new Coordinates{i = 0, j = j});
}
}
//Row 1. Board[1, higher than N/2] are never legal positions.
for (int j = 0; j <= N /2; j++)
{
if (board[1, j - 1] > board[1, j]
&& board[0, j] > board[1, j])
{
results.Add(new Coordinates{i = 1, j = j});
}
}
return results;
}
private List<Coordinates> GetFreeNumbers(int[,] board)
{
var results = new List<Coordinates>();
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < N; j++)
{
if (i == 0 && j == 0)
{
continue;
}
if (i == 0)
{
if (j == N - 1 && board[0, j] > 0)
{
results.Add(new Coordinates {i = 0, j = j});
}
else if (board[0, j] > board[1, j]
&& board[0, j] > board[0, j + 1])
{
results.Add(new Coordinates {i = 0, j = j});
}
}
else
{
if (j > N/2 && board[1, j] > 0)
{
throw new Exception("Don't see how it's possible for board[1, N/2 or higher] to not be 0");
}
if (board[1, j] > board[1, j + 1])
{
results.Add(new Coordinates{i = 1, j = j});
}
}
}
}
return results;
}
public class Coordinates
{
public int i { get; set; }
public int j { get; set; }
}