Checkstyle and additional test

This commit is contained in:
Arne Keller 2020-03-08 10:37:26 +01:00
parent f0b35e0707
commit a9348c4bdc
8 changed files with 87 additions and 88 deletions

View File

@ -134,6 +134,11 @@ class MainTest {
cmpInOut("fuzz12_input.txt", "fuzz12_output.txt"); cmpInOut("fuzz12_input.txt", "fuzz12_output.txt");
} }
@Test
void test13() throws IOException {
cmpInOut("test13_input.txt", "test13_output.txt");
}
private void cmpInOut(String in, String out) throws IOException { private void cmpInOut(String in, String out) throws IOException {
System.setIn(new ByteArrayInputStream(readFile(in))); System.setIn(new ByteArrayInputStream(readFile(in)));
ByteArrayOutputStream output = new ByteArrayOutputStream(); ByteArrayOutputStream output = new ByteArrayOutputStream();

View File

@ -198,8 +198,8 @@ public class RailwayNetwork {
} else if (touchingRails.length == 1) { // simply move along the rail } else if (touchingRails.length == 1) { // simply move along the rail
return touchingRails[0].move(position, direction, 1); return touchingRails[0].move(position, direction, 1);
} // else: check movement along both rails and pick the correct rail } // else: check movement along both rails and pick the correct rail
final Vector2D onRailOne = touchingRails[0].move(position, new Vector2D(direction), steps); final Vector2D onRailOne = touchingRails[0].move(position, direction, steps);
final Vector2D onRailTwo = touchingRails[1].move(position, new Vector2D(direction), steps); final Vector2D onRailTwo = touchingRails[1].move(position, direction, steps);
// if we are stuck on the first rail // if we are stuck on the first rail
// or derail on the first rail // or derail on the first rail
// or move in the correct direction on the second rail // or move in the correct direction on the second rail

View File

@ -153,6 +153,6 @@ public final class Switch extends Rail {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(positionOne, positionTwo, selection); return Objects.hash(positionOne, positionTwo);
} }
} }

View File

@ -78,9 +78,9 @@ public final class Track extends Rail {
if (contains(nextPosition) || connectsTo(nextPosition)) { if (contains(nextPosition) || connectsTo(nextPosition)) {
return nextPosition; return nextPosition;
} else if (direction.equals(getDirectionFrom(start))) { } else if (direction.equals(getDirectionFrom(start))) {
return new Vector2D(end); return end;
} else if (direction.equals(getDirectionFrom(end))) { } else if (direction.equals(getDirectionFrom(end))) {
return new Vector2D(start); return start;
} else if (position.equals(end) && !direction.equals(getDirectionFrom(start))) { } else if (position.equals(end) && !direction.equals(getDirectionFrom(start))) {
return move(position, getDirectionFrom(end), steps); return move(position, getDirectionFrom(end), steps);
} else if (position.equals(start) && !direction.equals(getDirectionFrom(end))) { } else if (position.equals(start) && !direction.equals(getDirectionFrom(end))) {
@ -119,7 +119,7 @@ public final class Track extends Rail {
* @return start position of this track * @return start position of this track
*/ */
public Vector2D getStart() { public Vector2D getStart() {
return new Vector2D(start); return start;
} }
/** /**
@ -128,7 +128,7 @@ public final class Track extends Rail {
* @return end position of this track * @return end position of this track
*/ */
public Vector2D getEnd() { public Vector2D getEnd() {
return new Vector2D(end); return end;
} }
@Override @Override

View File

@ -8,7 +8,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -181,19 +180,17 @@ public final class Train implements Comparable<Train> {
} }
/** /**
* @return position of the train head * @return position of the front of the train
*/ */
public Vector2D getFrontPosition() { public Vector2D getFrontPosition() {
// make sure caller can not modify internal data return positions != null ? positions.getFirst() : null;
return positions != null ? new Vector2D(positions.getFirst()) : null;
} }
/** /**
* @return position of the rear of the train * @return position of the back of the train
*/ */
public Vector2D getRearPosition() { public Vector2D getRearPosition() {
// make sure caller can not modify internal data return positions != null ? positions.getLast() : null;
return positions != null ? new Vector2D(positions.getLast()) : null;
} }
/** /**
@ -217,7 +214,8 @@ public final class Train implements Comparable<Train> {
* @return a set of the rails this train occupies * @return a set of the rails this train occupies
*/ */
public Set<Rail> getOccupiedRails() { public Set<Rail> getOccupiedRails() {
// make sure caller can not modify internal state // need a copy (not a view) because the set will be modified when moving,
// but caller expects *current* state, not some updating state
return new HashSet<>(occupiedRails); return new HashSet<>(occupiedRails);
} }
@ -229,17 +227,14 @@ public final class Train implements Comparable<Train> {
*/ */
public void moveTo(RailwayNetwork railNetwork, Vector2D nextPosition) { public void moveTo(RailwayNetwork railNetwork, Vector2D nextPosition) {
final Optional<Rail> railUnderBackOfTrain = railNetwork.findContainingRail(positions.getLast()); final Optional<Rail> railUnderBackOfTrain = railNetwork.findContainingRail(positions.getLast());
positions.getLast().subtractInPlace(getRearDirection()); positions.set(positions.size() - 1, positions.getLast().subtract(getRearDirection()));
if (positions.getLast().equals(positions.get(positions.size() - 2))) { if (positions.getLast().equals(positions.get(positions.size() - 2))) { // left a rail behind
if (!railNetwork.findContainingRail(nextPosition).equals(railUnderBackOfTrain)
|| nextPosition == null) {
occupiedRails.remove(railUnderBackOfTrain.orElse(null)); occupiedRails.remove(railUnderBackOfTrain.orElse(null));
}
positions.removeLast(); positions.removeLast();
} }
if (nextPosition != null) { if (nextPosition != null) {
// not derailing // not derailing
positions.addFirst(new Vector2D(nextPosition)); positions.addFirst(nextPosition);
simplifyPositions(railNetwork); simplifyPositions(railNetwork);
occupiedRails.add(railNetwork.findRail(positions.get(1), nextPosition).get()); occupiedRails.add(railNetwork.findRail(positions.get(1), nextPosition).get());
} // else: derailing } // else: derailing
@ -255,24 +250,22 @@ public final class Train implements Comparable<Train> {
public void moveBackTo(RailwayNetwork railNetwork, Vector2D backPosition) { public void moveBackTo(RailwayNetwork railNetwork, Vector2D backPosition) {
// a common method for both directions would be a huge mess: requires at least six (!) extra parameters // a common method for both directions would be a huge mess: requires at least six (!) extra parameters
final Optional<Rail> railUnderFrontOfTrain = railNetwork.findContainingRail(positions.getFirst()); final Optional<Rail> railUnderFrontOfTrain = railNetwork.findContainingRail(positions.getFirst());
positions.getFirst().subtractInPlace(getDirection()); positions.set(0, positions.getFirst().subtract(getDirection()));
if (positions.getFirst().equals(positions.get(1))) { if (positions.getFirst().equals(positions.get(1))) { // left a rail behind
if (!railNetwork.findContainingRail(backPosition).equals(railUnderFrontOfTrain)
|| backPosition == null) {
occupiedRails.remove(railUnderFrontOfTrain.orElse(null)); occupiedRails.remove(railUnderFrontOfTrain.orElse(null));
}
positions.removeFirst(); positions.removeFirst();
} }
if (backPosition != null) { if (backPosition != null) {
// not derailing // not derailing
positions.addLast(new Vector2D(backPosition)); positions.addLast(backPosition);
simplifyPositions(railNetwork); simplifyPositions(railNetwork);
occupiedRails.add(railNetwork.findRail(positions.get(positions.size() - 2), backPosition).get()); occupiedRails.add(railNetwork.findRail(positions.get(positions.size() - 2), backPosition).get());
} // else: derailing } // else: derailing
} }
/** /**
* Simplify internal position data. Removes positions that are contained between two other positions. * Simplify internal position data.
* Removes positions that are contained between two other positions at the front or back of the train.
* *
* @param railNetwork railway network to use * @param railNetwork railway network to use
*/ */

View File

@ -4,19 +4,20 @@ import java.util.Objects;
/** /**
* A two-dimensional vector, usually a position or movement direction vector. * A two-dimensional vector, usually a position or movement direction vector.
* An object of this class is immutable.
* *
* @author Arne Keller * @author Arne Keller
* @version 1.0 * @version 1.1
*/ */
public class Vector2D { public class Vector2D {
/** /**
* First coordinate of the vector, usually referred to as 'x'. * First coordinate of the vector, usually referred to as 'x'.
*/ */
private long x; private final long x;
/** /**
* Second coordinate of the vector, usually referred to as 'y'. * Second coordinate of the vector, usually referred to as 'y'.
*/ */
private long y; private final long y;
/** /**
* Construct a new vector. * Construct a new vector.
@ -29,16 +30,6 @@ public class Vector2D {
this.y = y; this.y = y;
} }
/**
* Copy a vector, creating a new object.
*
* @param other a vector
*/
public Vector2D(Vector2D other) {
this.x = other.x;
this.y = other.y;
}
/** /**
* @param input two 32-bit numbers separated by a comma * @param input two 32-bit numbers separated by a comma
* @return a vector containing the two numbers, null otherwise * @return a vector containing the two numbers, null otherwise
@ -98,6 +89,40 @@ public class Vector2D {
|| y == 0 && y == other.y && Long.signum(x) == Long.signum(other.x); || y == 0 && y == other.y && Long.signum(x) == Long.signum(other.x);
} }
/**
* @param movement vector to add
* @return component-wise sum of this vector and the other vector
*/
public Vector2D add(Vector2D movement) {
return new Vector2D(x + movement.x, y + movement.y);
}
/**
* Subtract another vector from this one.
*
* @param other another vector
* @return the difference of this vector and the other vector
*/
public Vector2D subtract(Vector2D other) {
return new Vector2D(x - other.x, y - other.y);
}
/**
* @return (- 1) * this vector
*/
public Vector2D negated() {
return new Vector2D(-x, -y);
}
/**
* Calculate multiplier * this, and return a new vector.
*
* @param multiplier any scalar
* @return scaled vector
*/
public Vector2D scale(long multiplier) {
return new Vector2D(x * multiplier, y * multiplier);
}
/** /**
* Normalize this vector. Will essentially return a new vector with (x/|x|, y/|y|). * Normalize this vector. Will essentially return a new vector with (x/|x|, y/|y|).
@ -116,51 +141,6 @@ public class Vector2D {
} }
} }
/**
* @return (- 1) * this vector
*/
public Vector2D negated() {
return new Vector2D(-x, -y);
}
/**
* Subtract another vector from this one.
*
* @param other another vector
* @return the difference of this vector and the other vector
*/
public Vector2D subtract(Vector2D other) {
return new Vector2D(x - other.x, y - other.y);
}
/**
* Subtract another vector from this one, modifying this vector.
*
* @param other another vector
*/
public void subtractInPlace(Vector2D other) {
x -= other.x;
y -= other.y;
}
/**
* @param movement vector to add
* @return component-wise sum of this vector and the other vector
*/
public Vector2D add(Vector2D movement) {
return new Vector2D(x + movement.x, y + movement.y);
}
/**
* Calculate multiplier * this, and return a new vector.
*
* @param multiplier any scalar
* @return scaled vector
*/
public Vector2D scale(long multiplier) {
return new Vector2D(x * multiplier, y * multiplier);
}
/** /**
* @return the first component of this vector * @return the first component of this vector
*/ */

11
test13_input.txt Normal file
View File

@ -0,0 +1,11 @@
add track (0,0) -> (10,0)
add track (10,0) -> (20,0)
add track (20,0) -> (30,0)
create engine diesel T6 Lux 4 true true
create engine diesel T6 Lumen 4 true false
add train 1 T6-Lux
add train 2 T6-Lumen
put train 1 at (20,0) in direction 1,0
put train 2 at (8,0) in direction 1,0
step 3
exit

10
test13_output.txt Normal file
View File

@ -0,0 +1,10 @@
1
2
3
T6-Lux
T6-Lumen
diesel engine T6-Lux added to train 1
diesel engine T6-Lumen added to train 2
OK
OK
Crash of train 1,2