I'm seeing a strange behaviour in a coding puzzle I was working on 'Knights Path'. I generate the set of possible moves and store these in a HashSet (the Move class simply has an x,y co-ordinates and a standard hashcode and equals). When I use a HashSet in the generateMoves() method the program doesn't find a solution whereas when I change to the LinkedHashSet it does.
public static Collection<Move> generateMoves(int startX, int startY){
Set<Move> moves = new HashSet<Move>(); <-- doesn't work
public static Collection<Move> generateMoves(int startX, int startY){
Set<Move> moves = new LinkedHashSet<Move>(); <-- works
I know that HashSet doesn't provide any guarantees on the ordering of the iterator elements but the ordering of the moves should not matter in terms of the eventual finding of a solution using backtracking method (some ordering of moves would be more optimal than others but with this brute force approach eventually all paths should be considered).
Clearly there is something funky going on with the iterator of the Collection from HashSet but I have conducted multiple tests to compare the output of the generateMoves for every board position using a LinkedHashSet and a HashSet and they are the same.
Full code below, any pointers greatly appreciated as I'm very curious to understand what may be going on here!
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
public class KnightTour {
private static int countSteps = 0;
public static void main(String[] args){
int[][] board = new int[8][8];
board[0][0] = 1;
solveTour(board,0,0,1);
}
public static class Move{
#Override
public String toString() {
return "["+ x + "," + y + "]";
}
int x;
int y;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Move other = (Move) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
private static void printBoard(int[][] board){
System.out.println("---------");
for(int i=0;i <8;i++){
for(int j=0; j<8; j++){
if(board[i][j] != 0){
System.out.print('x');
}else{
System.out.print('0');
}
}
System.out.println('\r');
}
System.out.println("---------");
}
public static boolean solveTour(int[][] sol, int x, int y, int movei){
countSteps++;
if(countSteps%100000 == 0){
System.out.println("Count:"+countSteps);
}
Collection<Move> moves = generateMoves(x,y);
if(movei == 64){
printBoard(sol);
return true;
}
for(Move tryMove : moves){
int next_x = tryMove.x;
int next_y = tryMove.y;
if(isValidMove(sol, next_x,next_y)){
sol[next_x][next_y] = movei;
if(solveTour(sol, next_x, next_y, movei+1)){
return true;
}else{
sol[next_x][next_y] = 0;
}
}
}
return false;
}
public static boolean isValidMove(int[][] board, int destX, int destY){
if(destX < 0 || destX > 7 || destY < 0 || destY > 7){
return false;//Off the board!
}
return board[destX][destY] == 0;
}
public static Collection<Move> generateMoves(int startX, int startY){
Set<Move> moves = new HashSet<Move>();//Doesn't terminate
// Set<Move> moves = new LinkedHashSet<Move>();//Works with Linked
for(int i=-2; i<=2; i++){
for(int j=-2; j<=2; j++){
if(Math.abs(i) == Math.abs(j) || i == 0 || j==0 ){
//no op
}else{
Move m = new Move();
m.x = startX + i;
m.y = startY + j;
moves.add(m);
}
}
}
return moves;
}
}
It looks to me like what you might be seeing is a side effect of LinkedHashMap iteration, which guarantees to iterate in the order of insert. HashSet does not have this same guarantee and can return the results in any order.
I think that the ordering of moves is probably important to your algorithm and perhaps an accidental heuristic you are applying by traversing in that order. The random ordering of moves may increase the complexity and introduce many new and suboptimal routes to explore recursively.
The HashSet solution might complete, it might be interesting to try with a small board and see if you get a result from that.
Related
First, sorry for my bad english, especially for programming words, english isnt my first language.
So, i have programmed a software that detect all continuous sprites on an image and list their palettes.
Full explanation of the software here: https://www.vg-resource.com/thread-33373.html
It works alright, however, if the sprite has at least 4300-ish pixels, a stackoverflow exception is thrown.
In order to find the boundaries of every sprite, first i find the first pixel in the sheet that isnt the color of the background. Then, i start my recursive method that verify every adjacent pixels to see if they dont have the background color, then call itself on that position, their position being recorded in a boolean matrix.
The recursive method:
//pixelPosition > the position found of the current sprite, posX/posY > position of the current pixel being examined
public boolean[][] moveToNextPixel(boolean[][] pixelPosition, int posX, int posY)
{
pixelPosition[posX][posY] = true;
//If the next position isnt outside of the boundaries of the image AND if it hasnt already been recorded
// AND if it isnt the color of the background, move to that position.
if(posX + 1 < pixelPosition.length)
{
if(!pixelPosition[posX+1][posY] && !panBackgroundColor.isColorPresentInPalette(workingImage.getRGB(posX+1,posY)) )
{
moveToNextPixel(pixelPosition,posX+1,posY);
}
}
if(posX - 1 >= 0)
{
if(!pixelPosition[posX-1][posY] && !panBackgroundColor.isColorPresentInPalette(workingImage.getRGB(posX-1,posY)))
{
moveToNextPixel(pixelPosition,posX-1,posY);
}
}
if(posY + 1 < pixelPosition[0].length)
{
if(!pixelPosition[posX][posY+1] && !panBackgroundColor.isColorPresentInPalette(workingImage.getRGB(posX,posY+1)))
{
moveToNextPixel(pixelPosition,posX,posY+1);
}
}
if(posY - 1 >= 0)
{
if(!pixelPosition[posX][posY-1] && !panBackgroundColor.isColorPresentInPalette(workingImage.getRGB(posX,posY-1)))
{
moveToNextPixel(pixelPosition,posX,posY-1);
}
}
return pixelPosition;
}
//the method isColorPresentInPalette(int) check if the color in entry is in the background colors
public boolean isColorPresentInPalette( int colorRgb)
{
boolean result = false;
for( int i =0; i< backgroundPalette.length && !result;i++)
{
if(backgroundPalette[i] != null)
{
if(backgroundPalette[i].getRGB() == colorRgb)
{
result = true;
}
}
}
return result;
}
Also, if i load a sheet with normal-sized sprite first, and then load one with a huge sprite (4400+ pixels), it doesnt do the stackoverflow error... So, in the end, im pretty confused on what is the problem exactly.
So, is a recursive method really the right way for this kind of problem? If so what could i do to fix this? Otherwise, anyone see a way to determine each individuals continuous sprites and their positions?
EDITED: Originally I posted a recursive solution but didn't realize that you were doing that. I think after reading more carefully, it seems Recursion might not be the best since you will be adding so many calls given 4300 pixels.
I would just do DFS in memory in this case then. Alternatively, you might try BFS (which will search outwards from the center).
An example of DFS in memory. This basically does the same thing as the recursion above except instead of storing things on the callstack which has a limited buffer size, you would be storing memory:
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Stack;
public class FindNeedleInHaystack {
String[][] haystack;
class Coordinate {
int x;
int y;
public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Coordinate that = (Coordinate) o;
return x == that.x &&
y == that.y;
}
#Override
public int hashCode() {
return Objects.hash(x, y);
}
}
public FindNeedleInHaystack() {
this.haystack = new String[10][10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
this.haystack[i][j] = "";
}
}
}
public void addNeedle(int a_x, int a_y) {
this.haystack[a_y][a_x] = "needle";
}
public boolean hasNeedle() {
boolean[][] visited = new boolean[10][10];
return hasNeedleHelper(0, 0);
}
private List<Coordinate> neighbors(Coordinate coord, boolean[][] visited) {
List<Coordinate> neighbors = new ArrayList<>();
int x = coord.x;
int y = coord.y;
if (y + 1 < 10 && !visited[y+1][x]) neighbors.add(new Coordinate(x, y+1));
if (y - 1 >= 0 && !visited[y-1][x]) neighbors.add(new Coordinate(x, y-1));
if (x + 1 < 10 && !visited[y][x+1]) neighbors.add(new Coordinate(x + 1, y));
if (x - 1 >= 0 && !visited[y][x-1]) neighbors.add(new Coordinate(x - 1, y));
return neighbors;
}
private boolean hasNeedleHelper(int x, int y) {
Stack<Coordinate> fringe = new Stack<>();
boolean[][] visited = new boolean[10][10];
fringe.push(new Coordinate(x, y));
while(!fringe.isEmpty()) {
Coordinate toVisit = fringe.pop();
if (this.haystack[toVisit.y][toVisit.x].equals("needle")) {
return true;
} else {
visited[toVisit.y][toVisit.x] = true;
for(Coordinate coord : this.neighbors(toVisit, visited)) {
fringe.push(coord);
}
}
}
return false;
}
public static void main(String...args) {
FindNeedleInHaystack hasNeedle = new FindNeedleInHaystack();
hasNeedle.addNeedle(3, 4);
System.out.println("Has a needle?: " + hasNeedle.hasNeedle());
FindNeedleInHaystack doesntHaveNeedle = new FindNeedleInHaystack();
System.out.println("Has a needle?: " + doesntHaveNeedle.hasNeedle());
}
}
I am using an ArrayList of ArrayLists for a data structure to play a game of towers of hanoi. The game is constructed and initialized as follows:
private ArrayList<ArrayList> lists = new ArrayList<ArrayList>();
private ArrayList<Integer> peg1 = new ArrayList<Integer>();
private ArrayList<Integer> peg2 = new ArrayList<Integer>();
private ArrayList<Integer> peg3 = new ArrayList<Integer>();
//Constructor
public TowersOfHanoi() {
lists.add(null);
lists.add(peg1);
lists.add(peg2);
lists.add(peg3);
}
public ArrayList initializeGame(int n) {
for (int i = 0; i < n; i++) {
peg1.add(i+1);
}
return peg1;
}
}
I am trying to use a Boolean method to do a check and make sure the user doesn't try to move a larger disc on top of a smaller disc, however, I don't understand how I would grab the the integer value stored in the arrayList. The integer values should serve as a way to gauge the diameter of the discs. I.E. 1 is smaller than two is smaller than 3 etc. This is the code I have come up with... I believe I am just getting the indexes and not the actual values of the integers stored there. How can I get the actual values?
public boolean isMoveLegal(int moveFrom, int moveTo){
ArrayList<Integer> fromPeg = lists.get(moveFrom);
int x = (fromPeg.remove(0)).intValue();
ArrayList<Integer> toPeg = lists.get(moveTo);
int y = (toPeg.get(0)).compareTo(x);
if(x<y){
System.out.println("illegal move");
}
return false;
}
The problem with your code is that isMoveLegal does not have a path where it would return true: the only return statement returns false. You should change the return statement as follows:
return x >= y;
This line is wrong too:
int y = (toPeg.get(0)).compareTo(x);
rather than getting the actual value into y, you are storing the result of comparison of y to x, which is not something you should compare to x again.
Additionally, your check is invasive: it removes the disks at the top of your pegs (it is apparent from your code that the top of the tower corresponds to position zero; this is unorthodox, but you can certainly make it work).
Rather than using remove(0), you should use get(0) after checking that the peg's content is not empty.
If the "from" peg is empty, the move is invalid. If the "to" peg is empty, the move is valid. Otherwise, the regular comparison rules apply (i.e. a bigger disk cannot go on top of a smaller disk).
public boolean isMoveLegal(int moveFrom, int moveTo){
ArrayList<Integer> toPeg = lists.get(moveTo);
if (toPeg.isEmpty()) return true; // You can move anything on an empty peg
int y = toPeg.get(0).intValue();
ArrayList<Integer> fromPeg = lists.get(moveFrom);
if (fromPeg.isEmpty()) return false; // No disks on the "from" peg
int x = fromPeg.get(0).intValue();
if(x>y){
System.out.println("illegal move");
return false;
}
return true;
}
This,
int y = (toPeg.get(0)).compareTo(x);
should be something like
int y = (toPeg.size() > 0) ? toPeg.get(0).intValue() : -1;
Then you can use
if (x > y) { // <-- the reverse of like you were, because the to peg is y.
public boolean isMoveLegal(int moveFrom, int moveTo){
ArrayList<Integer> fromPeg = lists.get(moveFrom);
if(fromPeg != null && fromPeg.size() > 0) {
int x = fromPeg.get(0).intValue();
ArrayList<Integer> toPeg = lists.get(moveTo);
if(toPeg != null) {
if(toPeg.size() == 0) {
return true;
} else {
int y = toPeg.get(0).intValue();
if(x<y){
return true;
}
}
}
}
System.out.println("illegal move");
return false;
}
For my programming course I have to write recursive functions, but aside from the theoretical questions given during the classes I can't figure out how to do it with my own code.
If anyone could help me out and give me a pointer on where to start it'd be great!
The method is as follows:
public boolean hasColumn(Marble m) {
boolean hasColumn = false;
for (int i = 0; i < DIM && hasColumn == false; i++) {
int winCount = 0;
for (int j = 0; j < DIM && hasColumn == false; j++) {
if (j == 0) {
winCount = 1;
} else {
if (getField(j, i).equals(getField(j - 1, i))
&& getField(j, i).equals(m)) {
winCount++;
if (winCount == WINLENGTH) {
hasColumn = true;
}
} else {
winCount = 1;
}
}
if (!(getField(j, i).equals(m))) {
hasColumn = false;
}
}
}
return hasColumn;
}
There's a field[DIM][DIM], which stores Marbles. Marble has a Mark, which is 0-4, with 0 being empty and 1-4 being colour values. The method determines whether someone has a marble column of 5 and wins.
Input is the Marble type of a player. Output is boolean hasColumn true or false. The output value is correct, there's just no recursion.
The idea is to make it find a vertical column in a recursive way. This also has to be done with horizontal/vertical, but I figured when I get this figured out I'll manage those by myself.
Thank you in advance!
public boolean hasColumn(Marble m, int i, int j, int wincount) {
if (wincount == WINLENGTH)
return true;
if (i == DIM)
return false;
if (j == DIM)
return hasColumn(m, i + 1, 0, 0);
return hasColumn(m, i, j + 1, getField(j, i).equals(m) ? wincount + 1 : 0);
}
Depending on whether you'd like to find a line/column of elements equal to a given Marble element or rather of same value, you may call this method:
hasColumn(aMarble, 0, 0, 0);
hasColumn(getField(0, 0), 0, 0, 0);
There's a duality between certain types of recursion and iteration.
Consider that in your iterative function you are iteratinng over columns using two variables, i and j. Could you transform those local variables into parameters to the function? You would be transforming state internal to the function (local variables) into state implicit in the function call.
Looks like task sounds like:
1. We have a square matrix of Marble elements(it can be simple integers) with dimension DIM.
2. We have a method getField(int, int) return a marble from this matrix
3. We have an iterative decision to discover if this matrix has any column with equal values of marble elements
Our goal is write recursive variant of this method
So, look here. Recursive algorithm check ROW existing with same value:
public class Marble {
public static final int DIM = 10;
public int[][] marbleAr = new int[DIM][DIM];
public void init(){
for(int i=0;i<DIM;i++){
for(int j=0;j<DIM;j++){
marbleAr[i][j] = new Random().nextInt(10);
if(i == 2){
marbleAr[i][j] = 7;
}
}
}
}
public int get(int i, int j){
return marbleAr[i][j];
}
public void printMarbleAr(){
for(int i=0;i<DIM;i++){
for(int j=0;j<DIM;j++){
System.out.print(marbleAr[i][j] + " ");
}
System.out.println();
}
}
public boolean hasColumn(int val, int col, int row){
if(row == 0){
return true;
}
if(this.hasColumn(val, col, row-1)){
if(this.get(col, row) == this.get(col,row-1)){
return true;
}else{
if(col == DIM-1){
return false;
}
return this.hasColumn(val, col+1, row);
}
}
return false;
}
public static void main(String[] args) {
int v = 7;
Marble marble = new Marble();
marble.init();
marble.printMarbleAr();
System.out.println(marble.hasColumn(v, 0, DIM-1));
}
}
Your method name is hasColumn and return variable
name is hasColumn. That's BAD.
I don't see hasColumn invoked inside the method again to actually
go down to recursion path.
i am currently working on this for personal gratification and would like some advice on how i can make this code faster :
I have one ArrayList composed of an object note, which have coordinates and color value stored in it.
Each "note" is created in real time during the rendering call.
I have made this function :
void keyPressed() {
if (key == 's' || key == 'S') {
PImage img = createImage(posX, specSize, RGB);
for(int x = 0; x < posX; x++){
for(int y = 0; y < specSize; y++){
for(int i = 0; i < notes.size(); i++){
if( (notes.get(i).getX() == x)
&& (notes.get(i).getY() == y) ){
int loc = x + y*posX;
img.pixels[loc] = color(notes.get(i).getR(),
notes.get(i).getG(), notes.get(i).getB());
}
}
}
}
img.updatePixels();
img.save("outputImage.png");
}
}
So when i press the "S" key, i run a loop on the width and height because they can be different in each run, and then on my arrayList and get the corresponding "note" with it's x and y position.
then i write my picture file.
As you can imagine, this is really, really, slow...
Around 5 to 6 minutes for a 1976x256px file.
For me it's okay but it would be great to shorten this a little.
Is there a way to optimize this three loops?
If you need more code, please let me know it's a small code and i don't mind.
How about this?
void keyPressed() {
if (key == 's' || key == 'S') {
PImage img = createImage(posX, specSize, RGB);
for(int i = 0; i < notes.size(); i++){
int x = notes.get(i).getX();
int y = notes.get(i).getY();
int loc = x + y*posX;
img.pixels[loc] = color(notes.get(i).getR(),
notes.get(i).getG(), notes.get(i).getB());
}
img.updatePixels();
img.save("outputImage.png");
}
}
Update:
Not sure what the type of notes is, but something like this might work too. Insert the correct type for one element of Notes into the for loop where I wrote ???.
void keyPressed() {
if (key == 's' || key == 'S') {
PImage img = createImage(posX, specSize, RGB);
for(??? note : notes ){
int x = note.getX();
int y = note.getY();
int loc = x + y * posX;
img.pixels[loc] = color(note.getR(), note.getG(), note.getB());
}
img.updatePixels();
img.save("outputImage.png");
}
}
Can clone notes (and any other object that is used to save) and do this in a different thread so its async to UI. the code will take same or more time but the user can use the rest of the app. Clone is neccesary as you want a snap shot of state when save was clicked.
Dont make a thread put use a ThreadPoolExecutor with one thread max. In the run method could apply what David suggested - one loop instead of two.
Convert your list of notes into a structure mapped like
Map<Integer, Map<Integer, Note> noteMap
Then replace your inner-most loop with a single call like
yNoteMap = note.get(x);
if (yNoteMap != null) {
note = yNoteMap.get(y);
if (note != null) {
// do stuff with note
}
}
Your computational complexity will go from about O(n^3) to O(n^2).
Create a class such as Point with two properties of x and y and implement proper equals and hashcode methods as:
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Point point = (Point) o;
if (x != point.x)
return false;
if (y != point.y)
return false;
return true;
}
#Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
now put the Point as key of a map, and find your points using this, so you don't have to iterate over the whole lists.
In my program I have a class called Cell, defined like so:
public class Cell {
private int x;
private int y;
public Cell (int x, int y) {
this.x = x;
this.y = y;
}
#Override
public boolean equals (Object o) {
boolean result = false;
if (o instanceof Cell) {
Cell other = (Cell) o;
result = (this.x == other.x && this.y == other.y)
}
return result;
}
#Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
I have a Grid class, like so (many methods cut out and variable names simplified):
public class Grid {
private Set<Cell> cellArray;
public Grid() {
cellArray = new HashSet<Cell>();
}
public Set<Cell> getCellArray() {
return cellArray;
}
public void addCellArray(Cell cell) {
cellArray.add(cell)
}
}
In my main body of code, I take in a grid object, like so:
public class Controller {
private Grid grid;
public Controller (Grid grid) (
this.grid = grid;
Then, I have a series of loops that look like this:
private set<Cell> cellArray = grid.getCellArray();
boolean endLoop = false;
do {
x = randomGenerator.nextInt(10);
y = randomGenerator.nextInt(10);
for (int i = 0; i < length; i++) {
if (cellArray.contains(new Cell(x, y+i))) {
continue;
}
}
for (int j = 0; j < length; j++) {
cellArray.add(new Cell(x, y+i));
}
endLoop = true;
} while(!endLoop);
I'm aware it's a very messy, with too much instantiation going on (and if anyone has pointers to make it cleaner, feel free to point them out) - however, the main issue is the fact that the first for loop is meant to check if the cellArray contains the items - it doesn't seem to be doing this.
There's no error message, no null pointer or anything like that. I've tried debugging it and have seen it compare two cells with identical x and y values, without proceeding to the continue statement to start the do while loop again.
I am assuming this is because even though they have identical values, they are different 'objects' and so aren't coming back as equal.
How could I fix this and get them to equate to one another if their values are the same?
Your continue statement continues the inner for-loop (which is quite useless here). You probably want to continue the outer loop: continue outerLoop;, with the label outerLoop: put in front of do {.
As the Java API states, the contains method should rely on your equals method, so object equality should work as you expect it.