diff --git a/CCSPiJ/src/chapter1/CompressedGene.java b/CCSPiJ/src/chapter1/CompressedGene.java index 5c51ceb..fc209fe 100644 --- a/CCSPiJ/src/chapter1/CompressedGene.java +++ b/CCSPiJ/src/chapter1/CompressedGene.java @@ -64,7 +64,7 @@ public String decompress() { return ""; } // create a mutable place for characters with right capacity - StringBuilder builder = new StringBuilder(length); + StringBuilder builder = new StringBuilder(length / 2); for (int i = 0; i < (length * 2); i += 2) { final int firstBit = (bitSet.get(i) ? 1 : 0); final int secondBit = (bitSet.get(i + 1) ? 1 : 0); diff --git a/CCSPiJ/src/chapter1/Hanoi.java b/CCSPiJ/src/chapter1/Hanoi.java index 5fb8c6d..5512e8d 100644 --- a/CCSPiJ/src/chapter1/Hanoi.java +++ b/CCSPiJ/src/chapter1/Hanoi.java @@ -17,6 +17,8 @@ package chapter1; import java.util.Stack; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class Hanoi { private final int numDiscs; @@ -27,13 +29,16 @@ public class Hanoi { public Hanoi(int discs) { numDiscs = discs; for (int i = 1; i <= discs; i++) { - towerA.push(i); + towerA.push(Integer.valueOf(i)); } } private void move(Stack begin, Stack end, Stack temp, int n) { if (n == 1) { end.push(begin.pop()); + System.out.println(Stream.of(towerA, towerB, towerC) + .map(Stack::toString) + .collect(Collectors.joining(" "))); } else { move(begin, temp, end, n - 1); move(begin, end, temp, 1); diff --git a/CCSPiJ/src/chapter2/Gene.java b/CCSPiJ/src/chapter2/Gene.java index a8457e4..022eef7 100644 --- a/CCSPiJ/src/chapter2/Gene.java +++ b/CCSPiJ/src/chapter2/Gene.java @@ -49,7 +49,7 @@ public int compareTo(Codon other) { private ArrayList codons = new ArrayList<>(); public Gene(String geneStr) { - for (int i = 0; i < geneStr.length() - 3; i += 3) { + for (int i = 0; i < geneStr.length() - 3; i++) { // Take every 3 characters in the String and form a Codon codons.add(new Codon(geneStr.substring(i, i + 3))); } diff --git a/CCSPiJ/src/chapter2/GenericSearch.java b/CCSPiJ/src/chapter2/GenericSearch.java index 97d1cb7..1b5e3df 100644 --- a/CCSPiJ/src/chapter2/GenericSearch.java +++ b/CCSPiJ/src/chapter2/GenericSearch.java @@ -32,7 +32,7 @@ public class GenericSearch { - public static > boolean linearContains(List list, T key) { + public static > boolean linearContains(List list, T key) { for (T item : list) { if (item.compareTo(key) == 0) { return true; // found a match @@ -42,7 +42,7 @@ public static > boolean linearContains(List list, T k } // assumes *list* is already sorted - public static > boolean binaryContains(List list, T key) { + public static > boolean binaryContains(List list, T key) { int low = 0; int high = list.size() - 1; while (low <= high) { // while there is still a search space diff --git a/CCSPiJ/src/chapter3/MapColoringConstraint.java b/CCSPiJ/src/chapter3/MapColoringConstraint.java index 0cde5ba..f7a2dc0 100644 --- a/CCSPiJ/src/chapter3/MapColoringConstraint.java +++ b/CCSPiJ/src/chapter3/MapColoringConstraint.java @@ -21,6 +21,15 @@ import java.util.Map; public final class MapColoringConstraint extends Constraint { + + private static final String WESTERN = "Western Australia"; + private static final String NORTHERN = "Northern Territory"; + private static final String SOUTH = "South Australia"; + private static final String QUEENSLAND = "Queensland"; + private static final String NEW_SOUTH_WALES = "New South Wales"; + private static final String VICTORIA = "Victoria"; + private static final String TASMANIA = "Tasmania"; + private String place1, place2; public MapColoringConstraint(String place1, String place2) { @@ -42,23 +51,23 @@ public boolean satisfied(Map assignment) { } public static void main(String[] args) { - List variables = List.of("Western Australia", "Northern Territory", - "South Australia", "Queensland", "New South Wales", "Victoria", "Tasmania"); + List variables = List.of(WESTERN, NORTHERN, SOUTH, QUEENSLAND, + NEW_SOUTH_WALES, VICTORIA, TASMANIA); Map> domains = new HashMap<>(); for (String variable : variables) { domains.put(variable, List.of("red", "green", "blue")); } CSP csp = new CSP<>(variables, domains); - csp.addConstraint(new MapColoringConstraint("Western Australia", "Northern Territory")); - csp.addConstraint(new MapColoringConstraint("Western Australia", "South Australia")); - csp.addConstraint(new MapColoringConstraint("South Australia", "Northern Territory")); - csp.addConstraint(new MapColoringConstraint("Queensland", "Northern Territory")); - csp.addConstraint(new MapColoringConstraint("Queensland", "South Australia")); - csp.addConstraint(new MapColoringConstraint("Queensland", "New South Wales")); - csp.addConstraint(new MapColoringConstraint("New South Wales", "South Australia")); - csp.addConstraint(new MapColoringConstraint("Victoria", "South Australia")); - csp.addConstraint(new MapColoringConstraint("Victoria", "New South Wales")); - csp.addConstraint(new MapColoringConstraint("Victoria", "Tasmania")); + csp.addConstraint(new MapColoringConstraint(WESTERN, NORTHERN)); + csp.addConstraint(new MapColoringConstraint(WESTERN, SOUTH)); + csp.addConstraint(new MapColoringConstraint(SOUTH, NORTHERN)); + csp.addConstraint(new MapColoringConstraint(QUEENSLAND, NORTHERN)); + csp.addConstraint(new MapColoringConstraint(QUEENSLAND, SOUTH)); + csp.addConstraint(new MapColoringConstraint(QUEENSLAND, NEW_SOUTH_WALES)); + csp.addConstraint(new MapColoringConstraint(NEW_SOUTH_WALES, SOUTH)); + csp.addConstraint(new MapColoringConstraint(VICTORIA, SOUTH)); + csp.addConstraint(new MapColoringConstraint(VICTORIA, NEW_SOUTH_WALES)); + csp.addConstraint(new MapColoringConstraint(VICTORIA, TASMANIA)); Map solution = csp.backtrackingSearch(); if (solution == null) { System.out.println("No solution found!"); diff --git a/CCSPiJ/src/chapter3/SendMoreMoneyConstraint.java b/CCSPiJ/src/chapter3/SendMoreMoneyConstraint.java index a632ed5..fb471c2 100644 --- a/CCSPiJ/src/chapter3/SendMoreMoneyConstraint.java +++ b/CCSPiJ/src/chapter3/SendMoreMoneyConstraint.java @@ -39,10 +39,18 @@ public boolean satisfied(Map assignment) { // if all variables have been assigned, check if it adds correctly if (assignment.size() == letters.size()) { int s = assignment.get('S'); + // so we don't get answers starting with a 0 + if (s == 0) { + return false; + } int e = assignment.get('E'); int n = assignment.get('N'); int d = assignment.get('D'); int m = assignment.get('M'); + // so we don't get answers starting with a 0 + if (m == 0) { + return false; + } int o = assignment.get('O'); int r = assignment.get('R'); int y = assignment.get('Y'); @@ -60,8 +68,6 @@ public static void main(String[] args) { for (Character letter : letters) { possibleDigits.put(letter, List.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); } - // so we don't get answers starting with a 0 - possibleDigits.replace('M', List.of(1)); CSP csp = new CSP<>(letters, possibleDigits); csp.addConstraint(new SendMoreMoneyConstraint(letters)); Map solution = csp.backtrackingSearch(); diff --git a/CCSPiJ/src/chapter4/Cities.java b/CCSPiJ/src/chapter4/Cities.java new file mode 100644 index 0000000..3b9da12 --- /dev/null +++ b/CCSPiJ/src/chapter4/Cities.java @@ -0,0 +1,69 @@ +package chapter4; + +import java.util.List; + +public interface Cities { + + String SEATTLE = "Seattle"; + String SAN_FRANCISCO = "San Francisco"; + String LOS_ANGELES = "Los Angeles"; + String RIVERSIDE = "Riverside"; + String PHOENIX = "Phoenix"; + String CHICAGO = "Chicago"; + String BOSTON = "Boston"; + String NEW_YORK = "New York"; + String ATLANTA = "Atlanta"; + String MIAMI = "Miami"; + String DALLAS = "Dallas"; + String HOUSTON = "Houston"; + String DETROIT = "Detroit"; + String PHILADELPHIA = "Philadelphia"; + String WASHINGTON = "Washington"; + + List CITIES = List.of( + SEATTLE, SAN_FRANCISCO, LOS_ANGELES, RIVERSIDE, PHOENIX, + CHICAGO, BOSTON, NEW_YORK, ATLANTA, MIAMI, + DALLAS, HOUSTON, DETROIT, PHILADELPHIA, WASHINGTON + ); + + class Route { + public final String city1; + public final String city2; + public final float distance; + + public Route(String city1, String city2, float distance) { + this.city1 = city1; + this.city2 = city2; + this.distance = distance; + } + } + + List ROUTES = List.of( + new Route(SEATTLE, CHICAGO, 1737), + new Route(SEATTLE, SAN_FRANCISCO, 678), + new Route(SAN_FRANCISCO, RIVERSIDE, 386), + new Route(SAN_FRANCISCO, LOS_ANGELES, 348), + new Route(LOS_ANGELES, RIVERSIDE, 50), + new Route(LOS_ANGELES, PHOENIX, 357), + new Route(RIVERSIDE, PHOENIX, 307), + new Route(RIVERSIDE, CHICAGO, 1704), + new Route(PHOENIX, DALLAS, 887), + new Route(PHOENIX, HOUSTON, 1015), + new Route(DALLAS, CHICAGO, 805), + new Route(DALLAS, ATLANTA, 721), + new Route(DALLAS, HOUSTON, 225), + new Route(HOUSTON, ATLANTA, 702), + new Route(HOUSTON, MIAMI, 968), + new Route(ATLANTA, CHICAGO, 588), + new Route(ATLANTA, WASHINGTON, 543), + new Route(ATLANTA, MIAMI, 604), + new Route(MIAMI, WASHINGTON, 923), + new Route(CHICAGO, DETROIT, 238), + new Route(DETROIT, BOSTON, 613), + new Route(DETROIT, WASHINGTON, 396), + new Route(DETROIT, NEW_YORK, 482), + new Route(BOSTON, NEW_YORK, 190), + new Route(NEW_YORK, PHILADELPHIA, 81), + new Route(PHILADELPHIA, WASHINGTON, 123) + ); +} diff --git a/CCSPiJ/src/chapter4/UnweightedGraph.java b/CCSPiJ/src/chapter4/UnweightedGraph.java index 7fc6cf3..baf081f 100644 --- a/CCSPiJ/src/chapter4/UnweightedGraph.java +++ b/CCSPiJ/src/chapter4/UnweightedGraph.java @@ -21,7 +21,7 @@ import chapter2.GenericSearch; import chapter2.GenericSearch.Node; -public class UnweightedGraph extends Graph { +public class UnweightedGraph extends Graph implements Cities { public UnweightedGraph(List vertices) { super(vertices); @@ -47,40 +47,15 @@ public void addEdge(V first, V second) { // Test basic Graph construction public static void main(String[] args) { // Represents the 15 largest MSAs in the United States - UnweightedGraph cityGraph = new UnweightedGraph<>( - List.of("Seattle", "San Francisco", "Los Angeles", "Riverside", "Phoenix", "Chicago", "Boston", - "New York", "Atlanta", "Miami", "Dallas", "Houston", "Detroit", "Philadelphia", "Washington")); + UnweightedGraph cityGraph = new UnweightedGraph<>(CITIES); - cityGraph.addEdge("Seattle", "Chicago"); - cityGraph.addEdge("Seattle", "San Francisco"); - cityGraph.addEdge("San Francisco", "Riverside"); - cityGraph.addEdge("San Francisco", "Los Angeles"); - cityGraph.addEdge("Los Angeles", "Riverside"); - cityGraph.addEdge("Los Angeles", "Phoenix"); - cityGraph.addEdge("Riverside", "Phoenix"); - cityGraph.addEdge("Riverside", "Chicago"); - cityGraph.addEdge("Phoenix", "Dallas"); - cityGraph.addEdge("Phoenix", "Houston"); - cityGraph.addEdge("Dallas", "Chicago"); - cityGraph.addEdge("Dallas", "Atlanta"); - cityGraph.addEdge("Dallas", "Houston"); - cityGraph.addEdge("Houston", "Atlanta"); - cityGraph.addEdge("Houston", "Miami"); - cityGraph.addEdge("Atlanta", "Chicago"); - cityGraph.addEdge("Atlanta", "Washington"); - cityGraph.addEdge("Atlanta", "Miami"); - cityGraph.addEdge("Miami", "Washington"); - cityGraph.addEdge("Chicago", "Detroit"); - cityGraph.addEdge("Detroit", "Boston"); - cityGraph.addEdge("Detroit", "Washington"); - cityGraph.addEdge("Detroit", "New York"); - cityGraph.addEdge("Boston", "New York"); - cityGraph.addEdge("New York", "Philadelphia"); - cityGraph.addEdge("Philadelphia", "Washington"); - System.out.println(cityGraph.toString()); + for (Route route : ROUTES) { + cityGraph.addEdge(route.city1, route.city2); + } + System.out.println(cityGraph); - Node bfsResult = GenericSearch.bfs("Boston", - v -> v.equals("Miami"), + Node bfsResult = GenericSearch.bfs(BOSTON, + v -> v.equals(MIAMI), cityGraph::neighborsOf); if (bfsResult == null) { System.out.println("No solution found using breadth-first search!"); diff --git a/CCSPiJ/src/chapter4/WeightedGraph.java b/CCSPiJ/src/chapter4/WeightedGraph.java index 8e19b1b..eb3e49a 100644 --- a/CCSPiJ/src/chapter4/WeightedGraph.java +++ b/CCSPiJ/src/chapter4/WeightedGraph.java @@ -25,7 +25,7 @@ import java.util.PriorityQueue; import java.util.function.IntConsumer; -public class WeightedGraph extends Graph { +public class WeightedGraph extends Graph implements Cities { public WeightedGraph(List vertices) { super(vertices); @@ -199,36 +199,11 @@ public static List pathMapToPath(int start, int end, Map cityGraph2 = new WeightedGraph<>( - List.of("Seattle", "San Francisco", "Los Angeles", "Riverside", "Phoenix", "Chicago", "Boston", - "New York", "Atlanta", "Miami", "Dallas", "Houston", "Detroit", "Philadelphia", "Washington")); - - cityGraph2.addEdge("Seattle", "Chicago", 1737); - cityGraph2.addEdge("Seattle", "San Francisco", 678); - cityGraph2.addEdge("San Francisco", "Riverside", 386); - cityGraph2.addEdge("San Francisco", "Los Angeles", 348); - cityGraph2.addEdge("Los Angeles", "Riverside", 50); - cityGraph2.addEdge("Los Angeles", "Phoenix", 357); - cityGraph2.addEdge("Riverside", "Phoenix", 307); - cityGraph2.addEdge("Riverside", "Chicago", 1704); - cityGraph2.addEdge("Phoenix", "Dallas", 887); - cityGraph2.addEdge("Phoenix", "Houston", 1015); - cityGraph2.addEdge("Dallas", "Chicago", 805); - cityGraph2.addEdge("Dallas", "Atlanta", 721); - cityGraph2.addEdge("Dallas", "Houston", 225); - cityGraph2.addEdge("Houston", "Atlanta", 702); - cityGraph2.addEdge("Houston", "Miami", 968); - cityGraph2.addEdge("Atlanta", "Chicago", 588); - cityGraph2.addEdge("Atlanta", "Washington", 543); - cityGraph2.addEdge("Atlanta", "Miami", 604); - cityGraph2.addEdge("Miami", "Washington", 923); - cityGraph2.addEdge("Chicago", "Detroit", 238); - cityGraph2.addEdge("Detroit", "Boston", 613); - cityGraph2.addEdge("Detroit", "Washington", 396); - cityGraph2.addEdge("Detroit", "New York", 482); - cityGraph2.addEdge("Boston", "New York", 190); - cityGraph2.addEdge("New York", "Philadelphia", 81); - cityGraph2.addEdge("Philadelphia", "Washington", 123); + WeightedGraph cityGraph2 = new WeightedGraph<>(CITIES); + + for (Route route : ROUTES) { + cityGraph2.addEdge(route.city1, route.city2, route.distance); + } System.out.println(cityGraph2); @@ -237,7 +212,7 @@ public static void main(String[] args) { System.out.println(); // spacing - DijkstraResult dijkstraResult = cityGraph2.dijkstra("Los Angeles"); + DijkstraResult dijkstraResult = cityGraph2.dijkstra(LOS_ANGELES); Map nameDistance = cityGraph2.distanceArrayToDistanceMap(dijkstraResult.distances); System.out.println("Distances from Los Angeles:"); nameDistance.forEach((name, distance) -> System.out.println(name + " : " + distance)); @@ -245,7 +220,7 @@ public static void main(String[] args) { System.out.println(); // spacing System.out.println("Shortest path from Los Angeles to Boston:"); - List path = pathMapToPath(cityGraph2.indexOf("Los Angeles"), cityGraph2.indexOf("Boston"), + List path = pathMapToPath(cityGraph2.indexOf(LOS_ANGELES), cityGraph2.indexOf(BOSTON), dijkstraResult.pathMap); cityGraph2.printWeightedPath(path); } diff --git a/CCSPiJ/src/chapter6/KMeans.java b/CCSPiJ/src/chapter6/KMeans.java index f55b877..0208335 100644 --- a/CCSPiJ/src/chapter6/KMeans.java +++ b/CCSPiJ/src/chapter6/KMeans.java @@ -85,7 +85,7 @@ private DataPoint randomPoint() { for (int dimension = 0; dimension < points.get(0).numDimensions; dimension++) { List values = dimensionSlice(dimension); Statistics stats = new Statistics(values); - Double randValue = random.doubles(stats.min(), stats.max()).findFirst().getAsDouble(); + Double randValue = stats.min() + random.nextDouble() * (stats.max() - stats.min()); randDimensions.add(randValue); } return new DataPoint(randDimensions); diff --git a/CCSPiJ/src/chapter8/C4Piece.java b/CCSPiJ/src/chapter8/C4Piece.java index 8a82f87..59b8055 100644 --- a/CCSPiJ/src/chapter8/C4Piece.java +++ b/CCSPiJ/src/chapter8/C4Piece.java @@ -17,31 +17,31 @@ package chapter8; public enum C4Piece implements Piece { - B, R, E; // E is Empty + B("B"), + R("R"), + E(" "); // E is Empty + + private String code; + private C4Piece opposite; + + static { + B.opposite = R; + R.opposite = B; + E.opposite = E; + } + + private C4Piece(String c) { + code = c; + } @Override public C4Piece opposite() { - switch (this) { - case B: - return C4Piece.R; - case R: - return C4Piece.B; - default: // E, empty - return C4Piece.E; - } + return opposite; } @Override public String toString() { - switch (this) { - case B: - return "B"; - case R: - return "R"; - default: // E, empty - return " "; - } - + return code; } } diff --git a/CCSPiJ/src/chapter8/TTTMinimaxTests.java b/CCSPiJ/src/chapter8/TTTMinimaxTests.java index 1366a11..97b8f9f 100644 --- a/CCSPiJ/src/chapter8/TTTMinimaxTests.java +++ b/CCSPiJ/src/chapter8/TTTMinimaxTests.java @@ -19,6 +19,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; +import java.util.Objects; // Annotation for unit tests @Retention(RetentionPolicy.RUNTIME) @@ -30,7 +31,7 @@ public class TTTMinimaxTests { // Check if two values are equal and report back public static void assertEquality(T actual, T expected) { - if (actual.equals(expected)) { + if (Objects.equals(actual, expected)) { System.out.println("Passed!"); } else { System.out.println("Failed!"); diff --git a/CCSPiJ/src/chapter8/TTTPiece.java b/CCSPiJ/src/chapter8/TTTPiece.java index 8e48a31..a5cd113 100644 --- a/CCSPiJ/src/chapter8/TTTPiece.java +++ b/CCSPiJ/src/chapter8/TTTPiece.java @@ -17,31 +17,31 @@ package chapter8; public enum TTTPiece implements Piece { - X, O, E; // E is Empty + X("X"), + O("O"), + E(" "); // E is Empty + + private String code; + private TTTPiece opposite; + + static { + X.opposite = O; + O.opposite = X; + E.opposite = E; + } + + private TTTPiece(String c) { + code = c; + } @Override public TTTPiece opposite() { - switch (this) { - case X: - return TTTPiece.O; - case O: - return TTTPiece.X; - default: // E, empty - return TTTPiece.E; - } + return opposite; } @Override public String toString() { - switch (this) { - case X: - return "X"; - case O: - return "O"; - default: // E, empty - return " "; - } - + return code; } } diff --git a/CCSPiJ/src/chapter9/TSP.java b/CCSPiJ/src/chapter9/TSP.java index 65a9910..dbd1573 100644 --- a/CCSPiJ/src/chapter9/TSP.java +++ b/CCSPiJ/src/chapter9/TSP.java @@ -18,10 +18,18 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Stream; public class TSP { + private static final String RUTLAND = "Rutland"; + private static final String BURLINGTON = "Burlington"; + private static final String WHITE_RIVER_JUNCTION = "White River Junction"; + private static final String BENNINGTON = "Bennington"; + private static final String BRATTLEBORO = "Brattleboro"; + private final Map> distances; public TSP(Map> distances) { @@ -87,37 +95,31 @@ public String[] findShortestPath() { return shortestPath; } + private static void addDistance(Map> vtDistances, + String city1, String city2, int distance) { + vtDistances.get(city1).put(city2, distance); + vtDistances.get(city2).put(city1, distance); + } + public static void main(String[] args) { - Map> vtDistances = Map.of( - "Rutland", Map.of( - "Burlington", 67, - "White River Junction", 46, - "Bennington", 55, - "Brattleboro", 75), - "Burlington", Map.of( - "Rutland", 67, - "White River Junction", 91, - "Bennington", 122, - "Brattleboro", 153), - "White River Junction", Map.of( - "Rutland", 46, - "Burlington", 91, - "Bennington", 98, - "Brattleboro", 65), - "Bennington", Map.of( - "Rutland", 55, - "Burlington", 122, - "White River Junction", 98, - "Brattleboro", 40), - "Brattleboro", Map.of( - "Rutland", 75, - "Burlington", 153, - "White River Junction", 65, - "Bennington", 40)); + Map> vtDistances = new HashMap<>(); + Stream.of(RUTLAND, BURLINGTON, WHITE_RIVER_JUNCTION, BENNINGTON, BRATTLEBORO) + .forEach(city -> vtDistances.put(city, new HashMap<>())); + addDistance(vtDistances, RUTLAND, BURLINGTON, 67); + addDistance(vtDistances, RUTLAND, WHITE_RIVER_JUNCTION, 46); + addDistance(vtDistances, RUTLAND, BENNINGTON, 55); + addDistance(vtDistances, RUTLAND, BRATTLEBORO, 75); + addDistance(vtDistances, BURLINGTON, WHITE_RIVER_JUNCTION, 91); + addDistance(vtDistances, BURLINGTON, BENNINGTON, 122); + addDistance(vtDistances, BURLINGTON, BRATTLEBORO, 153); + addDistance(vtDistances, WHITE_RIVER_JUNCTION, BENNINGTON, 98); + addDistance(vtDistances, WHITE_RIVER_JUNCTION, BRATTLEBORO, 65); + addDistance(vtDistances, BENNINGTON, BRATTLEBORO, 40); + TSP tsp = new TSP(vtDistances); String[] shortestPath = tsp.findShortestPath(); int distance = tsp.pathDistance(shortestPath); - System.out.println("The shortest path is " + Arrays.toString(shortestPath) + " in " + - distance + " miles."); + System.out.printf("The shortest path is %s in %d miles.%n", + Arrays.toString(shortestPath), distance); } }