2d array game that moves to adjacent spaces picking up coins - java

So I've been working on this problem for the better part of today. Can someone help me figure out where I went wrong?
It’s greedy because it moves to the location with the highest number of coins; and it’s lazy because it will stop moving if no adjacent location increases its coin treasure. If several adjacent locations had the same highest number of coins, the gatherer will choose to move to the highest in a clockwise fashion. The gatherer empties the coins from any location it visits.
public static int receiveCoins(int[][]map,int r,int c){
int[] coins = {0,0,0,0};
boolean moreCoins = true;
int numOfCoins = 0;
if(map[r][c] > 0){
numOfCoins += map[r][c];
map[r][c] = 0;
}
while(moreCoins == true){
if(c < (map.length-1)){
if(map[r][c+1] > 0){
coins[1] = map[r][c+1];
}
}
if(r < map[0].length-1){
if(map[r+1][c] > 0){
coins[2] = map[r+1][c];
}
}
if(row > 0){
if(map[r-1][c] > 0){
coins[0] = map[r-1][c];
}
}
if(c > 0){
if(map[r][c-1] > 0){
coins[3] = map[r][c-1];
}
}
int maxCoin = 0;
int nRow = 0;
int nCol = 0;
for(int i = 0; i < coins.length; i++){
if(coins[i] > maxCoin){
maxCoin = coins[i];
if(i == 0){
nCol = c;
nRow = r - 1;
}else if(i == 1){
nRow = r;
nCol = c + 1;
}else if(i == 2){
nCol = c;
nRow = r + 1;
}else{
nRow = r;
nCol = c - 1;
}
}
coins[i] = 0;
}
}
}
if (maxCoin == 0){
moreCoins = false;
}else{
r = nRow;
c = nCol;
numOfCoins += map[r][c];
map[r][c] = 0;
}
}
return numOfCoins;
}

A few corrections to your algorithm:
Suggestion from user1509803
You should reset coins[] back to zero after checking them for the highest, so that in the next iteration you are not reusing the values from the previous iteration. For example, if a value is non-zero in one iteration and then zero in the next.
Why the break near the end? This will cause your program to always break after the first iteration in the while loop.
map[row][col] = 0;
if(map[row][col] == 0){
break; // why?
}
When checking for the highest-valued next position, be sure to set both the row and column in case a previous position had been identified as the highest.
if(coins[i] > highestCoin){
highestCoin = coins[i];
if(i == 0){
newCol = col; // this is important! do this for all cases!
newRow = row - 1;
}
...
}
Switch the two bounds comparisons. row should compare to map.length, whereas col should compare to map[0].length. This is because rows can be thought of as vertical stacks (and so represent the first index in a 2d-array), whereas columns can be thought of as the horizontal units that make up the stacks (and so appear in the second index). Think of selecting first the stack, and then the unit in the stack.

Well I think col must be less than (map.length-1) instead of (map.length-2)
For {1},{1}, map.length == 2 so map.length-2 = 0, then col must be less than 0 to execute the if block.
Btw, you have map.length comparison to both col and row, so you map will be a square in any case?

Related

How do i correct my DP solution for the Cherry Pickup problem

My approach seems to be correct , the issue is whether multiple trips are allowed.
My solution seems to exceed the correct answer.
The Question:
In a N x N grid representing a field of cherries, each cell is one of three possible integers.
0 means the cell is empty, so you can pass through;
1 means the cell contains a cherry, that you can pick up and pass through;
-1 means the cell contains a thorn that blocks your way.
Your task is to collect maximum number of cherries possible by following the rules below:
Starting at the position (0, 0) and reaching (N-1, N-1) by moving right or down through valid path cells (cells with value 0 or 1);
After reaching (N-1, N-1), returning to (0, 0) by moving left or up through valid path cells;
When passing through a path cell containing a cherry, you pick it up and the cell becomes an empty cell (0);
If there is no valid path between (0, 0) and (N-1, N-1), then no cherries can be collected.
My Solution:
class Solution {
public int cherryPickup(int[][] grid) {
int N = grid.length;
int[][] dp;
char[][] track;
boolean f = true;
int sum = 0;
int count = 0;
while(f)
{
dp = new int[N][N];
track = new char[N][N];
dp[0][0] = grid[0][0];
track[0][0] = 'a';
char c;
c='u';
for(int i=1;i<N;i++)
{
if(c=='r'||grid[i][0]==-1)
{
c='r';
dp[i][0]=-1;
}
else
dp[i][0] = dp[i-1][0] + grid[i][0];
track[i][0] = c;
}
c='s';
for(int j=1;j<N;j++)
{
if(c=='r'||grid[0][j]==-1)
{
c='r';
dp[0][j]=-1;
}
else
dp[0][j] = dp[0][j-1] + grid[0][j];
track[0][j] = c;
}
for(int i=1;i<N;i++)
for(int j=1;j<N;j++)
{
if(grid[i][j]==-1||(track[i-1][j]=='r' && track[i][j-1]=='r'))
{
track[i][j] = 'r';
dp[i][j] = -1;
}
else
{
if(dp[i-1][j]>=dp[i][j-1])
{
track[i][j] = 'u';
dp[i][j] = dp[i-1][j] + grid[i][j];
}
else
{
track[i][j] = 's';
dp[i][j] = dp[i][j-1] + grid[i][j];
}
}
}
if(dp[N-1][N-1]<=0)
break;
sum += dp[N-1][N-1];
int r = N-1 , cr = N-1;
while(r>0||cr>0)
{
grid[r][cr]=0;
if(track[r][cr]=='s')
cr--;
else
r--;
}
grid[0][0] = 0;
}
return sum;
}
}
Can someone help??

Algorithm to count free blocks until there is a used block

It exists a 2 Dimensional Array for a field of (x,y) length, here for instance 9x6. What I need to do here is to check how many free fields are around the Orange and Red Star. The black (filled) fields represent the occupied fields. In this example for instance I have 7 free fields for Orange, 1 for Red. I know that I can loop through each field and see whether one field is occupied or not, but how could I loop through so that I know that these non-occupied fields are next to the Star or in the Radius of the Star of non-occupied fields? I hope I could elaborate my question well.
Field[][] fields = new Field[9][6];
private void checkEmptyFields(Star star) {
for (int i = 0; i < 9; i++){ // Hardcoded size as an example
for (int j = 0; i < 6; i++) {
if(fields[i][j].isOccupied())
{
//It is occupied, but what now?
}
}
}
}
isOccupied Function:
public boolean isOccupied(){
return occupied;
}
I expect the output to be in this example Orange: 7, Red: 1 (because Red is blocked by the Orange Star and the occupied boxes)
This seems like a problem where breadth-first-search is the appropriate algorithm to use here. Breadth-first-search, or BFS, is when you visit all of a node's, or in this case fields', neighbors first. In your case, "visiting", will just mean checking if it's occupied or not. If it the neighboring field is not occupied and hasn't been visited before, then you can search that field and it's neighbors. The order in which you search is determined by using a Queue-like data structure like so,
private void checkEmptyFields(Star star) {
boolean visited[9][6] = new visited[9][6];
//get the star's coordinates somehow, you may have to change this
int i = star.row;
int j = star.col;
visited[i][j] = true;
int freeFieldCount = 0;
Queue<Field> q = new LinkedList<Field>();
q.add(fields[i][j]);
while(!q.isEmpty()) {
Field current = q.poll();
//get the coordinates from the field, you may have to change this
i = current.row;
j = current.col;
int rowUpperLimit = i + 1;
int rowLowerLimit = i - 1;
int colUpperLimit = j + 1;
int colLowerLimit = j - 1;
if(rowUpperLimit >= 9) {
rowUpperLimit = 8;
}
if(rowLowerLimit < 0) {
rowLowerLimit = 0;
}
if(colUpperLimit >= 6) {
colUpperLimit = 5;
}
if(colLowerLimit < 0) {
colUpperLimit = 0;
}
//check immediate neighbors
for(int m = rowLowerLimit; m <= rowUpperLimit; m++) {
for(int n = colLowerLimit; n <= colUpperLimit; n++) {
if((m != i && n != j) && !visited[m][n] && !fields[m][n].isOccupied()) {
freeFieldCount++;
visited[m][n] = true;
q.add(fields[m][n]);
}
}
}
}
return freeFieldCount;
}
As user #juvian mentioned, this is an 8-neighbor approach. If you want to do a 4-neighbor approach, simply visit only the neighbors immediately to the left, right, above, or below the current field. You can modify the while loop like so,
while(!q.isEmpty()) {
Field current = q.poll();
//get the coordinates from the field, you may have to change this
i = current.row;
j = current.col;
int rowUpperLimit = i + 1;
int rowLowerLimit = i - 1;
int colUpperLimit = j + 1;
int colLowerLimit = j - 1;
if(colLowerLimit > -1) {
//check neighbor to the left
if(!visited[i][colLowerLimit] && !fields[i][colLowerLimit].isOccupied()) {
freeFieldCount++;
visited[i][colLowerLimit] = true;
q.add(fields[i][colLowerLimit]);
}
}
if(colUpperLimit < 6) {
//check neighbor to the right
if(!visited[i][colUpperLimit] && !fields[i][colUpperLimit].isOccupied()) {
freeFieldCount++;
visited[i][colUpperLimit] = true;
q.add(fields[i][colUpperLimit]);
}
}
if(rowLowerLimit > -1) {
//check neighbor below
if(!visited[rowLowerLimit][j] && !fields[rowLowerLimit][j].isOccupied()) {
freeFieldCount++;
visited[rowLowerLimit][j] = true;
q.add(fields[rowLowerLimit][j]);
}
}
if(rowUpperLimit < 9) {
//check neighbor above
if(!visited[rowUpperLimit][j] && !fields[rowUpperLimit][j].isOccupied()) {
freeFieldCount++;
visited[rowUpperLimit][j] = true;
q.add(fields[rowUpperLimit][j]);
}
}
}
}

Program hangs and won't finish

I'm writing a program that is supposed to take as input, several arrays of objects, and process them with the output being all the elements that the lists have in common. In other words, find the intersection of three arrays.
When I attempt to run the program, it all goes fine until the program starts executing the while loop within findCommonElements(). It hangs there and doesn't step forward, and I can't figure out why. Any help would be greatly appreciated.
edit When the arrays are passed to this method, they are already sorted
public static Comparable[] findCommonElements(Comparable[][] collections)
{
team[] intersection = new team[50];
int index = 0;
int i = 0; //counter for collections[0]
int j = 0; //counter for collections[1]
int k = 0; //counter for collections[2]
System.out.print("test");
while (i < collections[0].length && j < collections[1].length && k < collections[2].length)
{
//if query value > collections[2] value, increment collections[2]
if (collections[0][i].compareTo(collections[1][j]) > 0)
{
j++;
incComparisons();
}
//if query value > collections[2] value, increment collections[2]
else if (collections[0][i].compareTo(collections[2][k]) > 0)
{
k++;
incComparisons();
}
else if (collections[0][i] == collections[1][j] && collections[0][i] == collections[2][k])
{
// add entry to intersection array
intersection[index] = (team) collections[0][i];
index++;
incComparisons();
// if the next item in each collection also matches, then add an extra instance of that item to the list
if (collections[1][j + 1] == collections[0][i] || collections[2][k + 1] == collections[0][i])
{
intersection[index] = (team) collections[0][i];
index++;
incComparisons();
}
i++;
j++;
k++;
}
}
return intersection;
}

Java, how to add 2 arrayLists of different sizes

So i am currently working on a project for a course that i am doing, and i am writing a method that needs to add two ArrayLists containing integers together, and sets the sum in a new ArrayList. currently i have this, which is working fine
public BigInt add(BigInt otherBigInt) {
BigInt result = new BigInt();
int length = digitList.size() - 1;
int lengthOther = otherBigInt.digitList.size() - 1;
int temp = 0;
int whole = 0;
int carry = 0;
for (int i = length; i >= 0; i--){
temp = (digitList.get(i) + otherBigInt.digitList.get(i));
temp += carry;
// temp is equal to the sum of this(i) and otherBigInt(i), plus any number carried over.
if (temp >= 10){
whole = temp - 10;
carry = 1;
result.digitList.add(whole);
}
else if (temp < 10){
carry = 0;
result.digitList.add(temp);
}
}
if (carry == 1){
result.digitList.add(carry);
}
//adds any remaining carried number after for loop
// Supply this code.
return result;
}
however, currently the method only works if the arrayLists are of the same size, how would i modify the method to accommodate lists of varying size? an example of this would be two lists containing 735934 and 68945 giving the result 804879.
p.s.
not sure if it's needed, (still new to posting here) but the two lists I'm currently adding are 7359 and 6894, giving the answer 14253.
If my assumption is correct, then you are trying to simulate a case where you add two numbers using two lists, where one digit of the number occupies one index of the list.
Simplest solution would be to assume that the shortest list has zero's instead of no value and add till the max of the two lists:
public BigInt add(BigInt otherBigInt) {
BigInt result = new BigInt();
int length = Math.max(digitList.size(), otherBigInt.digitList.size()) - 1;
int lengthOther = otherBigInt.digitList.size() - 1;
int temp = 0;
int whole = 0;
int carry = 0;
for (int i = length; i >= 0; i--){
temp = ( checkAndGet(digitList, i) + checkAndGet(otherBigInt.digitList, i) );
temp += carry;
// temp is equal to the sum of this(i) and otherBigInt(i), plus any number carried over.
if (temp >= 10) {
whole = temp - 10;
carry = 1;
result.digitList.add(whole);
}
else {
carry = 0;
result.digitList.add(temp);
}
}
if (carry == 1){
result.digitList.add(carry);
}
//adds any remaining carried number after for loop
// Supply this code.
return result;
}
// if the index position being retrieved is larger than the size, assume 0
private int checkAndGet(List<Integer> input, position) {
return (input.size() < position) ? input.get(position) : 0;
}
Let the two digit array be a1[0 ... n1] and a2[0 ... n2]. Now your algorithm would be something like :
add(a1, a2):
min_length = min{a1.length, a2.length}
result[0 ... max{a1.length, a2.length} + 1]
carry = 0
for(i in [0 ... min_length - 1])
result[i] = carry + a1[i] + a2[i]
carry = result[i] / 10
result[i] %= 10
while(i < a1.length)
result[i] = a1[i]
while(i < a2.length)
result[i] = a2[i]
result[i] = carry
Notice that you have to add the remaining digits in case they are not of same size. I assume that the digits are stored in order i.e. a[0] is the 1st digit.
I would iterate through the smaller array backwards, adding the indexes together as you go:
ArrayList<Integer> toIterate = (array1.size() > array2.size)? a1 : a2;
ArrayList<Integer> seperate = (array1.size() > array2.size)? a2 : a1;
for (int i = toIterate.size - 1; i >= 0; i --) {
if (seperate.get(i) != null) {
arrayResult.add(toIterate.get(i) + seperate.get(i));
}
else {
arrayResult.add(toIterate.get(i));
}
}

Java Bishop Chess Board

Im working on figuring out the maximum number of bishops I can place on a nxn board without them being able to attack each other. Im having trouble checking the Diagonals. below is my method to check the diagonals. The squares where a bishop currently is are marked as true so the method is supposed to check the diagonals and if it returns true then the method to place the bishops will move to the next row.
Im not quite sure whats going wrong, any help would be appreciated.
private boolean bishopAttack(int row, int column)
{
int a,b,c;
for(a = 1; a <= column; a++)
{
if(row<a)
{
break;
}
if(board[row-a][column-a])
{
return true;
}
}
for(b = 1; b <= column; b++)
{
if(row<b)
{
break;
}
if(board[row+b][column-b])
{
return true;
}
}
for(c = 1; b <= column; b++)
{
if(row<c)
{
break;
}
if(board[row+c][column+c])
{
return true;
}
}
return false;
}
for(c = 1; b <= column; b++)
Shouldn't it be
for(c = 1; c <= column; c++)
By the way:
1) Use i, j, k instead of a, b, c, etc. No REAL reason why... it's just convention.
2) You don't have to keep naming new variables. Try something like this:
for(int i = 1; i <= column; i++)
{
...
}
//because i was declared in the for loop, after the } it no longer exists and we can redeclare and reuse it
for(int i = 1; i <= column; i++)
{
...
}
3) Your error checking is incorrect. It should be something like this:
for(int i = 1; i < 8; i++)
{
int newrow = row - i;
int newcolumn = column - i;
if (newrow < 0 || newrow > 7 || newcolumn < 0 || newcolumn > 7)
{
break;
}
if (board[newrow][newcolumn])
{
return true;
}
}
Now when you copy+paste your for loop, you only have to change how newrow and newcolumn are calculated, and everything else (including loop variable name) will be identical. The less you have to edit when copy+pasting, the better. We also attempt all 7 squares so we don't have to change the ending condition - the if check within the loop will stop us if we attempt to go out of bounds in ANY direction.
4) Better still, of course, would be using the for loop only once and passing only the changing thing into it... something like...
private boolean bishopAttackOneDirection(int rowdelta, int coldelta, int row, int column)
{
for(int i = 1; i < 8; i++)
{
int newrow = row + rowdelta*i;
int newcolumn = column + columndelta*i;
if (newrow < 0 || newrow > 7 || newcolumn < 0 || newcolumn > 7)
{
break;
}
if (board[newrow][newcolumn])
{
return true;
}
}
return false;
}
private boolean BishopAttack(int row, int column)
{
return BishopAttackInOneDirection(-1, -1, row, column)
|| BishopAttackInOneDirection(1, -1, row, column)
|| BishopAttackInOneDirection(1, 1, row, column)
|| BishopAttackInOneDirection(-1, 1, row, column);
}
Probably not quite the expected answer, but there is no reason to make life more complex then it is.
Im working on figuring out the maximum number of bishops I can place on a nxn board without them being able to attack each other.
public int getMaximumNumberOfNonAttackingBishopsForSquareBoardSize(final int boardSize) {
if (boardSize < 2 || boardSize > (Integer.MAX_VALUE / 2))
throw new IllegalArgumentException("Invalid boardSize, must be between 2 and " + Integer.MAX_VALUE / 2 + ", got: " + boardSize);
return 2 * boardSize - 2;
}
Source: http://mathworld.wolfram.com/BishopsProblem.html

Categories

Resources