Knapsack variation, Java - java

i have this assigment which is a variation of a knapsack problem.
I have a board (Knapstack type, which inner variable is int[][] knapsack) and an array of tiles(with size of nXm, not all of them with the same size). I need to write a function which returns true if i can place all the tiles within the knapsack board (without rotating them). For example:
if the tiles dimensions are:
and the board size is 4X4, a possible solution is:
this is the code i have thus far:
public boolean insertIntoKnapsack(Tile[] tiles) {
boolean ans = false;
ans=solution(this.knapsack,tiles,0,0,0);
return ans;
}
public boolean solution(int[][] knapsack, Tile[] tiles,int i,int j, int k) {
boolean ans=false; int a; int b=0;
if(j>=knapsack.length || k>=knapsack[0].length || i>=tiles.length)
return ans;
if(j<knapsack.length && k<knapsack[0].length && i==tiles.length) {
ans=isValid(knapsack,tiles);
return ans; }
for(a=0; knapsack.length-(j+a)>0 && a<tiles[i].getN(); a++) {
for(b=0; knapsack[0].length-(k+b)>0 && b<tiles[i].getM(); b++) {
if(knapsack[j+a][k+b]==0)
knapsack[j+a][k+b]=i+1;
}
}
return ans= solution(knapsack,tiles,i+1,j+a,k) || solution(knapsack,tiles,i+1,j,k+b) || solution(knapsack,tiles,i+1,j+a,k+b);
}
the knapsack class is defined as:
public class Knapsack {
// Holds the current state of the Knapsack
private int[][] knapsack;
public Knapsack(int n, int m) {
if(n<=0 || m<=0)
System.out.println("Bad Input");
else {
int knapsack[][] = new int[n][m];
}
}
the function isValid:
public boolean isValid(int[][] knapsack,Tile[] tiles) {
boolean ans=true;
for(int i=0;i<tiles.length; i++) {
int count=0;
for(int j=0; j<knapsack.length;j++) {
for(int k=0; k<knapsack[0].length; k++) {
if(knapsack[j][k]==i)
count=count+1;
}
}
if(count != tiles[i].getN() * tiles[i].getM())
ans=false;
}
return ans;
}
a tile is defined as:
public class Tile {
private int n;
private int m;
/*
* Construct a Tile of size nXm
*/
public Tile(int n, int m) {
if(n<=0 || m<=0)
System.out.println("Bad Input");
else {
this.n=n;
this.m=m;
}
}
/*
* Get the Tile's height
*/
public int getN(){
return n;
}
/*
* Get the Tile's width
*/
public int getM(){
return m;
}
}
Not only that i don't know if my solution is correct, whenever i try to test it i get a NullPointerException. I tried to change the conditions of the for loops at the solution method, but no matter how i change it i keep getting an error. Can someone please tell me if i'm headed the right way with the solution method or why do i keep getting a NullPointerException?

Related

Solving a backtracking question of N Queens

I am currently trying to learn the topic of Backtracking in Java. It is really really confusing for me because I am stuck.
The problem is to find ways in which N Queens can be placed in NxN Chess board so that none of the Queens can attack each other. A queen can attack in the same row, same column and diagonally. My code goes like this:
import java.util.Scanner;
class Main {
public static void putZero(int[][] board,int n){
for(int i = 0;i<n;i++){
for(int j=0;j<n;j++){
board[i][j]=0;
}
}
}
public static void printBoard(int[][] board,int n){
for(int i = 0;i<n;i++){
for(int j=0;j<n;j++){
System.out.print(board[i][j]);
}
System.out.print("\n");
}
System.out.print("\n\n\n");
}
public static void SolveNQ(int n){
int[][] board = new int[n][n];
putZero(board,n);
if(SolveQUtil(board,0,n)==true){
printBoard(board,n);
}
}
public static boolean isSafe(int row, int col, int[][] board,int n){
int i,j;
for(i=0;i<col;i++){
if(board[row][i]==1)
return false;
}
for(i=row,j = col; i >= 0 && j >= 0; i--, j--){
if(board[i][j]==1)
return false;
}
for (i = row, j = col; j >= 0 && i < n; i++, j--)
if (board[i][j] == 1)
return false;
return true;
}
public static boolean SolveQUtil(int[][] board, int col, int n){
if(col>=n){
return true;
}
else
for(int i=0;i<n;i++){
if(isSafe(i,col,board,n)==true){
board[i][col]=1;
boolean a = SolveQUtil(board,col+1,n);
if(a==true)
return true;
else
board[i][col]=0;
}
}
return false;
}
public static void main(String[] args){
Scanner scan = new Scanner(`enter code here`System.in);
int n = scan.nextInt();;
SolveNQ(n);
}
}
It is producing the result I want, but I am not understanding how this works. In my method SolveQUtil(), the method is called again which is "recursive". When col = 0 is called, the Q1 is placed at [0,0] as there are no existing queens. But when col = 1 is called recursively, it searches for the suitable place and returns 'true'. Now, isn't the SolveNQ() supposed to print the solution every time true is returned? When does it return false? How is this working? I am a beginner and can anyone please explain this to me, step by step? Thank you in advance.
SolveNQ, which does the printing, is not called recursively; SolveQUtil, which SolveNQ calls, and which does not print anything, is recursive.

Java 2D Array Specific Move

I have made a class where a 6x10 2D array is generated to act as a board.
A random starting location is then generated in the constructor.I only want adjacent moves to be possible.
For example, if the random location has been generated as (2,3) then for example the user enters (1,2) it would be a valid move, but (6,1) would be an invalid move.
Then if the user enters say (1,2), they can then go to any adjacent cell from (1,2).
I have included the class below, and the adjacent method I tried to make to test it, but I'm a bit confused on how I am approaching this.
import java.util.Arrays;
import java.util.Random;
public class Test {
public static final int ROWS = 6;
public static final int COLUMNS = 10;
public int[][] board;
public static void main(String[] args)
{
Test t = new Test();
t.getBoard();
t.makeMove(6,1); //I want this to be an invalid move.
t.getBoard();
t.makeMove(1,2); // this should be a valid move
t.getBoard();
}
public Test()
{
board = new int[ROWS][COLUMNS];
createRandomLocation();
}
public void createRandomLocation()
{
Random rand = new Random();
int x = rand.nextInt(6);
int y = rand.nextInt(10);
board[x][y] = 1;
}
public void makeMove(int x,int y){
if (Math.abs(x-cur_x)==0 || Math.abs(y-cur_y)==0) {
board[x][y] = 1;
}
public String getBoard() {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
System.out.print(board[i][j] + " ");
}
System.out.println();
}
System.out.println();
return Arrays.deepToString(board);
}
}
Adjacent:
/*public boolean isMoveAllowed(int [][] array,int x, int y){
boolean adjacent = false;
int trueCount = 0;
if(array[x-1][y-1] == 0) trueCount++; //topleft
if(array[x-1][y] == 0) trueCount++; //top
if(array[x-1][y+1] == 0) trueCount++;//topright
if(array[x][y+1] == 0) trueCount++;//right
if(array[x][y-1] == 0) trueCount++;//left
if(array[x+1][y-1] == 0) trueCount++;//bottomleft
if(array[x+1][y] == 0) trueCount++;//bottom
if(array[x+1][y+1] == 0) trueCount++; //bottomright
if (trueCount == 8)
{
adjacent = true;
}
return adjacent;
}*/
Your problem description has the answer baked into it already. You want any move from (a,b) to (c,d) to be legal if the distance between a and c, and b and d, is zero or one. So if you see Math.abs(a-c)>1, that's an illegal move. So: have the current position stored in some variables, and compare them to the desired new location:
public static void main(String[] args)
{
Board b = new Board(6, 10);
try {
b.tryMove(6,1);
} catch(IllegalMoveException e) {
// do whatever you need to do to inform the user that move is illegal
}
}
With the Board class responsible for tracking coordinates:
class Board {
protected int cur_x, cur_y, rows, cols;
public Board(int rows, int cols) {
this.rows = rows;
this.cols = cols;
this.setRandomPosition();
}
public void setRandomPosition() {
cur_x = (int) Math.round(Math.random() * cols);
cur_y = (int) Math.round(Math.random() * rows);
}
public void tryMove(int x, int y) throws IllegalMoveException {
if (Math.abs(x-cur_x)>1 || Math.abs(y-cur_y)>1) {
throw new IllegalMoveException(...);
}
// bounds check omitted here, but: ensure that
// 0<=x<cols and 0<=y<rows, otherwise throw an
// IllegalMoveException as well.
cur_x = x;
cur_y = y;
}
// with getters for the current x and y, etc.
}
It would be much easier to test for a true case rather than a false case like you currently have, the isMoveAllowed method should look something like this:
public boolean isMoveAllowed(int[][] array, int x, int y) {
return ((array[x + 1][y] == 1) ||
(array[x - 1][y] == 1) ||
(array[x][y + 1] == 1) ||
(array[x][y - 1] == 1));
}
This will return true if the move is adjacent to the current player position

Recursive Maze Solver method Issue

Given a 2 dimensional char array filled with 0's and 1 where 0 represents a wall and 1 represents a valid path, I have developed a recursive method called findPath(int r, int c) to find the exit in the maze marked with an 'x'. The method takes in the current row and column of the maze and goes through N,E,S,W directions until it finds a valid path and marks that valid path with a '+'. Given an instance where all directions are found to be blocked by a wall, the method then is suppose to backtrack until this is not the case anymore, and then marking that path traveled with an 'F' to symbolize the bad path.
Right now I can't figure out why the findPath method doesn't seem to transverse through all the directions as my display method just shows the program starting from the coordinates I pass in and not moving anywhere from there, why could this be?
Here is my Driver class
public class MazeMain2
{
public static void main(String[]args)
{
char[][] mazeArr = {{'0','0','0','1','0','0','0','0','0','0','0','0','0','0','0'},
{'0','0','0','1','0','0','0','0','1','0','0','0','0','1','0'},
{'0','0','0','1','1','1','1','1','1','1','1','1','0','0','0'},
{'0','0','0','1','0','0','0','0','0','0','0','1','0','0','0'},
{'0','0','0','1','1','1','1','1','0','0','0','1','0','0','0'},
{'0','0','0','0','0','0','0','1','0','0','0','1','0','0','0'},
{'0','0','0','0','1','1','1','1','0','0','0','1','0','0','0'},
{'0','0','0','0','1','0','0','1','0','0','0','1','0','1','0'},
{'0','0','0','0','1','0','0','1','0','0','0','0','0','0','0'},
{'0','0','0','0','1','0','0','0','0','0','0','0','0','0','0'},
{'0','0','0','0','1','1','1','1','1','1','1','0','0','0','0'},
{'0','0','0','0','0','0','0','0','0','0','1','0','0','0','0'},
{'0','0','0','0','0','0','0','0','0','0','1','0','0','0','0'},
{'0','0','0','0','0','1','0','0','0','0','1','1','1','1','0'},
{'0','0','0','0','0','0','0','0','0','0','1','0','0','0','0'}};
MazeSolver2 mazeS = new MazeSolver2(mazeArr);
mazeS.markEntry();
mazeS.markExit();
mazeS.solve(0, mazeS.start);
}
}
And here is my maze solver class with the findPath method
public class MazeSolver2
{
int start;
int exit;
char[][] maze;
public MazeSolver2(char[][] currentMaze)
{
maze = currentMaze;
}
//Finds where the first 1 is in the top row of the
//maze (entrance)
public void markEntry()
{
for(int x = 0; x < maze.length; x++)
{
if(maze[0][x] == '1')
{
maze[0][x] = 'E';
start = x;
}
}
}
//Finds where the last 1 is in the bottom row of the
//maze (exit)
public void markExit()
{
for(int x = 0; x < maze.length; x++)
{
if(maze[maze.length - 1][x] == '1')
{
maze[maze.length - 1][x] = 'x';
exit = x;
}
}
}
public void solve(int x, int y)
{
if(findPath(x, y))
{
System.out.println(maze[x][y]);
}
else
System.out.println("No solution");
}
public boolean findPath(int r, int c)
{
displayMaze(maze);
//Found the exit
if(maze[r][c] == 'x')
{
return true;
}
if(maze[r][c] == '0' || maze[r][c] == '+' || maze[r][c] == 'F')
{
return false;
}
maze[r][c] = '+';
//If row is currently at zero then don't check north
//direction because it will be outside of the maze
if(r <= 0)
{
if(findPath(r, c++))
{
return true;
}
if(findPath(r++, c))
{
return true;
}
if(findPath(r, c--))
{
return true;
}
}
else
{
//check N, E, S, W directions
if(findPath(r--, c) || findPath(r, c++) ||
findPath(r++, c) || findPath(r, c--))
{
return true;
}
}
//Marking the bad path
maze[r][c] = 'F';
return false;
}
//Displays maze
public void displayMaze(char[][] maze)
{
for(int row = 0; row < maze.length; row++)
{
for(int col = 0; col < maze.length; col++)
{
if(col == 14)
{
System.out.print(maze[row][col]);
System.out.println();
}
else
{
System.out.print(maze[row][col]);
}
}
}
System.out.println();
}
}
Your algorithm has several flow in itself, which I don't feel right to point out. You can search for maze traverse problems, and get many good tutorials.
However, give attention to the method calls. Notice that if findPath(int r, int c) get called with findPath(5, 5) then a call to findPath(r, c++) passes the values findPath(5, 5) again, not with findPath(5, 6).
Because in that case findPath(r, c++) get called with current value of c and after that c++ gets executed.
Same goes for findPath(r, c--) findPath(r++ , c) etc, etc.
A good idea to understand the fact is to print the values int r, int c at the starting of method findPath().
Also play a little with post increments/decrements(x++/--x) and pre increments/decrements(++x/--x).
Hope it helps.

Array Index Out of Bounds Exception while solving N Queens

I am working on code that uses recursive backtracking to solve the 8 queens problem(placing n chess queens on an n × n board so that none of the queens attack each other).
My task was to create two methods:
Write a public solveQueens(int n) method to solve the problem for an nxn board
Write a private recursive placeQueen(board, column) method to attempt to place a queen in the specified column.
So far I have written this in my program:
public class Queen {
public static boolean isLegal(int[] board, int n) {
for (int i = 0; i < n; i++) {
if (board[i] == board[n]) {
return false;
}
if ((board[i] - board[n]) == (n - i)) {
return false;
}
if ((board[n] - board[i]) == (n - i)) {
return false;
}
}
return true;
}
public static void solver(int n) {
int[] board = new int[n];
PlaceQueen(board, 0);
}
private static int[] PlaceQueen(int[] board, int column) {
int n = board.length;
if (column == n); else {
for (int row = 0; row < n; row++) {
board[column] = row;
if (isLegal(board, column)) {
PlaceQueen(board, column + 1);
}
}
}
return (board);
}
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
solver(n);
}
}
My program successfully compiles, but whenever I try to run it, I get this error.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Queen.main(Queen.java:39)
Any suggestions on feedback on where I should edit my code to get rid of this Exception?
Do you provide a argument to the program ?
It expects to have a integer argument.
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
solver(n);
}
If you try to access to an index which is not in the range of the args array, it rises java.lang.ArrayIndexOutOfBoundsException

Java field has wrong value after returned from a method, while calculating it with a void method produces correct result

Here is the following piece of code I wrote to compute the equilibrium index of a given array.
public class Equilibrium{
private int lowerSum =0;
public int equilibrium(int[] A) {
for(int i=0; i<A.length;i++)
{
if(lowerSum(A, i) == upperSum(A,i))
{
return i;
}
}
return -1;
}
private int lowerSum(int[] ar, int index)
{
if(index == 0)
return 0;
lowerSum += ar[--index];
return lowerSum;
}
//This can be fixed accordingly in a similar way lowerSum
//was implemented to have a time complexity of O(n) but
//this is not relevant to the problem here
private int upperSum(int[] ar, int index)
{
int sum=0;
for(int i= index+1; i<ar.length; i++)
{
sum+=ar[i];
}
return sum;
}
}
The above code does not produce the right results. For example for the following tests:
assertEquals(1, solution.solution(new int[]{1,2,1}));
assertEquals(3, solution.solution(new int[]{3,5,8,9,5,3,8}));
The first passes but the second does not. This is because the calculation of the
lowerSum field is by +1 wrong.
However making the following changes to the code produces the right result:
private int lowerSum =0;
public int solution(int[] A) {
for(int i=0; i<A.length;i++)
{
lowerSum(A, i);
if( lowerSum== upperSum(A,i))
{
return i;
}
}
return -1;
}
private void lowerSum(int[] ar, int index)
{
if(index == 0)
lowerSum = 0;
else
lowerSum += ar[--index];
}
Can someone please explain to me why this is happening?
In your first implementation you simply return 0. In your second implementation you set lowerSum to 0 before returning lowerSum.
Fixed:
private int lowerSum(int[] ar, int index)
{
if(index == 0) {
lowerSum = 0;
} else {
lowerSum += ar[--index];
}
return lowerSum;
}

Categories

Resources