Made all variables and parameter final where available

This commit is contained in:
Niklas Birk 2019-04-02 20:34:15 +02:00
parent 4a0b04aefe
commit d4e54493c7
13 changed files with 95 additions and 117 deletions

View File

@ -1,6 +0,0 @@
public class Main
{
public static void main(String[] args)
{
}
}

View File

@ -4,22 +4,21 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.IntStream;
public class EightPuzzleNode extends Node<int[][]> public class EightPuzzleNode extends Node<int[][]>
{ {
public EightPuzzleNode(int[][] state) public EightPuzzleNode(final int[][] state)
{ {
super(state); super(state);
} }
private EightPuzzleNode(int[][] value, Node<int[][]> parent) private EightPuzzleNode(final int[][] value, final Node<int[][]> parent)
{ {
super(value, parent); super(value, parent);
} }
@Override @Override
public boolean isTargetReached(Node<int[][]> target) public boolean isTargetReached(final Node<int[][]> target)
{ {
return valueEquals(target); return valueEquals(target);
} }
@ -27,25 +26,25 @@ public class EightPuzzleNode extends Node<int[][]>
@Override @Override
public List<Node<int[][]>> generateSuccessors() public List<Node<int[][]>> generateSuccessors()
{ {
var successors = new ArrayList<Node<int[][]>>(); final var successors = new ArrayList<Node<int[][]>>();
var emptyPosition = Objects.requireNonNull(detectEmptyPosition()); final var emptyPosition = Objects.requireNonNull(detectEmptyPosition());
int x = emptyPosition.getX(); final int x = emptyPosition.getX();
int y = emptyPosition.getY(); final int y = emptyPosition.getY();
for (Direction dir : Direction.values()) for (final Direction dir : Direction.values())
{ {
var newState = copyOfState(); final var newState = copyOfState();
try try
{ {
var posToSwap = switch (dir) { final var posToSwap = switch (dir) {
case TOP -> new IntPair(x, y-1); case TOP -> new IntPair(x, y-1);
case RIGHT -> new IntPair(x+1, y); case RIGHT -> new IntPair(x+1, y);
case DOWN -> new IntPair(x, y+1); case DOWN -> new IntPair(x, y+1);
case LEFT -> new IntPair(x-1, y); case LEFT -> new IntPair(x-1, y);
}; };
var successor = this.swapStateField(newState, emptyPosition, posToSwap); final var successor = this.swapStateField(newState, emptyPosition, posToSwap);
if (!successor.valueEquals(this) && !successor.valueEquals(super.getParent())) if (!successor.valueEquals(this) && !successor.valueEquals(super.getParent()))
{ {
@ -53,7 +52,7 @@ public class EightPuzzleNode extends Node<int[][]>
} }
} }
catch (ArrayIndexOutOfBoundsException ignored) catch (final ArrayIndexOutOfBoundsException ignored)
{ {
} }
} }
@ -61,20 +60,12 @@ public class EightPuzzleNode extends Node<int[][]>
return successors; return successors;
} }
@Override
protected boolean isValidParameterValue(int[][] state)
{
var numbers = Arrays.stream(state).flatMapToInt(IntStream::of).toArray();
return numbersAreInAllowedRange(numbers) && numbersAreUnique(numbers);
}
@Override @Override
public String toString() public String toString()
{ {
StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
for (int[] row : super.value) for (final int[] row : super.value)
{ {
builder.append(Arrays.toString(row)).append("\n"); builder.append(Arrays.toString(row)).append("\n");
} }
@ -82,7 +73,7 @@ public class EightPuzzleNode extends Node<int[][]>
return builder.toString(); return builder.toString();
} }
private boolean valueEquals(Node<int[][]> node) private boolean valueEquals(final Node<int[][]> node)
{ {
if (node == null) if (node == null)
{ {
@ -103,16 +94,6 @@ public class EightPuzzleNode extends Node<int[][]>
return true; return true;
} }
private boolean numbersAreInAllowedRange(int[] numbers)
{
return Arrays.stream(numbers).min().getAsInt() == 0 && Arrays.stream(numbers).max().getAsInt() == 8;
}
private boolean numbersAreUnique(int[] numbers)
{
return Arrays.stream(numbers).count() == Arrays.stream(numbers).distinct().count();
}
private IntPair detectEmptyPosition() private IntPair detectEmptyPosition()
{ {
for (int row = 0; row < super.value.length; row++) for (int row = 0; row < super.value.length; row++)
@ -131,7 +112,7 @@ public class EightPuzzleNode extends Node<int[][]>
private int[][] copyOfState() private int[][] copyOfState()
{ {
var copy = new int[3][3]; final var copy = new int[3][3];
for (int y = 0; y < copy.length; y++) for (int y = 0; y < copy.length; y++)
{ {
@ -141,13 +122,13 @@ public class EightPuzzleNode extends Node<int[][]>
return copy; return copy;
} }
private EightPuzzleNode swapStateField(int[][] newState, IntPair emptyPos, IntPair posToSwap) private EightPuzzleNode swapStateField(final int[][] newState, final IntPair emptyPos, final IntPair posToSwap)
{ {
int posToSwapX = posToSwap.getX(); final int posToSwapX = posToSwap.getX();
int postToSwapY = posToSwap.getY(); final int postToSwapY = posToSwap.getY();
int emptyX = emptyPos.getX(); final int emptyX = emptyPos.getX();
int emptyY = emptyPos.getY(); final int emptyY = emptyPos.getY();
int tmp; final int tmp;
tmp = newState[postToSwapY][posToSwapX]; tmp = newState[postToSwapY][posToSwapX];
newState[postToSwapY][posToSwapX] = newState[emptyY][emptyX]; newState[postToSwapY][posToSwapX] = newState[emptyY][emptyX];
@ -161,7 +142,7 @@ public class EightPuzzleNode extends Node<int[][]>
private final int x; private final int x;
private final int y; private final int y;
public IntPair(int x, int y) public IntPair(final int x, final int y)
{ {
this.x = x; this.x = x;
this.y = y; this.y = y;
@ -177,6 +158,7 @@ public class EightPuzzleNode extends Node<int[][]>
} }
} }
private enum Direction private enum Direction
{ {
TOP, RIGHT, DOWN, LEFT TOP, RIGHT, DOWN, LEFT

View File

@ -4,21 +4,16 @@ import java.util.List;
public abstract class Node<T> public abstract class Node<T>
{ {
protected T value; protected final T value;
private Node<T> parent; private final Node<T> parent;
protected Node(T value) protected Node(final T value)
{ {
this(value, null); this(value, null);
} }
protected Node(T value, Node<T> parent) protected Node(final T value, final Node<T> parent)
{ {
if (!isValidParameterValue(value))
{
throw new IllegalArgumentException("Illegal node value");
}
this.value = value; this.value = value;
this.parent = parent; this.parent = parent;
} }
@ -33,7 +28,6 @@ public abstract class Node<T>
return this.parent; return this.parent;
} }
protected abstract boolean isValidParameterValue(T value);
public abstract boolean isTargetReached(Node<T> target); public abstract boolean isTargetReached(Node<T> target);
public abstract List<Node<T>> generateSuccessors(); public abstract List<Node<T>> generateSuccessors();
} }

View File

@ -0,0 +1,5 @@
package search.heuristic;
public class AStar
{
}

View File

@ -7,11 +7,11 @@ import java.util.List;
public class BreadthFirstSearch public class BreadthFirstSearch
{ {
public <T> Node<T> breadthFirstSearch(List<Node<T>> nodes, Node<T> target) public <T> Node<T> breadthFirstSearch(final List<Node<T>> nodes, final Node<T> target)
{ {
var newNodes = new ArrayList<Node<T>>(); final var newNodes = new ArrayList<Node<T>>();
for (Node<T> node : nodes) for (final Node<T> node : nodes)
{ {
if (node.isTargetReached(target)) if (node.isTargetReached(target))
{ {

View File

@ -4,18 +4,18 @@ import search.Node;
public class DepthFirstSearch public class DepthFirstSearch
{ {
public <T> Node<T> depthFirstSearch(Node<T> node, Node<T> target) public <T> Node<T> depthFirstSearch(final Node<T> node, final Node<T> target)
{ {
if (node.isTargetReached(target)) if (node.isTargetReached(target))
{ {
return node; return node;
} }
var newNodes = node.generateSuccessors(); final var newNodes = node.generateSuccessors();
while (!newNodes.isEmpty()) while (!newNodes.isEmpty())
{ {
var resultNode = depthFirstSearch(newNodes.get(0), target); final var resultNode = depthFirstSearch(newNodes.get(0), target);
if (resultNode != null) if (resultNode != null)
{ {

View File

@ -4,7 +4,7 @@ import search.Node;
public class IterativeDeepening public class IterativeDeepening
{ {
public <T> Node<T> iterativeDeepening(Node<T> node, Node<T> target) public <T> Node<T> iterativeDeepening(final Node<T> node, final Node<T> target)
{ {
int lowBarrier = 0; int lowBarrier = 0;
@ -19,18 +19,18 @@ public class IterativeDeepening
return resultNode; return resultNode;
} }
private <T> Node<T> depthFirstSearch(Node<T> node, Node<T> target, int depth, int barrier) private <T> Node<T> depthFirstSearch(final Node<T> node, final Node<T> target, int depth, final int barrier)
{ {
if (node.isTargetReached(target)) if (node.isTargetReached(target))
{ {
return node; return node;
} }
var newNodes = node.generateSuccessors(); final var newNodes = node.generateSuccessors();
while (!newNodes.isEmpty() && depth < barrier) while (!newNodes.isEmpty() && depth < barrier)
{ {
var resultNode = depthFirstSearch(newNodes.get(0), target, ++depth, barrier); final var resultNode = depthFirstSearch(newNodes.get(0), target, ++depth, barrier);
if (resultNode != null) if (resultNode != null)
{ {

View File

@ -9,7 +9,7 @@ class EightPuzzleNodeTest
@Test @Test
public void shouldThrowExceptionWhileStateHasDuplicateNumbers() public void shouldThrowExceptionWhileStateHasDuplicateNumbers()
{ {
int[][] state = { final int[][] state = {
{1, 1, 3}, {1, 1, 3},
{4, 5, 6}, {4, 5, 6},
{7, 8, 0} {7, 8, 0}
@ -21,7 +21,7 @@ class EightPuzzleNodeTest
@Test @Test
public void shouldThrowExceptionWhileStateHasNumbersOutOfRange() public void shouldThrowExceptionWhileStateHasNumbersOutOfRange()
{ {
int[][] state = { final int[][] state = {
{1, 2, 3}, {1, 2, 3},
{4, 5, 6}, {4, 5, 6},
{7, 8, 9} {7, 8, 9}
@ -33,14 +33,14 @@ class EightPuzzleNodeTest
@Test @Test
public void shouldReturnTrueWhenTargetReached() public void shouldReturnTrueWhenTargetReached()
{ {
int[][] state = { final int[][] state = {
{1, 2, 3}, {1, 2, 3},
{4, 5, 6}, {4, 5, 6},
{7, 8, 0} {7, 8, 0}
}; };
var node = new EightPuzzleNode(state); final var node = new EightPuzzleNode(state);
var target = new EightPuzzleNode(state); final var target = new EightPuzzleNode(state);
Assertions.assertTrue(node.isTargetReached(target)); Assertions.assertTrue(node.isTargetReached(target));
} }
@ -48,20 +48,20 @@ class EightPuzzleNodeTest
@Test @Test
public void shouldReturnFalseWhenTargetNotReached() public void shouldReturnFalseWhenTargetNotReached()
{ {
int[][] actualState = { final int[][] actualState = {
{7, 1, 6}, {7, 1, 6},
{0, 4, 2}, {0, 4, 2},
{3, 5, 8} {3, 5, 8}
}; };
int[][] targetState = { final int[][] targetState = {
{1, 2, 3}, {1, 2, 3},
{4, 5, 6}, {4, 5, 6},
{7, 8, 0} {7, 8, 0}
}; };
var node = new EightPuzzleNode(actualState); final var node = new EightPuzzleNode(actualState);
var target = new EightPuzzleNode(targetState); final var target = new EightPuzzleNode(targetState);
Assertions.assertFalse(node.isTargetReached(target)); Assertions.assertFalse(node.isTargetReached(target));
} }
@ -69,50 +69,45 @@ class EightPuzzleNodeTest
@Test @Test
public void shouldReturnNonEmptyListOfSuccessors() public void shouldReturnNonEmptyListOfSuccessors()
{ {
int[][] state = { final int[][] state = {
{7, 1, 6}, {7, 1, 6},
{0, 4, 2}, {0, 4, 2},
{3, 5, 8} {3, 5, 8}
}; };
var node = new EightPuzzleNode(state); final var node = new EightPuzzleNode(state);
var successors = node.generateSuccessors(); final var successors = node.generateSuccessors();
Assertions.assertFalse(successors.isEmpty()); Assertions.assertFalse(successors.isEmpty());
} }
@Test
public void shouldReturnEmptyListOfSuccessors()
{
}
@Test @Test
public void shouldReturnCorrectSuccessors() public void shouldReturnCorrectSuccessors()
{ {
int[][] state = { final int[][] state = {
{7, 1, 6}, {7, 1, 6},
{0, 4, 2}, {0, 4, 2},
{3, 5, 8} {3, 5, 8}
}; };
var node = new EightPuzzleNode(state); final var node = new EightPuzzleNode(state);
var successors = node.generateSuccessors(); final var successors = node.generateSuccessors();
Assertions.assertEquals(3, successors.size()); Assertions.assertEquals(3, successors.size());
int[][] newState1 = { final int[][] newState1 = {
{0, 1, 6}, {0, 1, 6},
{7, 4, 2}, {7, 4, 2},
{3, 5, 8} {3, 5, 8}
}; };
int[][] newState2 = { final int[][] newState2 = {
{7, 1, 6}, {7, 1, 6},
{4, 0, 2}, {4, 0, 2},
{3, 5, 8} {3, 5, 8}
}; };
int[][] newState3 = { final int[][] newState3 = {
{7, 1, 6}, {7, 1, 6},
{3, 4, 2}, {3, 4, 2},
{0, 5, 8} {0, 5, 8}

View File

@ -2,7 +2,7 @@ package search;
public class SearchTestUtils public class SearchTestUtils
{ {
public static <T> void printSolution(Node<T> targetNode) public static <T> void printSolution(final Node<T> targetNode)
{ {
var node = targetNode; var node = targetNode;

View File

@ -0,0 +1,8 @@
package search.heuristic;
import static org.junit.jupiter.api.Assertions.*;
class AStarTest
{
}

View File

@ -12,21 +12,21 @@ class BreadthFirstSearchTest
@Test @Test
void shouldReturnCorrectTarget() void shouldReturnCorrectTarget()
{ {
int[][] state = { final int[][] state = {
{5, 0, 3}, {5, 0, 3},
{2, 1, 6}, {2, 1, 6},
{4, 7, 8} {4, 7, 8}
}; };
var root = new EightPuzzleNode(state); final var root = new EightPuzzleNode(state);
int[][] targetState = { final int[][] targetState = {
{1, 2, 3}, {1, 2, 3},
{4, 5, 6}, {4, 5, 6},
{7, 8, 0} {7, 8, 0}
}; };
var expected = new EightPuzzleNode(targetState); final var expected = new EightPuzzleNode(targetState);
var actual = new BreadthFirstSearch().breadthFirstSearch(List.of(root), expected); final var actual = new BreadthFirstSearch().breadthFirstSearch(List.of(root), expected);
printSolution(actual); printSolution(actual);
} }
@ -34,21 +34,21 @@ class BreadthFirstSearchTest
@Test @Test
void shouldReturnCorrectTargetCubekNode() void shouldReturnCorrectTargetCubekNode()
{ {
int[][] state = { final int[][] state = {
{2, 0, 4}, {2, 0, 4},
{6, 7, 1}, {6, 7, 1},
{8, 5, 3} {8, 5, 3}
}; };
var root = new EightPuzzleNode(state); final var root = new EightPuzzleNode(state);
int[][] targetState = { final int[][] targetState = {
{1, 2, 3}, {1, 2, 3},
{4, 5, 6}, {4, 5, 6},
{7, 8, 0} {7, 8, 0}
}; };
var expected = new EightPuzzleNode(targetState); final var expected = new EightPuzzleNode(targetState);
var actual = new BreadthFirstSearch().breadthFirstSearch(List.of(root), expected); final var actual = new BreadthFirstSearch().breadthFirstSearch(List.of(root), expected);
printSolution(actual); printSolution(actual);
} }

View File

@ -10,21 +10,21 @@ class DepthFirstSearchTest
@Test @Test
void shouldReturnCorrectTarget() void shouldReturnCorrectTarget()
{ {
int[][] state = { final int[][] state = {
{1, 2, 3}, {1, 2, 3},
{4, 5, 6}, {4, 5, 6},
{7, 0, 8} {7, 0, 8}
}; };
var root = new EightPuzzleNode(state); final var root = new EightPuzzleNode(state);
int[][] targetState = { final int[][] targetState = {
{1, 2, 3}, {1, 2, 3},
{4, 5, 6}, {4, 5, 6},
{7, 8, 0} {7, 8, 0}
}; };
var expected = new EightPuzzleNode(targetState); final var expected = new EightPuzzleNode(targetState);
var actual = new DepthFirstSearch().depthFirstSearch(root, expected); final var actual = new DepthFirstSearch().depthFirstSearch(root, expected);
printSolution(actual); printSolution(actual);
} }

View File

@ -10,21 +10,21 @@ class IterativeDeepeningTest
@Test @Test
void shouldReturnCorrectTarget() void shouldReturnCorrectTarget()
{ {
int[][] state = { final int[][] state = {
{5, 0, 3}, {5, 0, 3},
{2, 1, 6}, {2, 1, 6},
{4, 7, 8} {4, 7, 8}
}; };
var root = new EightPuzzleNode(state); final var root = new EightPuzzleNode(state);
int[][] targetState = { final int[][] targetState = {
{1, 2, 3}, {1, 2, 3},
{4, 5, 6}, {4, 5, 6},
{7, 8, 0} {7, 8, 0}
}; };
var expected = new EightPuzzleNode(targetState); final var expected = new EightPuzzleNode(targetState);
var actual = new IterativeDeepening().iterativeDeepening(root, expected); final var actual = new IterativeDeepening().iterativeDeepening(root, expected);
printSolution(actual); printSolution(actual);
} }
@ -32,21 +32,21 @@ class IterativeDeepeningTest
@Test @Test
void shouldReturnCorrectTargetCubekNode() void shouldReturnCorrectTargetCubekNode()
{ {
int[][] state = { final int[][] state = {
{2, 0, 4}, {2, 0, 4},
{6, 7, 1}, {6, 7, 1},
{8, 5, 3} {8, 5, 3}
}; };
var root = new EightPuzzleNode(state); final var root = new EightPuzzleNode(state);
int[][] targetState = { final int[][] targetState = {
{1, 2, 3}, {1, 2, 3},
{4, 5, 6}, {4, 5, 6},
{7, 8, 0} {7, 8, 0}
}; };
var expected = new EightPuzzleNode(targetState); final var expected = new EightPuzzleNode(targetState);
var actual = new IterativeDeepening().iterativeDeepening(root, expected); final var actual = new IterativeDeepening().iterativeDeepening(root, expected);
printSolution(actual); printSolution(actual);
} }