├── 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 | 
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