Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -7,8 +7,6 @@ This module contains articles about algorithms. Some classes of algorithms, e.g.
|
|||||||
|
|
||||||
- [Validating Input With Finite Automata in Java](https://www.baeldung.com/java-finite-automata)
|
- [Validating Input With Finite Automata in Java](https://www.baeldung.com/java-finite-automata)
|
||||||
- [Example of Hill Climbing Algorithm](https://www.baeldung.com/java-hill-climbing-algorithm)
|
- [Example of Hill Climbing Algorithm](https://www.baeldung.com/java-hill-climbing-algorithm)
|
||||||
- [Monte Carlo Tree Search for Tic-Tac-Toe Game](https://www.baeldung.com/java-monte-carlo-tree-search)
|
|
||||||
- [Binary Search Algorithm in Java](https://www.baeldung.com/java-binary-search)
|
|
||||||
- [Introduction to Minimax Algorithm](https://www.baeldung.com/java-minimax-algorithm)
|
- [Introduction to Minimax Algorithm](https://www.baeldung.com/java-minimax-algorithm)
|
||||||
- [How to Calculate Levenshtein Distance in Java?](https://www.baeldung.com/java-levenshtein-distance)
|
- [How to Calculate Levenshtein Distance in Java?](https://www.baeldung.com/java-levenshtein-distance)
|
||||||
- [How to Find the Kth Largest Element in Java](https://www.baeldung.com/java-kth-largest-element)
|
- [How to Find the Kth Largest Element in Java](https://www.baeldung.com/java-kth-largest-element)
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.baeldung.algorithms.astar;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
|
public class Graph<T extends GraphNode> {
|
||||||
|
private final Set<T> nodes;
|
||||||
|
|
||||||
|
private final Map<String, Set<String>> connections;
|
||||||
|
|
||||||
|
public Graph(Set<T> nodes, Map<String, Set<String>> connections) {
|
||||||
|
this.nodes = nodes;
|
||||||
|
this.connections = connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getNode(String id) {
|
||||||
|
return nodes.stream()
|
||||||
|
.filter(node -> node.getId().equals(id))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("No node found with ID"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<T> getConnections(T node) {
|
||||||
|
return connections.get(node.getId()).stream()
|
||||||
|
.map(this::getNode)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.baeldung.algorithms.astar;
|
||||||
|
|
||||||
|
public interface GraphNode {
|
||||||
|
String getId();
|
||||||
|
}
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
package com.baeldung.algorithms.astar;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class RouteFinder<T extends GraphNode> {
|
||||||
|
private final Graph<T> graph;
|
||||||
|
private final Scorer<T> nextNodeScorer;
|
||||||
|
private final Scorer<T> targetScorer;
|
||||||
|
|
||||||
|
public RouteFinder(Graph<T> graph, Scorer<T> nextNodeScorer, Scorer<T> targetScorer) {
|
||||||
|
this.graph = graph;
|
||||||
|
this.nextNodeScorer = nextNodeScorer;
|
||||||
|
this.targetScorer = targetScorer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> findRoute(T from, T to) {
|
||||||
|
Map<T, RouteNode<T>> allNodes = new HashMap<>();
|
||||||
|
Queue<RouteNode> openSet = new PriorityQueue<>();
|
||||||
|
|
||||||
|
RouteNode<T> start = new RouteNode<>(from, null, 0d, targetScorer.computeCost(from, to));
|
||||||
|
allNodes.put(from, start);
|
||||||
|
openSet.add(start);
|
||||||
|
|
||||||
|
while (!openSet.isEmpty()) {
|
||||||
|
System.out.println("Open Set contains: " + openSet.stream().map(RouteNode::getCurrent).collect(Collectors.toSet()));
|
||||||
|
RouteNode<T> next = openSet.poll();
|
||||||
|
System.out.println("Looking at node: " + next);
|
||||||
|
if (next.getCurrent().equals(to)) {
|
||||||
|
System.out.println("Found our destination!");
|
||||||
|
|
||||||
|
List<T> route = new ArrayList<>();
|
||||||
|
RouteNode<T> current = next;
|
||||||
|
do {
|
||||||
|
route.add(0, current.getCurrent());
|
||||||
|
current = allNodes.get(current.getPrevious());
|
||||||
|
} while (current != null);
|
||||||
|
|
||||||
|
System.out.println("Route: " + route);
|
||||||
|
return route;
|
||||||
|
}
|
||||||
|
|
||||||
|
graph.getConnections(next.getCurrent()).forEach(connection -> {
|
||||||
|
double newScore = next.getRouteScore() + nextNodeScorer.computeCost(next.getCurrent(), connection);
|
||||||
|
RouteNode<T> nextNode = allNodes.getOrDefault(connection, new RouteNode<>(connection));
|
||||||
|
allNodes.put(connection, nextNode);
|
||||||
|
|
||||||
|
if (nextNode.getRouteScore() > newScore) {
|
||||||
|
nextNode.setPrevious(next.getCurrent());
|
||||||
|
nextNode.setRouteScore(newScore);
|
||||||
|
nextNode.setEstimatedScore(newScore + targetScorer.computeCost(connection, to));
|
||||||
|
openSet.add(nextNode);
|
||||||
|
System.out.println("Found a better route to node: " + nextNode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("No route found");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package com.baeldung.algorithms.astar;
|
||||||
|
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
|
class RouteNode<T extends GraphNode> implements Comparable<RouteNode> {
|
||||||
|
private final T current;
|
||||||
|
private T previous;
|
||||||
|
private double routeScore;
|
||||||
|
private double estimatedScore;
|
||||||
|
|
||||||
|
RouteNode(T current) {
|
||||||
|
this(current, null, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
RouteNode(T current, T previous, double routeScore, double estimatedScore) {
|
||||||
|
this.current = current;
|
||||||
|
this.previous = previous;
|
||||||
|
this.routeScore = routeScore;
|
||||||
|
this.estimatedScore = estimatedScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
T getCurrent() {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
T getPrevious() {
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
double getRouteScore() {
|
||||||
|
return routeScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
double getEstimatedScore() {
|
||||||
|
return estimatedScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPrevious(T previous) {
|
||||||
|
this.previous = previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRouteScore(double routeScore) {
|
||||||
|
this.routeScore = routeScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEstimatedScore(double estimatedScore) {
|
||||||
|
this.estimatedScore = estimatedScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(RouteNode other) {
|
||||||
|
if (this.estimatedScore > other.estimatedScore) {
|
||||||
|
return 1;
|
||||||
|
} else if (this.estimatedScore < other.estimatedScore) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new StringJoiner(", ", RouteNode.class.getSimpleName() + "[", "]").add("current=" + current)
|
||||||
|
.add("previous=" + previous).add("routeScore=" + routeScore).add("estimatedScore=" + estimatedScore)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.baeldung.algorithms.astar;
|
||||||
|
|
||||||
|
public interface Scorer<T extends GraphNode> {
|
||||||
|
double computeCost(T from, T to);
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package com.baeldung.algorithms.astar.underground;
|
||||||
|
|
||||||
|
import com.baeldung.algorithms.astar.Scorer;
|
||||||
|
|
||||||
|
public class HaversineScorer implements Scorer<Station> {
|
||||||
|
@Override
|
||||||
|
public double computeCost(Station from, Station to) {
|
||||||
|
double R = 6372.8; // In kilometers
|
||||||
|
|
||||||
|
double dLat = Math.toRadians(to.getLatitude() - from.getLatitude());
|
||||||
|
double dLon = Math.toRadians(to.getLongitude() - from.getLongitude());
|
||||||
|
double lat1 = Math.toRadians(from.getLatitude());
|
||||||
|
double lat2 = Math.toRadians(to.getLatitude());
|
||||||
|
|
||||||
|
double a = Math.pow(Math.sin(dLat / 2),2) + Math.pow(Math.sin(dLon / 2),2) * Math.cos(lat1) * Math.cos(lat2);
|
||||||
|
double c = 2 * Math.asin(Math.sqrt(a));
|
||||||
|
return R * c;
|
||||||
|
}
|
||||||
|
}
|
||||||
+643
File diff suppressed because it is too large
Load Diff
+42
@@ -0,0 +1,42 @@
|
|||||||
|
package com.baeldung.algorithms.astar.underground;
|
||||||
|
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
|
import com.baeldung.algorithms.astar.GraphNode;
|
||||||
|
|
||||||
|
public class Station implements GraphNode {
|
||||||
|
private final String id;
|
||||||
|
private final String name;
|
||||||
|
private final double latitude;
|
||||||
|
private final double longitude;
|
||||||
|
|
||||||
|
public Station(String id, String name, double latitude, double longitude) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.latitude = latitude;
|
||||||
|
this.longitude = longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLatitude() {
|
||||||
|
return latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLongitude() {
|
||||||
|
return longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new StringJoiner(", ", Station.class.getSimpleName() + "[", "]").add("id='" + id + "'")
|
||||||
|
.add("name='" + name + "'").add("latitude=" + latitude).add("longitude=" + longitude).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,8 +14,6 @@ This module contains articles about algorithms. Some classes of algorithms, e.g.
|
|||||||
- [A Guide to the Folding Technique in Java](https://www.baeldung.com/folding-hashing-technique)
|
- [A Guide to the Folding Technique in Java](https://www.baeldung.com/folding-hashing-technique)
|
||||||
- [Creating a Triangle with for Loops in Java](https://www.baeldung.com/java-print-triangle)
|
- [Creating a Triangle with for Loops in Java](https://www.baeldung.com/java-print-triangle)
|
||||||
- [Efficient Word Frequency Calculator in Java](https://www.baeldung.com/java-word-frequency)
|
- [Efficient Word Frequency Calculator in Java](https://www.baeldung.com/java-word-frequency)
|
||||||
- [Interpolation Search in Java](https://www.baeldung.com/java-interpolation-search)
|
|
||||||
- [The K-Means Clustering Algorithm in Java](https://www.baeldung.com/java-k-means-clustering-algorithm)
|
- [The K-Means Clustering Algorithm in Java](https://www.baeldung.com/java-k-means-clustering-algorithm)
|
||||||
- [Creating a Custom Annotation in Java](https://www.baeldung.com/java-custom-annotation)
|
- [Creating a Custom Annotation in Java](https://www.baeldung.com/java-custom-annotation)
|
||||||
- [Breadth-First Search Algorithm in Java](https://www.baeldung.com/java-breadth-first-search)
|
|
||||||
- More articles: [[<-- prev]](/algorithms-miscellaneous-2) [[next -->]](/algorithms-miscellaneous-4)
|
- More articles: [[<-- prev]](/algorithms-miscellaneous-2) [[next -->]](/algorithms-miscellaneous-4)
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ This module contains articles about algorithms. Some classes of algorithms, e.g.
|
|||||||
### Relevant articles:
|
### Relevant articles:
|
||||||
|
|
||||||
- [Multi-Swarm Optimization Algorithm in Java](https://www.baeldung.com/java-multi-swarm-algorithm)
|
- [Multi-Swarm Optimization Algorithm in Java](https://www.baeldung.com/java-multi-swarm-algorithm)
|
||||||
- [String Search Algorithms for Large Texts](https://www.baeldung.com/java-full-text-search-algorithms)
|
|
||||||
- [Check If a String Contains All The Letters of The Alphabet](https://www.baeldung.com/java-string-contains-all-letters)
|
- [Check If a String Contains All The Letters of The Alphabet](https://www.baeldung.com/java-string-contains-all-letters)
|
||||||
- [Find the Middle Element of a Linked List](https://www.baeldung.com/java-linked-list-middle-element)
|
- [Find the Middle Element of a Linked List](https://www.baeldung.com/java-linked-list-middle-element)
|
||||||
- [Find Substrings That Are Palindromes in Java](https://www.baeldung.com/java-palindrome-substrings)
|
- [Find Substrings That Are Palindromes in Java](https://www.baeldung.com/java-palindrome-substrings)
|
||||||
- [Find the Longest Substring without Repeating Characters](https://www.baeldung.com/java-longest-substring-without-repeated-characters)
|
- [Find the Longest Substring without Repeating Characters](https://www.baeldung.com/java-longest-substring-without-repeated-characters)
|
||||||
- [Permutations of an Array in Java](https://www.baeldung.com/java-array-permutations)
|
- [Permutations of an Array in Java](https://www.baeldung.com/java-array-permutations)
|
||||||
|
- [Find the Smallest Missing Integer in an Array](https://www.baeldung.com/java-smallest-missing-integer-in-array)
|
||||||
- More articles: [[<-- prev]](/algorithms-miscellaneous-3) [[next -->]](/algorithms-miscellaneous-5)
|
- More articles: [[<-- prev]](/algorithms-miscellaneous-3) [[next -->]](/algorithms-miscellaneous-5)
|
||||||
|
|||||||
-25
@@ -1,25 +0,0 @@
|
|||||||
package com.baeldung.algorithms;
|
|
||||||
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import com.baeldung.algorithms.string.search.StringSearchAlgorithms;
|
|
||||||
|
|
||||||
public class StringSearchAlgorithmsUnitTest {
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStringSearchAlgorithms(){
|
|
||||||
String text = "This is some nice text.";
|
|
||||||
String pattern = "some";
|
|
||||||
|
|
||||||
int realPosition = text.indexOf(pattern);
|
|
||||||
Assert.assertTrue(realPosition == StringSearchAlgorithms.simpleTextSearch(pattern.toCharArray(), text.toCharArray()));
|
|
||||||
Assert.assertTrue(realPosition == StringSearchAlgorithms.RabinKarpMethod(pattern.toCharArray(), text.toCharArray()));
|
|
||||||
Assert.assertTrue(realPosition == StringSearchAlgorithms.KnuthMorrisPrattSearch(pattern.toCharArray(), text.toCharArray()));
|
|
||||||
Assert.assertTrue(realPosition == StringSearchAlgorithms.BoyerMooreHorspoolSimpleSearch(pattern.toCharArray(), text.toCharArray()));
|
|
||||||
Assert.assertTrue(realPosition == StringSearchAlgorithms.BoyerMooreHorspoolSearch(pattern.toCharArray(), text.toCharArray()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -9,4 +9,5 @@ This module contains articles about algorithms. Some classes of algorithms, e.g.
|
|||||||
- [Reversing a Binary Tree in Java](https://www.baeldung.com/java-reversing-a-binary-tree)
|
- [Reversing a Binary Tree in Java](https://www.baeldung.com/java-reversing-a-binary-tree)
|
||||||
- [Find If Two Numbers Are Relatively Prime in Java](https://www.baeldung.com/java-two-relatively-prime-numbers)
|
- [Find If Two Numbers Are Relatively Prime in Java](https://www.baeldung.com/java-two-relatively-prime-numbers)
|
||||||
- [Knapsack Problem Implementation in Java](https://www.baeldung.com/java-knapsack)
|
- [Knapsack Problem Implementation in Java](https://www.baeldung.com/java-knapsack)
|
||||||
|
- [How to Determine if a Binary Tree is Balanced](https://www.baeldung.com/java-balanced-binary-tree)
|
||||||
- More articles: [[<-- prev]](/../algorithms-miscellaneous-4)
|
- More articles: [[<-- prev]](/../algorithms-miscellaneous-4)
|
||||||
|
|||||||
@@ -17,6 +17,11 @@
|
|||||||
<artifactId>commons-codec</artifactId>
|
<artifactId>commons-codec</artifactId>
|
||||||
<version>${commons-codec.version}</version>
|
<version>${commons-codec.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-math3</artifactId>
|
||||||
|
<version>${commons-math3.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
@@ -28,6 +33,7 @@
|
|||||||
<artifactId>tradukisto</artifactId>
|
<artifactId>tradukisto</artifactId>
|
||||||
<version>${tradukisto.version}</version>
|
<version>${tradukisto.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.assertj</groupId>
|
<groupId>org.assertj</groupId>
|
||||||
<artifactId>assertj-core</artifactId>
|
<artifactId>assertj-core</artifactId>
|
||||||
@@ -52,6 +58,7 @@
|
|||||||
<tradukisto.version>1.0.1</tradukisto.version>
|
<tradukisto.version>1.0.1</tradukisto.version>
|
||||||
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||||
<commons-codec.version>1.11</commons-codec.version>
|
<commons-codec.version>1.11</commons-codec.version>
|
||||||
|
<commons-math3.version>3.6.1</commons-math3.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
package com.baeldung.algorithms.caesarcipher;
|
||||||
|
|
||||||
|
import org.apache.commons.math3.stat.inference.ChiSquareTest;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class CaesarCipher {
|
||||||
|
private static final char LETTER_A = 'a';
|
||||||
|
private static final char LETTER_Z = 'z';
|
||||||
|
private static final int ALPHABET_SIZE = LETTER_Z - LETTER_A + 1;
|
||||||
|
private static final double[] ENGLISH_LETTERS_PROBABILITIES = {0.073, 0.009, 0.030, 0.044, 0.130, 0.028, 0.016, 0.035, 0.074, 0.002, 0.003, 0.035, 0.025, 0.078, 0.074, 0.027, 0.003, 0.077, 0.063, 0.093, 0.027, 0.013, 0.016, 0.005, 0.019, 0.001};
|
||||||
|
|
||||||
|
public String cipher(String message, int offset) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
|
||||||
|
for (char character : message.toCharArray()) {
|
||||||
|
if (character != ' ') {
|
||||||
|
int originalAlphabetPosition = character - LETTER_A;
|
||||||
|
int newAlphabetPosition = (originalAlphabetPosition + offset) % ALPHABET_SIZE;
|
||||||
|
char newCharacter = (char) (LETTER_A + newAlphabetPosition);
|
||||||
|
result.append(newCharacter);
|
||||||
|
} else {
|
||||||
|
result.append(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String decipher(String message, int offset) {
|
||||||
|
return cipher(message, ALPHABET_SIZE - (offset % ALPHABET_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int breakCipher(String message) {
|
||||||
|
return probableOffset(chiSquares(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
private double[] chiSquares(String message) {
|
||||||
|
double[] expectedLettersFrequencies = expectedLettersFrequencies(message.length());
|
||||||
|
|
||||||
|
double[] chiSquares = new double[ALPHABET_SIZE];
|
||||||
|
|
||||||
|
for (int offset = 0; offset < chiSquares.length; offset++) {
|
||||||
|
String decipheredMessage = decipher(message, offset);
|
||||||
|
long[] lettersFrequencies = observedLettersFrequencies(decipheredMessage);
|
||||||
|
double chiSquare = new ChiSquareTest().chiSquare(expectedLettersFrequencies, lettersFrequencies);
|
||||||
|
chiSquares[offset] = chiSquare;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chiSquares;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long[] observedLettersFrequencies(String message) {
|
||||||
|
return IntStream.rangeClosed(LETTER_A, LETTER_Z)
|
||||||
|
.mapToLong(letter -> countLetter((char) letter, message))
|
||||||
|
.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long countLetter(char letter, String message) {
|
||||||
|
return message.chars()
|
||||||
|
.filter(character -> character == letter)
|
||||||
|
.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
private double[] expectedLettersFrequencies(int messageLength) {
|
||||||
|
return Arrays.stream(ENGLISH_LETTERS_PROBABILITIES)
|
||||||
|
.map(probability -> probability * messageLength)
|
||||||
|
.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int probableOffset(double[] chiSquares) {
|
||||||
|
int probableOffset = 0;
|
||||||
|
for (int offset = 0; offset < chiSquares.length; offset++) {
|
||||||
|
System.out.println(String.format("Chi-Square for offset %d: %.2f", offset, chiSquares[offset]));
|
||||||
|
if (chiSquares[offset] < chiSquares[probableOffset]) {
|
||||||
|
probableOffset = offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return probableOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
package com.baeldung.algorithms.caesarcipher;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
class CaesarCipherUnitTest {
|
||||||
|
private static final String SENTENCE = "he told me i could never teach a llama to drive";
|
||||||
|
private static final String SENTENCE_SHIFTED_THREE = "kh wrog ph l frxog qhyhu whdfk d oodpd wr gulyh";
|
||||||
|
private static final String SENTENCE_SHIFTED_TEN = "ro dyvn wo s myevn xofob dokmr k vvkwk dy nbsfo";
|
||||||
|
|
||||||
|
private CaesarCipher algorithm = new CaesarCipher();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenSentenceAndShiftThree_whenCipher_thenCipheredMessageWithoutOverflow() {
|
||||||
|
String cipheredSentence = algorithm.cipher(SENTENCE, 3);
|
||||||
|
|
||||||
|
assertThat(cipheredSentence)
|
||||||
|
.isEqualTo(SENTENCE_SHIFTED_THREE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenSentenceAndShiftTen_whenCipher_thenCipheredMessageWithOverflow() {
|
||||||
|
String cipheredSentence = algorithm.cipher(SENTENCE, 10);
|
||||||
|
|
||||||
|
assertThat(cipheredSentence)
|
||||||
|
.isEqualTo(SENTENCE_SHIFTED_TEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenSentenceAndShiftThirtySix_whenCipher_thenCipheredLikeTenMessageWithOverflow() {
|
||||||
|
String cipheredSentence = algorithm.cipher(SENTENCE, 36);
|
||||||
|
|
||||||
|
assertThat(cipheredSentence)
|
||||||
|
.isEqualTo(SENTENCE_SHIFTED_TEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenSentenceShiftedThreeAndShiftThree_whenDecipher_thenOriginalSentenceWithoutOverflow() {
|
||||||
|
String decipheredSentence = algorithm.decipher(SENTENCE_SHIFTED_THREE, 3);
|
||||||
|
|
||||||
|
assertThat(decipheredSentence)
|
||||||
|
.isEqualTo(SENTENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenSentenceShiftedTenAndShiftTen_whenDecipher_thenOriginalSentenceWithOverflow() {
|
||||||
|
String decipheredSentence = algorithm.decipher(SENTENCE_SHIFTED_TEN, 10);
|
||||||
|
|
||||||
|
assertThat(decipheredSentence)
|
||||||
|
.isEqualTo(SENTENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenSentenceShiftedTenAndShiftThirtySix_whenDecipher_thenOriginalSentenceWithOverflow() {
|
||||||
|
String decipheredSentence = algorithm.decipher(SENTENCE_SHIFTED_TEN, 36);
|
||||||
|
|
||||||
|
assertThat(decipheredSentence)
|
||||||
|
.isEqualTo(SENTENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenSentenceShiftedThree_whenBreakCipher_thenOriginalSentence() {
|
||||||
|
int offset = algorithm.breakCipher(SENTENCE_SHIFTED_THREE);
|
||||||
|
|
||||||
|
assertThat(offset)
|
||||||
|
.isEqualTo(3);
|
||||||
|
|
||||||
|
assertThat(algorithm.decipher(SENTENCE_SHIFTED_THREE, offset))
|
||||||
|
.isEqualTo(SENTENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenSentenceShiftedTen_whenBreakCipher_thenOriginalSentence() {
|
||||||
|
int offset = algorithm.breakCipher(SENTENCE_SHIFTED_TEN);
|
||||||
|
|
||||||
|
assertThat(offset)
|
||||||
|
.isEqualTo(10);
|
||||||
|
|
||||||
|
assertThat(algorithm.decipher(SENTENCE_SHIFTED_TEN, offset))
|
||||||
|
.isEqualTo(SENTENCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
## Algorithms - Searching
|
||||||
|
|
||||||
|
This module contains articles about searching algorithms.
|
||||||
|
|
||||||
|
### Relevant articles:
|
||||||
|
- [Binary Search Algorithm in Java](https://www.baeldung.com/java-binary-search)
|
||||||
|
- [Depth First Search in Java](https://www.baeldung.com/java-depth-first-search)
|
||||||
|
- [Interpolation Search in Java](https://www.baeldung.com/java-interpolation-search)
|
||||||
|
- [Breadth-First Search Algorithm in Java](https://www.baeldung.com/java-breadth-first-search)
|
||||||
|
- [String Search Algorithms for Large Texts](https://www.baeldung.com/java-full-text-search-algorithms)
|
||||||
|
- [Monte Carlo Tree Search for Tic-Tac-Toe Game](https://www.baeldung.com/java-monte-carlo-tree-search)
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>algorithms-searching</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>algorithms-searching</name>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<version>${org.assertj.core.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>algorithms-searching</finalName>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
||||||
+55
-55
@@ -1,55 +1,55 @@
|
|||||||
package com.baeldung.algorithms.binarysearch;
|
package com.baeldung.algorithms.binarysearch;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class BinarySearch {
|
public class BinarySearch {
|
||||||
|
|
||||||
public int runBinarySearchIteratively(int[] sortedArray, int key, int low, int high) {
|
public int runBinarySearchIteratively(int[] sortedArray, int key, int low, int high) {
|
||||||
|
|
||||||
int index = Integer.MAX_VALUE;
|
int index = Integer.MAX_VALUE;
|
||||||
|
|
||||||
while (low <= high) {
|
while (low <= high) {
|
||||||
|
|
||||||
int mid = (low + high) / 2;
|
int mid = (low + high) / 2;
|
||||||
|
|
||||||
if (sortedArray[mid] < key) {
|
if (sortedArray[mid] < key) {
|
||||||
low = mid + 1;
|
low = mid + 1;
|
||||||
} else if (sortedArray[mid] > key) {
|
} else if (sortedArray[mid] > key) {
|
||||||
high = mid - 1;
|
high = mid - 1;
|
||||||
} else if (sortedArray[mid] == key) {
|
} else if (sortedArray[mid] == key) {
|
||||||
index = mid;
|
index = mid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int runBinarySearchRecursively(int[] sortedArray, int key, int low, int high) {
|
public int runBinarySearchRecursively(int[] sortedArray, int key, int low, int high) {
|
||||||
|
|
||||||
int middle = (low + high) / 2;
|
int middle = (low + high) / 2;
|
||||||
if (high < low) {
|
if (high < low) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == sortedArray[middle]) {
|
if (key == sortedArray[middle]) {
|
||||||
return middle;
|
return middle;
|
||||||
} else if (key < sortedArray[middle]) {
|
} else if (key < sortedArray[middle]) {
|
||||||
return runBinarySearchRecursively(sortedArray, key, low, middle - 1);
|
return runBinarySearchRecursively(sortedArray, key, low, middle - 1);
|
||||||
} else {
|
} else {
|
||||||
return runBinarySearchRecursively(sortedArray, key, middle + 1, high);
|
return runBinarySearchRecursively(sortedArray, key, middle + 1, high);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int runBinarySearchUsingJavaArrays(int[] sortedArray, Integer key) {
|
public int runBinarySearchUsingJavaArrays(int[] sortedArray, Integer key) {
|
||||||
int index = Arrays.binarySearch(sortedArray, key);
|
int index = Arrays.binarySearch(sortedArray, key);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int runBinarySearchUsingJavaCollections(List<Integer> sortedList, Integer key) {
|
public int runBinarySearchUsingJavaCollections(List<Integer> sortedList, Integer key) {
|
||||||
int index = Collections.binarySearch(sortedList, key);
|
int index = Collections.binarySearch(sortedList, key);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
package com.baeldung.algorithms.dfs;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
public class BinaryTree {
|
||||||
|
|
||||||
|
Node root;
|
||||||
|
|
||||||
|
public void add(int value) {
|
||||||
|
root = addRecursive(root, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node addRecursive(Node current, int value) {
|
||||||
|
|
||||||
|
if (current == null) {
|
||||||
|
return new Node(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < current.value) {
|
||||||
|
current.left = addRecursive(current.left, value);
|
||||||
|
} else if (value > current.value) {
|
||||||
|
current.right = addRecursive(current.right, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return root == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return getSizeRecursive(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSizeRecursive(Node current) {
|
||||||
|
return current == null ? 0 : getSizeRecursive(current.left) + 1 + getSizeRecursive(current.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsNode(int value) {
|
||||||
|
return containsNodeRecursive(root, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsNodeRecursive(Node current, int value) {
|
||||||
|
if (current == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == current.value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value < current.value
|
||||||
|
? containsNodeRecursive(current.left, value)
|
||||||
|
: containsNodeRecursive(current.right, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(int value) {
|
||||||
|
root = deleteRecursive(root, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node deleteRecursive(Node current, int value) {
|
||||||
|
if (current == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == current.value) {
|
||||||
|
// Case 1: no children
|
||||||
|
if (current.left == null && current.right == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case 2: only 1 child
|
||||||
|
if (current.right == null) {
|
||||||
|
return current.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current.left == null) {
|
||||||
|
return current.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case 3: 2 children
|
||||||
|
int smallestValue = findSmallestValue(current.right);
|
||||||
|
current.value = smallestValue;
|
||||||
|
current.right = deleteRecursive(current.right, smallestValue);
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
if (value < current.value) {
|
||||||
|
current.left = deleteRecursive(current.left, value);
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
current.right = deleteRecursive(current.right, value);
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int findSmallestValue(Node root) {
|
||||||
|
return root.left == null ? root.value : findSmallestValue(root.left);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void traverseInOrder(Node node) {
|
||||||
|
if (node != null) {
|
||||||
|
traverseInOrder(node.left);
|
||||||
|
visit(node.value);
|
||||||
|
traverseInOrder(node.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void traversePreOrder(Node node) {
|
||||||
|
if (node != null) {
|
||||||
|
visit(node.value);
|
||||||
|
traversePreOrder(node.left);
|
||||||
|
traversePreOrder(node.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void traversePostOrder(Node node) {
|
||||||
|
if (node != null) {
|
||||||
|
traversePostOrder(node.left);
|
||||||
|
traversePostOrder(node.right);
|
||||||
|
visit(node.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void traverseLevelOrder() {
|
||||||
|
if (root == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Queue<Node> nodes = new LinkedList<>();
|
||||||
|
nodes.add(root);
|
||||||
|
|
||||||
|
while (!nodes.isEmpty()) {
|
||||||
|
|
||||||
|
Node node = nodes.remove();
|
||||||
|
|
||||||
|
System.out.print(" " + node.value);
|
||||||
|
|
||||||
|
if (node.left != null) {
|
||||||
|
nodes.add(node.left);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.left != null) {
|
||||||
|
nodes.add(node.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void traverseInOrderWithoutRecursion() {
|
||||||
|
Stack<Node> stack = new Stack<Node>();
|
||||||
|
Node current = root;
|
||||||
|
stack.push(root);
|
||||||
|
while(! stack.isEmpty()) {
|
||||||
|
while(current.left != null) {
|
||||||
|
current = current.left;
|
||||||
|
stack.push(current);
|
||||||
|
}
|
||||||
|
current = stack.pop();
|
||||||
|
visit(current.value);
|
||||||
|
if(current.right != null) {
|
||||||
|
current = current.right;
|
||||||
|
stack.push(current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void traversePreOrderWithoutRecursion() {
|
||||||
|
Stack<Node> stack = new Stack<Node>();
|
||||||
|
Node current = root;
|
||||||
|
stack.push(root);
|
||||||
|
while(! stack.isEmpty()) {
|
||||||
|
current = stack.pop();
|
||||||
|
visit(current.value);
|
||||||
|
|
||||||
|
if(current.right != null)
|
||||||
|
stack.push(current.right);
|
||||||
|
|
||||||
|
if(current.left != null)
|
||||||
|
stack.push(current.left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void traversePostOrderWithoutRecursion() {
|
||||||
|
Stack<Node> stack = new Stack<Node>();
|
||||||
|
Node prev = root;
|
||||||
|
Node current = root;
|
||||||
|
stack.push(root);
|
||||||
|
|
||||||
|
while (!stack.isEmpty()) {
|
||||||
|
current = stack.peek();
|
||||||
|
boolean hasChild = (current.left != null || current.right != null);
|
||||||
|
boolean isPrevLastChild = (prev == current.right || (prev == current.left && current.right == null));
|
||||||
|
|
||||||
|
if (!hasChild || isPrevLastChild) {
|
||||||
|
current = stack.pop();
|
||||||
|
visit(current.value);
|
||||||
|
prev = current;
|
||||||
|
} else {
|
||||||
|
if (current.right != null) {
|
||||||
|
stack.push(current.right);
|
||||||
|
}
|
||||||
|
if (current.left != null) {
|
||||||
|
stack.push(current.left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visit(int value) {
|
||||||
|
System.out.print(" " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
int value;
|
||||||
|
Node left;
|
||||||
|
Node right;
|
||||||
|
|
||||||
|
Node(int value) {
|
||||||
|
this.value = value;
|
||||||
|
right = null;
|
||||||
|
left = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.graph;
|
package com.baeldung.algorithms.dfs;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user