Puzzle8 fix
- fixed bug causing the solve function to use all the memory and then crash - added new test cases - removed unused counter in AStar
This commit is contained in:
@@ -22,9 +22,6 @@ public class AStar<State, Action> {
|
||||
private BiFunction<State, State, Integer> heuristic;
|
||||
private TriFunction<State, State, Action, Integer> cost;
|
||||
|
||||
private int lastStateVisitedCount = 0;
|
||||
private int lastStateTotalCount = 0;
|
||||
|
||||
/**
|
||||
* Crea una istanza dell'algoritmo A* con una funzione di azioni possibili da compiere dato uno stato
|
||||
* e una funzione di transizione che dato uno stato permette di raggiungerne un'altro tramite un'azione.
|
||||
@@ -95,16 +92,11 @@ public class AStar<State, Action> {
|
||||
Objects.requireNonNull(initial);
|
||||
Objects.requireNonNull(goal);
|
||||
|
||||
this.lastStateVisitedCount = 0;
|
||||
this.lastStateTotalCount = 1;
|
||||
|
||||
NodeState found = null;
|
||||
var list = new PriorityQueue<NodeState>();
|
||||
list.add(new NodeState(null, initial, null, 0, 0));
|
||||
|
||||
while(list.size() > 0) {
|
||||
this.lastStateVisitedCount += 1;
|
||||
|
||||
var current = list.poll();
|
||||
if(current.state.equals(goal)) {
|
||||
found = current;
|
||||
@@ -112,8 +104,6 @@ public class AStar<State, Action> {
|
||||
}
|
||||
|
||||
for(var action : this.actions.apply(current.state)) try {
|
||||
|
||||
this.lastStateTotalCount += 1;
|
||||
var next = this.transition.apply(current.state, action);
|
||||
var cost = this.cost.apply(current.state, next, action);
|
||||
var dist = this.heuristic.apply(next, goal);
|
||||
@@ -137,16 +127,6 @@ public class AStar<State, Action> {
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
public int lastStateVisitedCount() {
|
||||
return this.lastStateVisitedCount;
|
||||
}
|
||||
|
||||
public int lastStateTotalCount() {
|
||||
return this.lastStateTotalCount;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Classe privata per mantenere i dati all'interno della PriorityQueue.
|
||||
* Non è stata messa statica dato che ho bisogno dello stato e dell'azione.
|
||||
@@ -168,7 +148,7 @@ public class AStar<State, Action> {
|
||||
|
||||
@Override
|
||||
public int compareTo(NodeState other) {
|
||||
return this.total - other.total;
|
||||
return Integer.compare(this.total, other.total);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ public class Puzzle8 implements Iterable<Integer> {
|
||||
|
||||
for(var i = 0; i < n; i++) index[p1.puzzle[i]] = i;
|
||||
for(var i = 0; i < n; i++) {
|
||||
var curr = p2.puzzle[i];
|
||||
if(curr == 0) continue;
|
||||
if(i == p2.blank) continue;
|
||||
|
||||
var curr = p2.puzzle[i];
|
||||
var i2 = index[curr];
|
||||
sum += Math.abs((i / LENGTH) - (i2 / LENGTH)) + Math.abs((i % LENGTH) - (i2 % LENGTH));
|
||||
}
|
||||
@@ -117,7 +117,28 @@ public class Puzzle8 implements Iterable<Integer> {
|
||||
*/
|
||||
public int get(int x, int y) {
|
||||
if(x >= LENGTH) throw new IndexOutOfBoundsException();
|
||||
return puzzle[y * LENGTH + x];
|
||||
return get(y * LENGTH + x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Permette di ricevere in input il valore della coordinata passata in input.
|
||||
* Il valore in input ha formato flat2D, ovvero è un numero che rappresenta una coordinata 2D in uno spazio finito.
|
||||
* La formula generale per calcolare il numero è la seguente: x + (MAX_X + 1) * y.
|
||||
* Quindi nel nostro caso si può calcolare la formula con: x + Puzzle8.LENGTH * y.
|
||||
* NOTA: non usare questo metodo se non si ha capito che cosa significhi. Piuttosto utilizzare {@link #get(int, int)}
|
||||
* @param flat2D la rappresentazione monodimensionale della coordinata 2D
|
||||
* @return il valore in quel punto del puzzle.
|
||||
*/
|
||||
public int get(int flat2D) {
|
||||
return puzzle[flat2D];
|
||||
}
|
||||
|
||||
/**
|
||||
* Permette di avere la posizione della tessera vuota in formato flat2D utilizzabile nel metodo {@link #get(int)}
|
||||
* @return la posizione dello 0 o tessera vuota
|
||||
*/
|
||||
public int getBlankPosition() {
|
||||
return this.blank;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,13 +222,14 @@ public class Puzzle8 implements Iterable<Integer> {
|
||||
var rand = new Random();
|
||||
for(var i = this.puzzle.length - 1; i > 0; i--) {
|
||||
var j = rand.nextInt(i + 1);
|
||||
|
||||
var temp = this.puzzle[i];
|
||||
this.puzzle[i] = this.puzzle[j];
|
||||
this.puzzle[j] = temp;
|
||||
|
||||
if(this.puzzle[i] == 0) this.blank = i;
|
||||
}
|
||||
|
||||
for(var i = 0; i < this.puzzle.length; i++)
|
||||
if(this.puzzle[i] == 0)
|
||||
this.blank = i;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ public class TestPuzzle {
|
||||
var puzzle = new Puzzle8(goalArray);
|
||||
|
||||
for(var i = 0; i < goalArray.length; i++)
|
||||
assertEquals(goalArray[i], puzzle.get(i%3, i/3), "Error in initialization");
|
||||
assertEquals(goalArray[i], puzzle.get(i), "Error in initialization");
|
||||
|
||||
var puzzle2 = new Puzzle8(goalArray);
|
||||
assertEquals(puzzle, puzzle2, "Error in equality");
|
||||
@@ -71,8 +71,7 @@ public class TestPuzzle {
|
||||
var puzzle = new Puzzle8(goalArray);
|
||||
var moves = new Puzzle8.Move[] {RIGHT, DOWN, LEFT, UP, DOWN, RIGHT, UP, LEFT};
|
||||
|
||||
for(var move : moves)
|
||||
puzzle = new Puzzle8(puzzle, move);
|
||||
for(var move : moves) puzzle = new Puzzle8(puzzle, move);
|
||||
assertEquals(new Puzzle8(goalArray), puzzle, "After useless moves the puzzle must be the same as before!");
|
||||
}
|
||||
|
||||
@@ -158,4 +157,21 @@ public class TestPuzzle {
|
||||
for(var move : actions) puzzle.move(move);
|
||||
assertEquals(puzzle, goal);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShuffleBlankPosition() {
|
||||
var puzzle = new Puzzle8(Puzzle8.DEFAULT_GOAL);
|
||||
var tot = Puzzle8.LENGTH * Puzzle8.LENGTH;
|
||||
|
||||
for(var i = 0; i < 1000; i++) {
|
||||
puzzle.shuffle();
|
||||
|
||||
var blank = 10;
|
||||
for(var j = 0; j < tot; j++)
|
||||
if(puzzle.get(j) == 0)
|
||||
blank = j;
|
||||
|
||||
assertEquals(blank, puzzle.getBlankPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user