Finding minimum value within adjacent locations of array - java

I'm new to coding and have not been coding for more than two months.
For my assignment, I'm making an escape the maze algorithm.
The user defines a 2D array and a start point, then the program must take the least damaging route to find its way out. The "AI" can only move north, east, south, or west. It can escape from any edge of the array.
Enter the starting x coordinate: 2
Enter the starting y coordinate: 4
0 1 4 2 6 0 1
1 7 4 2 2 6 0
0 0 0 8 * 4 1
1 1 2 7 3 4 2
5 1 6 4 2 2 1
In this example, the user has selected [2,4] as the start location of the array (remember, indexing begins at 0).
The AI can escape from any edge of the array. It is going to want to pick the smallest integer for each movement. For this example, the AI will move up to 2, then left, then up. Thus it took a sum amount of "6 damage" to exit the array.
My issue is comparing whether North is smaller than East, and if North is smaller than East, is it smaller than West? Or South? If East is smaller than North, is it smaller than West? Or South? & so on and so forth.
I'm not sure whether I'm going about this in the correct manner.
My attempt can be found at lines 44 - 78 in the hastebin link below.
I have no idea what I'm doing.
I created an int minimumValue; but I'm not sure how to utilize it, or where. If boardArray[north][currentY] < boardArray[east][currentY] then boardArray[north][currentY] is my new minimum value correct? Then I would need to write code comparing that to west and south as well. I feel like there has to be a simpler method to go about it.
I've tried googling solutions, Reddit, The Coding Den discord server, but I simply can't get this down.
Any and all help will be appreciated!
https://hastebin.com/acopoborut.java

Holy nested else's Batman!
I would replace lines 55-78 with something like this:
//find the least danger:
int leastDanger = northDanger;
if(southDanger < leastDanger) leastDanger = southDanger;
if(eastDanger < leastDanger) leastDanger = eastDanger;
if(westDanger < leastDanger) leastDanger = westDanger;
// Go the first direction equal to least danger
if (northDanger == leastDanger) { moveNorth
}else if(southDanger == leastDanger) { moveSouth
}else if(eastDanger == leastDanger) { moveEast
}else if(westDanger == leastDanger) { moveWest
}
The moveDirections would be your code like
visitedPath = visitedPath + "[" + currentX + "," + currentY + "]";
And the danger values are your code like
boardArray[north][currentY]
It could also be done with a switch statement, if you know those.

I assume by saying north you refer to -y direction and east you refer to +x direction
if boardArray[x][y] represent coordinate (x,y), then the coordinate north of it should be (x,y-1) and east is (x+1,y). You can compare them like this
boardArray[x][y-1] < boardArray[x+1][y] //Is North smaller than East?
Of course you should first check if the north and east are both inside the array, otherwise you will get ArrayIndexOutOfBoundException

Related

Java - Finding a the row and column in a 2d array based on where another value is

Here's the question explicitly:
I want to get the coordinate of the mouse and put that in a variable that I can plug into the equation shown in the code below [method movePosition()]. Is this possible or do I have to figure out a different approach?
The question is won't make sense without context, so here's a description:
A mouse has 8 possible moves to make in a maze, which work wherever it is. A random number is picked to represent the move the mouse has to take. In my head it looks like this, the "-" being the mouse itself:
1 2 3
4 - 5
6 7 8
If the mouse is at move #F, for example, how would I get it to move to position 8 (move #G from the example below)
A B 0 F 0 0 0 0
0 0 C E G J K L
0 0 D H I 0 M N
I was thinking to make a switch statement with each "coordinate" matching to a number from 1-8 which would look like so:
public int movePosition()
{
int moveToPosition = movePicker();
switch (moveToPosition)
{
case 1:
this.getMaze()[row - 1][column - 1] = mouse;
break;
case 2:
this.getMaze()[row - 1][column] = mouse;
break;
case 3:
this.getMaze()[row - 1][column + 1] = mouse;
break;
//and so on...
}
But I realized that wouldn't work for obvious reasons. (row and column are the user defined row and column)
Is there a way I could follow this same logic wherever the mouse is? I want to get the coordinate of the mouse and put that in a variable that I can plug into the equation above. Or do I have to figure out a different approach?
This is what I found similar to what I want (click here) and other questions are sort of like that too. However they all are asking how to find the coordinates from the size of the array. I need to know how to find the coordinate from the position of the mouse which could be anywhere.
Some Background:
This is homework. I have looked at other questions and although some are related to what I'm looking for, they don't have what I need.
I have a mouse that's thrown in a user defined maze. This means that I, the programmer, don't know what the size of the maze is. After the user defines the size of the maze, it gets set up with 0's. For example's sake, let's do a 3 x 8 maze.
The maze then looks like this (but user can't see this part):
array[3][8]:
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
By the end of the program, the mouse would have crossed to the end leaving behind a number indicated to the move it made. A for the first move, B for the second, C for the third, etc. this is just an example the actual code has numbers not letters. I just need to differentiate for clarity
The output would look as so (user sees this):
A B 0 F 0 0 0 0
0 0 C E G J K L
0 0 D H I 0 M N
Thanks!
This is how I would structure the methods, although there's plenty of other ways to do it:
private int mouseCol;
private int mouseRow;
int[][] maze;
private final String LEFT = "left";
private final String LEFT_UP = "left_up";
private final String LEFT_DOWN = "left_down";
//Etc
public String getRandomMove(){
List<String> moves = getValidMoves();
//pick a random one
}
public List<String> getValidMoves(){
List<String> validMoves = new ArrayList<>();
//Check left
if(mouseCol != 0 && maze[mouseRow][mouseCol-1] == 0){
validMoves.add(LEFT);
}
//Check left_up
if(mouseRow != 0 && mouseCol != 0 && maze[mouseRow-1][mouseCol-1] == 0){
validMoves.add(LEFT_UP);
}
//Etc
}

Scanning through 2d boolean array to find closest true coordinate

I am using a 2 dimensional boolean array to check where an entity is inside of my 2D side scroller as well as for collision. I know I am not looking for how high or low an entity away is and that is intentional. When I run this code it says the closest entity is 15 cells away. However, when I run my code it says the closest entity away is 15 blocks. Also when I print out distanceX it prints out the following:
9
0
0
2
2
15
9
0
0
2
2
15. I don't know why it won't register 9 as the closest even though that's is the first closest distance it recieves.
I can't post pictures yet however the reason 0,0,2, and 2 get printed is because I have 4 rectangles in all four corners of my player that are considered true in the grid so it detects the two on top of eachother and the other 2 or 2 spots away in the grid. Since I cant upload pictures try to see what I mean with this image i made. https://lh3.googleusercontent.com/OLSDPshjeU0YMahcmc0MDk-NocBMoG-7iN2xFTeFsQ8mAfF-sEPD8NBqXP4ENoN4YWmfUQ=s114
Thanks for any help!!
//Loop through my grid of booleans
for (int x = 0; x < map.getMapGrid().length; x++) {
for (int y = 0; y < map.getMapGrid().length; y++) {
//For comparison
Long distance = Long.MAX_VALUE;
// The second part of the if statement is to make sure it is checking for
// entities that arent the floor, therefor one above the grid position of the player
if (map.getMapGrid()[x][y] && y > ((Player) player).getGridPositionLeft().y - 1){
// distanceX = where something true was found (x) - where the player is in the grid
// Ex: 1 - 4 = |-3|, there is an entity 3 away
distanceX = Math.abs((int)(x - ((Player) player).getGridPositionLeft().x));
// if the distance of the entity from the player is less then the comparison variable,
// the closest entity x coordinate is distanceX
if(distanceX < distance){
closestCoord.x = distanceX;
closestCoord.y = 0;
}
}
}
}
return closestCoord;
}
Long distance = Long.MAX_VALUE;
This variable is never re-assigned, so it will always have the value Long.MAX_VALUE.
Also it is declared inside the innermost loop, so it will reset on each iteration. If you want the value of a variable to be remembered between iterations you need to declare and initialize it outside the loops.

Pretty good heuristic evaluation rules for big TicTacToe 5x5 board

I have created TicTacToe game. I use minmax algorithm.
When the board is 3x3 I just calculate every possible move for a game till the end and -1 for loss, 0 for tie, 1 for win.
When it comes to 5x5 it can't be done(to many options(like 24^24) so I have created evaluation method which gives: 10^0 for one CIRCLE inline, 10^1 for 2 CIRCLE inline, ..., 10^4 for 5 CIRCLES inline, but it is useless.
Does anybody have better idea for assesment?
Example:
O|X|X| | |
----------
|O| | | |
----------
X|O| | | |
----------
| | | | |
----------
| | | | |
Evaluation -10, 2 circles across once and inline once (+200), 2 crosses inline(-100), and -1 three times and + 1 three times for single cross and circle.
This is my evaluation method now:
public void setEvaluationForBigBoards() {
int evaluation = 0;
int howManyInLine = board.length;
for(; howManyInLine > 0; howManyInLine--) {
evaluation += countInlines(player.getStamp(), howManyInLine);
evaluation -= countInlines(player.getOppositeStamp(), howManyInLine);
}
this.evaluation = evaluation;
}
public int countInlines(int sign, int howManyInLine) {
int points = (int) Math.pow(10, howManyInLine - 1);
int postiveCounter = 0;
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[i].length; j++) {
//czy od tego miejsca jest cos po przekatnej w prawo w dol, w lewo w dol, w dol, w prawo
if(toRigth(i, j, sign, howManyInLine))
postiveCounter++;
if(howManyInLine > 1) {
if(toDown(i, j, sign, howManyInLine))
postiveCounter++;
if(toRightDiagonal(i, j, sign, howManyInLine))
postiveCounter++;
if(toLeftDiagonal(i, j, sign, howManyInLine))
postiveCounter++;
}
}
}
return points * postiveCounter;
}
Number of options (possible sequences of moves) after the first move is 24! and not 24^24. It is still a too much high
number so it is correct to implement an heuristic.
Note that answers about good heuristics are necessarily based on the opinion of the writer so I give my opinion but to find
out what is "the best heuristic" you should make the various ideas playing one against the other in the following way:
take the two heuristics A and B that you want to compare
generate at random a starting configuration
let A play with O and B play with X
from the same starting configuration let A play with X and B play with O
take stats of which one wins more
Now my thoughts about good possible heuristics starting points for an nxn playfield with winning sequence length of n:
since the winning condition for a player it to form a straight sequence of its marks my idea is to use as base values the number of possibilities that each player has still available to built such a straight sequence.
in an empty field both O and X have ideally the possibility to realize the winning sequence in several ways:
horizontal possibilities: n
vertical possibilities: n
diagonal possibilities: 2
total possibilities: 2n+2
in the middle of a round the number of remaining opportunities for a player are calculated as: "the number of rows without opponent's marks + the number of columns without opponent's marks + the number of diagonals without opponent's marks.
instead than calculate all each time it can be considered that:
after a move of one player the umber of still available possibilities are:
unchanged for him
equal or lowered for the opponent (if the mark has been placed in a row/col/diagonal where no marks had already been placed by the considered player)
as heuristic i can propose -
is possible that - k * with k > 1 give better results and in the end this can be related to how a draw is considered with regard to a lose.
One side consideration:
playfield cells are n^2
winning possibilities are 2n+2 if we keep the winning length equal to the field edge size
this give me the idea that the more the size is increased the less interesting is to play because the probability of a draw after a low number of moves (with reference to the playfield area) becomes higher and higher.
for this reason I think that the game with a winning length lower that n (for example 3 independently from the playfield size) is more interesting.
Named l the wining length we have that the number of possibilities is 2*((n+1-l)*(2n+1-l)) = O(n^2) and so well proportioned with the field area.

Manhattan distance in A*

I am implementing a NxN puzzle solver using A* search algorithm and using Manhattan distance as a heuristic and I've run into a curious bug (?) which I can't wrap my head around.
Consider these puzzles (0 element being blank space):
(initial)
1 0 2
7 5 4
8 6 3
(goal)
1 2 3
4 5 6
7 8 0
The minumum number of moves to reach solution from initial state is 11. However, my solver, reaches goal in 17 moves.
And therein lies the problem - my puzzle solver mostly solves the solvable puzzles in a correct (minimum) number of moves but for this particular puzzle, my solver overshoots the minimum number of moves and I think I've nailed down the problem to a miscalculation of Manhattan distance in this particular case.
At this link you can see what my solver is doing (on the right) and what a tried-n-tested solver is doing (Brian Borowski's excellent solver, available here).
In the very first move, Brian's solver immediately chooses solution that pushes element 5 up, but my solver has other ideas, and on the stacktrace (given on the link), my solver chooses solution which pushes 2 to the left (since that board's Manhattan distance is lower, the board is on the front of priority queue).
I can't see what is the problem and I can't blame my Manhattan distance calculation, since it correctly solves a number of other 3x3 puzzles.
Here is how I calculate the Manhattan distance of a given Board:
/**
* Calculates sum of Manhattan distances for this board and stores it in private field to promote immutability.
*/
private void calculateManhattanDistance() {
int manhattanDistanceSum = 0;
for (int x = 0; x < N; x++) // x-dimension, traversing rows (i)
for (int y = 0; y < N; y++) { // y-dimension, traversing cols (j)
int value = tiles[x][y]; // tiles array contains board elements
if (value != 0) { // we don't compute MD for element 0
int targetX = (value - 1) / N; // expected x-coordinate (row)
int targetY = (value - 1) % N; // expected y-coordinate (col)
int dx = x - targetX; // x-distance to expected coordinate
int dy = y - targetY; // y-distance to expected coordinate
manhattanDistanceSum += Math.abs(dx) + Math.abs(dy);
}
}
manhattanDistance = manhattanDistanceSum;
}
I would appreciate any insight or idea you may have.
If any additional code is needed, I'll post it right away.
I was stuck in the same place sometime back where I was solving this in 17 moves.The problem was that I was only using heuristic h(n) for the A* algorithm and whereas for choosing the next node A* uses manhattan distance(heuristic) + pathcost (cost to reach the node from root called as g(n)) to make the choice.
Once you plug in this to the algorithm it works like a charm.
Hope this helps someone who is stuck in the same place.
If your heuristic it's admissible (and it is, check this) than A* always return optimal solution. Can be slower or faster (expand more or less nodes) but it returns the optimal solution.
So, cause your heuristic is admissible the problem must be in A* algorithm implementation.
In addition the fact that its first step it's different from the optimal one is meaningless: the algorithm can correctly performs backtrace to get the correct solution path in the future. All the open nodes are candidates for the next step, not only the child of the current node.

Tennis tournament algorithm

After a tennis tournament each player was asked how many matches he had.
An athlete can't play more than one match with another athlete.
As an input the only thing you have is the number of athletes and the matches each athlete had. As an output you will have 1 if the tournament was possible to be done according to the athletes answers or 0 if not. For example:
Input: 4 3 3 3 3 Output: 1
Input: 6 2 4 5 5 2 1 Output: 0
Input: 2 1 1 Output: 1
Input: 1 0 Output: 0
Input: 3 1 1 1 Output: 0
Input: 3 2 2 0 Output: 0
Input: 3 4 3 2 Output: 0
the first number of the input is not part of the athletes answer it's the number of athletes that took part in the tournament for example in 6 2 4 5 5 2 1 we have 6 athletes that took part and their answers were 2 4 5 5 2 1.
So far this is what we wrote but didn't work that great:
import java.util.Scanner;
import java.util.Arrays;
public class Tennis {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String N;
int count;
int sum = 0;
int max;
int activeAthletes;
int flag;
System.out.printf("Give: ");
N = input.nextLine();
String[] arr = N.split(" ");
int[] array = new int[arr.length];
for (count = 0; count < arr.length; count++) {
array[count] = Integer.parseInt(arr[count]);
//System.out.print(arr[count] + " ");
}
for (count = 1; count < arr.length; count++) {
sum += array[count];
}
//System.out.println("\n" + sum);
activeAthletes = array[0];
for (count = 1; count < array.length; count++) {
if (array[count] == 0) {
activeAthletes--;
}
}
max = array[1];
for (count = 2; count < array.length; count++) {
if (array[count] > max) {
max = array[count];
}
}
// System.out.println(max);
if ((sum % 2 == 0) && (max < activeAthletes)) {
flag = 1;
} else{
flag = 0;
}
System.out.println(flag);
}
}
I do not want a straight solution just maybe some tips and hints because we really have no idea what else to do and I repeat even though I'll tag it as a homework (because I feel the moderators will close it again) it is not, it's just something my brother found and we are trying to solve.
Well many of you have answered and I'm really grateful but as I have work tomorrow I need to go to sleep, so I'll probably read the rest of the answers tomorrow and see what works
Not sure if it works 100%, i would go like:
Sort input
for each element going from right to left in array (bigger to smaller)
based on value n of element at index i decrease n left elements by 1
return fail if cant decrease because you reached end of list or value 0
return success.
This logic (if correct) can lead whit some modifications to O(N*log(N)) solution, but I currently think that that would be just too much for novice programmer.
EDIT:
This does not work correct on input
2 2 1 1
All steps are then (whitout sorting):
while any element in list L not 0:
find largest element N in list L
decrease N other values in list L by 1 if value >= 1 (do not decrease this largest element)
return fail if failure at this step
set this element N on 0
return OK
Here's a hint. Answer these questions
Given N athletes, what is the maximum number of matches?
Given athlete X, what is the maximum number of matches he could do?
Is this sufficient to check just these? If you're not sure, try writing a program to generate every possible matching of players and check if at least one satisfies the input. This will only work for small #s of atheletes, but it's a good exercise. Or just do it by hand
Another way of asking this question, can we create a symmetric matrix of 1s and 0s whose rows are equal the values. This would be the table of 'who played who'. Think of this like an N by N grid where grid[i][j] = grid[j][i] (if you play someone they play you) and grid[i][i] = 0 (no one plays themselves)
For example
Input: 4 3 3 3 3 Output: 1
Looks like
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
We can't do this with this one, though:
Input: 3 2 2 0 Output: 0
EDIT
This is equivalent to this (from Degree (graph theory))
Hakimi (1962) proved that (d1, d2, ..., dn) is a degree sequence of a
simple graph if and only if (d2 − 1, d3 − 1, ..., dd1+1 − 1, dd1+2,
dd1+3, ..., dn) is. This fact leads to a simple algorithm for finding
a simple graph that has a given realizable degree sequence:
Begin with a graph with no edges.
Maintain a list of vertices whose degree requirement has not yet been met in non-increasing order of residual degree requirement.
Connect the first vertex to the next d1 vertices in this list, and then remove it from the list. Re-sort the list and repeat until all
degree requirements are met.
The problem of finding or estimating the number of graphs with a given
degree sequence is a problem from the field of graph enumeration.
Maybe you can take the array of athletes' match qties, and determine the largest number in there.
Then see if you can split that number into 1's and subtract those 1's from a few other members of the array.
Zero out that largest number array member, and remove it from the array, and update the other members with reduced values.
Now, repeat the process - determine the new largest number, and subtract it from other members of the array.
If at any point there are not enough array members to subtract the 1's from, then have the app return 0. otherwise continue doing it until there are no more members in the array, at which point you can have the app return 1.
Also, remember to remove array members that were reduced down to zero.
Your examples can all trivially be solved by counting the matches and looking whether they divide by 2.
A problem not covered by your examples would be a player, who has more games than the sum of the other players:
Input: 4 5 1 1 1 Output: 0
This can be complicated if we add more players:
Input: 6 5 5 5 1 1 1 Output: 0
How to solve this question? Well, remove one game pairwise from the maximum and the minimum player, and see what happens:
Input: 6 5 5 5 1 1 1
Input: 5 5 5 4 1 1 -
Input: 4 5 4 4 1 - -
Input: 3 4 4 4 - - -
It violates the rule:
An athlete can't play more than one match with another athlete.
If 3 players are left, they can't have had more than 2 games each.
Edit: Below solution passes some invalid inputs as valid. It's a fast way to check for definite negatives, but it allows false positives.
Here's what a mathematician would suggest:
The sum of the number of matches must be even. 3 3 4 2 1 sums to 13, which would imply someone played a match against themselves.
For n players, if every match eliminates one player at least n-1 distinct matches must be played. (A knockout tournament.) To see this, draw a tree of matches for 2, 4, 8, 16, 32... players, requiring 1, 3, 7, 31... matches to decide a winner.
For n players, the maximum number of matches if everyone plays everyone once, assuming no repeat matches, is n choose 2, or (n!)/(2!)(n-2)! (Round robin tournament). n! is the factorial function, n! = n * n-1 * n-2 * ... * 3 * 2 * 1..
So the criteria are:
Sum of the number of matches must be even.
Sum of the number of matches must be at least 2n-2. (Note the multiplication by 2 - each match results in both players increasing their count by one.)
Sum of the number of matches must be at most 2 * n choose 2.
[Edit] Each player must participate in at least one match.
If your tournament is a cross between a knockout tournament and a round robin tournament, you could have somewhere between n-1 and n choose 2 matches.
Edit:
If any player plays more than n-1 matches, they played someone at least twice.
If your tournament is a knockout tournament ordered so that each player participates in as few matches as possible, then each player can participate in at most log_2(n) matches or so (Take log base 2 and round up.) In a tournament with 16 players, at most 4 matches. In a tournament of 1024 players, at most 10 matches.

Categories