this seems to work
This commit is contained in:
parent
e396b1ce39
commit
99db1345ae
5 changed files with 134 additions and 28 deletions
16
pom.xml
16
pom.xml
|
|
@ -7,12 +7,20 @@
|
||||||
<groupId>org.github.shautvast.exceptional</groupId>
|
<groupId>org.github.shautvast.exceptional</groupId>
|
||||||
<artifactId>avalor</artifactId>
|
<artifactId>avalor</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.3.5</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>22</maven.compiler.source>
|
<maven.compiler.source>22</maven.compiler.source>
|
||||||
<maven.compiler.target>22</maven.compiler.target>
|
<maven.compiler.target>22</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
|
@ -22,4 +30,12 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -1,15 +1,19 @@
|
||||||
package assessment;
|
package assessment;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.PriorityQueue;
|
|
||||||
|
|
||||||
|
//TODO make non static (CH)
|
||||||
public class BestPathFinder {
|
public class BestPathFinder {
|
||||||
private final static double timeDistanceFactor = .2;
|
private final static double timeDistanceFactor = .2;
|
||||||
|
// overall best path
|
||||||
private static Path max;
|
private static Path max;
|
||||||
|
|
||||||
|
// paths to be considered
|
||||||
private final static PriorityQueue<Path> paths = new PriorityQueue<>();
|
private final static PriorityQueue<Path> paths = new PriorityQueue<>();
|
||||||
|
// TODO replace by time check (MH)
|
||||||
private static volatile boolean running = true;
|
private static volatile boolean running = true;
|
||||||
|
|
||||||
|
private final static Set<Path> takenPaths = new HashSet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param g het Grid (vierkant)
|
* @param g het Grid (vierkant)
|
||||||
|
|
@ -18,7 +22,7 @@ public class BestPathFinder {
|
||||||
* @param T maximale tijdsduur
|
* @param T maximale tijdsduur
|
||||||
* @param x startpositie X
|
* @param x startpositie X
|
||||||
* @param y startpositie Y
|
* @param y startpositie Y
|
||||||
* @return het meest waardevole pad
|
* @return het meest waardevolle pad
|
||||||
*/
|
*/
|
||||||
public static Path findMaxValPath(Grid g, int N, int t, int T, int x, int y) {
|
public static Path findMaxValPath(Grid g, int N, int t, int T, int x, int y) {
|
||||||
Path path = Path.newPath(g, x, y);
|
Path path = Path.newPath(g, x, y);
|
||||||
|
|
@ -27,35 +31,57 @@ public class BestPathFinder {
|
||||||
|
|
||||||
// start looping until T is reached or all paths have been considered
|
// start looping until T is reached or all paths have been considered
|
||||||
while (running && !paths.isEmpty()) {
|
while (running && !paths.isEmpty()) {
|
||||||
|
|
||||||
|
//TODO take out (MH)
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (System.currentTimeMillis() > T) {
|
||||||
|
// running = false;
|
||||||
|
// }
|
||||||
|
|
||||||
// take current highest ranking path
|
// take current highest ranking path
|
||||||
path = paths.peek();
|
path = paths.peek();
|
||||||
assert path != null;
|
assert path != null;
|
||||||
while (path.length() > t) {
|
while (path.length() > t) {
|
||||||
// dit pad heeft lengte t bereikt
|
// dit pad heeft lengte t bereikt, we kunnen niet verder
|
||||||
paths.poll(); // geen nieuwe paden op basis van deze, we pakken de vorige in waardering
|
paths.poll(); // geen nieuwe paden op basis van deze, we pakken de vorige in waardering
|
||||||
// heeft dit pad meer waarde dan de huidige max ?
|
// heeft dit pad meer waarde dan de huidige max ?
|
||||||
if (path.value() > max.value()) {
|
if (path.value() > max.value()) {
|
||||||
max = path;
|
max = path;
|
||||||
}
|
}
|
||||||
|
path = paths.peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("paths:" + paths.size());
|
||||||
|
System.out.println("CUR: " + path);
|
||||||
|
Point currentPos = path.getHead();
|
||||||
|
x = currentPos.x;
|
||||||
|
y = currentPos.y;
|
||||||
|
|
||||||
// find best new directions
|
// find best new directions
|
||||||
List<Point> newPointsFromHere = new ArrayList<>();
|
List<Point> newPointsFromHere = new ArrayList<>();
|
||||||
if (y > 0) {
|
if (y > 0) {
|
||||||
newPointsFromHere.add(new Point(x, y - 1, getValueFromGrid(g, path, x, y - 1)));
|
newPointsFromHere.add(new Point(x, y - 1, getValueFromGrid(g, path, x, y - 1)));
|
||||||
if (x < N - 1)
|
if (x < N - 1) {
|
||||||
newPointsFromHere.add(new Point(x + 1, y - 1, getValueFromGrid(g, path, x + 1, y - 1)));
|
newPointsFromHere.add(new Point(x + 1, y - 1, getValueFromGrid(g, path, x + 1, y - 1)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (x > 0) {
|
if (x > 0) {
|
||||||
newPointsFromHere.add(new Point(x - 1, y, getValueFromGrid(g, path, x - 1, y)));
|
newPointsFromHere.add(new Point(x - 1, y, getValueFromGrid(g, path, x - 1, y)));
|
||||||
if (y > 0)
|
if (y > 0) {
|
||||||
newPointsFromHere.add(new Point(x - 1, y - 1, getValueFromGrid(g, path, x - 1, y - 1)));
|
newPointsFromHere.add(new Point(x - 1, y - 1, getValueFromGrid(g, path, x - 1, y - 1)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (x < N - 1) {
|
if (x < N - 1) {
|
||||||
newPointsFromHere.add(new Point(x + 1, y, getValueFromGrid(g, path, x + 1, y)));
|
newPointsFromHere.add(new Point(x + 1, y, getValueFromGrid(g, path, x + 1, y)));
|
||||||
if (y < N - 1)
|
if (y < N - 1) {
|
||||||
newPointsFromHere.add(new Point(x + 1, y + 1, getValueFromGrid(g, path, x + 1, y + 1)));
|
newPointsFromHere.add(new Point(x + 1, y + 1, getValueFromGrid(g, path, x + 1, y + 1)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (y < N - 1) {
|
if (y < N - 1) {
|
||||||
newPointsFromHere.add(new Point(x, y + 1, getValueFromGrid(g, path, x, y + 1)));
|
newPointsFromHere.add(new Point(x, y + 1, getValueFromGrid(g, path, x, y + 1)));
|
||||||
if (x > 0)
|
if (x > 0)
|
||||||
|
|
@ -64,17 +90,31 @@ public class BestPathFinder {
|
||||||
|
|
||||||
// sort the new points in descending order of value
|
// sort the new points in descending order of value
|
||||||
newPointsFromHere.sort(Point::compareTo);
|
newPointsFromHere.sort(Point::compareTo);
|
||||||
double max = newPointsFromHere.getFirst().value;
|
|
||||||
|
if (!newPointsFromHere.isEmpty()) {
|
||||||
|
boolean pointsAdded = false;
|
||||||
for (Point p : newPointsFromHere) {
|
for (Point p : newPointsFromHere) {
|
||||||
|
// is it worthwile going there?
|
||||||
|
if (p.value > 0) {
|
||||||
// create a new Path based on the current
|
// create a new Path based on the current
|
||||||
Path newPath = path.copy();
|
Path newPath = path.copy();
|
||||||
|
|
||||||
// add the new point
|
// add the new point
|
||||||
newPath.add(g, p);
|
newPath.add(g, p);
|
||||||
|
if (!takenPaths.contains(newPath)) {
|
||||||
// stop adding points once their value decreases
|
paths.add(newPath);
|
||||||
if (p.value < max) {
|
takenPaths.add(newPath);
|
||||||
break;
|
pointsAdded = true;
|
||||||
|
System.out.println("add " + newPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pointsAdded) {
|
||||||
|
//evict
|
||||||
|
Path ended = paths.poll();
|
||||||
|
if (ended != null && ended.value() > max.value()) {
|
||||||
|
max = ended;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -90,12 +130,12 @@ public class BestPathFinder {
|
||||||
*/
|
*/
|
||||||
private static double getValueFromGrid(Grid grid, Path path, int x, int y) {
|
private static double getValueFromGrid(Grid grid, Path path, int x, int y) {
|
||||||
int gridValue = grid.get(x, y);
|
int gridValue = grid.get(x, y);
|
||||||
if (path.hasPoint(x, y)) {
|
if (path.hasPoint(grid, x, y)) {
|
||||||
// been there
|
// been there
|
||||||
int distanceInPath = path.getDistanceInPath(x, y);
|
int distanceInPath = path.getDistanceInPath(x, y);
|
||||||
double increment = gridValue / timeDistanceFactor;
|
double increment = gridValue * timeDistanceFactor;
|
||||||
|
|
||||||
return Math.max((distanceInPath - 1) * increment, gridValue);
|
return Math.min((distanceInPath - 1) * increment, gridValue);
|
||||||
} else {
|
} else {
|
||||||
return gridValue;
|
return gridValue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package assessment;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Path implements Comparable<Path> {
|
public class Path implements Comparable<Path> {
|
||||||
// beide bevatten de al afgelegde punten
|
// beide bevatten de al afgelegde punten
|
||||||
|
|
@ -15,9 +16,10 @@ public class Path implements Comparable<Path> {
|
||||||
private Path() {
|
private Path() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// meh row/col vs x/y
|
||||||
static Path newPath(Grid g, int x, int y) {
|
static Path newPath(Grid g, int x, int y) {
|
||||||
Path p = new Path();
|
Path p = new Path();
|
||||||
newPath(g, x, y);
|
p.add(g, new Point(x, y, g.get(y, x)));
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,34 +32,61 @@ public class Path implements Comparable<Path> {
|
||||||
return points.stream().mapToDouble(point -> point.value).sum();
|
return points.stream().mapToDouble(point -> point.value).sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compare descending, highest value first
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Path o) {
|
public int compareTo(Path o) {
|
||||||
return this.value().compareTo(o.value());
|
return -this.value().compareTo(o.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int length() {
|
public int length() {
|
||||||
return points.size();
|
return points.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasPoint(int x, int y) {
|
public Point getHead() {
|
||||||
return trodden.contains(x * y);
|
return points.get(points.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasPoint(Grid g, int x, int y) {
|
||||||
|
return trodden.contains(y * g.getWidth() + x);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getDistanceInPath(int x, int y) {
|
int getDistanceInPath(int x, int y) {
|
||||||
for (int i = points.size() - 1; i >= 0; i++) {
|
if (points.isEmpty()) {
|
||||||
if (points.get(i).x == x && points.get(i).y == y) {
|
return -1;
|
||||||
|
}
|
||||||
|
for (int i = points.size() - 1; i >= 0; i--) {
|
||||||
|
Point p = points.get(i);
|
||||||
|
if (p.x == x && p.y == y) {
|
||||||
return points.size() - i;
|
return points.size() - i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Path copy(){
|
public Path copy() {
|
||||||
Path p = new Path();
|
Path p = new Path();
|
||||||
p.points.addAll(points);
|
p.points.addAll(points);
|
||||||
p.trodden.addAll(trodden);
|
p.trodden.addAll(trodden);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "P:" + points + ":" + value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Path path = (Path) o;
|
||||||
|
return Objects.equals(points, path.points);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(points);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package assessment;
|
package assessment;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Point implements Comparable<Point> {
|
public class Point implements Comparable<Point> {
|
||||||
|
|
||||||
final int x;
|
final int x;
|
||||||
|
|
@ -16,4 +18,23 @@ public class Point implements Comparable<Point> {
|
||||||
public int compareTo(Point that) {
|
public int compareTo(Point that) {
|
||||||
return -Double.compare(this.value, that.value);
|
return -Double.compare(this.value, that.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
// return "(" + x + "," + y + ")";
|
||||||
|
return "(" + x + "," + y + ":" + value + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Point point = (Point) o;
|
||||||
|
return x == point.x && y == point.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ public class PathFinderTest {
|
||||||
@Test
|
@Test
|
||||||
public void testBestPath() {
|
public void testBestPath() {
|
||||||
Grid grid = Grid.fromFile("grids/20.txt");
|
Grid grid = Grid.fromFile("grids/20.txt");
|
||||||
Path path = BestPathFinder.findMaxValPath(grid, 20, 10, 1000, 9, 9);
|
Path path = BestPathFinder.findMaxValPath(grid, 20, 3, 1000, 9, 9);
|
||||||
System.out.println(path);
|
System.out.println(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue