├── CCSPiJ ├── .gitignore ├── .classpath ├── .project ├── src │ ├── chapter8 │ │ ├── Piece.java │ │ ├── C4Location.java │ │ ├── Board.java │ │ ├── C4Piece.java │ │ ├── TTTPiece.java │ │ ├── TicTacToe.java │ │ ├── ConnectFour.java │ │ ├── TTTBoard.java │ │ ├── TTTMinimaxTests.java │ │ ├── Minimax.java │ │ └── C4Board.java │ ├── chapter1 │ │ ├── KeyPair.java │ │ ├── Fib2.java │ │ ├── Fib1.java │ │ ├── Fib4.java │ │ ├── Fib5.java │ │ ├── PiCalculator.java │ │ ├── Fib3.java │ │ ├── Hanoi.java │ │ ├── UnbreakableEncryption.java │ │ └── CompressedGene.java │ ├── chapter4 │ │ ├── Edge.java │ │ ├── WeightedEdge.java │ │ ├── Graph.java │ │ ├── UnweightedGraph.java │ │ └── WeightedGraph.java │ ├── chapter3 │ │ ├── Constraint.java │ │ ├── QueensConstraint.java │ │ ├── SendMoreMoneyConstraint.java │ │ ├── WordSearchConstraint.java │ │ ├── MapColoringConstraint.java │ │ ├── CSP.java │ │ └── WordGrid.java │ ├── chapter5 │ │ ├── Chromosome.java │ │ ├── SimpleEquation.java │ │ ├── ListCompression.java │ │ ├── SendMoreMoney2.java │ │ └── GeneticAlgorithm.java │ ├── chapter6 │ │ ├── DataPoint.java │ │ ├── Statistics.java │ │ ├── Album.java │ │ ├── Governor.java │ │ └── KMeans.java │ ├── chapter7 │ │ ├── Neuron.java │ │ ├── Layer.java │ │ ├── Util.java │ │ ├── WineTest.java │ │ ├── IrisTest.java │ │ ├── Network.java │ │ └── data │ │ │ ├── iris.csv │ │ │ └── wine.csv │ ├── chapter9 │ │ ├── PhoneNumberMnemonics.java │ │ ├── Knapsack.java │ │ └── TSP.java │ └── chapter2 │ │ ├── Gene.java │ │ ├── MCState.java │ │ ├── Maze.java │ │ └── GenericSearch.java └── .settings │ └── org.eclipse.jdt.core.prefs ├── cover.jpg ├── .gitignore ├── README.md └── LICENSE /CCSPiJ/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davecom/ClassicComputerScienceProblemsInJava/HEAD/cover.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | /.metadata/ 25 | 26 | .DS_STORE 27 | .metadata 28 | -------------------------------------------------------------------------------- /CCSPiJ/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CCSPiJ/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | CCSPiJ 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter8/Piece.java: -------------------------------------------------------------------------------- 1 | // Piece.java 2 | // From Classic Computer Science Problems in Java Chapter 8 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter8; 18 | 19 | public interface Piece { 20 | Piece opposite(); 21 | } 22 | -------------------------------------------------------------------------------- /CCSPiJ/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=11 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 12 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning 13 | org.eclipse.jdt.core.compiler.release=enabled 14 | org.eclipse.jdt.core.compiler.source=11 15 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter8/C4Location.java: -------------------------------------------------------------------------------- 1 | // C4Location.java 2 | // From Classic Computer Science Problems in Java Chapter 8 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter8; 18 | 19 | public final class C4Location { 20 | public final int column, row; 21 | 22 | public C4Location(int column, int row) { 23 | this.column = column; 24 | this.row = row; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter1/KeyPair.java: -------------------------------------------------------------------------------- 1 | // KeyPair.java 2 | // From Classic Computer Science Problems in Java Chapter 1 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter1; 18 | 19 | public final class KeyPair { 20 | public final byte[] key1; 21 | public final byte[] key2; 22 | 23 | KeyPair(byte[] key1, byte[] key2) { 24 | this.key1 = key1; 25 | this.key2 = key2; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter1/Fib2.java: -------------------------------------------------------------------------------- 1 | // Fib2.java 2 | // From Classic Computer Science Problems in Java Chapter 1 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter1; 18 | 19 | public class Fib2 { 20 | private static int fib2(int n) { 21 | if (n < 2) { 22 | return n; 23 | } 24 | return fib2(n - 1) + fib2(n - 2); 25 | } 26 | 27 | public static void main(String[] args) { 28 | System.out.println(fib2(5)); 29 | System.out.println(fib2(10)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter1/Fib1.java: -------------------------------------------------------------------------------- 1 | // Fib1.java 2 | // From Classic Computer Science Problems in Java Chapter 1 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter1; 18 | 19 | public class Fib1 { 20 | 21 | // This method will cause a java.lang.StackOverflowError 22 | private static int fib1(int n) { 23 | return fib1(n - 1) + fib1(n - 2); 24 | } 25 | 26 | public static void main(String[] args) { 27 | // Don't run this! 28 | System.out.println(fib1(5)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter8/Board.java: -------------------------------------------------------------------------------- 1 | // Board.java 2 | // From Classic Computer Science Problems in Java Chapter 8 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter8; 18 | 19 | import java.util.List; 20 | 21 | public interface Board { 22 | Piece getTurn(); 23 | 24 | Board move(Move location); 25 | 26 | List getLegalMoves(); 27 | 28 | boolean isWin(); 29 | 30 | default boolean isDraw() { 31 | return !isWin() && getLegalMoves().isEmpty(); 32 | } 33 | 34 | double evaluate(Piece player); 35 | } 36 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter4/Edge.java: -------------------------------------------------------------------------------- 1 | // Edge.java 2 | // From Classic Computer Science Problems in Java Chapter 4 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter4; 18 | 19 | public class Edge { 20 | public final int u; // the "from" vertex 21 | public final int v; // the "to" vertex 22 | 23 | public Edge(int u, int v) { 24 | this.u = u; 25 | this.v = v; 26 | } 27 | 28 | public Edge reversed() { 29 | return new Edge(v, u); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return u + " -> " + v; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter1/Fib4.java: -------------------------------------------------------------------------------- 1 | // Fib4.java 2 | // From Classic Computer Science Problems in Java Chapter 1 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter1; 18 | 19 | public class Fib4 { 20 | 21 | private static int fib4(int n) { 22 | int last = 0, next = 1; // fib(0), fib(1) 23 | for (int i = 0; i < n; i++) { 24 | int oldLast = last; 25 | last = next; 26 | next = oldLast + next; 27 | } 28 | return last; 29 | } 30 | 31 | public static void main(String[] args) { 32 | System.out.println(fib4(5)); 33 | System.out.println(fib4(40)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter3/Constraint.java: -------------------------------------------------------------------------------- 1 | // Constraint.java 2 | // From Classic Computer Science Problems in Java Chapter 3 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter3; 18 | 19 | import java.util.List; 20 | import java.util.Map; 21 | 22 | // V is the variable type, and D is the domain type 23 | public abstract class Constraint { 24 | 25 | // the variables that the constraint is between 26 | protected List variables; 27 | 28 | public Constraint(List variables) { 29 | this.variables = variables; 30 | } 31 | 32 | // must be overridden by subclasses 33 | public abstract boolean satisfied(Map assignment); 34 | } 35 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter1/Fib5.java: -------------------------------------------------------------------------------- 1 | // Fib5.java 2 | // From Classic Computer Science Problems in Java Chapter 1 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter1; 18 | 19 | import java.util.stream.IntStream; 20 | 21 | public class Fib5 { 22 | private int last = 0, next = 1; // fib(0), fib(1) 23 | 24 | public IntStream stream() { 25 | return IntStream.generate(() -> { 26 | int oldLast = last; 27 | last = next; 28 | next = oldLast + next; 29 | return oldLast; 30 | }); 31 | } 32 | 33 | public static void main(String[] args) { 34 | Fib5 fib5 = new Fib5(); 35 | fib5.stream().limit(41).forEachOrdered(System.out::println); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter5/Chromosome.java: -------------------------------------------------------------------------------- 1 | // Chromosome.java 2 | // From Classic Computer Science Problems in Java Chapter 5 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter5; 18 | 19 | import java.util.List; 20 | 21 | public abstract class Chromosome> implements Comparable { 22 | public abstract double fitness(); 23 | 24 | public abstract List crossover(T other); 25 | 26 | public abstract void mutate(); 27 | 28 | public abstract T copy(); 29 | 30 | @Override 31 | public int compareTo(T other) { 32 | Double mine = this.fitness(); 33 | Double theirs = other.fitness(); 34 | return mine.compareTo(theirs); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter1/PiCalculator.java: -------------------------------------------------------------------------------- 1 | // PiCalculator.java 2 | // From Classic Computer Science Problems in Java Chapter 1 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter1; 18 | 19 | public class PiCalculator { 20 | 21 | public static double calculatePi(int nTerms) { 22 | final double numerator = 4.0; 23 | double denominator = 1.0; 24 | double operation = 1.0; 25 | double pi = 0.0; 26 | for (int i = 0; i < nTerms; i++) { 27 | pi += operation * (numerator / denominator); 28 | denominator += 2.0; 29 | operation *= -1.0; 30 | } 31 | return pi; 32 | } 33 | 34 | public static void main(String[] args) { 35 | System.out.println(calculatePi(1000000)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter8/C4Piece.java: -------------------------------------------------------------------------------- 1 | // C4Piece.java 2 | // From Classic Computer Science Problems in Java Chapter 8 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter8; 18 | 19 | public enum C4Piece implements Piece { 20 | B, R, E; // E is Empty 21 | 22 | @Override 23 | public C4Piece opposite() { 24 | switch (this) { 25 | case B: 26 | return C4Piece.R; 27 | case R: 28 | return C4Piece.B; 29 | default: // E, empty 30 | return C4Piece.E; 31 | } 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | switch (this) { 37 | case B: 38 | return "B"; 39 | case R: 40 | return "R"; 41 | default: // E, empty 42 | return " "; 43 | } 44 | 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter8/TTTPiece.java: -------------------------------------------------------------------------------- 1 | // TTTPiece.java 2 | // From Classic Computer Science Problems in Java Chapter 8 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter8; 18 | 19 | public enum TTTPiece implements Piece { 20 | X, O, E; // E is Empty 21 | 22 | @Override 23 | public TTTPiece opposite() { 24 | switch (this) { 25 | case X: 26 | return TTTPiece.O; 27 | case O: 28 | return TTTPiece.X; 29 | default: // E, empty 30 | return TTTPiece.E; 31 | } 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | switch (this) { 37 | case X: 38 | return "X"; 39 | case O: 40 | return "O"; 41 | default: // E, empty 42 | return " "; 43 | } 44 | 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter1/Fib3.java: -------------------------------------------------------------------------------- 1 | // Fib3.java 2 | // From Classic Computer Science Problems in Java Chapter 1 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter1; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | @SuppressWarnings("boxing") 23 | public class Fib3 { 24 | 25 | // Map.of() was introduced in Java 9 but returns 26 | // an immutable Map 27 | // This creates a map with 0->0 and 1->1 28 | // Which represent our base cases 29 | static Map memo = new HashMap<>(Map.of(0, 0, 1, 1)); 30 | 31 | private static int fib3(int n) { 32 | if (!memo.containsKey(n)) { 33 | // memoization step 34 | memo.put(n, fib3(n - 1) + fib3(n - 2)); 35 | } 36 | return memo.get(n); 37 | } 38 | 39 | public static void main(String[] args) { 40 | System.out.println(fib3(5)); 41 | System.out.println(fib3(40)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter4/WeightedEdge.java: -------------------------------------------------------------------------------- 1 | // WeightedEdge.java 2 | // From Classic Computer Science Problems in Java Chapter 4 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter4; 18 | 19 | public class WeightedEdge extends Edge implements Comparable { 20 | public final double weight; 21 | 22 | public WeightedEdge(int u, int v, double weight) { 23 | super(u, v); 24 | this.weight = weight; 25 | } 26 | 27 | @Override 28 | public WeightedEdge reversed() { 29 | return new WeightedEdge(v, u, weight); 30 | } 31 | 32 | // so that we can order edges by weight to find the minimum weight edge 33 | @Override 34 | public int compareTo(WeightedEdge other) { 35 | Double mine = weight; 36 | Double theirs = other.weight; 37 | return mine.compareTo(theirs); 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return u + " " + weight + "> " + v; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter6/DataPoint.java: -------------------------------------------------------------------------------- 1 | // DataPoint.java 2 | // From Classic Computer Science Problems in Java Chapter 6 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter6; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public class DataPoint { 23 | public final int numDimensions; 24 | private List originals; 25 | public List dimensions; 26 | 27 | public DataPoint(List initials) { 28 | originals = initials; 29 | dimensions = new ArrayList<>(initials); 30 | numDimensions = dimensions.size(); 31 | } 32 | 33 | public double distance(DataPoint other) { 34 | double differences = 0.0; 35 | for (int i = 0; i < numDimensions; i++) { 36 | double difference = dimensions.get(i) - other.dimensions.get(i); 37 | differences += Math.pow(difference, 2); 38 | } 39 | return Math.sqrt(differences); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return originals.toString(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter7/Neuron.java: -------------------------------------------------------------------------------- 1 | // Neuron.java 2 | // From Classic Computer Science Problems in Java Chapter 7 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter7; 18 | 19 | import java.util.function.DoubleUnaryOperator; 20 | 21 | public class Neuron { 22 | public double[] weights; 23 | public final double learningRate; 24 | public double outputCache; 25 | public double delta; 26 | public final DoubleUnaryOperator activationFunction; 27 | public final DoubleUnaryOperator derivativeActivationFunction; 28 | 29 | public Neuron(double[] weights, double learningRate, DoubleUnaryOperator activationFunction, 30 | DoubleUnaryOperator derivativeActivationFunction) { 31 | this.weights = weights; 32 | this.learningRate = learningRate; 33 | outputCache = 0.0; 34 | delta = 0.0; 35 | this.activationFunction = activationFunction; 36 | this.derivativeActivationFunction = derivativeActivationFunction; 37 | } 38 | 39 | public double output(double[] inputs) { 40 | outputCache = Util.dotProduct(inputs, weights); 41 | return activationFunction.applyAsDouble(outputCache); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter1/Hanoi.java: -------------------------------------------------------------------------------- 1 | // Hanoi.java 2 | // From Classic Computer Science Problems in Java Chapter 1 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter1; 18 | 19 | import java.util.Stack; 20 | 21 | public class Hanoi { 22 | private final int numDiscs; 23 | public final Stack towerA = new Stack<>(); 24 | public final Stack towerB = new Stack<>(); 25 | public final Stack towerC = new Stack<>(); 26 | 27 | public Hanoi(int discs) { 28 | numDiscs = discs; 29 | for (int i = 1; i <= discs; i++) { 30 | towerA.push(i); 31 | } 32 | } 33 | 34 | private void move(Stack begin, Stack end, Stack temp, int n) { 35 | if (n == 1) { 36 | end.push(begin.pop()); 37 | } else { 38 | move(begin, temp, end, n - 1); 39 | move(begin, end, temp, 1); 40 | move(temp, end, begin, n - 1); 41 | } 42 | } 43 | 44 | public void solve() { 45 | move(towerA, towerC, towerB, numDiscs); 46 | } 47 | 48 | public static void main(String[] args) { 49 | Hanoi hanoi = new Hanoi(3); 50 | hanoi.solve(); 51 | System.out.println(hanoi.towerA); 52 | System.out.println(hanoi.towerB); 53 | System.out.println(hanoi.towerC); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter1/UnbreakableEncryption.java: -------------------------------------------------------------------------------- 1 | // UnbreakableEncryption.java 2 | // From Classic Computer Science Problems in Java Chapter 1 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter1; 18 | 19 | import java.util.Random; 20 | 21 | public class UnbreakableEncryption { 22 | // Generate *length* random bytes 23 | private static byte[] randomKey(int length) { 24 | byte[] dummy = new byte[length]; 25 | Random random = new Random(); 26 | random.nextBytes(dummy); 27 | return dummy; 28 | } 29 | 30 | public static KeyPair encrypt(String original) { 31 | byte[] originalBytes = original.getBytes(); 32 | byte[] dummyKey = randomKey(originalBytes.length); 33 | byte[] encryptedKey = new byte[originalBytes.length]; 34 | for (int i = 0; i < originalBytes.length; i++) { 35 | // XOR every byte 36 | encryptedKey[i] = (byte) (originalBytes[i] ^ dummyKey[i]); 37 | } 38 | return new KeyPair(dummyKey, encryptedKey); 39 | } 40 | 41 | public static String decrypt(KeyPair kp) { 42 | byte[] decrypted = new byte[kp.key1.length]; 43 | for (int i = 0; i < kp.key1.length; i++) { 44 | // XOR every byte 45 | decrypted[i] = (byte) (kp.key1[i] ^ kp.key2[i]); 46 | } 47 | return new String(decrypted); 48 | } 49 | 50 | public static void main(String[] args) { 51 | KeyPair kp = encrypt("One Time Pad!"); 52 | String result = decrypt(kp); 53 | System.out.println(result); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter8/TicTacToe.java: -------------------------------------------------------------------------------- 1 | // TicTacToe.java 2 | // From Classic Computer Science Problems in Java Chapter 8 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter8; 18 | 19 | import java.util.Scanner; 20 | 21 | public class TicTacToe { 22 | 23 | private TTTBoard board = new TTTBoard(); 24 | private Scanner scanner = new Scanner(System.in); 25 | 26 | private Integer getPlayerMove() { 27 | Integer playerMove = -1; 28 | while (!board.getLegalMoves().contains(playerMove)) { 29 | System.out.println("Enter a legal square (0-8):"); 30 | Integer play = scanner.nextInt(); 31 | playerMove = play; 32 | } 33 | return playerMove; 34 | } 35 | 36 | private void runGame() { 37 | // main game loop 38 | while (true) { 39 | Integer humanMove = getPlayerMove(); 40 | board = board.move(humanMove); 41 | if (board.isWin()) { 42 | System.out.println("Human wins!"); 43 | break; 44 | } else if (board.isDraw()) { 45 | System.out.println("Draw!"); 46 | break; 47 | } 48 | Integer computerMove = Minimax.findBestMove(board, 9); 49 | System.out.println("Computer move is " + computerMove); 50 | board = board.move(computerMove); 51 | System.out.println(board); 52 | if (board.isWin()) { 53 | System.out.println("Computer wins!"); 54 | break; 55 | } else if (board.isDraw()) { 56 | System.out.println("Draw!"); 57 | break; 58 | } 59 | } 60 | } 61 | 62 | public static void main(String[] args) { 63 | new TicTacToe().runGame(); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter8/ConnectFour.java: -------------------------------------------------------------------------------- 1 | // ConnectFour.java 2 | // From Classic Computer Science Problems in Java Chapter 8 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter8; 18 | 19 | import java.util.Scanner; 20 | 21 | public class ConnectFour { 22 | 23 | private C4Board board = new C4Board(); 24 | private Scanner scanner = new Scanner(System.in); 25 | 26 | private Integer getPlayerMove() { 27 | Integer playerMove = -1; 28 | while (!board.getLegalMoves().contains(playerMove)) { 29 | System.out.println("Enter a legal column (0-6):"); 30 | Integer play = scanner.nextInt(); 31 | playerMove = play; 32 | } 33 | return playerMove; 34 | } 35 | 36 | private void runGame() { 37 | // main game loop 38 | while (true) { 39 | Integer humanMove = getPlayerMove(); 40 | board = board.move(humanMove); 41 | if (board.isWin()) { 42 | System.out.println("Human wins!"); 43 | break; 44 | } else if (board.isDraw()) { 45 | System.out.println("Draw!"); 46 | break; 47 | } 48 | Integer computerMove = Minimax.findBestMove(board, 7); 49 | System.out.println("Computer move is " + computerMove); 50 | board = board.move(computerMove); 51 | System.out.println(board); 52 | if (board.isWin()) { 53 | System.out.println("Computer wins!"); 54 | break; 55 | } else if (board.isDraw()) { 56 | System.out.println("Draw!"); 57 | break; 58 | } 59 | } 60 | } 61 | 62 | public static void main(String[] args) { 63 | new ConnectFour().runGame(); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter6/Statistics.java: -------------------------------------------------------------------------------- 1 | // Statistics.java 2 | // From Classic Computer Science Problems in Java Chapter 6 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter6; 18 | 19 | import java.util.DoubleSummaryStatistics; 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | 23 | public final class Statistics { 24 | private List list; 25 | private DoubleSummaryStatistics dss; 26 | 27 | public Statistics(List list) { 28 | this.list = list; 29 | dss = list.stream().collect(Collectors.summarizingDouble(d -> d)); 30 | } 31 | 32 | public double sum() { 33 | return dss.getSum(); 34 | } 35 | 36 | // Find the average (mean) 37 | public double mean() { 38 | return dss.getAverage(); 39 | } 40 | 41 | // Find the variance sum((Xi - mean)^2) / N 42 | public double variance() { 43 | double mean = mean(); 44 | return list.stream().mapToDouble(x -> Math.pow((x - mean), 2)) 45 | .average().getAsDouble(); 46 | } 47 | 48 | // Find the standard deviation sqrt(variance) 49 | public double std() { 50 | return Math.sqrt(variance()); 51 | } 52 | 53 | // Convert elements to respective z-scores (formula z-score = 54 | // (x - mean) / std) 55 | public List zscored() { 56 | double mean = mean(); 57 | double std = std(); 58 | return list.stream() 59 | .map(x -> std != 0 ? ((x - mean) / std) : 0.0) 60 | .collect(Collectors.toList()); 61 | } 62 | 63 | public double max() { 64 | return dss.getMax(); 65 | } 66 | 67 | public double min() { 68 | return dss.getMin(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter6/Album.java: -------------------------------------------------------------------------------- 1 | // Album.java 2 | // From Classic Computer Science Problems in Java Chapter 6 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter6; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public class Album extends DataPoint { 23 | 24 | private String name; 25 | private int year; 26 | 27 | public Album(String name, int year, double length, double tracks) { 28 | super(List.of(length, tracks)); 29 | this.name = name; 30 | this.year = year; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "(" + name + ", " + year + ")"; 36 | } 37 | 38 | public static void main(String[] args) { 39 | List albums = new ArrayList<>(); 40 | albums.add(new Album("Got to Be There", 1972, 35.45, 10)); 41 | albums.add(new Album("Ben", 1972, 31.31, 10)); 42 | albums.add(new Album("Music & Me", 1973, 32.09, 10)); 43 | albums.add(new Album("Forever, Michael", 1975, 33.36, 10)); 44 | albums.add(new Album("Off the Wall", 1979, 42.28, 10)); 45 | albums.add(new Album("Thriller", 1982, 42.19, 9)); 46 | albums.add(new Album("Bad", 1987, 48.16, 10)); 47 | albums.add(new Album("Dangerous", 1991, 77.03, 14)); 48 | albums.add(new Album("HIStory: Past, Present and Future, Book I", 1995, 148.58, 30)); 49 | albums.add(new Album("Invincible", 2001, 77.05, 16)); 50 | KMeans kmeans = new KMeans<>(2, albums); 51 | List.Cluster> clusters = kmeans.run(100); 52 | for (int clusterIndex = 0; clusterIndex < clusters.size(); clusterIndex++) { 53 | System.out.printf("Cluster %d Avg Length %f Avg Tracks %f: %s%n", 54 | clusterIndex, clusters.get(clusterIndex).centroid.dimensions.get(0), 55 | clusters.get(clusterIndex).centroid.dimensions.get(1), 56 | clusters.get(clusterIndex).points); 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter3/QueensConstraint.java: -------------------------------------------------------------------------------- 1 | // QueensConstraint.java 2 | // From Classic Computer Science Problems in Java Chapter 3 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter3; 18 | 19 | import java.util.HashMap; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.Map.Entry; 23 | 24 | public class QueensConstraint extends Constraint { 25 | private List columns; 26 | 27 | public QueensConstraint(List columns) { 28 | super(columns); 29 | this.columns = columns; 30 | } 31 | 32 | @Override 33 | public boolean satisfied(Map assignment) { 34 | for (Entry item : assignment.entrySet()) { 35 | // q1c = queen 1 column, q1r = queen 1 row 36 | int q1c = item.getKey(); 37 | int q1r = item.getValue(); 38 | // q2c = queen 2 column 39 | for (int q2c = q1c + 1; q2c <= columns.size(); q2c++) { 40 | if (assignment.containsKey(q2c)) { 41 | // q2r = queen 2 row 42 | int q2r = assignment.get(q2c); 43 | // same row? 44 | if (q1r == q2r) { 45 | return false; 46 | } 47 | // same diagonal? 48 | if (Math.abs(q1r - q2r) == Math.abs(q1c - q2c)) { 49 | return false; 50 | } 51 | } 52 | } 53 | } 54 | return true; // no conflict 55 | } 56 | 57 | public static void main(String[] args) { 58 | List columns = List.of(1, 2, 3, 4, 5, 6, 7, 8); 59 | Map> rows = new HashMap<>(); 60 | for (int column : columns) { 61 | rows.put(column, List.of(1, 2, 3, 4, 5, 6, 7, 8)); 62 | } 63 | CSP csp = new CSP<>(columns, rows); 64 | csp.addConstraint(new QueensConstraint(columns)); 65 | Map solution = csp.backtrackingSearch(); 66 | if (solution == null) { 67 | System.out.println("No solution found!"); 68 | } else { 69 | System.out.println(solution); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter9/PhoneNumberMnemonics.java: -------------------------------------------------------------------------------- 1 | // PhoneNumberMnemonics.java 2 | // From Classic Computer Science Problems in Java Chapter 9 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter9; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.Map; 22 | import java.util.Scanner; 23 | 24 | public class PhoneNumberMnemonics { 25 | Map phoneMapping = Map.of( 26 | '1', new String[] { "1" }, 27 | '2', new String[] { "a", "b", "c" }, 28 | '3', new String[] { "d", "e", "f" }, 29 | '4', new String[] { "g", "h", "i" }, 30 | '5', new String[] { "j", "k", "l" }, 31 | '6', new String[] { "m", "n", "o" }, 32 | '7', new String[] { "p", "q", "r", "s" }, 33 | '8', new String[] { "t", "u", "v" }, 34 | '9', new String[] { "w", "x", "y", "z" }, 35 | '0', new String[] { "0", }); 36 | private final String phoneNumber; 37 | 38 | public PhoneNumberMnemonics(String phoneNumber) { 39 | this.phoneNumber = phoneNumber; 40 | } 41 | 42 | public static String[] cartesianProduct(String[] first, String[] second) { 43 | ArrayList product = new ArrayList<>(first.length * second.length); 44 | for (String item1 : first) { 45 | for (String item2 : second) { 46 | product.add(item1 + item2); 47 | } 48 | } 49 | return product.toArray(String[]::new); 50 | } 51 | 52 | public String[] getMnemonics() { 53 | String[] mnemonics = { "" }; 54 | for (Character digit : phoneNumber.toCharArray()) { 55 | String[] combo = phoneMapping.get(digit); 56 | if (combo != null) { 57 | mnemonics = cartesianProduct(mnemonics, combo); 58 | } 59 | } 60 | return mnemonics; 61 | } 62 | 63 | public static void main(String[] args) { 64 | System.out.println("Enter a phone number:"); 65 | Scanner scanner = new Scanner(System.in); 66 | String phoneNumber = scanner.nextLine(); 67 | scanner.close(); 68 | System.out.println("The possible mnemonics are:"); 69 | PhoneNumberMnemonics pnm = new PhoneNumberMnemonics(phoneNumber); 70 | System.out.println(Arrays.toString(pnm.getMnemonics())); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter3/SendMoreMoneyConstraint.java: -------------------------------------------------------------------------------- 1 | // SendMoreMoneyConstraint.java 2 | // From Classic Computer Science Problems in Java Chapter 3 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter3; 18 | 19 | import java.util.HashMap; 20 | import java.util.HashSet; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | public class SendMoreMoneyConstraint extends Constraint { 25 | private List letters; 26 | 27 | public SendMoreMoneyConstraint(List letters) { 28 | super(letters); 29 | this.letters = letters; 30 | } 31 | 32 | @Override 33 | public boolean satisfied(Map assignment) { 34 | // if there are duplicate values then it's not a solution 35 | if ((new HashSet<>(assignment.values())).size() < assignment.size()) { 36 | return false; 37 | } 38 | 39 | // if all variables have been assigned, check if it adds correctly 40 | if (assignment.size() == letters.size()) { 41 | int s = assignment.get('S'); 42 | int e = assignment.get('E'); 43 | int n = assignment.get('N'); 44 | int d = assignment.get('D'); 45 | int m = assignment.get('M'); 46 | int o = assignment.get('O'); 47 | int r = assignment.get('R'); 48 | int y = assignment.get('Y'); 49 | int send = s * 1000 + e * 100 + n * 10 + d; 50 | int more = m * 1000 + o * 100 + r * 10 + e; 51 | int money = m * 10000 + o * 1000 + n * 100 + e * 10 + y; 52 | return send + more == money; 53 | } 54 | return true; // no conflicts 55 | } 56 | 57 | public static void main(String[] args) { 58 | List letters = List.of('S', 'E', 'N', 'D', 'M', 'O', 'R', 'Y'); 59 | Map> possibleDigits = new HashMap<>(); 60 | for (Character letter : letters) { 61 | possibleDigits.put(letter, List.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); 62 | } 63 | // so we don't get answers starting with a 0 64 | possibleDigits.replace('M', List.of(1)); 65 | CSP csp = new CSP<>(letters, possibleDigits); 66 | csp.addConstraint(new SendMoreMoneyConstraint(letters)); 67 | Map solution = csp.backtrackingSearch(); 68 | if (solution == null) { 69 | System.out.println("No solution found!"); 70 | } else { 71 | System.out.println(solution); 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter5/SimpleEquation.java: -------------------------------------------------------------------------------- 1 | // SimpleEquation.java 2 | // From Classic Computer Science Problems in Java Chapter 5 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter5; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Random; 22 | 23 | public class SimpleEquation extends Chromosome { 24 | private int x, y; 25 | 26 | private static final int MAX_START = 100; 27 | 28 | public SimpleEquation(int x, int y) { 29 | this.x = x; 30 | this.y = y; 31 | } 32 | 33 | public static SimpleEquation randomInstance() { 34 | Random random = new Random(); 35 | return new SimpleEquation(random.nextInt(MAX_START), random.nextInt(MAX_START)); 36 | } 37 | 38 | // 6x - x^2 + 4y - y^2 39 | @Override 40 | public double fitness() { 41 | return 6 * x - x * x + 4 * y - y * y; 42 | } 43 | 44 | @Override 45 | public List crossover(SimpleEquation other) { 46 | SimpleEquation child1 = new SimpleEquation(x, other.y); 47 | SimpleEquation child2 = new SimpleEquation(other.x, y); 48 | return List.of(child1, child2); 49 | } 50 | 51 | @Override 52 | public void mutate() { 53 | Random random = new Random(); 54 | if (random.nextDouble() > 0.5) { // mutate x 55 | if (random.nextDouble() > 0.5) { 56 | x += 1; 57 | } else { 58 | x -= 1; 59 | } 60 | } else { // otherwise mutate y 61 | if (random.nextDouble() > 0.5) { 62 | y += 1; 63 | } else { 64 | y -= 1; 65 | } 66 | } 67 | 68 | } 69 | 70 | @Override 71 | public SimpleEquation copy() { 72 | return new SimpleEquation(x, y); 73 | } 74 | 75 | @Override 76 | public String toString() { 77 | return "X: " + x + " Y: " + y + " Fitness: " + fitness(); 78 | } 79 | 80 | public static void main(String[] args) { 81 | ArrayList initialPopulation = new ArrayList<>(); 82 | final int POPULATION_SIZE = 20; 83 | final int GENERATIONS = 100; 84 | final double THRESHOLD = 13.0; 85 | for (int i = 0; i < POPULATION_SIZE; i++) { 86 | initialPopulation.add(SimpleEquation.randomInstance()); 87 | } 88 | GeneticAlgorithm ga = new GeneticAlgorithm<>( 89 | initialPopulation, 90 | 0.1, 0.7, GeneticAlgorithm.SelectionType.TOURNAMENT); 91 | SimpleEquation result = ga.run(GENERATIONS, THRESHOLD); 92 | System.out.println(result); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter3/WordSearchConstraint.java: -------------------------------------------------------------------------------- 1 | // WordSearchConstraint.java 2 | // From Classic Computer Science Problems in Java Chapter 3 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter3; 18 | 19 | import java.util.Collection; 20 | import java.util.Collections; 21 | import java.util.HashMap; 22 | import java.util.HashSet; 23 | import java.util.List; 24 | import java.util.Map; 25 | import java.util.Map.Entry; 26 | import java.util.Random; 27 | import java.util.Set; 28 | import java.util.stream.Collectors; 29 | 30 | import chapter3.WordGrid.GridLocation; 31 | 32 | public class WordSearchConstraint extends Constraint> { 33 | 34 | public WordSearchConstraint(List words) { 35 | super(words); 36 | } 37 | 38 | @Override 39 | public boolean satisfied(Map> assignment) { 40 | // combine all GridLocations into one giant List 41 | List allLocations = assignment.values().stream() 42 | .flatMap(Collection::stream).collect(Collectors.toList()); 43 | // a set will eliminate duplicates using equals() 44 | Set allLocationsSet = new HashSet<>(allLocations); 45 | // if there are any duplicate grid locations then there is an overlap 46 | return allLocations.size() == allLocationsSet.size(); 47 | } 48 | 49 | public static void main(String[] args) { 50 | WordGrid grid = new WordGrid(9, 9); 51 | List words = List.of("MATTHEW", "JOE", "MARY", "SARAH", "SALLY"); 52 | // generate domains for all words 53 | Map>> domains = new HashMap<>(); 54 | for (String word : words) { 55 | domains.put(word, grid.generateDomain(word)); 56 | } 57 | CSP> csp = new CSP<>(words, domains); 58 | csp.addConstraint(new WordSearchConstraint(words)); 59 | Map> solution = csp.backtrackingSearch(); 60 | if (solution == null) { 61 | System.out.println("No solution found!"); 62 | } else { 63 | Random random = new Random(); 64 | for (Entry> item : solution.entrySet()) { 65 | String word = item.getKey(); 66 | List locations = item.getValue(); 67 | // random reverse half the time 68 | if (random.nextBoolean()) { 69 | Collections.reverse(locations); 70 | } 71 | grid.mark(word, locations); 72 | } 73 | System.out.println(grid); 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter7/Layer.java: -------------------------------------------------------------------------------- 1 | // Layer.java 2 | // From Classic Computer Science Problems in Java Chapter 7 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter7; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Optional; 22 | import java.util.Random; 23 | import java.util.function.DoubleUnaryOperator; 24 | 25 | public class Layer { 26 | public Optional previousLayer; 27 | public List neurons = new ArrayList<>(); 28 | public double[] outputCache; 29 | 30 | public Layer(Optional previousLayer, int numNeurons, double learningRate, 31 | DoubleUnaryOperator activationFunction, DoubleUnaryOperator derivativeActivationFunction) { 32 | this.previousLayer = previousLayer; 33 | Random random = new Random(); 34 | for (int i = 0; i < numNeurons; i++) { 35 | double[] randomWeights = null; 36 | if (previousLayer.isPresent()) { 37 | randomWeights = random.doubles(previousLayer.get().neurons.size()).toArray(); 38 | } 39 | Neuron neuron = new Neuron(randomWeights, learningRate, activationFunction, derivativeActivationFunction); 40 | neurons.add(neuron); 41 | } 42 | outputCache = new double[numNeurons]; 43 | } 44 | 45 | public double[] outputs(double[] inputs) { 46 | if (previousLayer.isPresent()) { 47 | outputCache = neurons.stream().mapToDouble(n -> n.output(inputs)).toArray(); 48 | } else { 49 | outputCache = inputs; 50 | } 51 | return outputCache; 52 | } 53 | 54 | // should only be called on output layer 55 | public void calculateDeltasForOutputLayer(double[] expected) { 56 | for (int n = 0; n < neurons.size(); n++) { 57 | neurons.get(n).delta = neurons.get(n).derivativeActivationFunction.applyAsDouble(neurons.get(n).outputCache) 58 | * (expected[n] - outputCache[n]); 59 | } 60 | } 61 | 62 | // should not be called on output layer 63 | public void calculateDeltasForHiddenLayer(Layer nextLayer) { 64 | for (int i = 0; i < neurons.size(); i++) { 65 | int index = i; 66 | double[] nextWeights = nextLayer.neurons.stream().mapToDouble(n -> n.weights[index]).toArray(); 67 | double[] nextDeltas = nextLayer.neurons.stream().mapToDouble(n -> n.delta).toArray(); 68 | double sumWeightsAndDeltas = Util.dotProduct(nextWeights, nextDeltas); 69 | neurons.get(i).delta = neurons.get(i).derivativeActivationFunction 70 | .applyAsDouble(neurons.get(i).outputCache) * sumWeightsAndDeltas; 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Classic Computer Science Problems in Java 2 | This repository contains source code to accompany the book *Classic Computer Science Problems in Java* by David Kopec, [available from Manning](https://www.manning.com/books/classic-computer-science-problems-in-java?a_aid=oaksnow&a_bid=6430148a), [Amazon](https://amzn.to/2LkFICw), and other fine book sellers. You will find the source organized by chapter. **As you read the book, each code listing contains a file name that corresponds to a file in this repository.** The book was published in December, 2020. 3 | 4 | ![Classic Computer Science Problems in Java Cover](cover.jpg) 5 | 6 | ## Conventions 7 | The source code was written against version 11 of the Java language and should run on any known newer version at the time of publication. It makes use of no Java libraries beyond the standard library. It was developed in Eclipse and this folder can be opened as an Eclipse workspace. You can then right-click any file with a `main()` method and select "Run" to compile and execute it. All other popular Java IDEs can import Eclipse projects, but you can also easily create a project out of each chapter, which is bundled as a Java package. For directions importing Eclipse projects into IntelliJ see [this tutorial from Jetbrains.](https://www.jetbrains.com/help/idea/import-project-from-eclipse-page-1.html) 8 | 9 | ## Questions about the Book 10 | You can find general questions and descriptive information about the book on the [Classic Computer Science Problems](https://classicproblems.com/) website. Also, feel free to reach out to me on Twitter, [@davekopec](https://twitter.com/davekopec). If you think you found an error in the source code, please open an issue up here on GitHub. 11 | 12 | ## License 13 | All of the source code in this repository is released under the Apache License version 2.0. See `LICENSE`. 14 | 15 | ## Other Books and Languages 16 | 17 | Official Books from the Series by @davecom 18 | - [Classic Computer Science Problems in Python](https://github.com/davecom/ClassicComputerScienceProblemsInPython) 19 | - [Classic Computer Science Problems in Swift](https://github.com/davecom/ClassicComputerScienceProblemsInSwift) 20 | 21 | My Latest Book 22 | - [Computer Science from Scratch: Building Interpreters, Art, Emulators and ML in Python](https://github.com/davecom/ComputerScienceFromScratch) 23 | 24 | Ports 25 | - [C++ implementation by @aray-andres](https://github.com/araya-andres/classic_computer_sci) 26 | - [Go implementation by @arlima](https://github.com/arlima/problemas_classicos_CC) 27 | - [PHP implementation by @SaschaKersken (German translator of CCSPiP)](https://github.com/SaschaKersken/ClassicComputerScienceProblemsInPhp) 28 | - [JavaScript implementation by @SaschaKersken (German translator of CCSPiP)](https://github.com/SaschaKersken/ClassicComputerScienceProblemsInJavaScript) 29 | - [Ruby implementation by @tj84](https://github.com/tj84/cs_problems) 30 | - [Rust implementation by @marpetercontribs](https://github.com/marpetercontribs/classic-computer-science-problems-in-rust) 31 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter7/Util.java: -------------------------------------------------------------------------------- 1 | // Util.java 2 | // From Classic Computer Science Problems in Java Chapter 7 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter7; 18 | 19 | import java.io.BufferedReader; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.io.InputStreamReader; 23 | import java.util.ArrayList; 24 | import java.util.Arrays; 25 | import java.util.Collections; 26 | import java.util.List; 27 | import java.util.stream.Collectors; 28 | 29 | public final class Util { 30 | 31 | public static double dotProduct(double[] xs, double[] ys) { 32 | double sum = 0.0; 33 | for (int i = 0; i < xs.length; i++) { 34 | sum += xs[i] * ys[i]; 35 | } 36 | return sum; 37 | } 38 | 39 | // the classic sigmoid activation function 40 | public static double sigmoid(double x) { 41 | return 1.0 / (1.0 + Math.exp(-x)); 42 | } 43 | 44 | public static double derivativeSigmoid(double x) { 45 | double sig = sigmoid(x); 46 | return sig * (1.0 - sig); 47 | } 48 | 49 | // Assume all rows are of equal length 50 | // and feature scale each column to be in the range 0 - 1 51 | public static void normalizeByFeatureScaling(List dataset) { 52 | for (int colNum = 0; colNum < dataset.get(0).length; colNum++) { 53 | List column = new ArrayList<>(); 54 | for (double[] row : dataset) { 55 | column.add(row[colNum]); 56 | } 57 | double maximum = Collections.max(column); 58 | double minimum = Collections.min(column); 59 | double difference = maximum - minimum; 60 | for (double[] row : dataset) { 61 | row[colNum] = (row[colNum] - minimum) / difference; 62 | } 63 | } 64 | } 65 | 66 | // Load a CSV file into a List of String arrays 67 | public static List loadCSV(String filename) { 68 | try (InputStream inputStream = Util.class.getResourceAsStream(filename)) { 69 | InputStreamReader inputStreamReader = new InputStreamReader(inputStream); 70 | BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 71 | return bufferedReader.lines().map(line -> line.split(",")) 72 | .collect(Collectors.toList()); 73 | } 74 | catch (IOException e) { 75 | e.printStackTrace(); 76 | throw new RuntimeException(e.getMessage(), e); 77 | } 78 | } 79 | 80 | // Find the maximum in an array of doubles 81 | public static double max(double[] numbers) { 82 | return Arrays.stream(numbers) 83 | .max() 84 | .orElse(Double.MIN_VALUE); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter3/MapColoringConstraint.java: -------------------------------------------------------------------------------- 1 | // MapColoringContraint.java 2 | // From Classic Computer Science Problems in Java Chapter 3 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter3; 18 | 19 | import java.util.HashMap; 20 | import java.util.List; 21 | import java.util.Map; 22 | 23 | public final class MapColoringConstraint extends Constraint { 24 | private String place1, place2; 25 | 26 | public MapColoringConstraint(String place1, String place2) { 27 | super(List.of(place1, place2)); 28 | this.place1 = place1; 29 | this.place2 = place2; 30 | } 31 | 32 | @Override 33 | public boolean satisfied(Map assignment) { 34 | // if either place is not in the assignment, then it is not 35 | // yet possible for their colors to be conflicting 36 | if (!assignment.containsKey(place1) || !assignment.containsKey(place2)) { 37 | return true; 38 | } 39 | // check the color assigned to place1 is not the same as the 40 | // color assigned to place2 41 | return !assignment.get(place1).equals(assignment.get(place2)); 42 | } 43 | 44 | public static void main(String[] args) { 45 | List variables = List.of("Western Australia", "Northern Territory", 46 | "South Australia", "Queensland", "New South Wales", "Victoria", "Tasmania"); 47 | Map> domains = new HashMap<>(); 48 | for (String variable : variables) { 49 | domains.put(variable, List.of("red", "green", "blue")); 50 | } 51 | CSP csp = new CSP<>(variables, domains); 52 | csp.addConstraint(new MapColoringConstraint("Western Australia", "Northern Territory")); 53 | csp.addConstraint(new MapColoringConstraint("Western Australia", "South Australia")); 54 | csp.addConstraint(new MapColoringConstraint("South Australia", "Northern Territory")); 55 | csp.addConstraint(new MapColoringConstraint("Queensland", "Northern Territory")); 56 | csp.addConstraint(new MapColoringConstraint("Queensland", "South Australia")); 57 | csp.addConstraint(new MapColoringConstraint("Queensland", "New South Wales")); 58 | csp.addConstraint(new MapColoringConstraint("New South Wales", "South Australia")); 59 | csp.addConstraint(new MapColoringConstraint("Victoria", "South Australia")); 60 | csp.addConstraint(new MapColoringConstraint("Victoria", "New South Wales")); 61 | csp.addConstraint(new MapColoringConstraint("Victoria", "Tasmania")); 62 | Map solution = csp.backtrackingSearch(); 63 | if (solution == null) { 64 | System.out.println("No solution found!"); 65 | } else { 66 | System.out.println(solution); 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter4/Graph.java: -------------------------------------------------------------------------------- 1 | // Graph.java 2 | // From Classic Computer Science Problems in Java Chapter 4 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter4; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | import java.util.stream.Collectors; 23 | 24 | // V is the type of the vertices in the Graph 25 | // E is the type of the edges 26 | public abstract class Graph { 27 | 28 | private ArrayList vertices = new ArrayList<>(); 29 | protected ArrayList> edges = new ArrayList<>(); 30 | 31 | public Graph() { 32 | } 33 | 34 | public Graph(List vertices) { 35 | this.vertices.addAll(vertices); 36 | for (V vertex : vertices) { 37 | edges.add(new ArrayList<>()); 38 | } 39 | } 40 | 41 | // Number of vertices 42 | public int getVertexCount() { 43 | return vertices.size(); 44 | } 45 | 46 | // Number of edges 47 | public int getEdgeCount() { 48 | return edges.stream().mapToInt(ArrayList::size).sum(); 49 | } 50 | 51 | // Add a vertex to the graph and return its index 52 | public int addVertex(V vertex) { 53 | vertices.add(vertex); 54 | edges.add(new ArrayList<>()); 55 | return getVertexCount() - 1; 56 | } 57 | 58 | // Find the vertex at a specific index 59 | public V vertexAt(int index) { 60 | return vertices.get(index); 61 | } 62 | 63 | // Find the index of a vertex in the graph 64 | public int indexOf(V vertex) { 65 | return vertices.indexOf(vertex); 66 | } 67 | 68 | // Find the vertices that a vertex at some index is connected to 69 | public List neighborsOf(int index) { 70 | return edges.get(index).stream() 71 | .map(edge -> vertexAt(edge.v)) 72 | .collect(Collectors.toList()); 73 | } 74 | 75 | // Look up a vertice's index and find its neighbors (convenience method) 76 | public List neighborsOf(V vertex) { 77 | return neighborsOf(indexOf(vertex)); 78 | } 79 | 80 | // Return all of the edges associated with a vertex at some index 81 | public List edgesOf(int index) { 82 | return edges.get(index); 83 | } 84 | 85 | // Look up the index of a vertex and return its edges (convenience method) 86 | public List edgesOf(V vertex) { 87 | return edgesOf(indexOf(vertex)); 88 | } 89 | 90 | // Make it easy to pretty-print a Graph 91 | @Override 92 | public String toString() { 93 | StringBuilder sb = new StringBuilder(); 94 | for (int i = 0; i < getVertexCount(); i++) { 95 | sb.append(vertexAt(i)); 96 | sb.append(" -> "); 97 | sb.append(Arrays.toString(neighborsOf(i).toArray())); 98 | sb.append(System.lineSeparator()); 99 | } 100 | return sb.toString(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter3/CSP.java: -------------------------------------------------------------------------------- 1 | // CSP.java 2 | // From Classic Computer Science Problems in Java Chapter 3 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter3; 18 | 19 | import java.util.ArrayList; 20 | import java.util.HashMap; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | public class CSP { 25 | private List variables; 26 | private Map> domains; 27 | private Map>> constraints = new HashMap<>(); 28 | 29 | public CSP(List variables, Map> domains) { 30 | this.variables = variables; 31 | this.domains = domains; 32 | for (V variable : variables) { 33 | constraints.put(variable, new ArrayList<>()); 34 | if (!domains.containsKey(variable)) { 35 | throw new IllegalArgumentException("Every variable should have a domain assigned to it."); 36 | } 37 | } 38 | } 39 | 40 | public void addConstraint(Constraint constraint) { 41 | for (V variable : constraint.variables) { 42 | if (!variables.contains(variable)) { 43 | throw new IllegalArgumentException("Variable in constraint not in CSP"); 44 | } 45 | constraints.get(variable).add(constraint); 46 | } 47 | } 48 | 49 | // Check if the value assignment is consistent by checking all constraints 50 | // for the given variable against it 51 | public boolean consistent(V variable, Map assignment) { 52 | for (Constraint constraint : constraints.get(variable)) { 53 | if (!constraint.satisfied(assignment)) { 54 | return false; 55 | } 56 | } 57 | return true; 58 | } 59 | 60 | public Map backtrackingSearch(Map assignment) { 61 | // assignment is complete if every variable is assigned (our base case) 62 | if (assignment.size() == variables.size()) { 63 | return assignment; 64 | } 65 | // get the first variable in the CSP but not in the assignment 66 | V unassigned = variables.stream().filter(v -> !assignment.containsKey(v)).findFirst().get(); 67 | // get the every possible domain value of the first unassigned variable 68 | for (D value : domains.get(unassigned)) { 69 | // shallow copy of assignment that we can change 70 | Map localAssignment = new HashMap<>(assignment); 71 | localAssignment.put(unassigned, value); 72 | // if we're still consistent, we recurse (continue) 73 | if (consistent(unassigned, localAssignment)) { 74 | Map result = backtrackingSearch(localAssignment); 75 | // if we didn't find the result, we will end up backtracking 76 | if (result != null) { 77 | return result; 78 | } 79 | } 80 | } 81 | return null; 82 | } 83 | 84 | // helper for backtrackingSearch when nothing known yet 85 | public Map backtrackingSearch() { 86 | return backtrackingSearch(new HashMap<>()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter8/TTTBoard.java: -------------------------------------------------------------------------------- 1 | // TTTBoard.java 2 | // From Classic Computer Science Problems in Java Chapter 8 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter8; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | 23 | public class TTTBoard implements Board { 24 | private static final int NUM_SQUARES = 9; 25 | private TTTPiece[] position; 26 | private TTTPiece turn; 27 | 28 | public TTTBoard(TTTPiece[] position, TTTPiece turn) { 29 | this.position = position; 30 | this.turn = turn; 31 | } 32 | 33 | public TTTBoard() { 34 | // by default start with blank board 35 | position = new TTTPiece[NUM_SQUARES]; 36 | Arrays.fill(position, TTTPiece.E); 37 | // X goes first 38 | turn = TTTPiece.X; 39 | } 40 | 41 | @Override 42 | public Piece getTurn() { 43 | return turn; 44 | } 45 | 46 | @Override 47 | public TTTBoard move(Integer location) { 48 | TTTPiece[] tempPosition = Arrays.copyOf(position, position.length); 49 | tempPosition[location] = turn; 50 | return new TTTBoard(tempPosition, turn.opposite()); 51 | } 52 | 53 | @Override 54 | public List getLegalMoves() { 55 | ArrayList legalMoves = new ArrayList<>(); 56 | for (int i = 0; i < NUM_SQUARES; i++) { 57 | // empty squares are legal moves 58 | if (position[i] == TTTPiece.E) { 59 | legalMoves.add(i); 60 | } 61 | } 62 | return legalMoves; 63 | } 64 | 65 | @Override 66 | public boolean isWin() { 67 | // three row, three column, and then two diagonal checks 68 | return checkPos(0, 1, 2) || checkPos(3, 4, 5) || checkPos(6, 7, 8) 69 | || checkPos(0, 3, 6) || checkPos(1, 4, 7) || checkPos(2, 5, 8) 70 | || checkPos(0, 4, 8) || checkPos(2, 4, 6); 71 | } 72 | 73 | private boolean checkPos(int p0, int p1, int p2) { 74 | return position[p0] == position[p1] && position[p0] == position[p2] 75 | && position[p0] != TTTPiece.E; 76 | } 77 | 78 | @Override 79 | public double evaluate(Piece player) { 80 | if (isWin() && turn == player) { 81 | return -1; 82 | } else if (isWin() && turn != player) { 83 | return 1; 84 | } else { 85 | return 0.0; 86 | } 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | StringBuilder sb = new StringBuilder(); 92 | for (int row = 0; row < 3; row++) { 93 | for (int col = 0; col < 3; col++) { 94 | sb.append(position[row * 3 + col].toString()); 95 | if (col != 2) { 96 | sb.append("|"); 97 | } 98 | } 99 | sb.append(System.lineSeparator()); 100 | if (row != 2) { 101 | sb.append("-----"); 102 | sb.append(System.lineSeparator()); 103 | } 104 | } 105 | return sb.toString(); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter8/TTTMinimaxTests.java: -------------------------------------------------------------------------------- 1 | // TTTMinimaxTests.java 2 | // From Classic Computer Science Problems in Java Chapter 8 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter8; 18 | 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | import java.lang.reflect.Method; 22 | 23 | // Annotation for unit tests 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @interface UnitTest { 26 | String name() default ""; 27 | } 28 | 29 | public class TTTMinimaxTests { 30 | 31 | // Check if two values are equal and report back 32 | public static void assertEquality(T actual, T expected) { 33 | if (actual.equals(expected)) { 34 | System.out.println("Passed!"); 35 | } else { 36 | System.out.println("Failed!"); 37 | System.out.println("Actual: " + actual.toString()); 38 | System.out.println("Expected: " + expected.toString()); 39 | } 40 | } 41 | 42 | @UnitTest(name = "Easy Position") 43 | public void easyPosition() { 44 | TTTPiece[] toWinEasyPosition = new TTTPiece[] { 45 | TTTPiece.X, TTTPiece.O, TTTPiece.X, 46 | TTTPiece.X, TTTPiece.E, TTTPiece.O, 47 | TTTPiece.E, TTTPiece.E, TTTPiece.O }; 48 | TTTBoard testBoard1 = new TTTBoard(toWinEasyPosition, TTTPiece.X); 49 | Integer answer1 = Minimax.findBestMove(testBoard1, 8); 50 | assertEquality(answer1, 6); 51 | } 52 | 53 | @UnitTest(name = "Block Position") 54 | public void blockPosition() { 55 | TTTPiece[] toBlockPosition = new TTTPiece[] { 56 | TTTPiece.X, TTTPiece.E, TTTPiece.E, 57 | TTTPiece.E, TTTPiece.E, TTTPiece.O, 58 | TTTPiece.E, TTTPiece.X, TTTPiece.O }; 59 | TTTBoard testBoard2 = new TTTBoard(toBlockPosition, TTTPiece.X); 60 | Integer answer2 = Minimax.findBestMove(testBoard2, 8); 61 | assertEquality(answer2, 2); 62 | } 63 | 64 | @UnitTest(name = "Hard Position") 65 | public void hardPosition() { 66 | TTTPiece[] toWinHardPosition = new TTTPiece[] { 67 | TTTPiece.X, TTTPiece.E, TTTPiece.E, 68 | TTTPiece.E, TTTPiece.E, TTTPiece.O, 69 | TTTPiece.O, TTTPiece.X, TTTPiece.E }; 70 | TTTBoard testBoard3 = new TTTBoard(toWinHardPosition, TTTPiece.X); 71 | Integer answer3 = Minimax.findBestMove(testBoard3, 8); 72 | assertEquality(answer3, 1); 73 | } 74 | 75 | // Run all methods marked with the UnitTest annotation 76 | public void runAllTests() { 77 | for (Method method : this.getClass().getMethods()) { 78 | for (UnitTest annotation : method.getAnnotationsByType(UnitTest.class)) { 79 | System.out.println("Running Test " + annotation.name()); 80 | try { 81 | method.invoke(this); 82 | } catch (Exception e) { 83 | e.printStackTrace(); 84 | } 85 | System.out.println("____________________"); 86 | } 87 | } 88 | } 89 | 90 | public static void main(String[] args) { 91 | new TTTMinimaxTests().runAllTests(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter9/Knapsack.java: -------------------------------------------------------------------------------- 1 | // Knapsack.java 2 | // From Classic Computer Science Problems in Java Chapter 9 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter9; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public final class Knapsack { 23 | 24 | public static final class Item { 25 | public final String name; 26 | public final int weight; 27 | public final double value; 28 | 29 | public Item(String name, int weight, double value) { 30 | this.name = name; 31 | this.weight = weight; 32 | this.value = value; 33 | } 34 | } 35 | 36 | public static List knapsack(List items, int maxCapacity) { 37 | // build up dynamic programming table 38 | double[][] table = new double[items.size() + 1][maxCapacity + 1]; 39 | for (int i = 0; i < items.size(); i++) { 40 | Item item = items.get(i); 41 | for (int capacity = 1; capacity <= maxCapacity; capacity++) { 42 | double prevItemValue = table[i][capacity]; 43 | if (capacity >= item.weight) { // item fits in knapsack 44 | double valueFreeingWeightForItem = table[i][capacity - item.weight]; 45 | // only take if more valuable than previous item 46 | table[i + 1][capacity] = Math.max(valueFreeingWeightForItem + item.value, prevItemValue); 47 | } else { // no room for this item 48 | table[i + 1][capacity] = prevItemValue; 49 | } 50 | } 51 | } 52 | // figure out solution from table 53 | List solution = new ArrayList<>(); 54 | int capacity = maxCapacity; 55 | for (int i = items.size(); i > 0; i--) { // work backwards 56 | // was this item used? 57 | if (table[i - 1][capacity] != table[i][capacity]) { 58 | solution.add(items.get(i - 1)); 59 | // if the item was used, remove its weight 60 | capacity -= items.get(i - 1).weight; 61 | } 62 | } 63 | return solution; 64 | } 65 | 66 | public static void main(String[] args) { 67 | List items = new ArrayList<>(); 68 | items.add(new Item("television", 50, 500)); 69 | items.add(new Item("candlesticks", 2, 300)); 70 | items.add(new Item("stereo", 35, 400)); 71 | items.add(new Item("laptop", 3, 1000)); 72 | items.add(new Item("food", 15, 50)); 73 | items.add(new Item("clothing", 20, 800)); 74 | items.add(new Item("jewelry", 1, 4000)); 75 | items.add(new Item("books", 100, 300)); 76 | items.add(new Item("printer", 18, 30)); 77 | items.add(new Item("refrigerator", 200, 700)); 78 | items.add(new Item("painting", 10, 1000)); 79 | List toSteal = knapsack(items, 75); 80 | System.out.println("The best items for the thief to steal are:"); 81 | System.out.printf("%-15.15s %-15.15s %-15.15s%n", "Name", "Weight", "Value"); 82 | for (Item item : toSteal) { 83 | System.out.printf("%-15.15s %-15.15s %-15.15s%n", item.name, item.weight, item.value); 84 | } 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter1/CompressedGene.java: -------------------------------------------------------------------------------- 1 | // CompressedGene.java 2 | // From Classic Computer Science Problems in Java Chapter 1 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter1; 18 | 19 | import java.util.BitSet; 20 | 21 | public class CompressedGene { 22 | private BitSet bitSet; 23 | private int length; 24 | 25 | public CompressedGene(String gene) { 26 | compress(gene); 27 | } 28 | 29 | private void compress(String gene) { 30 | length = gene.length(); 31 | // reserve enough capacity for all of the bits 32 | bitSet = new BitSet(length * 2); 33 | // convert to upper case for consistency 34 | final String upperGene = gene.toUpperCase(); 35 | // convert String to bit representation 36 | for (int i = 0; i < length; i++) { 37 | final int firstLocation = 2 * i; 38 | final int secondLocation = 2 * i + 1; 39 | switch (upperGene.charAt(i)) { 40 | case 'A': // 00 are next two bits 41 | bitSet.set(firstLocation, false); 42 | bitSet.set(secondLocation, false); 43 | break; 44 | case 'C': // 01 are next two bits 45 | bitSet.set(firstLocation, false); 46 | bitSet.set(secondLocation, true); 47 | break; 48 | case 'G': // 10 are next two bits 49 | bitSet.set(firstLocation, true); 50 | bitSet.set(secondLocation, false); 51 | break; 52 | case 'T': // 11 are next two bits 53 | bitSet.set(firstLocation, true); 54 | bitSet.set(secondLocation, true); 55 | break; 56 | default: 57 | throw new IllegalArgumentException("The provided gene String contains characters other than ACGT"); 58 | } 59 | } 60 | } 61 | 62 | public String decompress() { 63 | if (bitSet == null) { 64 | return ""; 65 | } 66 | // create a mutable place for characters with right capacity 67 | StringBuilder builder = new StringBuilder(length); 68 | for (int i = 0; i < (length * 2); i += 2) { 69 | final int firstBit = (bitSet.get(i) ? 1 : 0); 70 | final int secondBit = (bitSet.get(i + 1) ? 1 : 0); 71 | final int lastBits = firstBit << 1 | secondBit; 72 | switch (lastBits) { 73 | case 0b00: // 00 is 'A' 74 | builder.append('A'); 75 | break; 76 | case 0b01: // 01 is 'C' 77 | builder.append('C'); 78 | break; 79 | case 0b10: // 10 is 'G' 80 | builder.append('G'); 81 | break; 82 | case 0b11: // 11 is 'T' 83 | builder.append('T'); 84 | break; 85 | } 86 | } 87 | return builder.toString(); 88 | } 89 | 90 | public static void main(String[] args) { 91 | final String original = "TAGGGATTAACCGTTATATATATATAGCCATGGATCGATTATATAGGGATTAACCGTTATATATATATAGCCATGGATCGATTATA"; 92 | CompressedGene compressed = new CompressedGene(original); 93 | final String decompressed = compressed.decompress(); 94 | System.out.println(decompressed); 95 | System.out.println("original is the same as decompressed: " + original.equalsIgnoreCase(decompressed)); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter2/Gene.java: -------------------------------------------------------------------------------- 1 | // Gene.java 2 | // From Classic Computer Science Problems in Java Chapter 2 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter2; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.Comparator; 22 | 23 | public class Gene { 24 | 25 | public enum Nucleotide { 26 | A, C, G, T 27 | } 28 | 29 | public static class Codon implements Comparable { 30 | public final Nucleotide first, second, third; 31 | private final Comparator comparator = Comparator.comparing((Codon c) -> c.first) 32 | .thenComparing((Codon c) -> c.second) 33 | .thenComparing((Codon c) -> c.third); 34 | 35 | public Codon(String codonStr) { 36 | first = Nucleotide.valueOf(codonStr.substring(0, 1)); 37 | second = Nucleotide.valueOf(codonStr.substring(1, 2)); 38 | third = Nucleotide.valueOf(codonStr.substring(2, 3)); 39 | } 40 | 41 | @Override 42 | public int compareTo(Codon other) { 43 | // first is compared first, then second, etc. 44 | // IOW first takes precedence over second and second over third 45 | return comparator.compare(this, other); 46 | } 47 | } 48 | 49 | private ArrayList codons = new ArrayList<>(); 50 | 51 | public Gene(String geneStr) { 52 | for (int i = 0; i <= geneStr.length() - 3; i += 3) { 53 | // Take every 3 characters in the String and form a Codon 54 | codons.add(new Codon(geneStr.substring(i, i + 3))); 55 | } 56 | } 57 | 58 | public boolean linearContains(Codon key) { 59 | for (Codon codon : codons) { 60 | if (codon.compareTo(key) == 0) { 61 | return true; // found a match 62 | } 63 | } 64 | return false; 65 | } 66 | 67 | public boolean binaryContains(Codon key) { 68 | // binary search only works on sorted collections 69 | ArrayList sortedCodons = new ArrayList<>(codons); 70 | Collections.sort(sortedCodons); 71 | int low = 0; 72 | int high = sortedCodons.size() - 1; 73 | while (low <= high) { // while there is still a search space 74 | int middle = (low + high) / 2; 75 | int comparison = sortedCodons.get(middle).compareTo(key); 76 | if (comparison < 0) { // middle codon is less than key 77 | low = middle + 1; 78 | } else if (comparison > 0) { // middle codon is greater than key 79 | high = middle - 1; 80 | } else { // middle codon is equal to key 81 | return true; 82 | } 83 | } 84 | return false; 85 | } 86 | 87 | public static void main(String[] args) { 88 | String geneStr = "ACGTGGCTCTCTAACGTACGTACGTACGGGGTTTATATATACCCTAGGACTCCCTTT"; 89 | Gene myGene = new Gene(geneStr); 90 | Codon acg = new Codon("ACG"); 91 | Codon gat = new Codon("GAT"); 92 | System.out.println(myGene.linearContains(acg)); // true 93 | System.out.println(myGene.linearContains(gat)); // false 94 | System.out.println(myGene.binaryContains(acg)); // true 95 | System.out.println(myGene.binaryContains(gat)); // false 96 | 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter7/WineTest.java: -------------------------------------------------------------------------------- 1 | // WineTest.java 2 | // From Classic Computer Science Problems in Java Chapter 7 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter7; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.Collections; 22 | import java.util.List; 23 | 24 | public class WineTest { 25 | private List wineParameters = new ArrayList<>(); 26 | private List wineClassifications = new ArrayList<>(); 27 | private List wineSpecies = new ArrayList<>(); 28 | 29 | public WineTest() { 30 | // make sure wine.csv is in the right place in your path 31 | List wineDataset = Util.loadCSV("/chapter7/data/wine.csv"); 32 | // get our lines of data in random order 33 | Collections.shuffle(wineDataset); 34 | for (String[] wine : wineDataset) { 35 | // last thirteen items are parameters (doubles) 36 | double[] parameters = Arrays.stream(wine) 37 | .skip(1) 38 | .mapToDouble(Double::parseDouble) 39 | .toArray(); 40 | wineParameters.add(parameters); 41 | // first item is species 42 | int species = Integer.parseInt(wine[0]); 43 | switch (species) { 44 | case 1: 45 | wineClassifications.add(new double[] { 1.0, 0.0, 0.0 }); 46 | break; 47 | case 2: 48 | wineClassifications.add(new double[] { 0.0, 1.0, 0.0 }); 49 | break; 50 | default: 51 | wineClassifications.add(new double[] { 0.0, 0.0, 1.0 }); 52 | ; 53 | break; 54 | } 55 | wineSpecies.add(species); 56 | } 57 | Util.normalizeByFeatureScaling(wineParameters); 58 | } 59 | 60 | public Integer wineInterpretOutput(double[] output) { 61 | double max = Util.max(output); 62 | if (max == output[0]) { 63 | return 1; 64 | } else if (max == output[1]) { 65 | return 2; 66 | } else { 67 | return 3; 68 | } 69 | } 70 | 71 | public Network.Results classify() { 72 | // 13, 7, 3 layer structure; 0.9 learning rate; sigmoid activation function 73 | Network wineNetwork = new Network<>(new int[] { 13, 7, 3 }, 0.9, Util::sigmoid, 74 | Util::derivativeSigmoid); 75 | // train over the first 150 wines in the data set 50 times 76 | List wineTrainers = wineParameters.subList(0, 150); 77 | List wineTrainersCorrects = wineClassifications.subList(0, 150); 78 | int trainingIterations = 10; 79 | for (int i = 0; i < trainingIterations; i++) { 80 | wineNetwork.train(wineTrainers, wineTrainersCorrects); 81 | } 82 | // test over the last 28 of the wines in the data set 83 | List wineTesters = wineParameters.subList(150, 178); 84 | List wineTestersCorrects = wineSpecies.subList(150, 178); 85 | return wineNetwork.validate(wineTesters, wineTestersCorrects, this::wineInterpretOutput); 86 | } 87 | 88 | public static void main(String[] args) { 89 | WineTest wineTest = new WineTest(); 90 | Network.Results results = wineTest.classify(); 91 | System.out.println(results.correct + " correct of " + results.trials + " = " + 92 | results.percentage * 100 + "%"); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter4/UnweightedGraph.java: -------------------------------------------------------------------------------- 1 | // UnweightedGraph.java 2 | // From Classic Computer Science Problems in Java Chapter 4 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter4; 18 | 19 | import java.util.List; 20 | 21 | import chapter2.GenericSearch; 22 | import chapter2.GenericSearch.Node; 23 | 24 | public class UnweightedGraph extends Graph { 25 | 26 | public UnweightedGraph(List vertices) { 27 | super(vertices); 28 | } 29 | 30 | // This is an undirected graph, so we always add 31 | // edges in both directions 32 | public void addEdge(Edge edge) { 33 | edges.get(edge.u).add(edge); 34 | edges.get(edge.v).add(edge.reversed()); 35 | } 36 | 37 | // Add an edge using vertex indices (convenience method) 38 | public void addEdge(int u, int v) { 39 | addEdge(new Edge(u, v)); 40 | } 41 | 42 | // Add an edge by looking up vertex indices (convenience method) 43 | public void addEdge(V first, V second) { 44 | addEdge(new Edge(indexOf(first), indexOf(second))); 45 | } 46 | 47 | // Test basic Graph construction 48 | public static void main(String[] args) { 49 | // Represents the 15 largest MSAs in the United States 50 | UnweightedGraph cityGraph = new UnweightedGraph<>( 51 | List.of("Seattle", "San Francisco", "Los Angeles", "Riverside", "Phoenix", "Chicago", "Boston", 52 | "New York", "Atlanta", "Miami", "Dallas", "Houston", "Detroit", "Philadelphia", "Washington")); 53 | 54 | cityGraph.addEdge("Seattle", "Chicago"); 55 | cityGraph.addEdge("Seattle", "San Francisco"); 56 | cityGraph.addEdge("San Francisco", "Riverside"); 57 | cityGraph.addEdge("San Francisco", "Los Angeles"); 58 | cityGraph.addEdge("Los Angeles", "Riverside"); 59 | cityGraph.addEdge("Los Angeles", "Phoenix"); 60 | cityGraph.addEdge("Riverside", "Phoenix"); 61 | cityGraph.addEdge("Riverside", "Chicago"); 62 | cityGraph.addEdge("Phoenix", "Dallas"); 63 | cityGraph.addEdge("Phoenix", "Houston"); 64 | cityGraph.addEdge("Dallas", "Chicago"); 65 | cityGraph.addEdge("Dallas", "Atlanta"); 66 | cityGraph.addEdge("Dallas", "Houston"); 67 | cityGraph.addEdge("Houston", "Atlanta"); 68 | cityGraph.addEdge("Houston", "Miami"); 69 | cityGraph.addEdge("Atlanta", "Chicago"); 70 | cityGraph.addEdge("Atlanta", "Washington"); 71 | cityGraph.addEdge("Atlanta", "Miami"); 72 | cityGraph.addEdge("Miami", "Washington"); 73 | cityGraph.addEdge("Chicago", "Detroit"); 74 | cityGraph.addEdge("Detroit", "Boston"); 75 | cityGraph.addEdge("Detroit", "Washington"); 76 | cityGraph.addEdge("Detroit", "New York"); 77 | cityGraph.addEdge("Boston", "New York"); 78 | cityGraph.addEdge("New York", "Philadelphia"); 79 | cityGraph.addEdge("Philadelphia", "Washington"); 80 | System.out.println(cityGraph.toString()); 81 | 82 | Node bfsResult = GenericSearch.bfs("Boston", 83 | v -> v.equals("Miami"), 84 | cityGraph::neighborsOf); 85 | if (bfsResult == null) { 86 | System.out.println("No solution found using breadth-first search!"); 87 | } else { 88 | List path = GenericSearch.nodeToPath(bfsResult); 89 | System.out.println("Path from Boston to Miami:"); 90 | System.out.println(path); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter8/Minimax.java: -------------------------------------------------------------------------------- 1 | // Minimax.java 2 | // From Classic Computer Science Problems in Java Chapter 8 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter8; 18 | 19 | public class Minimax { 20 | // Find the best possible outcome for originalPlayer 21 | public static double minimax(Board board, boolean maximizing, Piece originalPlayer, int maxDepth) { 22 | // Base case - terminal position or maximum depth reached 23 | if (board.isWin() || board.isDraw() || maxDepth == 0) { 24 | return board.evaluate(originalPlayer); 25 | } 26 | // Recursive case - maximize your gains or minimize the opponent's gains 27 | if (maximizing) { 28 | double bestEval = Double.NEGATIVE_INFINITY; // result must be higher 29 | for (Move move : board.getLegalMoves()) { 30 | double result = minimax(board.move(move), false, originalPlayer, maxDepth - 1); 31 | bestEval = Math.max(result, bestEval); 32 | } 33 | return bestEval; 34 | } else { // minimizing 35 | double worstEval = Double.POSITIVE_INFINITY; // result must be lower 36 | for (Move move : board.getLegalMoves()) { 37 | double result = minimax(board.move(move), true, originalPlayer, maxDepth - 1); 38 | worstEval = Math.min(result, worstEval); 39 | } 40 | return worstEval; 41 | } 42 | } 43 | 44 | // Find the best possible move in the current position 45 | // looking up to maxDepth ahead 46 | public static Move findBestMove(Board board, int maxDepth) { 47 | double bestEval = Double.NEGATIVE_INFINITY; 48 | Move bestMove = null; // won't stay null for sure 49 | for (Move move : board.getLegalMoves()) { 50 | double result = alphabeta(board.move(move), false, board.getTurn(), maxDepth); 51 | if (result > bestEval) { 52 | bestEval = result; 53 | bestMove = move; 54 | } 55 | } 56 | return bestMove; 57 | } 58 | 59 | // Helper that sets alpha and beta for the first call 60 | public static double alphabeta(Board board, boolean maximizing, Piece originalPlayer, int maxDepth) { 61 | return alphabeta(board, maximizing, originalPlayer, maxDepth, Double.NEGATIVE_INFINITY, 62 | Double.POSITIVE_INFINITY); 63 | } 64 | 65 | // Evaluates a Board b 66 | private static double alphabeta(Board board, boolean maximizing, Piece originalPlayer, int maxDepth, 67 | double alpha, 68 | double beta) { 69 | // Base case - terminal position or maximum depth reached 70 | if (board.isWin() || board.isDraw() || maxDepth == 0) { 71 | return board.evaluate(originalPlayer); 72 | } 73 | 74 | // Recursive case - maximize your gains or minimize the opponent's gains 75 | if (maximizing) { 76 | for (Move m : board.getLegalMoves()) { 77 | alpha = Math.max(alpha, alphabeta(board.move(m), false, originalPlayer, maxDepth - 1, alpha, beta)); 78 | if (beta <= alpha) { // check cutoff 79 | break; 80 | } 81 | } 82 | return alpha; 83 | } else { // minimizing 84 | for (Move m : board.getLegalMoves()) { 85 | beta = Math.min(beta, alphabeta(board.move(m), true, originalPlayer, maxDepth - 1, alpha, beta)); 86 | if (beta <= alpha) { // check cutoff 87 | break; 88 | } 89 | } 90 | return beta; 91 | } 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter7/IrisTest.java: -------------------------------------------------------------------------------- 1 | // IrisTest.java 2 | // From Classic Computer Science Problems in Java Chapter 7 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter7; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.Collections; 22 | import java.util.List; 23 | 24 | public class IrisTest { 25 | public static final String IRIS_SETOSA = "Iris-setosa"; 26 | public static final String IRIS_VERSICOLOR = "Iris-versicolor"; 27 | public static final String IRIS_VIRGINICA = "Iris-virginica"; 28 | 29 | private List irisParameters = new ArrayList<>(); 30 | private List irisClassifications = new ArrayList<>(); 31 | private List irisSpecies = new ArrayList<>(); 32 | 33 | public IrisTest() { 34 | // make sure iris.csv is in the right place in your path 35 | List irisDataset = Util.loadCSV("/chapter7/data/iris.csv"); 36 | // get our lines of data in random order 37 | Collections.shuffle(irisDataset); 38 | for (String[] iris : irisDataset) { 39 | // first four items are parameters (doubles) 40 | double[] parameters = Arrays.stream(iris) 41 | .limit(4) 42 | .mapToDouble(Double::parseDouble) 43 | .toArray(); 44 | irisParameters.add(parameters); 45 | // last item is species 46 | String species = iris[4]; 47 | switch (species) { 48 | case IRIS_SETOSA: 49 | irisClassifications.add(new double[] { 1.0, 0.0, 0.0 }); 50 | break; 51 | case IRIS_VERSICOLOR: 52 | irisClassifications.add(new double[] { 0.0, 1.0, 0.0 }); 53 | break; 54 | default: 55 | irisClassifications.add(new double[] { 0.0, 0.0, 1.0 }); 56 | break; 57 | } 58 | irisSpecies.add(species); 59 | } 60 | Util.normalizeByFeatureScaling(irisParameters); 61 | } 62 | 63 | public String irisInterpretOutput(double[] output) { 64 | double max = Util.max(output); 65 | if (max == output[0]) { 66 | return IRIS_SETOSA; 67 | } else if (max == output[1]) { 68 | return IRIS_VERSICOLOR; 69 | } else { 70 | return IRIS_VIRGINICA; 71 | } 72 | } 73 | 74 | public Network.Results classify() { 75 | // 4, 6, 3 layer structure; 0.3 learning rate; sigmoid activation function 76 | Network irisNetwork = new Network<>(new int[] { 4, 6, 3 }, 0.3, Util::sigmoid, Util::derivativeSigmoid); 77 | // train over the first 140 irises in the data set 50 times 78 | List irisTrainers = irisParameters.subList(0, 140); 79 | List irisTrainersCorrects = irisClassifications.subList(0, 140); 80 | int trainingIterations = 50; 81 | for (int i = 0; i < trainingIterations; i++) { 82 | irisNetwork.train(irisTrainers, irisTrainersCorrects); 83 | } 84 | // test over the last 10 of the irises in the data set 85 | List irisTesters = irisParameters.subList(140, 150); 86 | List irisTestersCorrects = irisSpecies.subList(140, 150); 87 | return irisNetwork.validate(irisTesters, irisTestersCorrects, this::irisInterpretOutput); 88 | } 89 | 90 | public static void main(String[] args) { 91 | IrisTest irisTest = new IrisTest(); 92 | Network.Results results = irisTest.classify(); 93 | System.out.println(results.correct + " correct of " + results.trials + " = " + 94 | results.percentage * 100 + "%"); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter5/ListCompression.java: -------------------------------------------------------------------------------- 1 | // ListCompression.java 2 | // From Classic Computer Science Problems in Java Chapter 5 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter5; 18 | 19 | import java.io.ByteArrayOutputStream; 20 | import java.io.IOException; 21 | import java.io.ObjectOutputStream; 22 | import java.util.ArrayList; 23 | import java.util.Collections; 24 | import java.util.List; 25 | import java.util.Random; 26 | import java.util.zip.GZIPOutputStream; 27 | 28 | public class ListCompression extends Chromosome { 29 | 30 | private static final List ORIGINAL_LIST = List.of("Michael", "Sarah", "Joshua", "Narine", 31 | "David", "Sajid", "Melanie", "Daniel", "Wei", "Dean", "Brian", "Murat", "Lisa"); 32 | private List myList; 33 | private Random random; 34 | 35 | public ListCompression(List list) { 36 | myList = new ArrayList<>(list); 37 | random = new Random(); 38 | } 39 | 40 | public static ListCompression randomInstance() { 41 | ArrayList tempList = new ArrayList<>(ORIGINAL_LIST); 42 | Collections.shuffle(tempList); 43 | return new ListCompression(tempList); 44 | } 45 | 46 | private int bytesCompressed() { 47 | try { 48 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 49 | GZIPOutputStream gos = new GZIPOutputStream(baos); 50 | ObjectOutputStream oos = new ObjectOutputStream(gos); 51 | oos.writeObject(myList); 52 | oos.close(); 53 | return baos.size(); 54 | } catch (IOException ioe) { 55 | System.out.println("Could not compress list!"); 56 | ioe.printStackTrace(); 57 | return 0; 58 | } 59 | 60 | } 61 | 62 | @Override 63 | public double fitness() { 64 | return 1.0 / bytesCompressed(); 65 | } 66 | 67 | @Override 68 | public List crossover(ListCompression other) { 69 | ListCompression child1 = new ListCompression(new ArrayList<>(myList)); 70 | ListCompression child2 = new ListCompression(new ArrayList<>(myList)); 71 | int idx1 = random.nextInt(myList.size()); 72 | int idx2 = random.nextInt(other.myList.size()); 73 | String s1 = myList.get(idx1); 74 | String s2 = other.myList.get(idx2); 75 | int idx3 = myList.indexOf(s2); 76 | int idx4 = other.myList.indexOf(s1); 77 | Collections.swap(child1.myList, idx1, idx3); 78 | Collections.swap(child2.myList, idx2, idx4); 79 | return List.of(child1, child2); 80 | } 81 | 82 | @Override 83 | public void mutate() { 84 | int idx1 = random.nextInt(myList.size()); 85 | int idx2 = random.nextInt(myList.size()); 86 | Collections.swap(myList, idx1, idx2); 87 | } 88 | 89 | @Override 90 | public ListCompression copy() { 91 | return new ListCompression(new ArrayList<>(myList)); 92 | } 93 | 94 | @Override 95 | public String toString() { 96 | return "Order: " + myList + " Bytes: " + bytesCompressed(); 97 | } 98 | 99 | public static void main(String[] args) { 100 | ListCompression originalOrder = new ListCompression(ORIGINAL_LIST); 101 | System.out.println(originalOrder); 102 | ArrayList initialPopulation = new ArrayList<>(); 103 | final int POPULATION_SIZE = 100; 104 | final int GENERATIONS = 100; 105 | final double THRESHOLD = 1.0; 106 | for (int i = 0; i < POPULATION_SIZE; i++) { 107 | initialPopulation.add(ListCompression.randomInstance()); 108 | } 109 | GeneticAlgorithm ga = new GeneticAlgorithm<>( 110 | initialPopulation, 111 | 0.2, 0.7, GeneticAlgorithm.SelectionType.TOURNAMENT); 112 | ListCompression result = ga.run(GENERATIONS, THRESHOLD); 113 | System.out.println(result); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter5/SendMoreMoney2.java: -------------------------------------------------------------------------------- 1 | // SendMoreMoney2.java 2 | // From Classic Computer Science Problems in Java Chapter 5 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter5; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | import java.util.Random; 23 | 24 | public class SendMoreMoney2 extends Chromosome { 25 | 26 | private List letters; 27 | private Random random; 28 | 29 | public SendMoreMoney2(List letters) { 30 | this.letters = letters; 31 | random = new Random(); 32 | } 33 | 34 | public static SendMoreMoney2 randomInstance() { 35 | List letters = new ArrayList<>( 36 | List.of('S', 'E', 'N', 'D', 'M', 'O', 'R', 'Y', ' ', ' ')); 37 | Collections.shuffle(letters); 38 | return new SendMoreMoney2(letters); 39 | } 40 | 41 | @Override 42 | public double fitness() { 43 | int s = letters.indexOf('S'); 44 | int e = letters.indexOf('E'); 45 | int n = letters.indexOf('N'); 46 | int d = letters.indexOf('D'); 47 | int m = letters.indexOf('M'); 48 | int o = letters.indexOf('O'); 49 | int r = letters.indexOf('R'); 50 | int y = letters.indexOf('Y'); 51 | int send = s * 1000 + e * 100 + n * 10 + d; 52 | int more = m * 1000 + o * 100 + r * 10 + e; 53 | int money = m * 10000 + o * 1000 + n * 100 + e * 10 + y; 54 | int difference = Math.abs(money - (send + more)); 55 | return 1.0 / (difference + 1.0); 56 | } 57 | 58 | @Override 59 | public List crossover(SendMoreMoney2 other) { 60 | SendMoreMoney2 child1 = new SendMoreMoney2(new ArrayList<>(letters)); 61 | SendMoreMoney2 child2 = new SendMoreMoney2(new ArrayList<>(other.letters)); 62 | int idx1 = random.nextInt(letters.size()); 63 | int idx2 = random.nextInt(other.letters.size()); 64 | Character l1 = letters.get(idx1); 65 | Character l2 = other.letters.get(idx2); 66 | int idx3 = letters.indexOf(l2); 67 | int idx4 = other.letters.indexOf(l1); 68 | Collections.swap(child1.letters, idx1, idx3); 69 | Collections.swap(child2.letters, idx2, idx4); 70 | return List.of(child1, child2); 71 | } 72 | 73 | @Override 74 | public void mutate() { 75 | int idx1 = random.nextInt(letters.size()); 76 | int idx2 = random.nextInt(letters.size()); 77 | Collections.swap(letters, idx1, idx2); 78 | } 79 | 80 | @Override 81 | public SendMoreMoney2 copy() { 82 | return new SendMoreMoney2(new ArrayList<>(letters)); 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | int s = letters.indexOf('S'); 88 | int e = letters.indexOf('E'); 89 | int n = letters.indexOf('N'); 90 | int d = letters.indexOf('D'); 91 | int m = letters.indexOf('M'); 92 | int o = letters.indexOf('O'); 93 | int r = letters.indexOf('R'); 94 | int y = letters.indexOf('Y'); 95 | int send = s * 1000 + e * 100 + n * 10 + d; 96 | int more = m * 1000 + o * 100 + r * 10 + e; 97 | int money = m * 10000 + o * 1000 + n * 100 + e * 10 + y; 98 | int difference = Math.abs(money - (send + more)); 99 | return (send + " + " + more + " = " + money + " Difference: " + difference); 100 | } 101 | 102 | public static void main(String[] args) { 103 | ArrayList initialPopulation = new ArrayList<>(); 104 | final int POPULATION_SIZE = 1000; 105 | final int GENERATIONS = 1000; 106 | final double THRESHOLD = 1.0; 107 | for (int i = 0; i < POPULATION_SIZE; i++) { 108 | initialPopulation.add(SendMoreMoney2.randomInstance()); 109 | } 110 | GeneticAlgorithm ga = new GeneticAlgorithm<>( 111 | initialPopulation, 112 | 0.2, 0.7, GeneticAlgorithm.SelectionType.ROULETTE); 113 | SendMoreMoney2 result = ga.run(GENERATIONS, THRESHOLD); 114 | System.out.println(result); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter9/TSP.java: -------------------------------------------------------------------------------- 1 | // TSP.java 2 | // From Classic Computer Science Problems in Java Chapter 9 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter9; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | public class TSP { 25 | private final Map> distances; 26 | 27 | public TSP(Map> distances) { 28 | this.distances = distances; 29 | } 30 | 31 | public static void swap(T[] array, int first, int second) { 32 | T temp = array[first]; 33 | array[first] = array[second]; 34 | array[second] = temp; 35 | } 36 | 37 | private static void allPermutationsHelper(T[] permutation, List permutations, int n) { 38 | // Base case - we found a new permutation, add it and return 39 | if (n <= 0) { 40 | permutations.add(permutation); 41 | return; 42 | } 43 | // Recursive case - find more permutations by doing swaps 44 | T[] tempPermutation = Arrays.copyOf(permutation, permutation.length); 45 | for (int i = 0; i < n; i++) { 46 | swap(tempPermutation, i, n - 1); // move element at i to the end 47 | // move everything else around, holding the end constant 48 | allPermutationsHelper(tempPermutation, permutations, n - 1); 49 | swap(tempPermutation, i, n - 1); // backtrack 50 | } 51 | } 52 | 53 | private static List permutations(T[] original) { 54 | List permutations = new ArrayList<>(); 55 | allPermutationsHelper(original, permutations, original.length); 56 | return permutations; 57 | } 58 | 59 | public int pathDistance(String[] path) { 60 | String last = path[0]; 61 | int distance = 0; 62 | for (String next : Arrays.copyOfRange(path, 1, path.length)) { 63 | distance += distances.get(last).get(next); 64 | // distance to get back from last city to first city 65 | last = next; 66 | } 67 | return distance; 68 | } 69 | 70 | public String[] findShortestPath() { 71 | String[] cities = distances.keySet().toArray(String[]::new); 72 | List paths = permutations(cities); 73 | String[] shortestPath = null; 74 | int minDistance = Integer.MAX_VALUE; // arbitrarily high 75 | for (String[] path : paths) { 76 | int distance = pathDistance(path); 77 | // distance from last to first must be added 78 | distance += distances.get(path[path.length - 1]).get(path[0]); 79 | if (distance < minDistance) { 80 | minDistance = distance; 81 | shortestPath = path; 82 | } 83 | } 84 | // add first city on to end and return 85 | shortestPath = Arrays.copyOf(shortestPath, shortestPath.length + 1); 86 | shortestPath[shortestPath.length - 1] = shortestPath[0]; 87 | return shortestPath; 88 | } 89 | 90 | public static void main(String[] args) { 91 | Map> vtDistances = Map.of( 92 | "Rutland", Map.of( 93 | "Burlington", 67, 94 | "White River Junction", 46, 95 | "Bennington", 55, 96 | "Brattleboro", 75), 97 | "Burlington", Map.of( 98 | "Rutland", 67, 99 | "White River Junction", 91, 100 | "Bennington", 122, 101 | "Brattleboro", 153), 102 | "White River Junction", Map.of( 103 | "Rutland", 46, 104 | "Burlington", 91, 105 | "Bennington", 98, 106 | "Brattleboro", 65), 107 | "Bennington", Map.of( 108 | "Rutland", 55, 109 | "Burlington", 122, 110 | "White River Junction", 98, 111 | "Brattleboro", 40), 112 | "Brattleboro", Map.of( 113 | "Rutland", 75, 114 | "Burlington", 153, 115 | "White River Junction", 65, 116 | "Bennington", 40)); 117 | TSP tsp = new TSP(vtDistances); 118 | String[] shortestPath = tsp.findShortestPath(); 119 | int distance = tsp.pathDistance(shortestPath); 120 | System.out.println("The shortest path is " + Arrays.toString(shortestPath) + " in " + 121 | distance + " miles."); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter7/Network.java: -------------------------------------------------------------------------------- 1 | // Network.java 2 | // From Classic Computer Science Problems in Java Chapter 7 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter7; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Optional; 22 | import java.util.function.DoubleUnaryOperator; 23 | import java.util.function.Function; 24 | 25 | public class Network { 26 | private List layers = new ArrayList<>(); 27 | 28 | public Network(int[] layerStructure, double learningRate, 29 | DoubleUnaryOperator activationFunction, DoubleUnaryOperator derivativeActivationFunction) { 30 | if (layerStructure.length < 3) { 31 | throw new IllegalArgumentException("Error: Should be at least 3 layers (1 input, 1 hidden, 1 output)."); 32 | } 33 | // input layer 34 | Layer inputLayer = new Layer(Optional.empty(), layerStructure[0], learningRate, activationFunction, 35 | derivativeActivationFunction); 36 | layers.add(inputLayer); 37 | // hidden layers and output layer 38 | for (int i = 1; i < layerStructure.length; i++) { 39 | Layer nextLayer = new Layer(Optional.of(layers.get(i - 1)), layerStructure[i], learningRate, 40 | activationFunction, 41 | derivativeActivationFunction); 42 | layers.add(nextLayer); 43 | } 44 | } 45 | 46 | // Pushes input data to the first layer, then output from the first 47 | // as input to the second, second to the third, etc. 48 | private double[] outputs(double[] input) { 49 | double[] result = input; 50 | for (Layer layer : layers) { 51 | result = layer.outputs(result); 52 | } 53 | return result; 54 | 55 | } 56 | 57 | // Figure out each neuron's changes based on the errors of the output 58 | // versus the expected outcome 59 | private void backpropagate(double[] expected) { 60 | // calculate delta for output layer neurons 61 | int lastLayer = layers.size() - 1; 62 | layers.get(lastLayer).calculateDeltasForOutputLayer(expected); 63 | // calculate delta for hidden layers in reverse order 64 | for (int i = lastLayer - 1; i >= 0; i--) { 65 | layers.get(i).calculateDeltasForHiddenLayer(layers.get(i + 1)); 66 | } 67 | } 68 | 69 | // backpropagate() doesn't actually change any weights 70 | // this function uses the deltas calculated in backpropagate() to 71 | // actually make changes to the weights 72 | private void updateWeights() { 73 | for (Layer layer : layers.subList(1, layers.size())) { 74 | for (Neuron neuron : layer.neurons) { 75 | for (int w = 0; w < neuron.weights.length; w++) { 76 | neuron.weights[w] = neuron.weights[w] + (neuron.learningRate * 77 | layer.previousLayer.get().outputCache[w] * neuron.delta); 78 | } 79 | } 80 | } 81 | } 82 | 83 | // train() uses the results of outputs() run over many inputs and compared 84 | // against expecteds to feed backpropagate() and updateWeights() 85 | public void train(List inputs, List expecteds) { 86 | for (int i = 0; i < inputs.size(); i++) { 87 | double[] xs = inputs.get(i); 88 | double[] ys = expecteds.get(i); 89 | outputs(xs); 90 | backpropagate(ys); 91 | updateWeights(); 92 | } 93 | } 94 | 95 | public class Results { 96 | public final int correct; 97 | public final int trials; 98 | public final double percentage; 99 | 100 | public Results(int correct, int trials, double percentage) { 101 | this.correct = correct; 102 | this.trials = trials; 103 | this.percentage = percentage; 104 | } 105 | } 106 | 107 | // for generalized results that require classification 108 | // this function will return the correct number of trials 109 | // and the percentage correct out of the total 110 | public Results validate(List inputs, List expecteds, Function interpret) { 111 | int correct = 0; 112 | for (int i = 0; i < inputs.size(); i++) { 113 | double[] input = inputs.get(i); 114 | T expected = expecteds.get(i); 115 | T result = interpret.apply(outputs(input)); 116 | if (result.equals(expected)) { 117 | correct++; 118 | } 119 | } 120 | double percentage = (double) correct / (double) inputs.size(); 121 | return new Results(correct, inputs.size(), percentage); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter6/Governor.java: -------------------------------------------------------------------------------- 1 | // Governor.java 2 | // From Classic Computer Science Problems in Java Chapter 6 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter6; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public class Governor extends DataPoint { 23 | private double longitude; 24 | private double age; 25 | private String state; 26 | 27 | public Governor(double longitude, double age, String state) { 28 | super(List.of(longitude, age)); 29 | this.longitude = longitude; 30 | this.age = age; 31 | this.state = state; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | return state + ": (longitude: " + longitude + ", age: " + age + ")"; 37 | } 38 | 39 | public static void main(String[] args) { 40 | List governors = new ArrayList<>(); 41 | governors.add(new Governor(-86.79113, 72, "Alabama")); 42 | governors.add(new Governor(-152.404419, 66, "Alaska")); 43 | governors.add(new Governor(-111.431221, 53, "Arizona")); 44 | governors.add(new Governor(-92.373123, 66, "Arkansas")); 45 | governors.add(new Governor(-119.681564, 79, "California")); 46 | governors.add(new Governor(-105.311104, 65, "Colorado")); 47 | governors.add(new Governor(-72.755371, 61, "Connecticut")); 48 | governors.add(new Governor(-75.507141, 61, "Delaware")); 49 | governors.add(new Governor(-81.686783, 64, "Florida")); 50 | governors.add(new Governor(-83.643074, 74, "Georgia")); 51 | governors.add(new Governor(-157.498337, 60, "Hawaii")); 52 | governors.add(new Governor(-114.478828, 75, "Idaho")); 53 | governors.add(new Governor(-88.986137, 60, "Illinois")); 54 | governors.add(new Governor(-86.258278, 49, "Indiana")); 55 | governors.add(new Governor(-93.210526, 57, "Iowa")); 56 | governors.add(new Governor(-96.726486, 60, "Kansas")); 57 | governors.add(new Governor(-84.670067, 50, "Kentucky")); 58 | governors.add(new Governor(-91.867805, 50, "Louisiana")); 59 | governors.add(new Governor(-69.381927, 68, "Maine")); 60 | governors.add(new Governor(-76.802101, 61, "Maryland")); 61 | governors.add(new Governor(-71.530106, 60, "Massachusetts")); 62 | governors.add(new Governor(-84.536095, 58, "Michigan")); 63 | governors.add(new Governor(-93.900192, 70, "Minnesota")); 64 | governors.add(new Governor(-89.678696, 62, "Mississippi")); 65 | governors.add(new Governor(-92.288368, 43, "Missouri")); 66 | governors.add(new Governor(-110.454353, 51, "Montana")); 67 | governors.add(new Governor(-98.268082, 52, "Nebraska")); 68 | governors.add(new Governor(-117.055374, 53, "Nevada")); 69 | governors.add(new Governor(-71.563896, 42, "New Hampshire")); 70 | governors.add(new Governor(-74.521011, 54, "New Jersey")); 71 | governors.add(new Governor(-106.248482, 57, "New Mexico")); 72 | governors.add(new Governor(-74.948051, 59, "New York")); 73 | governors.add(new Governor(-79.806419, 60, "North Carolina")); 74 | governors.add(new Governor(-99.784012, 60, "North Dakota")); 75 | governors.add(new Governor(-82.764915, 65, "Ohio")); 76 | governors.add(new Governor(-96.928917, 62, "Oklahoma")); 77 | governors.add(new Governor(-122.070938, 56, "Oregon")); 78 | governors.add(new Governor(-77.209755, 68, "Pennsylvania")); 79 | governors.add(new Governor(-71.51178, 46, "Rhode Island")); 80 | governors.add(new Governor(-80.945007, 70, "South Carolina")); 81 | governors.add(new Governor(-99.438828, 64, "South Dakota")); 82 | governors.add(new Governor(-86.692345, 58, "Tennessee")); 83 | governors.add(new Governor(-97.563461, 59, "Texas")); 84 | governors.add(new Governor(-111.862434, 70, "Utah")); 85 | governors.add(new Governor(-72.710686, 58, "Vermont")); 86 | governors.add(new Governor(-78.169968, 60, "Virginia")); 87 | governors.add(new Governor(-121.490494, 66, "Washington")); 88 | governors.add(new Governor(-80.954453, 66, "West Virginia")); 89 | governors.add(new Governor(-89.616508, 49, "Wisconsin")); 90 | governors.add(new Governor(-107.30249, 55, "Wyoming")); 91 | 92 | KMeans kmeans = new KMeans<>(2, governors); 93 | List.Cluster> govClusters = kmeans.run(100); 94 | for (int clusterIndex = 0; clusterIndex < govClusters.size(); clusterIndex++) { 95 | System.out.printf("Cluster %d: %s%n", clusterIndex, govClusters.get(clusterIndex).points); 96 | } 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter5/GeneticAlgorithm.java: -------------------------------------------------------------------------------- 1 | // GeneticAlgorithm.java 2 | // From Classic Computer Science Problems in Java Chapter 5 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter5; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.List; 22 | import java.util.Random; 23 | 24 | public class GeneticAlgorithm> { 25 | 26 | public enum SelectionType { 27 | ROULETTE, TOURNAMENT; 28 | } 29 | 30 | private ArrayList population; 31 | private double mutationChance; 32 | private double crossoverChance; 33 | private SelectionType selectionType; 34 | private Random random; 35 | 36 | public GeneticAlgorithm(List initialPopulation, 37 | double mutationChance, double crossoverChance, SelectionType selectionType) { 38 | this.population = new ArrayList<>(initialPopulation); 39 | this.mutationChance = mutationChance; 40 | this.crossoverChance = crossoverChance; 41 | this.selectionType = selectionType; 42 | this.random = new Random(); 43 | } 44 | 45 | // Use the probability distribution wheel to pick numPicks individuals 46 | private List pickRoulette(double[] wheel, int numPicks) { 47 | List picks = new ArrayList<>(); 48 | for (int i = 0; i < numPicks; i++) { 49 | double pick = random.nextDouble(); 50 | for (int j = 0; j < wheel.length; j++) { 51 | pick -= wheel[j]; 52 | if (pick <= 0) { // we had one that took us over, leads to a pick 53 | picks.add(population.get(j)); 54 | break; 55 | } 56 | } 57 | } 58 | return picks; 59 | } 60 | 61 | // Pick a certain number of individuals via a tournament 62 | private List pickTournament(int numParticipants, int numPicks) { 63 | // Find numParticipants random participants to be in the tournament 64 | Collections.shuffle(population); 65 | List tournament = population.subList(0, numParticipants); 66 | // Find the numPicks highest fitnesses in the tournament 67 | Collections.sort(tournament, Collections.reverseOrder()); 68 | return tournament.subList(0, numPicks); 69 | } 70 | 71 | // Replace the population with a new generation of individuals 72 | private void reproduceAndReplace() { 73 | ArrayList nextPopulation = new ArrayList<>(); 74 | // keep going until we've filled the new generation 75 | while (nextPopulation.size() < population.size()) { 76 | // pick the two parents 77 | List parents; 78 | if (selectionType == SelectionType.ROULETTE) { 79 | // create the probability distribution wheel 80 | double totalFitness = population.stream() 81 | .mapToDouble(C::fitness).sum(); 82 | double[] wheel = population.stream() 83 | .mapToDouble(C -> C.fitness() 84 | / totalFitness) 85 | .toArray(); 86 | parents = pickRoulette(wheel, 2); 87 | } else { // tournament 88 | parents = pickTournament(population.size() / 2, 2); 89 | } 90 | // potentially crossover the 2 parents 91 | if (random.nextDouble() < crossoverChance) { 92 | C parent1 = parents.get(0); 93 | C parent2 = parents.get(1); 94 | nextPopulation.addAll(parent1.crossover(parent2)); 95 | } else { // just add the two parents 96 | nextPopulation.addAll(parents); 97 | } 98 | } 99 | // if we have an odd number, we'll have 1 exra, so we remove it 100 | if (nextPopulation.size() > population.size()) { 101 | nextPopulation.remove(0); 102 | } 103 | // replace the reference/generation 104 | population = nextPopulation; 105 | } 106 | 107 | // With mutationChance probability, mutate each individual 108 | private void mutate() { 109 | for (C individual : population) { 110 | if (random.nextDouble() < mutationChance) { 111 | individual.mutate(); 112 | } 113 | } 114 | } 115 | 116 | // Run the genetic algorithm for maxGenerations iterations 117 | // and return the best individual found 118 | public C run(int maxGenerations, double threshold) { 119 | C best = Collections.max(population).copy(); 120 | for (int generation = 0; generation < maxGenerations; generation++) { 121 | // early exit if we beat threshold 122 | if (best.fitness() >= threshold) { 123 | return best; 124 | } 125 | // Debug printout 126 | System.out.println("Generation " + generation + 127 | " Best " + best.fitness() + 128 | " Avg " + population.stream() 129 | .mapToDouble(C::fitness).average().orElse(0.0)); 130 | reproduceAndReplace(); 131 | mutate(); 132 | C highest = Collections.max(population); 133 | if (highest.fitness() > best.fitness()) { 134 | best = highest.copy(); 135 | } 136 | } 137 | return best; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter7/data/iris.csv: -------------------------------------------------------------------------------- 1 | 5.1,3.5,1.4,0.2,Iris-setosa 2 | 4.9,3.0,1.4,0.2,Iris-setosa 3 | 4.7,3.2,1.3,0.2,Iris-setosa 4 | 4.6,3.1,1.5,0.2,Iris-setosa 5 | 5.0,3.6,1.4,0.2,Iris-setosa 6 | 5.4,3.9,1.7,0.4,Iris-setosa 7 | 4.6,3.4,1.4,0.3,Iris-setosa 8 | 5.0,3.4,1.5,0.2,Iris-setosa 9 | 4.4,2.9,1.4,0.2,Iris-setosa 10 | 4.9,3.1,1.5,0.1,Iris-setosa 11 | 5.4,3.7,1.5,0.2,Iris-setosa 12 | 4.8,3.4,1.6,0.2,Iris-setosa 13 | 4.8,3.0,1.4,0.1,Iris-setosa 14 | 4.3,3.0,1.1,0.1,Iris-setosa 15 | 5.8,4.0,1.2,0.2,Iris-setosa 16 | 5.7,4.4,1.5,0.4,Iris-setosa 17 | 5.4,3.9,1.3,0.4,Iris-setosa 18 | 5.1,3.5,1.4,0.3,Iris-setosa 19 | 5.7,3.8,1.7,0.3,Iris-setosa 20 | 5.1,3.8,1.5,0.3,Iris-setosa 21 | 5.4,3.4,1.7,0.2,Iris-setosa 22 | 5.1,3.7,1.5,0.4,Iris-setosa 23 | 4.6,3.6,1.0,0.2,Iris-setosa 24 | 5.1,3.3,1.7,0.5,Iris-setosa 25 | 4.8,3.4,1.9,0.2,Iris-setosa 26 | 5.0,3.0,1.6,0.2,Iris-setosa 27 | 5.0,3.4,1.6,0.4,Iris-setosa 28 | 5.2,3.5,1.5,0.2,Iris-setosa 29 | 5.2,3.4,1.4,0.2,Iris-setosa 30 | 4.7,3.2,1.6,0.2,Iris-setosa 31 | 4.8,3.1,1.6,0.2,Iris-setosa 32 | 5.4,3.4,1.5,0.4,Iris-setosa 33 | 5.2,4.1,1.5,0.1,Iris-setosa 34 | 5.5,4.2,1.4,0.2,Iris-setosa 35 | 4.9,3.1,1.5,0.2,Iris-setosa 36 | 5.0,3.2,1.2,0.2,Iris-setosa 37 | 5.5,3.5,1.3,0.2,Iris-setosa 38 | 4.9,3.6,1.4,0.1,Iris-setosa 39 | 4.4,3.0,1.3,0.2,Iris-setosa 40 | 5.1,3.4,1.5,0.2,Iris-setosa 41 | 5.0,3.5,1.3,0.3,Iris-setosa 42 | 4.5,2.3,1.3,0.3,Iris-setosa 43 | 4.4,3.2,1.3,0.2,Iris-setosa 44 | 5.0,3.5,1.6,0.6,Iris-setosa 45 | 5.1,3.8,1.9,0.4,Iris-setosa 46 | 4.8,3.0,1.4,0.3,Iris-setosa 47 | 5.1,3.8,1.6,0.2,Iris-setosa 48 | 4.6,3.2,1.4,0.2,Iris-setosa 49 | 5.3,3.7,1.5,0.2,Iris-setosa 50 | 5.0,3.3,1.4,0.2,Iris-setosa 51 | 7.0,3.2,4.7,1.4,Iris-versicolor 52 | 6.4,3.2,4.5,1.5,Iris-versicolor 53 | 6.9,3.1,4.9,1.5,Iris-versicolor 54 | 5.5,2.3,4.0,1.3,Iris-versicolor 55 | 6.5,2.8,4.6,1.5,Iris-versicolor 56 | 5.7,2.8,4.5,1.3,Iris-versicolor 57 | 6.3,3.3,4.7,1.6,Iris-versicolor 58 | 4.9,2.4,3.3,1.0,Iris-versicolor 59 | 6.6,2.9,4.6,1.3,Iris-versicolor 60 | 5.2,2.7,3.9,1.4,Iris-versicolor 61 | 5.0,2.0,3.5,1.0,Iris-versicolor 62 | 5.9,3.0,4.2,1.5,Iris-versicolor 63 | 6.0,2.2,4.0,1.0,Iris-versicolor 64 | 6.1,2.9,4.7,1.4,Iris-versicolor 65 | 5.6,2.9,3.6,1.3,Iris-versicolor 66 | 6.7,3.1,4.4,1.4,Iris-versicolor 67 | 5.6,3.0,4.5,1.5,Iris-versicolor 68 | 5.8,2.7,4.1,1.0,Iris-versicolor 69 | 6.2,2.2,4.5,1.5,Iris-versicolor 70 | 5.6,2.5,3.9,1.1,Iris-versicolor 71 | 5.9,3.2,4.8,1.8,Iris-versicolor 72 | 6.1,2.8,4.0,1.3,Iris-versicolor 73 | 6.3,2.5,4.9,1.5,Iris-versicolor 74 | 6.1,2.8,4.7,1.2,Iris-versicolor 75 | 6.4,2.9,4.3,1.3,Iris-versicolor 76 | 6.6,3.0,4.4,1.4,Iris-versicolor 77 | 6.8,2.8,4.8,1.4,Iris-versicolor 78 | 6.7,3.0,5.0,1.7,Iris-versicolor 79 | 6.0,2.9,4.5,1.5,Iris-versicolor 80 | 5.7,2.6,3.5,1.0,Iris-versicolor 81 | 5.5,2.4,3.8,1.1,Iris-versicolor 82 | 5.5,2.4,3.7,1.0,Iris-versicolor 83 | 5.8,2.7,3.9,1.2,Iris-versicolor 84 | 6.0,2.7,5.1,1.6,Iris-versicolor 85 | 5.4,3.0,4.5,1.5,Iris-versicolor 86 | 6.0,3.4,4.5,1.6,Iris-versicolor 87 | 6.7,3.1,4.7,1.5,Iris-versicolor 88 | 6.3,2.3,4.4,1.3,Iris-versicolor 89 | 5.6,3.0,4.1,1.3,Iris-versicolor 90 | 5.5,2.5,4.0,1.3,Iris-versicolor 91 | 5.5,2.6,4.4,1.2,Iris-versicolor 92 | 6.1,3.0,4.6,1.4,Iris-versicolor 93 | 5.8,2.6,4.0,1.2,Iris-versicolor 94 | 5.0,2.3,3.3,1.0,Iris-versicolor 95 | 5.6,2.7,4.2,1.3,Iris-versicolor 96 | 5.7,3.0,4.2,1.2,Iris-versicolor 97 | 5.7,2.9,4.2,1.3,Iris-versicolor 98 | 6.2,2.9,4.3,1.3,Iris-versicolor 99 | 5.1,2.5,3.0,1.1,Iris-versicolor 100 | 5.7,2.8,4.1,1.3,Iris-versicolor 101 | 6.3,3.3,6.0,2.5,Iris-virginica 102 | 5.8,2.7,5.1,1.9,Iris-virginica 103 | 7.1,3.0,5.9,2.1,Iris-virginica 104 | 6.3,2.9,5.6,1.8,Iris-virginica 105 | 6.5,3.0,5.8,2.2,Iris-virginica 106 | 7.6,3.0,6.6,2.1,Iris-virginica 107 | 4.9,2.5,4.5,1.7,Iris-virginica 108 | 7.3,2.9,6.3,1.8,Iris-virginica 109 | 6.7,2.5,5.8,1.8,Iris-virginica 110 | 7.2,3.6,6.1,2.5,Iris-virginica 111 | 6.5,3.2,5.1,2.0,Iris-virginica 112 | 6.4,2.7,5.3,1.9,Iris-virginica 113 | 6.8,3.0,5.5,2.1,Iris-virginica 114 | 5.7,2.5,5.0,2.0,Iris-virginica 115 | 5.8,2.8,5.1,2.4,Iris-virginica 116 | 6.4,3.2,5.3,2.3,Iris-virginica 117 | 6.5,3.0,5.5,1.8,Iris-virginica 118 | 7.7,3.8,6.7,2.2,Iris-virginica 119 | 7.7,2.6,6.9,2.3,Iris-virginica 120 | 6.0,2.2,5.0,1.5,Iris-virginica 121 | 6.9,3.2,5.7,2.3,Iris-virginica 122 | 5.6,2.8,4.9,2.0,Iris-virginica 123 | 7.7,2.8,6.7,2.0,Iris-virginica 124 | 6.3,2.7,4.9,1.8,Iris-virginica 125 | 6.7,3.3,5.7,2.1,Iris-virginica 126 | 7.2,3.2,6.0,1.8,Iris-virginica 127 | 6.2,2.8,4.8,1.8,Iris-virginica 128 | 6.1,3.0,4.9,1.8,Iris-virginica 129 | 6.4,2.8,5.6,2.1,Iris-virginica 130 | 7.2,3.0,5.8,1.6,Iris-virginica 131 | 7.4,2.8,6.1,1.9,Iris-virginica 132 | 7.9,3.8,6.4,2.0,Iris-virginica 133 | 6.4,2.8,5.6,2.2,Iris-virginica 134 | 6.3,2.8,5.1,1.5,Iris-virginica 135 | 6.1,2.6,5.6,1.4,Iris-virginica 136 | 7.7,3.0,6.1,2.3,Iris-virginica 137 | 6.3,3.4,5.6,2.4,Iris-virginica 138 | 6.4,3.1,5.5,1.8,Iris-virginica 139 | 6.0,3.0,4.8,1.8,Iris-virginica 140 | 6.9,3.1,5.4,2.1,Iris-virginica 141 | 6.7,3.1,5.6,2.4,Iris-virginica 142 | 6.9,3.1,5.1,2.3,Iris-virginica 143 | 5.8,2.7,5.1,1.9,Iris-virginica 144 | 6.8,3.2,5.9,2.3,Iris-virginica 145 | 6.7,3.3,5.7,2.5,Iris-virginica 146 | 6.7,3.0,5.2,2.3,Iris-virginica 147 | 6.3,2.5,5.0,1.9,Iris-virginica 148 | 6.5,3.0,5.2,2.0,Iris-virginica 149 | 6.2,3.4,5.4,2.3,Iris-virginica 150 | 5.9,3.0,5.1,1.8,Iris-virginica 151 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter3/WordGrid.java: -------------------------------------------------------------------------------- 1 | // WordGrid.java 2 | // From Classic Computer Science Problems in Java Chapter 3 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter3; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Random; 22 | 23 | public class WordGrid { 24 | 25 | public static class GridLocation { 26 | public final int row, column; 27 | 28 | public GridLocation(int row, int column) { 29 | this.row = row; 30 | this.column = column; 31 | } 32 | 33 | // auto-generated by Eclipse 34 | @Override 35 | public int hashCode() { 36 | final int prime = 31; 37 | int result = 1; 38 | result = prime * result + column; 39 | result = prime * result + row; 40 | return result; 41 | } 42 | 43 | // auto-generated by Eclipse 44 | @Override 45 | public boolean equals(Object obj) { 46 | if (this == obj) { 47 | return true; 48 | } 49 | if (obj == null) { 50 | return false; 51 | } 52 | if (getClass() != obj.getClass()) { 53 | return false; 54 | } 55 | GridLocation other = (GridLocation) obj; 56 | if (column != other.column) { 57 | return false; 58 | } 59 | if (row != other.row) { 60 | return false; 61 | } 62 | return true; 63 | } 64 | } 65 | 66 | private final char ALPHABET_LENGTH = 26; 67 | private final char FIRST_LETTER = 'A'; 68 | private final int rows, columns; 69 | private char[][] grid; 70 | 71 | public WordGrid(int rows, int columns) { 72 | this.rows = rows; 73 | this.columns = columns; 74 | grid = new char[rows][columns]; 75 | // initialize grid with random letters 76 | Random random = new Random(); 77 | for (int row = 0; row < rows; row++) { 78 | for (int column = 0; column < columns; column++) { 79 | char randomLetter = (char) (random.nextInt(ALPHABET_LENGTH) + FIRST_LETTER); 80 | grid[row][column] = randomLetter; 81 | } 82 | } 83 | } 84 | 85 | public void mark(String word, List locations) { 86 | for (int i = 0; i < word.length(); i++) { 87 | GridLocation location = locations.get(i); 88 | grid[location.row][location.column] = word.charAt(i); 89 | } 90 | } 91 | 92 | // get a pretty printed version of the grid 93 | @Override 94 | public String toString() { 95 | StringBuilder sb = new StringBuilder(); 96 | for (char[] rowArray : grid) { 97 | sb.append(rowArray); 98 | sb.append(System.lineSeparator()); 99 | } 100 | return sb.toString(); 101 | } 102 | 103 | public List> generateDomain(String word) { 104 | List> domain = new ArrayList<>(); 105 | int length = word.length(); 106 | 107 | for (int row = 0; row < rows; row++) { 108 | for (int column = 0; column < columns; column++) { 109 | if (column + length <= columns) { 110 | // left to right 111 | fillRight(domain, row, column, length); 112 | // diagonal towards bottom right 113 | if (row + length <= rows) { 114 | fillDiagonalRight(domain, row, column, length); 115 | } 116 | } 117 | if (row + length <= rows) { 118 | // top to bottom 119 | fillDown(domain, row, column, length); 120 | // diagonal towards bottom left 121 | if (column - length >= 0) { 122 | fillDiagonalLeft(domain, row, column, length); 123 | } 124 | } 125 | } 126 | } 127 | return domain; 128 | } 129 | 130 | private void fillRight(List> domain, int row, int column, int length) { 131 | List locations = new ArrayList<>(); 132 | for (int c = column; c < (column + length); c++) { 133 | locations.add(new GridLocation(row, c)); 134 | } 135 | domain.add(locations); 136 | } 137 | 138 | private void fillDiagonalRight(List> domain, int row, int column, int length) { 139 | List locations = new ArrayList<>(); 140 | int r = row; 141 | for (int c = column; c < (column + length); c++) { 142 | locations.add(new GridLocation(r, c)); 143 | r++; 144 | } 145 | domain.add(locations); 146 | } 147 | 148 | private void fillDown(List> domain, int row, int column, int length) { 149 | List locations = new ArrayList<>(); 150 | for (int r = row; r < (row + length); r++) { 151 | locations.add(new GridLocation(r, column)); 152 | } 153 | domain.add(locations); 154 | } 155 | 156 | private void fillDiagonalLeft(List> domain, int row, int column, int length) { 157 | List locations = new ArrayList<>(); 158 | int c = column; 159 | for (int r = row; r < (row + length); r++) { 160 | locations.add(new GridLocation(r, c)); 161 | c--; 162 | } 163 | domain.add(locations); 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter2/MCState.java: -------------------------------------------------------------------------------- 1 | // MCState.java 2 | // From Classic Computer Science Problems in Java Chapter 2 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter2; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.function.Predicate; 22 | 23 | import chapter2.GenericSearch.Node; 24 | 25 | public class MCState { 26 | private static final int MAX_NUM = 3; 27 | private final int wm; // west bank missionaries 28 | private final int wc; // west bank cannibals 29 | private final int em; // east bank missionaries 30 | private final int ec; // east bank cannibals 31 | private final boolean boat; // is boat on west bank? 32 | 33 | public MCState(int missionaries, int cannibals, boolean boat) { 34 | wm = missionaries; 35 | wc = cannibals; 36 | em = MAX_NUM - wm; 37 | ec = MAX_NUM - wc; 38 | this.boat = boat; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return String.format( 44 | "On the west bank there are %d missionaries and %d cannibals.%n" 45 | + "On the east bank there are %d missionaries and %d cannibals.%n" 46 | + "The boat is on the %s bank.", 47 | wm, wc, em, ec, 48 | boat ? "west" : "east"); 49 | } 50 | 51 | public boolean goalTest() { 52 | return isLegal() && em == MAX_NUM && ec == MAX_NUM; 53 | } 54 | 55 | public boolean isLegal() { 56 | if (wm < wc && wm > 0) { 57 | return false; 58 | } 59 | if (em < ec && em > 0) { 60 | return false; 61 | } 62 | return true; 63 | } 64 | 65 | public static List successors(MCState mcs) { 66 | List sucs = new ArrayList<>(); 67 | if (mcs.boat) { // boat on west bank 68 | if (mcs.wm > 1) { 69 | sucs.add(new MCState(mcs.wm - 2, mcs.wc, !mcs.boat)); 70 | } 71 | if (mcs.wm > 0) { 72 | sucs.add(new MCState(mcs.wm - 1, mcs.wc, !mcs.boat)); 73 | } 74 | if (mcs.wc > 1) { 75 | sucs.add(new MCState(mcs.wm, mcs.wc - 2, !mcs.boat)); 76 | } 77 | if (mcs.wc > 0) { 78 | sucs.add(new MCState(mcs.wm, mcs.wc - 1, !mcs.boat)); 79 | } 80 | if (mcs.wc > 0 && mcs.wm > 0) { 81 | sucs.add(new MCState(mcs.wm - 1, mcs.wc - 1, !mcs.boat)); 82 | } 83 | } else { // boat on east bank 84 | if (mcs.em > 1) { 85 | sucs.add(new MCState(mcs.wm + 2, mcs.wc, !mcs.boat)); 86 | } 87 | if (mcs.em > 0) { 88 | sucs.add(new MCState(mcs.wm + 1, mcs.wc, !mcs.boat)); 89 | } 90 | if (mcs.ec > 1) { 91 | sucs.add(new MCState(mcs.wm, mcs.wc + 2, !mcs.boat)); 92 | } 93 | if (mcs.ec > 0) { 94 | sucs.add(new MCState(mcs.wm, mcs.wc + 1, !mcs.boat)); 95 | } 96 | if (mcs.ec > 0 && mcs.em > 0) { 97 | sucs.add(new MCState(mcs.wm + 1, mcs.wc + 1, !mcs.boat)); 98 | } 99 | } 100 | sucs.removeIf(Predicate.not(MCState::isLegal)); 101 | return sucs; 102 | } 103 | 104 | public static void displaySolution(List path) { 105 | if (path.size() == 0) { // sanity check 106 | return; 107 | } 108 | MCState oldState = path.get(0); 109 | System.out.println(oldState); 110 | for (MCState currentState : path.subList(1, path.size())) { 111 | if (currentState.boat) { 112 | System.out.printf("%d missionaries and %d cannibals moved from the east bank to the west bank.%n", 113 | oldState.em - currentState.em, 114 | oldState.ec - currentState.ec); 115 | } else { 116 | System.out.printf("%d missionaries and %d cannibals moved from the west bank to the east bank.%n", 117 | oldState.wm - currentState.wm, 118 | oldState.wc - currentState.wc); 119 | } 120 | System.out.println(currentState); 121 | oldState = currentState; 122 | } 123 | } 124 | 125 | // auto-generated by Eclipse 126 | @Override 127 | public int hashCode() { 128 | final int prime = 31; 129 | int result = 1; 130 | result = prime * result + (boat ? 1231 : 1237); 131 | result = prime * result + ec; 132 | result = prime * result + em; 133 | result = prime * result + wc; 134 | result = prime * result + wm; 135 | return result; 136 | } 137 | 138 | // auto-generated by Eclipse 139 | @Override 140 | public boolean equals(Object obj) { 141 | if (this == obj) { 142 | return true; 143 | } 144 | if (obj == null) { 145 | return false; 146 | } 147 | if (getClass() != obj.getClass()) { 148 | return false; 149 | } 150 | MCState other = (MCState) obj; 151 | if (boat != other.boat) { 152 | return false; 153 | } 154 | if (ec != other.ec) { 155 | return false; 156 | } 157 | if (em != other.em) { 158 | return false; 159 | } 160 | if (wc != other.wc) { 161 | return false; 162 | } 163 | if (wm != other.wm) { 164 | return false; 165 | } 166 | return true; 167 | } 168 | 169 | public static void main(String[] args) { 170 | MCState start = new MCState(MAX_NUM, MAX_NUM, true); 171 | Node solution = GenericSearch.bfs(start, MCState::goalTest, MCState::successors); 172 | if (solution == null) { 173 | System.out.println("No solution found!"); 174 | } else { 175 | List path = GenericSearch.nodeToPath(solution); 176 | displaySolution(path); 177 | } 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter6/KMeans.java: -------------------------------------------------------------------------------- 1 | // KMeans.java 2 | // From Classic Computer Science Problems in Java Chapter 6 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter6; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Random; 22 | import java.util.stream.Collectors; 23 | 24 | public class KMeans { 25 | 26 | public class Cluster { 27 | public List points; 28 | public DataPoint centroid; 29 | 30 | public Cluster(List points, DataPoint randPoint) { 31 | this.points = points; 32 | this.centroid = randPoint; 33 | } 34 | } 35 | 36 | private List points; 37 | private List clusters; 38 | 39 | public KMeans(int k, List points) { 40 | if (k < 1) { // can't have negative or zero clusters 41 | throw new IllegalArgumentException("k must be >= 1"); 42 | } 43 | this.points = points; 44 | zScoreNormalize(); 45 | // initialize empty clusters with random centroids 46 | clusters = new ArrayList<>(); 47 | for (int i = 0; i < k; i++) { 48 | DataPoint randPoint = randomPoint(); 49 | Cluster cluster = new Cluster(new ArrayList(), randPoint); 50 | clusters.add(cluster); 51 | } 52 | } 53 | 54 | private List centroids() { 55 | return clusters.stream().map(cluster -> cluster.centroid) 56 | .collect(Collectors.toList()); 57 | } 58 | 59 | private List dimensionSlice(int dimension) { 60 | return points.stream().map(x -> x.dimensions.get(dimension)) 61 | .collect(Collectors.toList()); 62 | } 63 | 64 | private void zScoreNormalize() { 65 | List> zscored = new ArrayList<>(); 66 | for (Point point : points) { 67 | zscored.add(new ArrayList()); 68 | } 69 | for (int dimension = 0; dimension < points.get(0).numDimensions; dimension++) { 70 | List dimensionSlice = dimensionSlice(dimension); 71 | Statistics stats = new Statistics(dimensionSlice); 72 | List zscores = stats.zscored(); 73 | for (int index = 0; index < zscores.size(); index++) { 74 | zscored.get(index).add(zscores.get(index)); 75 | } 76 | } 77 | for (int i = 0; i < points.size(); i++) { 78 | points.get(i).dimensions = zscored.get(i); 79 | } 80 | } 81 | 82 | private DataPoint randomPoint() { 83 | List randDimensions = new ArrayList<>(); 84 | Random random = new Random(); 85 | for (int dimension = 0; dimension < points.get(0).numDimensions; dimension++) { 86 | List values = dimensionSlice(dimension); 87 | Statistics stats = new Statistics(values); 88 | Double randValue = random.doubles(stats.min(), stats.max()).findFirst().getAsDouble(); 89 | randDimensions.add(randValue); 90 | } 91 | return new DataPoint(randDimensions); 92 | } 93 | 94 | // Find the closest cluster centroid to each point and assign the point 95 | // to that cluster 96 | private void assignClusters() { 97 | for (Point point : points) { 98 | double lowestDistance = Double.MAX_VALUE; 99 | Cluster closestCluster = clusters.get(0); 100 | for (Cluster cluster : clusters) { 101 | double centroidDistance = point.distance(cluster.centroid); 102 | if (centroidDistance < lowestDistance) { 103 | lowestDistance = centroidDistance; 104 | closestCluster = cluster; 105 | } 106 | } 107 | closestCluster.points.add(point); 108 | } 109 | } 110 | 111 | // Find the center of each cluster and move the centroid to there 112 | private void generateCentroids() { 113 | for (Cluster cluster : clusters) { 114 | // Ignore if the cluster is empty 115 | if (cluster.points.isEmpty()) { 116 | continue; 117 | } 118 | List means = new ArrayList<>(); 119 | for (int i = 0; i < cluster.points.get(0).numDimensions; i++) { 120 | int dimension = i; // needed to use in scope of closure 121 | Double dimensionMean = cluster.points.stream() 122 | .mapToDouble(x -> x.dimensions.get(dimension)).average().getAsDouble(); 123 | means.add(dimensionMean); 124 | } 125 | cluster.centroid = new DataPoint(means); 126 | } 127 | } 128 | 129 | // Check if two Lists of DataPoints are of equivalent DataPoints 130 | private boolean listsEqual(List first, List second) { 131 | if (first.size() != second.size()) { 132 | return false; 133 | } 134 | for (int i = 0; i < first.size(); i++) { 135 | for (int j = 0; j < first.get(0).numDimensions; j++) { 136 | if (first.get(i).dimensions.get(j).doubleValue() != second.get(i).dimensions.get(j).doubleValue()) { 137 | return false; 138 | } 139 | } 140 | } 141 | return true; 142 | } 143 | 144 | public List run(int maxIterations) { 145 | for (int iteration = 0; iteration < maxIterations; iteration++) { 146 | for (Cluster cluster : clusters) { // clear all clusters 147 | cluster.points.clear(); 148 | } 149 | assignClusters(); 150 | List oldCentroids = new ArrayList<>(centroids()); 151 | generateCentroids(); // find new centroids 152 | if (listsEqual(oldCentroids, centroids())) { 153 | System.out.println("Converged after " + iteration + " iterations."); 154 | return clusters; 155 | } 156 | } 157 | return clusters; 158 | } 159 | 160 | public static void main(String[] args) { 161 | DataPoint point1 = new DataPoint(List.of(2.0, 1.0, 1.0)); 162 | DataPoint point2 = new DataPoint(List.of(2.0, 2.0, 5.0)); 163 | DataPoint point3 = new DataPoint(List.of(3.0, 1.5, 2.5)); 164 | KMeans kmeansTest = new KMeans<>(2, List.of(point1, point2, point3)); 165 | List.Cluster> testClusters = kmeansTest.run(100); 166 | for (int clusterIndex = 0; clusterIndex < testClusters.size(); clusterIndex++) { 167 | System.out.println("Cluster " + clusterIndex + ": " 168 | + testClusters.get(clusterIndex).points); 169 | } 170 | } 171 | 172 | } 173 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter8/C4Board.java: -------------------------------------------------------------------------------- 1 | // C4Board.java 2 | // From Classic Computer Science Problems in Java Chapter 8 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter8; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | 23 | public class C4Board implements Board { 24 | public static final int NUM_COLUMNS = 7; 25 | public static final int NUM_ROWS = 6; 26 | public static final int SEGMENT_LENGTH = 4; 27 | public static final ArrayList SEGMENTS = generateSegments(); 28 | 29 | // generate all of the segments for a given board 30 | // this static method is only run once 31 | private static ArrayList generateSegments() { 32 | ArrayList segments = new ArrayList<>(); 33 | // vertical 34 | for (int c = 0; c < NUM_COLUMNS; c++) { 35 | for (int r = 0; r <= NUM_ROWS - SEGMENT_LENGTH; r++) { 36 | C4Location[] bl = new C4Location[SEGMENT_LENGTH]; 37 | for (int i = 0; i < SEGMENT_LENGTH; i++) { 38 | bl[i] = new C4Location(c, r + i); 39 | } 40 | segments.add(bl); 41 | } 42 | } 43 | // horizontal 44 | for (int c = 0; c <= NUM_COLUMNS - SEGMENT_LENGTH; c++) { 45 | for (int r = 0; r < NUM_ROWS; r++) { 46 | C4Location[] bl = new C4Location[SEGMENT_LENGTH]; 47 | for (int i = 0; i < SEGMENT_LENGTH; i++) { 48 | bl[i] = new C4Location(c + i, r); 49 | } 50 | segments.add(bl); 51 | } 52 | } 53 | // diagonal from bottom left to top right 54 | for (int c = 0; c <= NUM_COLUMNS - SEGMENT_LENGTH; c++) { 55 | for (int r = 0; r <= NUM_ROWS - SEGMENT_LENGTH; r++) { 56 | C4Location[] bl = new C4Location[SEGMENT_LENGTH]; 57 | for (int i = 0; i < SEGMENT_LENGTH; i++) { 58 | bl[i] = new C4Location(c + i, r + i); 59 | } 60 | segments.add(bl); 61 | } 62 | } 63 | // diagonal from bottom right to top left 64 | for (int c = NUM_COLUMNS - SEGMENT_LENGTH; c >= 0; c--) { 65 | for (int r = SEGMENT_LENGTH - 1; r < NUM_ROWS; r++) { 66 | C4Location[] bl = new C4Location[SEGMENT_LENGTH]; 67 | for (int i = 0; i < SEGMENT_LENGTH; i++) { 68 | bl[i] = new C4Location(c + i, r - i); 69 | } 70 | segments.add(bl); 71 | } 72 | } 73 | 74 | return segments; 75 | } 76 | 77 | private C4Piece[][] position; // column first, then row 78 | private int[] columnCount; // number of pieces in each column 79 | private C4Piece turn; 80 | 81 | public C4Board() { 82 | // note that we're doing columns first 83 | position = new C4Piece[NUM_COLUMNS][NUM_ROWS]; 84 | for (C4Piece[] col : position) { 85 | Arrays.fill(col, C4Piece.E); 86 | } 87 | // ints by default are initialized to 0 88 | columnCount = new int[NUM_COLUMNS]; 89 | turn = C4Piece.B; // black goes first 90 | } 91 | 92 | public C4Board(C4Piece[][] position, C4Piece turn) { 93 | this.position = position; 94 | columnCount = new int[NUM_COLUMNS]; 95 | for (int c = 0; c < NUM_COLUMNS; c++) { 96 | int piecesInColumn = 0; 97 | for (int r = 0; r < NUM_ROWS; r++) { 98 | if (position[c][r] != C4Piece.E) { 99 | piecesInColumn++; 100 | } 101 | } 102 | columnCount[c] = piecesInColumn; 103 | } 104 | 105 | this.turn = turn; 106 | } 107 | 108 | @Override 109 | public Piece getTurn() { 110 | return turn; 111 | } 112 | 113 | @Override 114 | public C4Board move(Integer location) { 115 | C4Piece[][] tempPosition = Arrays.copyOf(position, position.length); 116 | for (int col = 0; col < NUM_COLUMNS; col++) { 117 | tempPosition[col] = Arrays.copyOf(position[col], position[col].length); 118 | } 119 | tempPosition[location][columnCount[location]] = turn; 120 | return new C4Board(tempPosition, turn.opposite()); 121 | } 122 | 123 | @Override 124 | public List getLegalMoves() { 125 | List legalMoves = new ArrayList<>(); 126 | for (int i = 0; i < NUM_COLUMNS; i++) { 127 | if (columnCount[i] < NUM_ROWS) { 128 | legalMoves.add(i); 129 | } 130 | } 131 | return legalMoves; 132 | } 133 | 134 | private int countSegment(C4Location[] segment, C4Piece color) { 135 | int count = 0; 136 | for (C4Location location : segment) { 137 | if (position[location.column][location.row] == color) { 138 | count++; 139 | } 140 | } 141 | return count; 142 | } 143 | 144 | @Override 145 | public boolean isWin() { 146 | for (C4Location[] segment : SEGMENTS) { 147 | int blackCount = countSegment(segment, C4Piece.B); 148 | int redCount = countSegment(segment, C4Piece.R); 149 | if (blackCount == SEGMENT_LENGTH || redCount == SEGMENT_LENGTH) { 150 | return true; 151 | } 152 | } 153 | return false; 154 | } 155 | 156 | private double evaluateSegment(C4Location[] segment, Piece player) { 157 | int blackCount = countSegment(segment, C4Piece.B); 158 | int redCount = countSegment(segment, C4Piece.R); 159 | if (redCount > 0 && blackCount > 0) { 160 | return 0.0; // mixed segments are neutral 161 | } 162 | int count = Math.max(blackCount, redCount); 163 | double score = 0.0; 164 | if (count == 2) { 165 | score = 1.0; 166 | } else if (count == 3) { 167 | score = 100.0; 168 | } else if (count == 4) { 169 | score = 1000000.0; 170 | } 171 | C4Piece color = (redCount > blackCount) ? C4Piece.R : C4Piece.B; 172 | if (color != player) { 173 | return -score; 174 | } 175 | return score; 176 | } 177 | 178 | @Override 179 | public double evaluate(Piece player) { 180 | double total = 0.0; 181 | for (C4Location[] segment : SEGMENTS) { 182 | total += evaluateSegment(segment, player); 183 | } 184 | return total; 185 | } 186 | 187 | @Override 188 | public String toString() { 189 | StringBuilder sb = new StringBuilder(); 190 | for (int r = NUM_ROWS - 1; r >= 0; r--) { 191 | sb.append("|"); 192 | for (int c = 0; c < NUM_COLUMNS; c++) { 193 | sb.append(position[c][r].toString()); 194 | sb.append("|"); 195 | } 196 | sb.append(System.lineSeparator()); 197 | } 198 | return sb.toString(); 199 | } 200 | 201 | } 202 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter2/Maze.java: -------------------------------------------------------------------------------- 1 | // Maze.java 2 | // From Classic Computer Science Problems in Java Chapter 2 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter2; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | 23 | import chapter2.GenericSearch.Node; 24 | 25 | public class Maze { 26 | 27 | public enum Cell { 28 | EMPTY(" "), 29 | BLOCKED("X"), 30 | START("S"), 31 | GOAL("G"), 32 | PATH("*"); 33 | 34 | private final String code; 35 | 36 | private Cell(String c) { 37 | code = c; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return code; 43 | } 44 | } 45 | 46 | public static class MazeLocation { 47 | public final int row; 48 | public final int column; 49 | 50 | public MazeLocation(int row, int column) { 51 | this.row = row; 52 | this.column = column; 53 | } 54 | 55 | // auto-generated by Eclipse 56 | @Override 57 | public int hashCode() { 58 | final int prime = 31; 59 | int result = 1; 60 | result = prime * result + column; 61 | result = prime * result + row; 62 | return result; 63 | } 64 | 65 | // auto-generated by Eclipse 66 | @Override 67 | public boolean equals(Object obj) { 68 | if (this == obj) { 69 | return true; 70 | } 71 | if (obj == null) { 72 | return false; 73 | } 74 | if (getClass() != obj.getClass()) { 75 | return false; 76 | } 77 | MazeLocation other = (MazeLocation) obj; 78 | if (column != other.column) { 79 | return false; 80 | } 81 | if (row != other.row) { 82 | return false; 83 | } 84 | return true; 85 | } 86 | } 87 | 88 | private final int rows, columns; 89 | private final MazeLocation start, goal; 90 | private Cell[][] grid; 91 | 92 | public Maze(int rows, int columns, MazeLocation start, MazeLocation goal, double sparseness) { 93 | // initialize basic instance variables 94 | this.rows = rows; 95 | this.columns = columns; 96 | this.start = start; 97 | this.goal = goal; 98 | // fill the grid with empty cells 99 | grid = new Cell[rows][columns]; 100 | for (Cell[] row : grid) { 101 | Arrays.fill(row, Cell.EMPTY); 102 | } 103 | // populate the grid with blocked cells 104 | randomlyFill(sparseness); 105 | // fill the start and goal locations 106 | grid[start.row][start.column] = Cell.START; 107 | grid[goal.row][goal.column] = Cell.GOAL; 108 | } 109 | 110 | public Maze() { 111 | this(10, 10, new MazeLocation(0, 0), new MazeLocation(9, 9), 0.2); 112 | } 113 | 114 | private void randomlyFill(double sparseness) { 115 | for (int row = 0; row < rows; row++) { 116 | for (int column = 0; column < columns; column++) { 117 | if (Math.random() < sparseness) { 118 | grid[row][column] = Cell.BLOCKED; 119 | } 120 | } 121 | } 122 | } 123 | 124 | // return a nicely formatted version of the maze for printing 125 | @Override 126 | public String toString() { 127 | StringBuilder sb = new StringBuilder(); 128 | for (Cell[] row : grid) { 129 | for (Cell cell : row) { 130 | sb.append(cell); 131 | } 132 | sb.append(System.lineSeparator()); 133 | } 134 | return sb.toString(); 135 | } 136 | 137 | public boolean goalTest(MazeLocation ml) { 138 | return goal.equals(ml); 139 | } 140 | 141 | public List successors(MazeLocation ml) { 142 | List locations = new ArrayList<>(); 143 | if (ml.row + 1 < rows && grid[ml.row + 1][ml.column] != Cell.BLOCKED) { 144 | locations.add(new MazeLocation(ml.row + 1, ml.column)); 145 | } 146 | if (ml.row - 1 >= 0 && grid[ml.row - 1][ml.column] != Cell.BLOCKED) { 147 | locations.add(new MazeLocation(ml.row - 1, ml.column)); 148 | } 149 | if (ml.column + 1 < columns && grid[ml.row][ml.column + 1] != Cell.BLOCKED) { 150 | locations.add(new MazeLocation(ml.row, ml.column + 1)); 151 | } 152 | if (ml.column - 1 >= 0 && grid[ml.row][ml.column - 1] != Cell.BLOCKED) { 153 | locations.add(new MazeLocation(ml.row, ml.column - 1)); 154 | } 155 | return locations; 156 | } 157 | 158 | public void mark(List path) { 159 | for (MazeLocation ml : path) { 160 | grid[ml.row][ml.column] = Cell.PATH; 161 | } 162 | grid[start.row][start.column] = Cell.START; 163 | grid[goal.row][goal.column] = Cell.GOAL; 164 | } 165 | 166 | public void clear(List path) { 167 | for (MazeLocation ml : path) { 168 | grid[ml.row][ml.column] = Cell.EMPTY; 169 | } 170 | grid[start.row][start.column] = Cell.START; 171 | grid[goal.row][goal.column] = Cell.GOAL; 172 | } 173 | 174 | public double euclideanDistance(MazeLocation ml) { 175 | int xdist = ml.column - goal.column; 176 | int ydist = ml.row - goal.row; 177 | return Math.sqrt((xdist * xdist) + (ydist * ydist)); 178 | } 179 | 180 | public double manhattanDistance(MazeLocation ml) { 181 | int xdist = Math.abs(ml.column - goal.column); 182 | int ydist = Math.abs(ml.row - goal.row); 183 | return (xdist + ydist); 184 | } 185 | 186 | public static void main(String[] args) { 187 | Maze m = new Maze(); 188 | System.out.println(m); 189 | 190 | Node solution1 = GenericSearch.dfs(m.start, m::goalTest, m::successors); 191 | if (solution1 == null) { 192 | System.out.println("No solution found using depth-first search!"); 193 | } else { 194 | List path1 = GenericSearch.nodeToPath(solution1); 195 | m.mark(path1); 196 | System.out.println(m); 197 | m.clear(path1); 198 | } 199 | 200 | Node solution2 = GenericSearch.bfs(m.start, m::goalTest, m::successors); 201 | if (solution2 == null) { 202 | System.out.println("No solution found using breadth-first search!"); 203 | } else { 204 | List path2 = GenericSearch.nodeToPath(solution2); 205 | m.mark(path2); 206 | System.out.println(m); 207 | m.clear(path2); 208 | } 209 | 210 | Node solution3 = GenericSearch.astar(m.start, m::goalTest, m::successors, m::manhattanDistance); 211 | if (solution3 == null) { 212 | System.out.println("No solution found using A*!"); 213 | } else { 214 | List path3 = GenericSearch.nodeToPath(solution3); 215 | m.mark(path3); 216 | System.out.println(m); 217 | m.clear(path3); 218 | } 219 | } 220 | 221 | } 222 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter2/GenericSearch.java: -------------------------------------------------------------------------------- 1 | // GenericSearch.java 2 | // From Classic Computer Science Problems in Java Chapter 2 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter2; 18 | 19 | import java.util.ArrayList; 20 | import java.util.HashMap; 21 | import java.util.HashSet; 22 | import java.util.LinkedList; 23 | import java.util.List; 24 | import java.util.Map; 25 | import java.util.PriorityQueue; 26 | import java.util.Queue; 27 | import java.util.Set; 28 | import java.util.Stack; 29 | import java.util.function.Function; 30 | import java.util.function.Predicate; 31 | import java.util.function.ToDoubleFunction; 32 | 33 | public class GenericSearch { 34 | 35 | public static > boolean linearContains(List list, T key) { 36 | for (T item : list) { 37 | if (item.compareTo(key) == 0) { 38 | return true; // found a match 39 | } 40 | } 41 | return false; 42 | } 43 | 44 | // assumes *list* is already sorted 45 | public static > boolean binaryContains(List list, T key) { 46 | int low = 0; 47 | int high = list.size() - 1; 48 | while (low <= high) { // while there is still a search space 49 | int middle = (low + high) / 2; 50 | int comparison = list.get(middle).compareTo(key); 51 | if (comparison < 0) { // middle codon is less than key 52 | low = middle + 1; 53 | } else if (comparison > 0) { // middle codon is greater than key 54 | high = middle - 1; 55 | } else { // middle codon is equal to key 56 | return true; 57 | } 58 | } 59 | return false; 60 | } 61 | 62 | public static class Node implements Comparable> { 63 | final T state; 64 | Node parent; 65 | double cost; 66 | double heuristic; 67 | 68 | // for dfs and bfs we won't use cost and heuristic 69 | Node(T state, Node parent) { 70 | this.state = state; 71 | this.parent = parent; 72 | } 73 | 74 | // for astar we will use cost and heuristic 75 | Node(T state, Node parent, double cost, double heuristic) { 76 | this.state = state; 77 | this.parent = parent; 78 | this.cost = cost; 79 | this.heuristic = heuristic; 80 | } 81 | 82 | @Override 83 | public int compareTo(Node other) { 84 | Double mine = cost + heuristic; 85 | Double theirs = other.cost + other.heuristic; 86 | return mine.compareTo(theirs); 87 | } 88 | } 89 | 90 | public static Node dfs(T initial, Predicate goalTest, 91 | Function> successors) { 92 | // frontier is where we've yet to go 93 | Stack> frontier = new Stack<>(); 94 | frontier.push(new Node<>(initial, null)); 95 | // explored is where we've been 96 | Set explored = new HashSet<>(); 97 | explored.add(initial); 98 | 99 | // keep going while there is more to explore 100 | while (!frontier.isEmpty()) { 101 | Node currentNode = frontier.pop(); 102 | T currentState = currentNode.state; 103 | // if we found the goal, we're done 104 | if (goalTest.test(currentState)) { 105 | return currentNode; 106 | } 107 | // check where we can go next and haven't explored 108 | for (T child : successors.apply(currentState)) { 109 | if (explored.contains(child)) { 110 | continue; // skip children we already explored 111 | } 112 | explored.add(child); 113 | frontier.push(new Node<>(child, currentNode)); 114 | } 115 | } 116 | return null; // went through everything and never found goal 117 | } 118 | 119 | public static List nodeToPath(Node node) { 120 | List path = new ArrayList<>(); 121 | path.add(node.state); 122 | // work backwards from end to front 123 | while (node.parent != null) { 124 | node = node.parent; 125 | path.add(0, node.state); // add to front 126 | } 127 | return path; 128 | } 129 | 130 | public static Node bfs(T initial, Predicate goalTest, 131 | Function> successors) { 132 | // frontier is where we've yet to go 133 | Queue> frontier = new LinkedList<>(); 134 | frontier.offer(new Node<>(initial, null)); 135 | // explored is where we've been 136 | Set explored = new HashSet<>(); 137 | explored.add(initial); 138 | 139 | // keep going while there is more to explore 140 | while (!frontier.isEmpty()) { 141 | Node currentNode = frontier.poll(); 142 | T currentState = currentNode.state; 143 | // if we found the goal, we're done 144 | if (goalTest.test(currentState)) { 145 | return currentNode; 146 | } 147 | // check where we can go next and haven't explored 148 | for (T child : successors.apply(currentState)) { 149 | if (explored.contains(child)) { 150 | continue; // skip children we already explored 151 | } 152 | explored.add(child); 153 | frontier.offer(new Node<>(child, currentNode)); 154 | } 155 | } 156 | return null; // went through everything and never found goal 157 | } 158 | 159 | public static Node astar(T initial, Predicate goalTest, 160 | Function> successors, ToDoubleFunction heuristic) { 161 | // frontier is where we've yet to go 162 | PriorityQueue> frontier = new PriorityQueue<>(); 163 | frontier.offer(new Node<>(initial, null, 0.0, heuristic.applyAsDouble(initial))); 164 | // explored is where we've been 165 | Map explored = new HashMap<>(); 166 | explored.put(initial, 0.0); 167 | // keep going while there is more to explore 168 | while (!frontier.isEmpty()) { 169 | Node currentNode = frontier.poll(); 170 | T currentState = currentNode.state; 171 | // if we found the goal, we're done 172 | if (goalTest.test(currentState)) { 173 | return currentNode; 174 | } 175 | // check where we can go next and haven't explored 176 | for (T child : successors.apply(currentState)) { 177 | // 1 here assumes a grid, need a cost function for more sophisticated apps 178 | double newCost = currentNode.cost + 1; 179 | if (!explored.containsKey(child) || explored.get(child) > newCost) { 180 | explored.put(child, newCost); 181 | frontier.offer(new Node<>(child, currentNode, newCost, heuristic.applyAsDouble(child))); 182 | } 183 | } 184 | } 185 | 186 | return null; // went through everything and never found goal 187 | } 188 | 189 | public static void main(String[] args) { 190 | System.out.println(linearContains(List.of(1, 5, 15, 15, 15, 15, 20), 5)); // true 191 | System.out.println(binaryContains(List.of("a", "d", "e", "f", "z"), "f")); // true 192 | System.out.println(binaryContains(List.of("john", "mark", "ronald", "sarah"), "sheila")); // false 193 | } 194 | 195 | } 196 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter4/WeightedGraph.java: -------------------------------------------------------------------------------- 1 | // WeightedGraph.java 2 | // From Classic Computer Science Problems in Java Chapter 4 3 | // Copyright 2020 David Kopec 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | package chapter4; 18 | 19 | import java.util.Arrays; 20 | import java.util.Collections; 21 | import java.util.HashMap; 22 | import java.util.LinkedList; 23 | import java.util.List; 24 | import java.util.Map; 25 | import java.util.PriorityQueue; 26 | import java.util.function.IntConsumer; 27 | 28 | public class WeightedGraph extends Graph { 29 | 30 | public WeightedGraph(List vertices) { 31 | super(vertices); 32 | } 33 | 34 | // This is an undirected graph, so we always add 35 | // edges in both directions 36 | public void addEdge(WeightedEdge edge) { 37 | edges.get(edge.u).add(edge); 38 | edges.get(edge.v).add(edge.reversed()); 39 | } 40 | 41 | public void addEdge(int u, int v, float weight) { 42 | addEdge(new WeightedEdge(u, v, weight)); 43 | } 44 | 45 | public void addEdge(V first, V second, float weight) { 46 | addEdge(indexOf(first), indexOf(second), weight); 47 | } 48 | 49 | // Make it easy to pretty-print a Graph 50 | @Override 51 | public String toString() { 52 | StringBuilder sb = new StringBuilder(); 53 | for (int i = 0; i < getVertexCount(); i++) { 54 | sb.append(vertexAt(i)); 55 | sb.append(" -> "); 56 | sb.append(Arrays.toString(edgesOf(i).stream() 57 | .map(we -> "(" + vertexAt(we.v) + ", " + we.weight + ")").toArray())); 58 | sb.append(System.lineSeparator()); 59 | } 60 | return sb.toString(); 61 | } 62 | 63 | public static double totalWeight(List path) { 64 | return path.stream().mapToDouble(we -> we.weight).sum(); 65 | } 66 | 67 | // Find the minimum-spanning tree of this graph using Jarnik's algorithm 68 | // *start* is the vertex index to start the search at 69 | public List mst(int start) { 70 | LinkedList result = new LinkedList<>(); // final mst 71 | if (start < 0 || start > (getVertexCount() - 1)) { 72 | return result; 73 | } 74 | PriorityQueue pq = new PriorityQueue<>(); 75 | boolean[] visited = new boolean[getVertexCount()]; // where we've been 76 | 77 | // this is like a "visit" inner function 78 | IntConsumer visit = index -> { 79 | visited[index] = true; // mark as visited 80 | for (WeightedEdge edge : edgesOf(index)) { 81 | // add all edges coming from here to pq 82 | if (!visited[edge.v]) { 83 | pq.offer(edge); 84 | } 85 | } 86 | }; 87 | 88 | visit.accept(start); // the first vertex is where everything begins 89 | while (!pq.isEmpty()) { // keep going while there are edges to process 90 | WeightedEdge edge = pq.poll(); 91 | if (visited[edge.v]) { 92 | continue; // don't ever revisit 93 | } 94 | // this is the current smallest, so add it to solution 95 | result.add(edge); 96 | visit.accept(edge.v); // visit where this connects 97 | } 98 | 99 | return result; 100 | } 101 | 102 | public void printWeightedPath(List wp) { 103 | for (WeightedEdge edge : wp) { 104 | System.out.println(vertexAt(edge.u) + " " + edge.weight + "> " + vertexAt(edge.v)); 105 | } 106 | System.out.println("Total Weight: " + totalWeight(wp)); 107 | } 108 | 109 | public static final class DijkstraNode implements Comparable { 110 | public final int vertex; 111 | public final double distance; 112 | 113 | public DijkstraNode(int vertex, double distance) { 114 | this.vertex = vertex; 115 | this.distance = distance; 116 | } 117 | 118 | @Override 119 | public int compareTo(DijkstraNode other) { 120 | Double mine = distance; 121 | Double theirs = other.distance; 122 | return mine.compareTo(theirs); 123 | } 124 | } 125 | 126 | public static final class DijkstraResult { 127 | public final double[] distances; 128 | public final Map pathMap; 129 | 130 | public DijkstraResult(double[] distances, Map pathMap) { 131 | this.distances = distances; 132 | this.pathMap = pathMap; 133 | } 134 | } 135 | 136 | public DijkstraResult dijkstra(V root) { 137 | int first = indexOf(root); // find starting index 138 | // distances are unknown at first 139 | double[] distances = new double[getVertexCount()]; 140 | distances[first] = 0; // root's distance to root is 0 141 | boolean[] visited = new boolean[getVertexCount()]; // where we've been 142 | visited[first] = true; 143 | // how we got to each vertex 144 | HashMap pathMap = new HashMap<>(); 145 | PriorityQueue pq = new PriorityQueue<>(); 146 | pq.offer(new DijkstraNode(first, 0)); 147 | 148 | while (!pq.isEmpty()) { 149 | int u = pq.poll().vertex; // explore the next closest vertex 150 | double distU = distances[u]; // should already have seen it 151 | // look at every edge/vertex from the vertex in question 152 | for (WeightedEdge we : edgesOf(u)) { 153 | // the old distance to this vertex 154 | double distV = distances[we.v]; 155 | // the new distance to this vertex 156 | double pathWeight = we.weight + distU; 157 | // new vertex or found shorter path? 158 | if (!visited[we.v] || (distV > pathWeight)) { 159 | visited[we.v] = true; 160 | // update the distance to this vertex 161 | distances[we.v] = pathWeight; 162 | // update the edge on the shortest path to this vertex 163 | pathMap.put(we.v, we); 164 | // explore it in the future 165 | pq.offer(new DijkstraNode(we.v, pathWeight)); 166 | } 167 | } 168 | } 169 | 170 | return new DijkstraResult(distances, pathMap); 171 | } 172 | 173 | // Helper function to get easier access to dijkstra results 174 | public Map distanceArrayToDistanceMap(double[] distances) { 175 | HashMap distanceMap = new HashMap<>(); 176 | for (int i = 0; i < distances.length; i++) { 177 | distanceMap.put(vertexAt(i), distances[i]); 178 | } 179 | return distanceMap; 180 | } 181 | 182 | // Takes a map of edges to reach each node and return a list of 183 | // edges that goes from *start* to *end* 184 | public static List pathMapToPath(int start, int end, Map pathMap) { 185 | if (pathMap.size() == 0) { 186 | return List.of(); 187 | } 188 | LinkedList path = new LinkedList<>(); 189 | WeightedEdge edge = pathMap.get(end); 190 | path.add(edge); 191 | while (edge.u != start) { 192 | edge = pathMap.get(edge.u); 193 | path.add(edge); 194 | } 195 | Collections.reverse(path); 196 | return path; 197 | } 198 | 199 | // Test basic Graph construction 200 | public static void main(String[] args) { 201 | // Represents the 15 largest MSAs in the United States 202 | WeightedGraph cityGraph2 = new WeightedGraph<>( 203 | List.of("Seattle", "San Francisco", "Los Angeles", "Riverside", "Phoenix", "Chicago", "Boston", 204 | "New York", "Atlanta", "Miami", "Dallas", "Houston", "Detroit", "Philadelphia", "Washington")); 205 | 206 | cityGraph2.addEdge("Seattle", "Chicago", 1737); 207 | cityGraph2.addEdge("Seattle", "San Francisco", 678); 208 | cityGraph2.addEdge("San Francisco", "Riverside", 386); 209 | cityGraph2.addEdge("San Francisco", "Los Angeles", 348); 210 | cityGraph2.addEdge("Los Angeles", "Riverside", 50); 211 | cityGraph2.addEdge("Los Angeles", "Phoenix", 357); 212 | cityGraph2.addEdge("Riverside", "Phoenix", 307); 213 | cityGraph2.addEdge("Riverside", "Chicago", 1704); 214 | cityGraph2.addEdge("Phoenix", "Dallas", 887); 215 | cityGraph2.addEdge("Phoenix", "Houston", 1015); 216 | cityGraph2.addEdge("Dallas", "Chicago", 805); 217 | cityGraph2.addEdge("Dallas", "Atlanta", 721); 218 | cityGraph2.addEdge("Dallas", "Houston", 225); 219 | cityGraph2.addEdge("Houston", "Atlanta", 702); 220 | cityGraph2.addEdge("Houston", "Miami", 968); 221 | cityGraph2.addEdge("Atlanta", "Chicago", 588); 222 | cityGraph2.addEdge("Atlanta", "Washington", 543); 223 | cityGraph2.addEdge("Atlanta", "Miami", 604); 224 | cityGraph2.addEdge("Miami", "Washington", 923); 225 | cityGraph2.addEdge("Chicago", "Detroit", 238); 226 | cityGraph2.addEdge("Detroit", "Boston", 613); 227 | cityGraph2.addEdge("Detroit", "Washington", 396); 228 | cityGraph2.addEdge("Detroit", "New York", 482); 229 | cityGraph2.addEdge("Boston", "New York", 190); 230 | cityGraph2.addEdge("New York", "Philadelphia", 81); 231 | cityGraph2.addEdge("Philadelphia", "Washington", 123); 232 | 233 | System.out.println(cityGraph2); 234 | 235 | List mst = cityGraph2.mst(0); 236 | cityGraph2.printWeightedPath(mst); 237 | 238 | System.out.println(); // spacing 239 | 240 | DijkstraResult dijkstraResult = cityGraph2.dijkstra("Los Angeles"); 241 | Map nameDistance = cityGraph2.distanceArrayToDistanceMap(dijkstraResult.distances); 242 | System.out.println("Distances from Los Angeles:"); 243 | nameDistance.forEach((name, distance) -> System.out.println(name + " : " + distance)); 244 | 245 | System.out.println(); // spacing 246 | 247 | System.out.println("Shortest path from Los Angeles to Boston:"); 248 | List path = pathMapToPath(cityGraph2.indexOf("Los Angeles"), cityGraph2.indexOf("Boston"), 249 | dijkstraResult.pathMap); 250 | cityGraph2.printWeightedPath(path); 251 | } 252 | 253 | } 254 | -------------------------------------------------------------------------------- /CCSPiJ/src/chapter7/data/wine.csv: -------------------------------------------------------------------------------- 1 | 1,14.23,1.71,2.43,15.6,127,2.8,3.06,.28,2.29,5.64,1.04,3.92,1065 2 | 1,13.2,1.78,2.14,11.2,100,2.65,2.76,.26,1.28,4.38,1.05,3.4,1050 3 | 1,13.16,2.36,2.67,18.6,101,2.8,3.24,.3,2.81,5.68,1.03,3.17,1185 4 | 1,14.37,1.95,2.5,16.8,113,3.85,3.49,.24,2.18,7.8,.86,3.45,1480 5 | 1,13.24,2.59,2.87,21,118,2.8,2.69,.39,1.82,4.32,1.04,2.93,735 6 | 1,14.2,1.76,2.45,15.2,112,3.27,3.39,.34,1.97,6.75,1.05,2.85,1450 7 | 1,14.39,1.87,2.45,14.6,96,2.5,2.52,.3,1.98,5.25,1.02,3.58,1290 8 | 1,14.06,2.15,2.61,17.6,121,2.6,2.51,.31,1.25,5.05,1.06,3.58,1295 9 | 1,14.83,1.64,2.17,14,97,2.8,2.98,.29,1.98,5.2,1.08,2.85,1045 10 | 1,13.86,1.35,2.27,16,98,2.98,3.15,.22,1.85,7.22,1.01,3.55,1045 11 | 1,14.1,2.16,2.3,18,105,2.95,3.32,.22,2.38,5.75,1.25,3.17,1510 12 | 1,14.12,1.48,2.32,16.8,95,2.2,2.43,.26,1.57,5,1.17,2.82,1280 13 | 1,13.75,1.73,2.41,16,89,2.6,2.76,.29,1.81,5.6,1.15,2.9,1320 14 | 1,14.75,1.73,2.39,11.4,91,3.1,3.69,.43,2.81,5.4,1.25,2.73,1150 15 | 1,14.38,1.87,2.38,12,102,3.3,3.64,.29,2.96,7.5,1.2,3,1547 16 | 1,13.63,1.81,2.7,17.2,112,2.85,2.91,.3,1.46,7.3,1.28,2.88,1310 17 | 1,14.3,1.92,2.72,20,120,2.8,3.14,.33,1.97,6.2,1.07,2.65,1280 18 | 1,13.83,1.57,2.62,20,115,2.95,3.4,.4,1.72,6.6,1.13,2.57,1130 19 | 1,14.19,1.59,2.48,16.5,108,3.3,3.93,.32,1.86,8.7,1.23,2.82,1680 20 | 1,13.64,3.1,2.56,15.2,116,2.7,3.03,.17,1.66,5.1,.96,3.36,845 21 | 1,14.06,1.63,2.28,16,126,3,3.17,.24,2.1,5.65,1.09,3.71,780 22 | 1,12.93,3.8,2.65,18.6,102,2.41,2.41,.25,1.98,4.5,1.03,3.52,770 23 | 1,13.71,1.86,2.36,16.6,101,2.61,2.88,.27,1.69,3.8,1.11,4,1035 24 | 1,12.85,1.6,2.52,17.8,95,2.48,2.37,.26,1.46,3.93,1.09,3.63,1015 25 | 1,13.5,1.81,2.61,20,96,2.53,2.61,.28,1.66,3.52,1.12,3.82,845 26 | 1,13.05,2.05,3.22,25,124,2.63,2.68,.47,1.92,3.58,1.13,3.2,830 27 | 1,13.39,1.77,2.62,16.1,93,2.85,2.94,.34,1.45,4.8,.92,3.22,1195 28 | 1,13.3,1.72,2.14,17,94,2.4,2.19,.27,1.35,3.95,1.02,2.77,1285 29 | 1,13.87,1.9,2.8,19.4,107,2.95,2.97,.37,1.76,4.5,1.25,3.4,915 30 | 1,14.02,1.68,2.21,16,96,2.65,2.33,.26,1.98,4.7,1.04,3.59,1035 31 | 1,13.73,1.5,2.7,22.5,101,3,3.25,.29,2.38,5.7,1.19,2.71,1285 32 | 1,13.58,1.66,2.36,19.1,106,2.86,3.19,.22,1.95,6.9,1.09,2.88,1515 33 | 1,13.68,1.83,2.36,17.2,104,2.42,2.69,.42,1.97,3.84,1.23,2.87,990 34 | 1,13.76,1.53,2.7,19.5,132,2.95,2.74,.5,1.35,5.4,1.25,3,1235 35 | 1,13.51,1.8,2.65,19,110,2.35,2.53,.29,1.54,4.2,1.1,2.87,1095 36 | 1,13.48,1.81,2.41,20.5,100,2.7,2.98,.26,1.86,5.1,1.04,3.47,920 37 | 1,13.28,1.64,2.84,15.5,110,2.6,2.68,.34,1.36,4.6,1.09,2.78,880 38 | 1,13.05,1.65,2.55,18,98,2.45,2.43,.29,1.44,4.25,1.12,2.51,1105 39 | 1,13.07,1.5,2.1,15.5,98,2.4,2.64,.28,1.37,3.7,1.18,2.69,1020 40 | 1,14.22,3.99,2.51,13.2,128,3,3.04,.2,2.08,5.1,.89,3.53,760 41 | 1,13.56,1.71,2.31,16.2,117,3.15,3.29,.34,2.34,6.13,.95,3.38,795 42 | 1,13.41,3.84,2.12,18.8,90,2.45,2.68,.27,1.48,4.28,.91,3,1035 43 | 1,13.88,1.89,2.59,15,101,3.25,3.56,.17,1.7,5.43,.88,3.56,1095 44 | 1,13.24,3.98,2.29,17.5,103,2.64,2.63,.32,1.66,4.36,.82,3,680 45 | 1,13.05,1.77,2.1,17,107,3,3,.28,2.03,5.04,.88,3.35,885 46 | 1,14.21,4.04,2.44,18.9,111,2.85,2.65,.3,1.25,5.24,.87,3.33,1080 47 | 1,14.38,3.59,2.28,16,102,3.25,3.17,.27,2.19,4.9,1.04,3.44,1065 48 | 1,13.9,1.68,2.12,16,101,3.1,3.39,.21,2.14,6.1,.91,3.33,985 49 | 1,14.1,2.02,2.4,18.8,103,2.75,2.92,.32,2.38,6.2,1.07,2.75,1060 50 | 1,13.94,1.73,2.27,17.4,108,2.88,3.54,.32,2.08,8.90,1.12,3.1,1260 51 | 1,13.05,1.73,2.04,12.4,92,2.72,3.27,.17,2.91,7.2,1.12,2.91,1150 52 | 1,13.83,1.65,2.6,17.2,94,2.45,2.99,.22,2.29,5.6,1.24,3.37,1265 53 | 1,13.82,1.75,2.42,14,111,3.88,3.74,.32,1.87,7.05,1.01,3.26,1190 54 | 1,13.77,1.9,2.68,17.1,115,3,2.79,.39,1.68,6.3,1.13,2.93,1375 55 | 1,13.74,1.67,2.25,16.4,118,2.6,2.9,.21,1.62,5.85,.92,3.2,1060 56 | 1,13.56,1.73,2.46,20.5,116,2.96,2.78,.2,2.45,6.25,.98,3.03,1120 57 | 1,14.22,1.7,2.3,16.3,118,3.2,3,.26,2.03,6.38,.94,3.31,970 58 | 1,13.29,1.97,2.68,16.8,102,3,3.23,.31,1.66,6,1.07,2.84,1270 59 | 1,13.72,1.43,2.5,16.7,108,3.4,3.67,.19,2.04,6.8,.89,2.87,1285 60 | 2,12.37,.94,1.36,10.6,88,1.98,.57,.28,.42,1.95,1.05,1.82,520 61 | 2,12.33,1.1,2.28,16,101,2.05,1.09,.63,.41,3.27,1.25,1.67,680 62 | 2,12.64,1.36,2.02,16.8,100,2.02,1.41,.53,.62,5.75,.98,1.59,450 63 | 2,13.67,1.25,1.92,18,94,2.1,1.79,.32,.73,3.8,1.23,2.46,630 64 | 2,12.37,1.13,2.16,19,87,3.5,3.1,.19,1.87,4.45,1.22,2.87,420 65 | 2,12.17,1.45,2.53,19,104,1.89,1.75,.45,1.03,2.95,1.45,2.23,355 66 | 2,12.37,1.21,2.56,18.1,98,2.42,2.65,.37,2.08,4.6,1.19,2.3,678 67 | 2,13.11,1.01,1.7,15,78,2.98,3.18,.26,2.28,5.3,1.12,3.18,502 68 | 2,12.37,1.17,1.92,19.6,78,2.11,2,.27,1.04,4.68,1.12,3.48,510 69 | 2,13.34,.94,2.36,17,110,2.53,1.3,.55,.42,3.17,1.02,1.93,750 70 | 2,12.21,1.19,1.75,16.8,151,1.85,1.28,.14,2.5,2.85,1.28,3.07,718 71 | 2,12.29,1.61,2.21,20.4,103,1.1,1.02,.37,1.46,3.05,.906,1.82,870 72 | 2,13.86,1.51,2.67,25,86,2.95,2.86,.21,1.87,3.38,1.36,3.16,410 73 | 2,13.49,1.66,2.24,24,87,1.88,1.84,.27,1.03,3.74,.98,2.78,472 74 | 2,12.99,1.67,2.6,30,139,3.3,2.89,.21,1.96,3.35,1.31,3.5,985 75 | 2,11.96,1.09,2.3,21,101,3.38,2.14,.13,1.65,3.21,.99,3.13,886 76 | 2,11.66,1.88,1.92,16,97,1.61,1.57,.34,1.15,3.8,1.23,2.14,428 77 | 2,13.03,.9,1.71,16,86,1.95,2.03,.24,1.46,4.6,1.19,2.48,392 78 | 2,11.84,2.89,2.23,18,112,1.72,1.32,.43,.95,2.65,.96,2.52,500 79 | 2,12.33,.99,1.95,14.8,136,1.9,1.85,.35,2.76,3.4,1.06,2.31,750 80 | 2,12.7,3.87,2.4,23,101,2.83,2.55,.43,1.95,2.57,1.19,3.13,463 81 | 2,12,.92,2,19,86,2.42,2.26,.3,1.43,2.5,1.38,3.12,278 82 | 2,12.72,1.81,2.2,18.8,86,2.2,2.53,.26,1.77,3.9,1.16,3.14,714 83 | 2,12.08,1.13,2.51,24,78,2,1.58,.4,1.4,2.2,1.31,2.72,630 84 | 2,13.05,3.86,2.32,22.5,85,1.65,1.59,.61,1.62,4.8,.84,2.01,515 85 | 2,11.84,.89,2.58,18,94,2.2,2.21,.22,2.35,3.05,.79,3.08,520 86 | 2,12.67,.98,2.24,18,99,2.2,1.94,.3,1.46,2.62,1.23,3.16,450 87 | 2,12.16,1.61,2.31,22.8,90,1.78,1.69,.43,1.56,2.45,1.33,2.26,495 88 | 2,11.65,1.67,2.62,26,88,1.92,1.61,.4,1.34,2.6,1.36,3.21,562 89 | 2,11.64,2.06,2.46,21.6,84,1.95,1.69,.48,1.35,2.8,1,2.75,680 90 | 2,12.08,1.33,2.3,23.6,70,2.2,1.59,.42,1.38,1.74,1.07,3.21,625 91 | 2,12.08,1.83,2.32,18.5,81,1.6,1.5,.52,1.64,2.4,1.08,2.27,480 92 | 2,12,1.51,2.42,22,86,1.45,1.25,.5,1.63,3.6,1.05,2.65,450 93 | 2,12.69,1.53,2.26,20.7,80,1.38,1.46,.58,1.62,3.05,.96,2.06,495 94 | 2,12.29,2.83,2.22,18,88,2.45,2.25,.25,1.99,2.15,1.15,3.3,290 95 | 2,11.62,1.99,2.28,18,98,3.02,2.26,.17,1.35,3.25,1.16,2.96,345 96 | 2,12.47,1.52,2.2,19,162,2.5,2.27,.32,3.28,2.6,1.16,2.63,937 97 | 2,11.81,2.12,2.74,21.5,134,1.6,.99,.14,1.56,2.5,.95,2.26,625 98 | 2,12.29,1.41,1.98,16,85,2.55,2.5,.29,1.77,2.9,1.23,2.74,428 99 | 2,12.37,1.07,2.1,18.5,88,3.52,3.75,.24,1.95,4.5,1.04,2.77,660 100 | 2,12.29,3.17,2.21,18,88,2.85,2.99,.45,2.81,2.3,1.42,2.83,406 101 | 2,12.08,2.08,1.7,17.5,97,2.23,2.17,.26,1.4,3.3,1.27,2.96,710 102 | 2,12.6,1.34,1.9,18.5,88,1.45,1.36,.29,1.35,2.45,1.04,2.77,562 103 | 2,12.34,2.45,2.46,21,98,2.56,2.11,.34,1.31,2.8,.8,3.38,438 104 | 2,11.82,1.72,1.88,19.5,86,2.5,1.64,.37,1.42,2.06,.94,2.44,415 105 | 2,12.51,1.73,1.98,20.5,85,2.2,1.92,.32,1.48,2.94,1.04,3.57,672 106 | 2,12.42,2.55,2.27,22,90,1.68,1.84,.66,1.42,2.7,.86,3.3,315 107 | 2,12.25,1.73,2.12,19,80,1.65,2.03,.37,1.63,3.4,1,3.17,510 108 | 2,12.72,1.75,2.28,22.5,84,1.38,1.76,.48,1.63,3.3,.88,2.42,488 109 | 2,12.22,1.29,1.94,19,92,2.36,2.04,.39,2.08,2.7,.86,3.02,312 110 | 2,11.61,1.35,2.7,20,94,2.74,2.92,.29,2.49,2.65,.96,3.26,680 111 | 2,11.46,3.74,1.82,19.5,107,3.18,2.58,.24,3.58,2.9,.75,2.81,562 112 | 2,12.52,2.43,2.17,21,88,2.55,2.27,.26,1.22,2,.9,2.78,325 113 | 2,11.76,2.68,2.92,20,103,1.75,2.03,.6,1.05,3.8,1.23,2.5,607 114 | 2,11.41,.74,2.5,21,88,2.48,2.01,.42,1.44,3.08,1.1,2.31,434 115 | 2,12.08,1.39,2.5,22.5,84,2.56,2.29,.43,1.04,2.9,.93,3.19,385 116 | 2,11.03,1.51,2.2,21.5,85,2.46,2.17,.52,2.01,1.9,1.71,2.87,407 117 | 2,11.82,1.47,1.99,20.8,86,1.98,1.6,.3,1.53,1.95,.95,3.33,495 118 | 2,12.42,1.61,2.19,22.5,108,2,2.09,.34,1.61,2.06,1.06,2.96,345 119 | 2,12.77,3.43,1.98,16,80,1.63,1.25,.43,.83,3.4,.7,2.12,372 120 | 2,12,3.43,2,19,87,2,1.64,.37,1.87,1.28,.93,3.05,564 121 | 2,11.45,2.4,2.42,20,96,2.9,2.79,.32,1.83,3.25,.8,3.39,625 122 | 2,11.56,2.05,3.23,28.5,119,3.18,5.08,.47,1.87,6,.93,3.69,465 123 | 2,12.42,4.43,2.73,26.5,102,2.2,2.13,.43,1.71,2.08,.92,3.12,365 124 | 2,13.05,5.8,2.13,21.5,86,2.62,2.65,.3,2.01,2.6,.73,3.1,380 125 | 2,11.87,4.31,2.39,21,82,2.86,3.03,.21,2.91,2.8,.75,3.64,380 126 | 2,12.07,2.16,2.17,21,85,2.6,2.65,.37,1.35,2.76,.86,3.28,378 127 | 2,12.43,1.53,2.29,21.5,86,2.74,3.15,.39,1.77,3.94,.69,2.84,352 128 | 2,11.79,2.13,2.78,28.5,92,2.13,2.24,.58,1.76,3,.97,2.44,466 129 | 2,12.37,1.63,2.3,24.5,88,2.22,2.45,.4,1.9,2.12,.89,2.78,342 130 | 2,12.04,4.3,2.38,22,80,2.1,1.75,.42,1.35,2.6,.79,2.57,580 131 | 3,12.86,1.35,2.32,18,122,1.51,1.25,.21,.94,4.1,.76,1.29,630 132 | 3,12.88,2.99,2.4,20,104,1.3,1.22,.24,.83,5.4,.74,1.42,530 133 | 3,12.81,2.31,2.4,24,98,1.15,1.09,.27,.83,5.7,.66,1.36,560 134 | 3,12.7,3.55,2.36,21.5,106,1.7,1.2,.17,.84,5,.78,1.29,600 135 | 3,12.51,1.24,2.25,17.5,85,2,.58,.6,1.25,5.45,.75,1.51,650 136 | 3,12.6,2.46,2.2,18.5,94,1.62,.66,.63,.94,7.1,.73,1.58,695 137 | 3,12.25,4.72,2.54,21,89,1.38,.47,.53,.8,3.85,.75,1.27,720 138 | 3,12.53,5.51,2.64,25,96,1.79,.6,.63,1.1,5,.82,1.69,515 139 | 3,13.49,3.59,2.19,19.5,88,1.62,.48,.58,.88,5.7,.81,1.82,580 140 | 3,12.84,2.96,2.61,24,101,2.32,.6,.53,.81,4.92,.89,2.15,590 141 | 3,12.93,2.81,2.7,21,96,1.54,.5,.53,.75,4.6,.77,2.31,600 142 | 3,13.36,2.56,2.35,20,89,1.4,.5,.37,.64,5.6,.7,2.47,780 143 | 3,13.52,3.17,2.72,23.5,97,1.55,.52,.5,.55,4.35,.89,2.06,520 144 | 3,13.62,4.95,2.35,20,92,2,.8,.47,1.02,4.4,.91,2.05,550 145 | 3,12.25,3.88,2.2,18.5,112,1.38,.78,.29,1.14,8.21,.65,2,855 146 | 3,13.16,3.57,2.15,21,102,1.5,.55,.43,1.3,4,.6,1.68,830 147 | 3,13.88,5.04,2.23,20,80,.98,.34,.4,.68,4.9,.58,1.33,415 148 | 3,12.87,4.61,2.48,21.5,86,1.7,.65,.47,.86,7.65,.54,1.86,625 149 | 3,13.32,3.24,2.38,21.5,92,1.93,.76,.45,1.25,8.42,.55,1.62,650 150 | 3,13.08,3.9,2.36,21.5,113,1.41,1.39,.34,1.14,9.40,.57,1.33,550 151 | 3,13.5,3.12,2.62,24,123,1.4,1.57,.22,1.25,8.60,.59,1.3,500 152 | 3,12.79,2.67,2.48,22,112,1.48,1.36,.24,1.26,10.8,.48,1.47,480 153 | 3,13.11,1.9,2.75,25.5,116,2.2,1.28,.26,1.56,7.1,.61,1.33,425 154 | 3,13.23,3.3,2.28,18.5,98,1.8,.83,.61,1.87,10.52,.56,1.51,675 155 | 3,12.58,1.29,2.1,20,103,1.48,.58,.53,1.4,7.6,.58,1.55,640 156 | 3,13.17,5.19,2.32,22,93,1.74,.63,.61,1.55,7.9,.6,1.48,725 157 | 3,13.84,4.12,2.38,19.5,89,1.8,.83,.48,1.56,9.01,.57,1.64,480 158 | 3,12.45,3.03,2.64,27,97,1.9,.58,.63,1.14,7.5,.67,1.73,880 159 | 3,14.34,1.68,2.7,25,98,2.8,1.31,.53,2.7,13,.57,1.96,660 160 | 3,13.48,1.67,2.64,22.5,89,2.6,1.1,.52,2.29,11.75,.57,1.78,620 161 | 3,12.36,3.83,2.38,21,88,2.3,.92,.5,1.04,7.65,.56,1.58,520 162 | 3,13.69,3.26,2.54,20,107,1.83,.56,.5,.8,5.88,.96,1.82,680 163 | 3,12.85,3.27,2.58,22,106,1.65,.6,.6,.96,5.58,.87,2.11,570 164 | 3,12.96,3.45,2.35,18.5,106,1.39,.7,.4,.94,5.28,.68,1.75,675 165 | 3,13.78,2.76,2.3,22,90,1.35,.68,.41,1.03,9.58,.7,1.68,615 166 | 3,13.73,4.36,2.26,22.5,88,1.28,.47,.52,1.15,6.62,.78,1.75,520 167 | 3,13.45,3.7,2.6,23,111,1.7,.92,.43,1.46,10.68,.85,1.56,695 168 | 3,12.82,3.37,2.3,19.5,88,1.48,.66,.4,.97,10.26,.72,1.75,685 169 | 3,13.58,2.58,2.69,24.5,105,1.55,.84,.39,1.54,8.66,.74,1.8,750 170 | 3,13.4,4.6,2.86,25,112,1.98,.96,.27,1.11,8.5,.67,1.92,630 171 | 3,12.2,3.03,2.32,19,96,1.25,.49,.4,.73,5.5,.66,1.83,510 172 | 3,12.77,2.39,2.28,19.5,86,1.39,.51,.48,.64,9.899999,.57,1.63,470 173 | 3,14.16,2.51,2.48,20,91,1.68,.7,.44,1.24,9.7,.62,1.71,660 174 | 3,13.71,5.65,2.45,20.5,95,1.68,.61,.52,1.06,7.7,.64,1.74,740 175 | 3,13.4,3.91,2.48,23,102,1.8,.75,.43,1.41,7.3,.7,1.56,750 176 | 3,13.27,4.28,2.26,20,120,1.59,.69,.43,1.35,10.2,.59,1.56,835 177 | 3,13.17,2.59,2.37,20,120,1.65,.68,.53,1.46,9.3,.6,1.62,840 178 | 3,14.13,4.1,2.74,24.5,96,2.05,.76,.56,1.35,9.2,.61,1.6,560 179 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------