Merge branch 'master' of https://github.com/eugenp/tutorials
This commit is contained in:
commit
7807c24d2b
|
@ -30,7 +30,7 @@ out/
|
|||
.DS_Store
|
||||
|
||||
# Maven
|
||||
log/
|
||||
log/*
|
||||
target/
|
||||
|
||||
# Gradle
|
||||
|
@ -84,3 +84,10 @@ software-security/sql-injection-samples/derby.log
|
|||
spring-soap/src/main/java/com/baeldung/springsoap/gen/
|
||||
/report-*.json
|
||||
transaction.log
|
||||
*-shell.log
|
||||
|
||||
apache-cxf/cxf-aegis/baeldung.xml
|
||||
apache-fop/src/test/resources/input.xml
|
||||
apache-fop/src/test/resources/output_herold.pdf
|
||||
apache-fop/src/test/resources/output_html2fo.pdf
|
||||
apache-fop/src/test/resources/output_jtidy.pdf
|
|
@ -1,3 +1,7 @@
|
|||
## Relevant articles:
|
||||
## Akka HTTP
|
||||
|
||||
This module contains articles about Akka HTTP.
|
||||
|
||||
### Relevant articles:
|
||||
|
||||
- [Introduction to Akka HTTP](https://www.baeldung.com/akka-http)
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
## Akka Streams
|
||||
|
||||
This module contains articles about Akka Streams.
|
||||
|
||||
### Relevant articles
|
||||
|
||||
- [Guide to Akka Streams](https://www.baeldung.com/akka-streams)
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
## Relevant articles:
|
||||
## Genetic Algorithms
|
||||
|
||||
This module contains articles about genetic algorithms.
|
||||
|
||||
### Relevant articles:
|
||||
|
||||
- [Introduction to Jenetics Library](https://www.baeldung.com/jenetics)
|
||||
- [Ant Colony Optimization](https://www.baeldung.com/java-ant-colony-optimization)
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
## Relevant articles:
|
||||
## Algorithms - Miscellaneous
|
||||
|
||||
This module contains articles about algorithms. Some classes of algorithms, e.g., [sorting](/../algorithms-sorting) and
|
||||
[genetic algorithms](/../algorithms-genetic), have their own dedicated modules.
|
||||
|
||||
### Relevant articles:
|
||||
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- More articles: [[next -->]](/../algorithms-miscellaneous-2)
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
## Relevant articles:
|
||||
## Algorithms - Miscellaneous
|
||||
|
||||
This module contains articles about algorithms. Some classes of algorithms, e.g., [sorting](/../algorithms-sorting) and
|
||||
[genetic algorithms](/../algorithms-genetic), have their own dedicated modules.
|
||||
|
||||
### Relevant articles:
|
||||
|
||||
- [Dijkstra Shortest Path Algorithm in Java](https://www.baeldung.com/java-dijkstra)
|
||||
- [Introduction to Cobertura](https://www.baeldung.com/cobertura)
|
||||
|
@ -8,3 +13,4 @@
|
|||
- [Create a Sudoku Solver in Java](https://www.baeldung.com/java-sudoku)
|
||||
- [Displaying Money Amounts in Words](https://www.baeldung.com/java-money-into-words)
|
||||
- [A Collaborative Filtering Recommendation System in Java](https://www.baeldung.com/java-collaborative-filtering-recommendations)
|
||||
- More articles: [[<-- prev]](/../algorithms-miscellaneous-1) [[next -->]](/../algorithms-miscellaneous-3)
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,643 @@
|
|||
package com.baeldung.algorithms.astar.underground;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.baeldung.algorithms.astar.Graph;
|
||||
import com.baeldung.algorithms.astar.RouteFinder;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RouteFinderIntegrationTest {
|
||||
|
||||
private Graph<Station> underground;
|
||||
|
||||
private RouteFinder<Station> routeFinder;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Set<Station> stations = new HashSet<>();
|
||||
Map<String, Set<String>> connections = new HashMap<>();
|
||||
|
||||
stations.add(new Station("1", "Acton Town", 51.5028, -0.2801));
|
||||
stations.add(new Station("2", "Aldgate", 51.5143, -0.0755));
|
||||
stations.add(new Station("3", "Aldgate East", 51.5154, -0.0726));
|
||||
stations.add(new Station("4", "All Saints", 51.5107, -0.013));
|
||||
stations.add(new Station("5", "Alperton", 51.5407, -0.2997));
|
||||
stations.add(new Station("6", "Amersham", 51.6736, -0.607));
|
||||
stations.add(new Station("7", "Angel", 51.5322, -0.1058));
|
||||
stations.add(new Station("8", "Archway", 51.5653, -0.1353));
|
||||
stations.add(new Station("9", "Arnos Grove", 51.6164, -0.1331));
|
||||
stations.add(new Station("10", "Arsenal", 51.5586, -0.1059));
|
||||
stations.add(new Station("11", "Baker Street", 51.5226, -0.1571));
|
||||
stations.add(new Station("12", "Balham", 51.4431, -0.1525));
|
||||
stations.add(new Station("13", "Bank", 51.5133, -0.0886));
|
||||
stations.add(new Station("14", "Barbican", 51.5204, -0.0979));
|
||||
stations.add(new Station("15", "Barking", 51.5396, 0.081));
|
||||
stations.add(new Station("16", "Barkingside", 51.5856, 0.0887));
|
||||
stations.add(new Station("17", "Barons Court", 51.4905, -0.2139));
|
||||
stations.add(new Station("18", "Bayswater", 51.5121, -0.1879));
|
||||
stations.add(new Station("19", "Beckton", 51.5148, 0.0613));
|
||||
stations.add(new Station("20", "Beckton Park", 51.5087, 0.055));
|
||||
stations.add(new Station("21", "Becontree", 51.5403, 0.127));
|
||||
stations.add(new Station("22", "Belsize Park", 51.5504, -0.1642));
|
||||
stations.add(new Station("23", "Bermondsey", 51.4979, -0.0637));
|
||||
stations.add(new Station("24", "Bethnal Green", 51.527, -0.0549));
|
||||
stations.add(new Station("25", "Blackfriars", 51.512, -0.1031));
|
||||
stations.add(new Station("26", "Blackhorse Road", 51.5867, -0.0417));
|
||||
stations.add(new Station("27", "Blackwall", 51.5079, -0.0066));
|
||||
stations.add(new Station("28", "Bond Street", 51.5142, -0.1494));
|
||||
stations.add(new Station("29", "Borough", 51.5011, -0.0943));
|
||||
stations.add(new Station("30", "Boston Manor", 51.4956, -0.325));
|
||||
stations.add(new Station("31", "Bounds Green", 51.6071, -0.1243));
|
||||
stations.add(new Station("32", "Bow Church", 51.5273, -0.0208));
|
||||
stations.add(new Station("33", "Bow Road", 51.5269, -0.0247));
|
||||
stations.add(new Station("34", "Brent Cross", 51.5766, -0.2136));
|
||||
stations.add(new Station("35", "Brixton", 51.4627, -0.1145));
|
||||
stations.add(new Station("36", "Bromley-By-Bow", 51.5248, -0.0119));
|
||||
stations.add(new Station("37", "Buckhurst Hill", 51.6266, 0.0471));
|
||||
stations.add(new Station("38", "Burnt Oak", 51.6028, -0.2641));
|
||||
stations.add(new Station("39", "Caledonian Road", 51.5481, -0.1188));
|
||||
stations.add(new Station("40", "Camden Town", 51.5392, -0.1426));
|
||||
stations.add(new Station("41", "Canada Water", 51.4982, -0.0502));
|
||||
stations.add(new Station("42", "Canary Wharf", 51.5051, -0.0209));
|
||||
stations.add(new Station("43", "Canning Town", 51.5147, 0.0082));
|
||||
stations.add(new Station("44", "Cannon Street", 51.5113, -0.0904));
|
||||
stations.add(new Station("45", "Canons Park", 51.6078, -0.2947));
|
||||
stations.add(new Station("46", "Chalfont & Latimer", 51.6679, -0.561));
|
||||
stations.add(new Station("47", "Chalk Farm", 51.5441, -0.1538));
|
||||
stations.add(new Station("48", "Chancery Lane", 51.5185, -0.1111));
|
||||
stations.add(new Station("49", "Charing Cross", 51.508, -0.1247));
|
||||
stations.add(new Station("50", "Chesham", 51.7052, -0.611));
|
||||
stations.add(new Station("51", "Chigwell", 51.6177, 0.0755));
|
||||
stations.add(new Station("52", "Chiswick Park", 51.4946, -0.2678));
|
||||
stations.add(new Station("53", "Chorleywood", 51.6543, -0.5183));
|
||||
stations.add(new Station("54", "Clapham Common", 51.4618, -0.1384));
|
||||
stations.add(new Station("55", "Clapham North", 51.4649, -0.1299));
|
||||
stations.add(new Station("56", "Clapham South", 51.4527, -0.148));
|
||||
stations.add(new Station("57", "Cockfosters", 51.6517, -0.1496));
|
||||
stations.add(new Station("58", "Colindale", 51.5955, -0.2502));
|
||||
stations.add(new Station("59", "Colliers Wood", 51.418, -0.1778));
|
||||
stations.add(new Station("60", "Covent Garden", 51.5129, -0.1243));
|
||||
stations.add(new Station("61", "Crossharbour & London Arena", 51.4957, -0.0144));
|
||||
stations.add(new Station("62", "Croxley", 51.647, -0.4412));
|
||||
stations.add(new Station("63", "Custom House", 51.5095, 0.0276));
|
||||
stations.add(new Station("64", "Cutty Sark", 51.4827, -0.0096));
|
||||
stations.add(new Station("65", "Cyprus", 51.5085, 0.064));
|
||||
stations.add(new Station("66", "Dagenham East", 51.5443, 0.1655));
|
||||
stations.add(new Station("67", "Dagenham Heathway", 51.5417, 0.1469));
|
||||
stations.add(new Station("68", "Debden", 51.6455, 0.0838));
|
||||
stations.add(new Station("69", "Deptford Bridge", 51.474, -0.0216));
|
||||
stations.add(new Station("70", "Devons Road", 51.5223, -0.0173));
|
||||
stations.add(new Station("71", "Dollis Hill", 51.552, -0.2387));
|
||||
stations.add(new Station("72", "Ealing Broadway", 51.5152, -0.3017));
|
||||
stations.add(new Station("73", "Ealing Common", 51.5101, -0.2882));
|
||||
stations.add(new Station("74", "Earl's Court", 51.492, -0.1973));
|
||||
stations.add(new Station("75", "Eastcote", 51.5765, -0.397));
|
||||
stations.add(new Station("76", "East Acton", 51.5168, -0.2474));
|
||||
stations.add(new Station("77", "East Finchley", 51.5874, -0.165));
|
||||
stations.add(new Station("78", "East Ham", 51.5394, 0.0518));
|
||||
stations.add(new Station("79", "East India", 51.5093, -0.0021));
|
||||
stations.add(new Station("80", "East Putney", 51.4586, -0.2112));
|
||||
stations.add(new Station("81", "Edgware", 51.6137, -0.275));
|
||||
stations.add(new Station("82", "Edgware Road (B)", 51.5199, -0.1679));
|
||||
stations.add(new Station("83", "Edgware Road (C)", 51.5203, -0.17));
|
||||
stations.add(new Station("84", "Elephant & Castle", 51.4943, -0.1001));
|
||||
stations.add(new Station("85", "Elm Park", 51.5496, 0.1977));
|
||||
stations.add(new Station("86", "Elverson Road", 51.4693, -0.0174));
|
||||
stations.add(new Station("87", "Embankment", 51.5074, -0.1223));
|
||||
stations.add(new Station("88", "Epping", 51.6937, 0.1139));
|
||||
stations.add(new Station("89", "Euston", 51.5282, -0.1337));
|
||||
stations.add(new Station("90", "Euston Square", 51.526, -0.1359));
|
||||
stations.add(new Station("91", "Fairlop", 51.596, 0.0912));
|
||||
stations.add(new Station("92", "Farringdon", 51.5203, -0.1053));
|
||||
stations.add(new Station("93", "Finchley Central", 51.6012, -0.1932));
|
||||
stations.add(new Station("94", "Finchley Road", 51.5472, -0.1803));
|
||||
stations.add(new Station("95", "Finsbury Park", 51.5642, -0.1065));
|
||||
stations.add(new Station("96", "Fulham Broadway", 51.4804, -0.195));
|
||||
stations.add(new Station("97", "Gallions Reach", 51.5096, 0.0716));
|
||||
stations.add(new Station("98", "Gants Hill", 51.5765, 0.0663));
|
||||
stations.add(new Station("99", "Gloucester Road", 51.4945, -0.1829));
|
||||
stations.add(new Station("100", "Golders Green", 51.5724, -0.1941));
|
||||
stations.add(new Station("101", "Goldhawk Road", 51.5018, -0.2267));
|
||||
stations.add(new Station("102", "Goodge Street", 51.5205, -0.1347));
|
||||
stations.add(new Station("103", "Grange Hill", 51.6132, 0.0923));
|
||||
stations.add(new Station("104", "Great Portland Street", 51.5238, -0.1439));
|
||||
stations.add(new Station("105", "Greenford", 51.5423, -0.3456));
|
||||
stations.add(new Station("106", "Greenwich", 51.4781, -0.0149));
|
||||
stations.add(new Station("107", "Green Park", 51.5067, -0.1428));
|
||||
stations.add(new Station("108", "Gunnersbury", 51.4915, -0.2754));
|
||||
stations.add(new Station("109", "Hainault", 51.603, 0.0933));
|
||||
stations.add(new Station("110", "Hammersmith", 51.4936, -0.2251));
|
||||
stations.add(new Station("111", "Hampstead", 51.5568, -0.178));
|
||||
stations.add(new Station("112", "Hanger Lane", 51.5302, -0.2933));
|
||||
stations.add(new Station("113", "Harlesden", 51.5362, -0.2575));
|
||||
stations.add(new Station("114", "Harrow & Wealdston", 51.5925, -0.3351));
|
||||
stations.add(new Station("115", "Harrow-on-the-Hill", 51.5793, -0.3366));
|
||||
stations.add(new Station("116", "Hatton Cross", 51.4669, -0.4227));
|
||||
stations.add(new Station("117", "Heathrow Terminals 1, 2 & 3", 51.4713, -0.4524));
|
||||
stations.add(new Station("118", "Heathrow Terminal 4", 51.4598, -0.4476));
|
||||
stations.add(new Station("119", "Hendon Central", 51.5829, -0.2259));
|
||||
stations.add(new Station("120", "Heron Quays", 51.5033, -0.0215));
|
||||
stations.add(new Station("121", "High Barnet", 51.6503, -0.1943));
|
||||
stations.add(new Station("122", "High Street Kensington", 51.5009, -0.1925));
|
||||
stations.add(new Station("123", "Highbury & Islington", 51.546, -0.104));
|
||||
stations.add(new Station("124", "Highgate", 51.5777, -0.1458));
|
||||
stations.add(new Station("125", "Hillingdon", 51.5538, -0.4499));
|
||||
stations.add(new Station("126", "Holborn", 51.5174, -0.12));
|
||||
stations.add(new Station("127", "Holland Park", 51.5075, -0.206));
|
||||
stations.add(new Station("128", "Holloway Road", 51.5526, -0.1132));
|
||||
stations.add(new Station("129", "Hornchurch", 51.5539, 0.2184));
|
||||
stations.add(new Station("130", "Hounslow Central", 51.4713, -0.3665));
|
||||
stations.add(new Station("131", "Hounslow East", 51.4733, -0.3564));
|
||||
stations.add(new Station("132", "Hounslow West", 51.4734, -0.3855));
|
||||
stations.add(new Station("133", "Hyde Park Corner", 51.5027, -0.1527));
|
||||
stations.add(new Station("134", "Ickenham", 51.5619, -0.4421));
|
||||
stations.add(new Station("135", "Island Gardens", 51.4871, -0.0101));
|
||||
stations.add(new Station("136", "Kennington", 51.4884, -0.1053));
|
||||
stations.add(new Station("137", "Kensal Green", 51.5304, -0.225));
|
||||
stations.add(new Station("138", "Kensington (Olympia)", 51.4983, -0.2106));
|
||||
stations.add(new Station("139", "Kentish Town", 51.5507, -0.1402));
|
||||
stations.add(new Station("140", "Kenton", 51.5816, -0.3162));
|
||||
stations.add(new Station("141", "Kew Gardens", 51.477, -0.285));
|
||||
stations.add(new Station("142", "Kilburn", 51.5471, -0.2047));
|
||||
stations.add(new Station("143", "Kilburn Park", 51.5351, -0.1939));
|
||||
stations.add(new Station("144", "Kingsbury", 51.5846, -0.2786));
|
||||
stations.add(new Station("145", "King's Cross St. Pancras", 51.5308, -0.1238));
|
||||
stations.add(new Station("146", "Knightsbridge", 51.5015, -0.1607));
|
||||
stations.add(new Station("147", "Ladbroke Grove", 51.5172, -0.2107));
|
||||
stations.add(new Station("148", "Lambeth North", 51.4991, -0.1115));
|
||||
stations.add(new Station("149", "Lancaster Gate", 51.5119, -0.1756));
|
||||
stations.add(new Station("150", "Latimer Road", 51.5139, -0.2172));
|
||||
stations.add(new Station("151", "Leicester Square", 51.5113, -0.1281));
|
||||
stations.add(new Station("152", "Lewisham", 51.4657, -0.0142));
|
||||
stations.add(new Station("153", "Leyton", 51.5566, -0.0053));
|
||||
stations.add(new Station("154", "Leytonstone", 51.5683, 0.0083));
|
||||
stations.add(new Station("155", "Limehouse", 51.5123, -0.0396));
|
||||
stations.add(new Station("156", "Liverpool Street", 51.5178, -0.0823));
|
||||
stations.add(new Station("157", "London Bridge", 51.5052, -0.0864));
|
||||
stations.add(new Station("158", "Loughton", 51.6412, 0.0558));
|
||||
stations.add(new Station("159", "Maida Vale", 51.53, -0.1854));
|
||||
stations.add(new Station("160", "Manor House", 51.5712, -0.0958));
|
||||
stations.add(new Station("161", "Mansion House", 51.5122, -0.094));
|
||||
stations.add(new Station("162", "Marble Arch", 51.5136, -0.1586));
|
||||
stations.add(new Station("163", "Marylebone", 51.5225, -0.1631));
|
||||
stations.add(new Station("164", "Mile End", 51.5249, -0.0332));
|
||||
stations.add(new Station("165", "Mill Hill East", 51.6082, -0.2103));
|
||||
stations.add(new Station("166", "Monument", 51.5108, -0.0863));
|
||||
stations.add(new Station("167", "Moorgate", 51.5186, -0.0886));
|
||||
stations.add(new Station("168", "Moor Park", 51.6294, -0.432));
|
||||
stations.add(new Station("169", "Morden", 51.4022, -0.1948));
|
||||
stations.add(new Station("170", "Mornington Crescent", 51.5342, -0.1387));
|
||||
stations.add(new Station("171", "Mudchute", 51.4902, -0.0145));
|
||||
stations.add(new Station("172", "Neasden", 51.5542, -0.2503));
|
||||
stations.add(new Station("173", "Newbury Park", 51.5756, 0.0899));
|
||||
stations.add(new Station("174", "New Cross", 51.4767, -0.0327));
|
||||
stations.add(new Station("175", "New Cross Gate", 51.4757, -0.0402));
|
||||
stations.add(new Station("176", "Northfields", 51.4995, -0.3142));
|
||||
stations.add(new Station("177", "Northolt", 51.5483, -0.3687));
|
||||
stations.add(new Station("178", "Northwick Park", 51.5784, -0.3184));
|
||||
stations.add(new Station("179", "Northwood", 51.6111, -0.424));
|
||||
stations.add(new Station("180", "Northwood Hills", 51.6004, -0.4092));
|
||||
stations.add(new Station("181", "North Acton", 51.5237, -0.2597));
|
||||
stations.add(new Station("182", "North Ealing", 51.5175, -0.2887));
|
||||
stations.add(new Station("183", "North Greenwich", 51.5005, 0.0039));
|
||||
stations.add(new Station("184", "North Harrow", 51.5846, -0.3626));
|
||||
stations.add(new Station("185", "North Wembley", 51.5621, -0.3034));
|
||||
stations.add(new Station("186", "Notting Hill Gate", 51.5094, -0.1967));
|
||||
stations.add(new Station("187", "Oakwood", 51.6476, -0.1318));
|
||||
stations.add(new Station("188", "Old Street", 51.5263, -0.0873));
|
||||
stations.add(new Station("189", "Osterley", 51.4813, -0.3522));
|
||||
stations.add(new Station("190", "Oval", 51.4819, -0.113));
|
||||
stations.add(new Station("191", "Oxford Circus", 51.515, -0.1415));
|
||||
stations.add(new Station("192", "Paddington", 51.5154, -0.1755));
|
||||
stations.add(new Station("193", "Park Royal", 51.527, -0.2841));
|
||||
stations.add(new Station("194", "Parsons Green", 51.4753, -0.2011));
|
||||
stations.add(new Station("195", "Perivale", 51.5366, -0.3232));
|
||||
stations.add(new Station("196", "Picadilly Circus", 51.5098, -0.1342));
|
||||
stations.add(new Station("197", "Pimlico", 51.4893, -0.1334));
|
||||
stations.add(new Station("198", "Pinner", 51.5926, -0.3805));
|
||||
stations.add(new Station("199", "Plaistow", 51.5313, 0.0172));
|
||||
stations.add(new Station("200", "Poplar", 51.5077, -0.0173));
|
||||
stations.add(new Station("201", "Preston Road", 51.572, -0.2954));
|
||||
stations.add(new Station("202", "Prince Regent", 51.5093, 0.0336));
|
||||
stations.add(new Station("203", "Pudding Mill Lane", 51.5343, -0.0139));
|
||||
stations.add(new Station("204", "Putney Bridge", 51.4682, -0.2089));
|
||||
stations.add(new Station("205", "Queen's Park", 51.5341, -0.2047));
|
||||
stations.add(new Station("206", "Queensbury", 51.5942, -0.2861));
|
||||
stations.add(new Station("207", "Queensway", 51.5107, -0.1877));
|
||||
stations.add(new Station("208", "Ravenscourt Park", 51.4942, -0.2359));
|
||||
stations.add(new Station("209", "Rayners Lane", 51.5753, -0.3714));
|
||||
stations.add(new Station("210", "Redbridge", 51.5763, 0.0454));
|
||||
stations.add(new Station("211", "Regent's Park", 51.5234, -0.1466));
|
||||
stations.add(new Station("212", "Richmond", 51.4633, -0.3013));
|
||||
stations.add(new Station("213", "Rickmansworth", 51.6404, -0.4733));
|
||||
stations.add(new Station("214", "Roding Valley", 51.6171, 0.0439));
|
||||
stations.add(new Station("215", "Rotherhithe", 51.501, -0.0525));
|
||||
stations.add(new Station("216", "Royal Albert", 51.5084, 0.0465));
|
||||
stations.add(new Station("217", "Royal Oak", 51.519, -0.188));
|
||||
stations.add(new Station("218", "Royal Victoria", 51.5091, 0.0181));
|
||||
stations.add(new Station("219", "Ruislip", 51.5715, -0.4213));
|
||||
stations.add(new Station("220", "Ruislip Gardens", 51.5606, -0.4103));
|
||||
stations.add(new Station("221", "Ruislip Manor", 51.5732, -0.4125));
|
||||
stations.add(new Station("222", "Russell Square", 51.523, -0.1244));
|
||||
stations.add(new Station("223", "Seven Sisters", 51.5822, -0.0749));
|
||||
stations.add(new Station("224", "Shadwell", 51.5117, -0.056));
|
||||
stations.add(new Station("225", "Shepherd's Bush (C)", 51.5046, -0.2187));
|
||||
stations.add(new Station("226", "Shepherd's Bush (H)", 51.5058, -0.2265));
|
||||
stations.add(new Station("227", "Shoreditch", 51.5227, -0.0708));
|
||||
stations.add(new Station("228", "Sloane Square", 51.4924, -0.1565));
|
||||
stations.add(new Station("229", "Snaresbrook", 51.5808, 0.0216));
|
||||
stations.add(new Station("230", "Southfields", 51.4454, -0.2066));
|
||||
stations.add(new Station("231", "Southgate", 51.6322, -0.128));
|
||||
stations.add(new Station("232", "Southwark", 51.501, -0.1052));
|
||||
stations.add(new Station("233", "South Ealing", 51.5011, -0.3072));
|
||||
stations.add(new Station("234", "South Harrow", 51.5646, -0.3521));
|
||||
stations.add(new Station("235", "South Kensington", 51.4941, -0.1738));
|
||||
stations.add(new Station("236", "South Kenton", 51.5701, -0.3081));
|
||||
stations.add(new Station("237", "South Quay", 51.5007, -0.0191));
|
||||
stations.add(new Station("238", "South Ruislip", 51.5569, -0.3988));
|
||||
stations.add(new Station("239", "South Wimbledon", 51.4154, -0.1919));
|
||||
stations.add(new Station("240", "South Woodford", 51.5917, 0.0275));
|
||||
stations.add(new Station("241", "Stamford Brook", 51.495, -0.2459));
|
||||
stations.add(new Station("242", "Stanmore", 51.6194, -0.3028));
|
||||
stations.add(new Station("243", "Stepney Green", 51.5221, -0.047));
|
||||
stations.add(new Station("244", "Stockwell", 51.4723, -0.123));
|
||||
stations.add(new Station("245", "Stonebridge Park", 51.5439, -0.2759));
|
||||
stations.add(new Station("246", "Stratford", 51.5416, -0.0042));
|
||||
stations.add(new Station("247", "St. James's Park", 51.4994, -0.1335));
|
||||
stations.add(new Station("248", "St. John's Wood", 51.5347, -0.174));
|
||||
stations.add(new Station("249", "St. Paul's", 51.5146, -0.0973));
|
||||
stations.add(new Station("250", "Sudbury Hill", 51.5569, -0.3366));
|
||||
stations.add(new Station("251", "Sudbury Town", 51.5507, -0.3156));
|
||||
stations.add(new Station("252", "Surrey Quays", 51.4933, -0.0478));
|
||||
stations.add(new Station("253", "Swiss Cottage", 51.5432, -0.1738));
|
||||
stations.add(new Station("254", "Temple", 51.5111, -0.1141));
|
||||
stations.add(new Station("255", "Theydon Bois", 51.6717, 0.1033));
|
||||
stations.add(new Station("256", "Tooting Bec", 51.4361, -0.1598));
|
||||
stations.add(new Station("257", "Tooting Broadway", 51.4275, -0.168));
|
||||
stations.add(new Station("258", "Tottenham Court Road", 51.5165, -0.131));
|
||||
stations.add(new Station("259", "Tottenham Hale", 51.5882, -0.0594));
|
||||
stations.add(new Station("260", "Totteridge & Whetstone", 51.6302, -0.1791));
|
||||
stations.add(new Station("261", "Tower Gateway", 51.5106, -0.0743));
|
||||
stations.add(new Station("262", "Tower Hill", 51.5098, -0.0766));
|
||||
stations.add(new Station("263", "Tufnell Park", 51.5567, -0.1374));
|
||||
stations.add(new Station("264", "Turnham Green", 51.4951, -0.2547));
|
||||
stations.add(new Station("265", "Turnpike Lane", 51.5904, -0.1028));
|
||||
stations.add(new Station("266", "Upminster", 51.559, 0.251));
|
||||
stations.add(new Station("267", "Upminster Bridge", 51.5582, 0.2343));
|
||||
stations.add(new Station("268", "Upney", 51.5385, 0.1014));
|
||||
stations.add(new Station("269", "Upton Park", 51.5352, 0.0343));
|
||||
stations.add(new Station("270", "Uxbridge", 51.5463, -0.4786));
|
||||
stations.add(new Station("271", "Vauxhall", 51.4861, -0.1253));
|
||||
stations.add(new Station("272", "Victoria", 51.4965, -0.1447));
|
||||
stations.add(new Station("273", "Walthamstow Central", 51.583, -0.0195));
|
||||
stations.add(new Station("274", "Wanstead", 51.5775, 0.0288));
|
||||
stations.add(new Station("275", "Wapping", 51.5043, -0.0558));
|
||||
stations.add(new Station("276", "Warren Street", 51.5247, -0.1384));
|
||||
stations.add(new Station("277", "Warwick Avenue", 51.5235, -0.1835));
|
||||
stations.add(new Station("278", "Waterloo", 51.5036, -0.1143));
|
||||
stations.add(new Station("279", "Watford", 51.6573, -0.4177));
|
||||
stations.add(new Station("280", "Wembley Central", 51.5519, -0.2963));
|
||||
stations.add(new Station("281", "Wembley Park", 51.5635, -0.2795));
|
||||
stations.add(new Station("282", "Westbourne Park", 51.521, -0.2011));
|
||||
stations.add(new Station("283", "Westferry", 51.5097, -0.0265));
|
||||
stations.add(new Station("284", "Westminster", 51.501, -0.1254));
|
||||
stations.add(new Station("285", "West Acton", 51.518, -0.2809));
|
||||
stations.add(new Station("286", "West Brompton", 51.4872, -0.1953));
|
||||
stations.add(new Station("287", "West Finchley", 51.6095, -0.1883));
|
||||
stations.add(new Station("288", "West Ham", 51.5287, 0.0056));
|
||||
stations.add(new Station("289", "West Hampstead", 51.5469, -0.1906));
|
||||
stations.add(new Station("290", "West Harrow", 51.5795, -0.3533));
|
||||
stations.add(new Station("291", "West India Quay", 51.507, -0.0203));
|
||||
stations.add(new Station("292", "West Kensington", 51.4907, -0.2065));
|
||||
stations.add(new Station("293", "West Ruislip", 51.5696, -0.4376));
|
||||
stations.add(new Station("294", "Whitechapel", 51.5194, -0.0612));
|
||||
stations.add(new Station("295", "White City", 51.512, -0.2239));
|
||||
stations.add(new Station("296", "Willesden Green", 51.5492, -0.2215));
|
||||
stations.add(new Station("297", "Willesden Junction", 51.5326, -0.2478));
|
||||
stations.add(new Station("298", "Wimbledon", 51.4214, -0.2064));
|
||||
stations.add(new Station("299", "Wimbledon Park", 51.4343, -0.1992));
|
||||
stations.add(new Station("300", "Woodford", 51.607, 0.0341));
|
||||
stations.add(new Station("301", "Woodside Park", 51.6179, -0.1856));
|
||||
stations.add(new Station("302", "Wood Green", 51.5975, -0.1097));
|
||||
|
||||
connections.put("1", Stream.of("52","73","73","233","264").collect(Collectors.toSet()));
|
||||
connections.put("2", Stream.of("156","262","156").collect(Collectors.toSet()));
|
||||
connections.put("3", Stream.of("262","294","156","294").collect(Collectors.toSet()));
|
||||
connections.put("4", Stream.of("70","200").collect(Collectors.toSet()));
|
||||
connections.put("5", Stream.of("193","251").collect(Collectors.toSet()));
|
||||
connections.put("6", Stream.of("46").collect(Collectors.toSet()));
|
||||
connections.put("7", Stream.of("145","188").collect(Collectors.toSet()));
|
||||
connections.put("8", Stream.of("124","263").collect(Collectors.toSet()));
|
||||
connections.put("9", Stream.of("31","231").collect(Collectors.toSet()));
|
||||
connections.put("10", Stream.of("95","128").collect(Collectors.toSet()));
|
||||
connections.put("11", Stream.of("163","211","83","104","83","104","28","248","94","104").collect(Collectors.toSet()));
|
||||
connections.put("12", Stream.of("56","256").collect(Collectors.toSet()));
|
||||
connections.put("13", Stream.of("156","249","224","157","167","278").collect(Collectors.toSet()));
|
||||
connections.put("14", Stream.of("92","167","92","167","92","167").collect(Collectors.toSet()));
|
||||
connections.put("15", Stream.of("78","268","78").collect(Collectors.toSet()));
|
||||
connections.put("16", Stream.of("91","173").collect(Collectors.toSet()));
|
||||
connections.put("17", Stream.of("110","292","74","110").collect(Collectors.toSet()));
|
||||
connections.put("18", Stream.of("186","192","186","192").collect(Collectors.toSet()));
|
||||
connections.put("19", Stream.of("97").collect(Collectors.toSet()));
|
||||
connections.put("20", Stream.of("65","216").collect(Collectors.toSet()));
|
||||
connections.put("21", Stream.of("67","268").collect(Collectors.toSet()));
|
||||
connections.put("22", Stream.of("47","111").collect(Collectors.toSet()));
|
||||
connections.put("23", Stream.of("41","157").collect(Collectors.toSet()));
|
||||
connections.put("24", Stream.of("156","164").collect(Collectors.toSet()));
|
||||
connections.put("25", Stream.of("161","254","161","254").collect(Collectors.toSet()));
|
||||
connections.put("26", Stream.of("259","273").collect(Collectors.toSet()));
|
||||
connections.put("27", Stream.of("79","200").collect(Collectors.toSet()));
|
||||
connections.put("28", Stream.of("162","191","11","107").collect(Collectors.toSet()));
|
||||
connections.put("29", Stream.of("84","157").collect(Collectors.toSet()));
|
||||
connections.put("30", Stream.of("176","189").collect(Collectors.toSet()));
|
||||
connections.put("31", Stream.of("9","302").collect(Collectors.toSet()));
|
||||
connections.put("32", Stream.of("70","203").collect(Collectors.toSet()));
|
||||
connections.put("33", Stream.of("36","164","36","164").collect(Collectors.toSet()));
|
||||
connections.put("34", Stream.of("100","119").collect(Collectors.toSet()));
|
||||
connections.put("35", Stream.of("244").collect(Collectors.toSet()));
|
||||
connections.put("36", Stream.of("33","288","33","288").collect(Collectors.toSet()));
|
||||
connections.put("37", Stream.of("158","300").collect(Collectors.toSet()));
|
||||
connections.put("38", Stream.of("58","81").collect(Collectors.toSet()));
|
||||
connections.put("39", Stream.of("128","145").collect(Collectors.toSet()));
|
||||
connections.put("40", Stream.of("47","89","139","170").collect(Collectors.toSet()));
|
||||
connections.put("41", Stream.of("215","252","23","42").collect(Collectors.toSet()));
|
||||
connections.put("42", Stream.of("120","291","41","183").collect(Collectors.toSet()));
|
||||
connections.put("43", Stream.of("79","218","183","288").collect(Collectors.toSet()));
|
||||
connections.put("44", Stream.of("161","166","161","166").collect(Collectors.toSet()));
|
||||
connections.put("45", Stream.of("206","242").collect(Collectors.toSet()));
|
||||
connections.put("46", Stream.of("6","50","53").collect(Collectors.toSet()));
|
||||
connections.put("47", Stream.of("22","40").collect(Collectors.toSet()));
|
||||
connections.put("48", Stream.of("126","249").collect(Collectors.toSet()));
|
||||
connections.put("49", Stream.of("87","196","87","151").collect(Collectors.toSet()));
|
||||
connections.put("50", Stream.of("46").collect(Collectors.toSet()));
|
||||
connections.put("51", Stream.of("103","214").collect(Collectors.toSet()));
|
||||
connections.put("52", Stream.of("1","264").collect(Collectors.toSet()));
|
||||
connections.put("53", Stream.of("46","213").collect(Collectors.toSet()));
|
||||
connections.put("54", Stream.of("55","56").collect(Collectors.toSet()));
|
||||
connections.put("55", Stream.of("54","244").collect(Collectors.toSet()));
|
||||
connections.put("56", Stream.of("12","54").collect(Collectors.toSet()));
|
||||
connections.put("57", Stream.of("187").collect(Collectors.toSet()));
|
||||
connections.put("58", Stream.of("38","119").collect(Collectors.toSet()));
|
||||
connections.put("59", Stream.of("239","257").collect(Collectors.toSet()));
|
||||
connections.put("60", Stream.of("126","151").collect(Collectors.toSet()));
|
||||
connections.put("61", Stream.of("171","237").collect(Collectors.toSet()));
|
||||
connections.put("62", Stream.of("168","279").collect(Collectors.toSet()));
|
||||
connections.put("63", Stream.of("202","218").collect(Collectors.toSet()));
|
||||
connections.put("64", Stream.of("106","135").collect(Collectors.toSet()));
|
||||
connections.put("65", Stream.of("20","97").collect(Collectors.toSet()));
|
||||
connections.put("66", Stream.of("67","85").collect(Collectors.toSet()));
|
||||
connections.put("67", Stream.of("21","66").collect(Collectors.toSet()));
|
||||
connections.put("68", Stream.of("158","255").collect(Collectors.toSet()));
|
||||
connections.put("69", Stream.of("86","106").collect(Collectors.toSet()));
|
||||
connections.put("70", Stream.of("4","32").collect(Collectors.toSet()));
|
||||
connections.put("71", Stream.of("172","296").collect(Collectors.toSet()));
|
||||
connections.put("72", Stream.of("285","73").collect(Collectors.toSet()));
|
||||
connections.put("73", Stream.of("72","1","1","182").collect(Collectors.toSet()));
|
||||
connections.put("74", Stream.of("99","122","138","286","292","17","99").collect(Collectors.toSet()));
|
||||
connections.put("75", Stream.of("209","221","209","221").collect(Collectors.toSet()));
|
||||
connections.put("76", Stream.of("181","295").collect(Collectors.toSet()));
|
||||
connections.put("77", Stream.of("93","124").collect(Collectors.toSet()));
|
||||
connections.put("78", Stream.of("15","269","15","269").collect(Collectors.toSet()));
|
||||
connections.put("79", Stream.of("27","43").collect(Collectors.toSet()));
|
||||
connections.put("80", Stream.of("204","230").collect(Collectors.toSet()));
|
||||
connections.put("81", Stream.of("38").collect(Collectors.toSet()));
|
||||
connections.put("82", Stream.of("163","192").collect(Collectors.toSet()));
|
||||
connections.put("83", Stream.of("11","192","192","11","192").collect(Collectors.toSet()));
|
||||
connections.put("84", Stream.of("148","29","136").collect(Collectors.toSet()));
|
||||
connections.put("85", Stream.of("66","129").collect(Collectors.toSet()));
|
||||
connections.put("86", Stream.of("69","152").collect(Collectors.toSet()));
|
||||
connections.put("87", Stream.of("49","278","254","284","254","284","49","278").collect(Collectors.toSet()));
|
||||
connections.put("88", Stream.of("255").collect(Collectors.toSet()));
|
||||
connections.put("89", Stream.of("40","145","170","276","145","276").collect(Collectors.toSet()));
|
||||
connections.put("90", Stream.of("104","145","104","145","104","145").collect(Collectors.toSet()));
|
||||
connections.put("91", Stream.of("16","109").collect(Collectors.toSet()));
|
||||
connections.put("92", Stream.of("14","145","14","145","14","145").collect(Collectors.toSet()));
|
||||
connections.put("93", Stream.of("77","165","287").collect(Collectors.toSet()));
|
||||
connections.put("94", Stream.of("253","289","11","281").collect(Collectors.toSet()));
|
||||
connections.put("95", Stream.of("10","160","123","223").collect(Collectors.toSet()));
|
||||
connections.put("96", Stream.of("194","286").collect(Collectors.toSet()));
|
||||
connections.put("97", Stream.of("19","65").collect(Collectors.toSet()));
|
||||
connections.put("98", Stream.of("173","210").collect(Collectors.toSet()));
|
||||
connections.put("99", Stream.of("122","235","74","235","74","235").collect(Collectors.toSet()));
|
||||
connections.put("100", Stream.of("34","111").collect(Collectors.toSet()));
|
||||
connections.put("101", Stream.of("110","226").collect(Collectors.toSet()));
|
||||
connections.put("102", Stream.of("258","276").collect(Collectors.toSet()));
|
||||
connections.put("103", Stream.of("51","109").collect(Collectors.toSet()));
|
||||
connections.put("104", Stream.of("11","90","11","90","11","90").collect(Collectors.toSet()));
|
||||
connections.put("105", Stream.of("177","195").collect(Collectors.toSet()));
|
||||
connections.put("106", Stream.of("64","69").collect(Collectors.toSet()));
|
||||
connections.put("107", Stream.of("28","284","133","196","191","272").collect(Collectors.toSet()));
|
||||
connections.put("108", Stream.of("141","264").collect(Collectors.toSet()));
|
||||
connections.put("109", Stream.of("91","103").collect(Collectors.toSet()));
|
||||
connections.put("110", Stream.of("17","208","101","17","264").collect(Collectors.toSet()));
|
||||
connections.put("111", Stream.of("22","100").collect(Collectors.toSet()));
|
||||
connections.put("112", Stream.of("181","195").collect(Collectors.toSet()));
|
||||
connections.put("113", Stream.of("245","297").collect(Collectors.toSet()));
|
||||
connections.put("114", Stream.of("140").collect(Collectors.toSet()));
|
||||
connections.put("115", Stream.of("178","184","290").collect(Collectors.toSet()));
|
||||
connections.put("116", Stream.of("117","118","132").collect(Collectors.toSet()));
|
||||
connections.put("117", Stream.of("116","118").collect(Collectors.toSet()));
|
||||
connections.put("118", Stream.of("116","117").collect(Collectors.toSet()));
|
||||
connections.put("119", Stream.of("34","58").collect(Collectors.toSet()));
|
||||
connections.put("120", Stream.of("42","237").collect(Collectors.toSet()));
|
||||
connections.put("121", Stream.of("260").collect(Collectors.toSet()));
|
||||
connections.put("122", Stream.of("99","186","74","186").collect(Collectors.toSet()));
|
||||
connections.put("123", Stream.of("95","145").collect(Collectors.toSet()));
|
||||
connections.put("124", Stream.of("8","77").collect(Collectors.toSet()));
|
||||
connections.put("125", Stream.of("134","270","134","270").collect(Collectors.toSet()));
|
||||
connections.put("126", Stream.of("48","258","60","222").collect(Collectors.toSet()));
|
||||
connections.put("127", Stream.of("186","225").collect(Collectors.toSet()));
|
||||
connections.put("128", Stream.of("10","39").collect(Collectors.toSet()));
|
||||
connections.put("129", Stream.of("85","267").collect(Collectors.toSet()));
|
||||
connections.put("130", Stream.of("131","132").collect(Collectors.toSet()));
|
||||
connections.put("131", Stream.of("130","189").collect(Collectors.toSet()));
|
||||
connections.put("132", Stream.of("116","130").collect(Collectors.toSet()));
|
||||
connections.put("133", Stream.of("107","146").collect(Collectors.toSet()));
|
||||
connections.put("134", Stream.of("125","219","125","219").collect(Collectors.toSet()));
|
||||
connections.put("135", Stream.of("64","171").collect(Collectors.toSet()));
|
||||
connections.put("136", Stream.of("84","190","278").collect(Collectors.toSet()));
|
||||
connections.put("137", Stream.of("205","297").collect(Collectors.toSet()));
|
||||
connections.put("138", Stream.of("74").collect(Collectors.toSet()));
|
||||
connections.put("139", Stream.of("40","263").collect(Collectors.toSet()));
|
||||
connections.put("140", Stream.of("114","236").collect(Collectors.toSet()));
|
||||
connections.put("141", Stream.of("108","212").collect(Collectors.toSet()));
|
||||
connections.put("142", Stream.of("289","296").collect(Collectors.toSet()));
|
||||
connections.put("143", Stream.of("159","205").collect(Collectors.toSet()));
|
||||
connections.put("144", Stream.of("206","281").collect(Collectors.toSet()));
|
||||
connections.put("145", Stream.of("90","92","90","92","90","92","7","89","39","222","89","123").collect(Collectors.toSet()));
|
||||
connections.put("146", Stream.of("133","235").collect(Collectors.toSet()));
|
||||
connections.put("147", Stream.of("150","282").collect(Collectors.toSet()));
|
||||
connections.put("148", Stream.of("84","278").collect(Collectors.toSet()));
|
||||
connections.put("149", Stream.of("162","207").collect(Collectors.toSet()));
|
||||
connections.put("150", Stream.of("147","226").collect(Collectors.toSet()));
|
||||
connections.put("151", Stream.of("49","258","60","196").collect(Collectors.toSet()));
|
||||
connections.put("152", Stream.of("86").collect(Collectors.toSet()));
|
||||
connections.put("153", Stream.of("154","246").collect(Collectors.toSet()));
|
||||
connections.put("154", Stream.of("153","229","274").collect(Collectors.toSet()));
|
||||
connections.put("155", Stream.of("224","283").collect(Collectors.toSet()));
|
||||
connections.put("156", Stream.of("13","24","2","167","3","167","2","167").collect(Collectors.toSet()));
|
||||
connections.put("157", Stream.of("23","232","13","29").collect(Collectors.toSet()));
|
||||
connections.put("158", Stream.of("37","68").collect(Collectors.toSet()));
|
||||
connections.put("159", Stream.of("143","277").collect(Collectors.toSet()));
|
||||
connections.put("160", Stream.of("95","265").collect(Collectors.toSet()));
|
||||
connections.put("161", Stream.of("25","44","25","44").collect(Collectors.toSet()));
|
||||
connections.put("162", Stream.of("28","149").collect(Collectors.toSet()));
|
||||
connections.put("163", Stream.of("11","82").collect(Collectors.toSet()));
|
||||
connections.put("164", Stream.of("24","246","33","243","33","243").collect(Collectors.toSet()));
|
||||
connections.put("165", Stream.of("93").collect(Collectors.toSet()));
|
||||
connections.put("166", Stream.of("44","262","44","262").collect(Collectors.toSet()));
|
||||
connections.put("167", Stream.of("14","156","14","156","14","156","13","188").collect(Collectors.toSet()));
|
||||
connections.put("168", Stream.of("62","179","213").collect(Collectors.toSet()));
|
||||
connections.put("169", Stream.of("239").collect(Collectors.toSet()));
|
||||
connections.put("170", Stream.of("40","89").collect(Collectors.toSet()));
|
||||
connections.put("171", Stream.of("61","135").collect(Collectors.toSet()));
|
||||
connections.put("172", Stream.of("71","281").collect(Collectors.toSet()));
|
||||
connections.put("173", Stream.of("16","98").collect(Collectors.toSet()));
|
||||
connections.put("174", Stream.of("252").collect(Collectors.toSet()));
|
||||
connections.put("175", Stream.of("252").collect(Collectors.toSet()));
|
||||
connections.put("176", Stream.of("30","233").collect(Collectors.toSet()));
|
||||
connections.put("177", Stream.of("105","238").collect(Collectors.toSet()));
|
||||
connections.put("178", Stream.of("115","201").collect(Collectors.toSet()));
|
||||
connections.put("179", Stream.of("168","180").collect(Collectors.toSet()));
|
||||
connections.put("180", Stream.of("179","198").collect(Collectors.toSet()));
|
||||
connections.put("181", Stream.of("76","112","285").collect(Collectors.toSet()));
|
||||
connections.put("182", Stream.of("73","193").collect(Collectors.toSet()));
|
||||
connections.put("183", Stream.of("42","43").collect(Collectors.toSet()));
|
||||
connections.put("184", Stream.of("115","198").collect(Collectors.toSet()));
|
||||
connections.put("185", Stream.of("236","280").collect(Collectors.toSet()));
|
||||
connections.put("186", Stream.of("127","207","18","122","18","122").collect(Collectors.toSet()));
|
||||
connections.put("187", Stream.of("57","231").collect(Collectors.toSet()));
|
||||
connections.put("188", Stream.of("7","167").collect(Collectors.toSet()));
|
||||
connections.put("189", Stream.of("30","131").collect(Collectors.toSet()));
|
||||
connections.put("190", Stream.of("136","244").collect(Collectors.toSet()));
|
||||
connections.put("191", Stream.of("196","211","28","258","107","276").collect(Collectors.toSet()));
|
||||
connections.put("192", Stream.of("82","277","18","83","18","83","83","217").collect(Collectors.toSet()));
|
||||
connections.put("193", Stream.of("5","182").collect(Collectors.toSet()));
|
||||
connections.put("194", Stream.of("96","204").collect(Collectors.toSet()));
|
||||
connections.put("195", Stream.of("105","112").collect(Collectors.toSet()));
|
||||
connections.put("196", Stream.of("49","191","107","151").collect(Collectors.toSet()));
|
||||
connections.put("197", Stream.of("271","272").collect(Collectors.toSet()));
|
||||
connections.put("198", Stream.of("180","184").collect(Collectors.toSet()));
|
||||
connections.put("199", Stream.of("269","288","269","288").collect(Collectors.toSet()));
|
||||
connections.put("200", Stream.of("4","27","283","291").collect(Collectors.toSet()));
|
||||
connections.put("201", Stream.of("178","281").collect(Collectors.toSet()));
|
||||
connections.put("202", Stream.of("63","216").collect(Collectors.toSet()));
|
||||
connections.put("203", Stream.of("32","246").collect(Collectors.toSet()));
|
||||
connections.put("204", Stream.of("80","194").collect(Collectors.toSet()));
|
||||
connections.put("205", Stream.of("137","143").collect(Collectors.toSet()));
|
||||
connections.put("206", Stream.of("45","144").collect(Collectors.toSet()));
|
||||
connections.put("207", Stream.of("149","186").collect(Collectors.toSet()));
|
||||
connections.put("208", Stream.of("110","241").collect(Collectors.toSet()));
|
||||
connections.put("209", Stream.of("75","290","75","234").collect(Collectors.toSet()));
|
||||
connections.put("210", Stream.of("98","274").collect(Collectors.toSet()));
|
||||
connections.put("211", Stream.of("11","191").collect(Collectors.toSet()));
|
||||
connections.put("212", Stream.of("141").collect(Collectors.toSet()));
|
||||
connections.put("213", Stream.of("53","168").collect(Collectors.toSet()));
|
||||
connections.put("214", Stream.of("51","300").collect(Collectors.toSet()));
|
||||
connections.put("215", Stream.of("41","275").collect(Collectors.toSet()));
|
||||
connections.put("216", Stream.of("20","202").collect(Collectors.toSet()));
|
||||
connections.put("217", Stream.of("192","282").collect(Collectors.toSet()));
|
||||
connections.put("218", Stream.of("43","63").collect(Collectors.toSet()));
|
||||
connections.put("219", Stream.of("134","221","134","221").collect(Collectors.toSet()));
|
||||
connections.put("220", Stream.of("238","293").collect(Collectors.toSet()));
|
||||
connections.put("221", Stream.of("75","219","75","219").collect(Collectors.toSet()));
|
||||
connections.put("222", Stream.of("126","145").collect(Collectors.toSet()));
|
||||
connections.put("223", Stream.of("95","259").collect(Collectors.toSet()));
|
||||
connections.put("224", Stream.of("13","155","261","275","294").collect(Collectors.toSet()));
|
||||
connections.put("225", Stream.of("127","295").collect(Collectors.toSet()));
|
||||
connections.put("226", Stream.of("101","150").collect(Collectors.toSet()));
|
||||
connections.put("227", Stream.of("294").collect(Collectors.toSet()));
|
||||
connections.put("228", Stream.of("235","272","235","272").collect(Collectors.toSet()));
|
||||
connections.put("229", Stream.of("154","240").collect(Collectors.toSet()));
|
||||
connections.put("230", Stream.of("80","299").collect(Collectors.toSet()));
|
||||
connections.put("231", Stream.of("9","187").collect(Collectors.toSet()));
|
||||
connections.put("232", Stream.of("157","278").collect(Collectors.toSet()));
|
||||
connections.put("233", Stream.of("1","176").collect(Collectors.toSet()));
|
||||
connections.put("234", Stream.of("209","250").collect(Collectors.toSet()));
|
||||
connections.put("235", Stream.of("99","228","99","228","99","146").collect(Collectors.toSet()));
|
||||
connections.put("236", Stream.of("140","185").collect(Collectors.toSet()));
|
||||
connections.put("237", Stream.of("61","120").collect(Collectors.toSet()));
|
||||
connections.put("238", Stream.of("177","220").collect(Collectors.toSet()));
|
||||
connections.put("239", Stream.of("59","169").collect(Collectors.toSet()));
|
||||
connections.put("240", Stream.of("229","300").collect(Collectors.toSet()));
|
||||
connections.put("241", Stream.of("208","264").collect(Collectors.toSet()));
|
||||
connections.put("242", Stream.of("45").collect(Collectors.toSet()));
|
||||
connections.put("243", Stream.of("164","294","164","294").collect(Collectors.toSet()));
|
||||
connections.put("244", Stream.of("55","190","35","271").collect(Collectors.toSet()));
|
||||
connections.put("245", Stream.of("113","280").collect(Collectors.toSet()));
|
||||
connections.put("246", Stream.of("153","164","203","288").collect(Collectors.toSet()));
|
||||
connections.put("247", Stream.of("272","284","272","284").collect(Collectors.toSet()));
|
||||
connections.put("248", Stream.of("11","253").collect(Collectors.toSet()));
|
||||
connections.put("249", Stream.of("13","48").collect(Collectors.toSet()));
|
||||
connections.put("250", Stream.of("234","251").collect(Collectors.toSet()));
|
||||
connections.put("251", Stream.of("5","250").collect(Collectors.toSet()));
|
||||
connections.put("252", Stream.of("41","174","175").collect(Collectors.toSet()));
|
||||
connections.put("253", Stream.of("94","248").collect(Collectors.toSet()));
|
||||
connections.put("254", Stream.of("25","87","25","87").collect(Collectors.toSet()));
|
||||
connections.put("255", Stream.of("68","88").collect(Collectors.toSet()));
|
||||
connections.put("256", Stream.of("12","257").collect(Collectors.toSet()));
|
||||
connections.put("257", Stream.of("59","256").collect(Collectors.toSet()));
|
||||
connections.put("258", Stream.of("126","191","102","151").collect(Collectors.toSet()));
|
||||
connections.put("259", Stream.of("26","223").collect(Collectors.toSet()));
|
||||
connections.put("260", Stream.of("121","301").collect(Collectors.toSet()));
|
||||
connections.put("261", Stream.of("224").collect(Collectors.toSet()));
|
||||
connections.put("262", Stream.of("2","166","3","166").collect(Collectors.toSet()));
|
||||
connections.put("263", Stream.of("8","139").collect(Collectors.toSet()));
|
||||
connections.put("264", Stream.of("52","108","241","1","110").collect(Collectors.toSet()));
|
||||
connections.put("265", Stream.of("160","302").collect(Collectors.toSet()));
|
||||
connections.put("266", Stream.of("267").collect(Collectors.toSet()));
|
||||
connections.put("267", Stream.of("129","266").collect(Collectors.toSet()));
|
||||
connections.put("268", Stream.of("15","21").collect(Collectors.toSet()));
|
||||
connections.put("269", Stream.of("78","199","78","199").collect(Collectors.toSet()));
|
||||
connections.put("270", Stream.of("125","125").collect(Collectors.toSet()));
|
||||
connections.put("271", Stream.of("197","244").collect(Collectors.toSet()));
|
||||
connections.put("272", Stream.of("228","247","228","247","107","197").collect(Collectors.toSet()));
|
||||
connections.put("273", Stream.of("26").collect(Collectors.toSet()));
|
||||
connections.put("274", Stream.of("154","210").collect(Collectors.toSet()));
|
||||
connections.put("275", Stream.of("215","224").collect(Collectors.toSet()));
|
||||
connections.put("276", Stream.of("89","102","89","191").collect(Collectors.toSet()));
|
||||
connections.put("277", Stream.of("159","192").collect(Collectors.toSet()));
|
||||
connections.put("278", Stream.of("87","148","232","284","87","136","13").collect(Collectors.toSet()));
|
||||
connections.put("279", Stream.of("62").collect(Collectors.toSet()));
|
||||
connections.put("280", Stream.of("185","245").collect(Collectors.toSet()));
|
||||
connections.put("281", Stream.of("144","172","94","201").collect(Collectors.toSet()));
|
||||
connections.put("282", Stream.of("147","217").collect(Collectors.toSet()));
|
||||
connections.put("283", Stream.of("155","200","291").collect(Collectors.toSet()));
|
||||
connections.put("284", Stream.of("87","247","87","247","107","278").collect(Collectors.toSet()));
|
||||
connections.put("285", Stream.of("72","181").collect(Collectors.toSet()));
|
||||
connections.put("286", Stream.of("74","96").collect(Collectors.toSet()));
|
||||
connections.put("287", Stream.of("93","301").collect(Collectors.toSet()));
|
||||
connections.put("288", Stream.of("36","199","36","199","43","246").collect(Collectors.toSet()));
|
||||
connections.put("289", Stream.of("94","142").collect(Collectors.toSet()));
|
||||
connections.put("290", Stream.of("115","209").collect(Collectors.toSet()));
|
||||
connections.put("291", Stream.of("42","200","283").collect(Collectors.toSet()));
|
||||
connections.put("292", Stream.of("17","74").collect(Collectors.toSet()));
|
||||
connections.put("293", Stream.of("220").collect(Collectors.toSet()));
|
||||
connections.put("294", Stream.of("3","243","224","227","3","243").collect(Collectors.toSet()));
|
||||
connections.put("295", Stream.of("76","225").collect(Collectors.toSet()));
|
||||
connections.put("296", Stream.of("71","142").collect(Collectors.toSet()));
|
||||
connections.put("297", Stream.of("113","137").collect(Collectors.toSet()));
|
||||
connections.put("298", Stream.of("299").collect(Collectors.toSet()));
|
||||
connections.put("299", Stream.of("230","298").collect(Collectors.toSet()));
|
||||
connections.put("300", Stream.of("37","214","240").collect(Collectors.toSet()));
|
||||
connections.put("301", Stream.of("260","287").collect(Collectors.toSet()));
|
||||
connections.put("302", Stream.of("31","265").collect(Collectors.toSet()));
|
||||
|
||||
underground = new Graph<>(stations, connections);
|
||||
routeFinder = new RouteFinder<>(underground, new HaversineScorer(), new HaversineScorer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findRoute() {
|
||||
List<Station> route = routeFinder.findRoute(underground.getNode("74"), underground.getNode("7"));
|
||||
|
||||
System.out.println(route.stream().map(Station::getName).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 10 KiB |
|
@ -14,4 +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)
|
||||
- [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)
|
||||
- [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)
|
||||
- More articles: [[<-- prev]](/algorithms-miscellaneous-2) [[next -->]](/algorithms-miscellaneous-4)
|
|
@ -1,9 +1,14 @@
|
|||
## Relevant articles:
|
||||
## Algorithms - Miscellaneous
|
||||
|
||||
This module contains articles about algorithms. Some classes of algorithms, e.g., [sorting](https://github.com/eugenp/tutorials/blob/algorithms-sorting) and [genetic algorithms](https://github.com/eugenp/tutorials/blob/algorithms-genetic), have their own dedicated modules.
|
||||
|
||||
### Relevant articles:
|
||||
|
||||
- [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)
|
||||
- [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 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)
|
||||
- [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)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package com.baeldung.algorithms.smallestinteger;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class SmallestMissingPositiveInteger {
|
||||
public static int searchInSortedArray(int[] input) {
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
if (i != input[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return input.length;
|
||||
}
|
||||
|
||||
public static int searchInUnsortedArraySortingFirst(int[] input) {
|
||||
Arrays.sort(input);
|
||||
return searchInSortedArray(input);
|
||||
}
|
||||
|
||||
public static int searchInUnsortedArrayBooleanArray(int[] input) {
|
||||
boolean[] flags = new boolean[input.length];
|
||||
for (int number : input) {
|
||||
if (number < flags.length) {
|
||||
flags[number] = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < flags.length; i++) {
|
||||
if (!flags[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return flags.length;
|
||||
}
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
package com.baeldung.algorithms.string.search;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
public class StringSearchAlgorithms {
|
||||
public static long getBiggerPrime(int m) {
|
||||
BigInteger prime = BigInteger.probablePrime(getNumberOfBits(m) + 1, new Random());
|
||||
return prime.longValue();
|
||||
}
|
||||
|
||||
public static long getLowerPrime(long number) {
|
||||
BigInteger prime = BigInteger.probablePrime(getNumberOfBits(number) - 1, new Random());
|
||||
return prime.longValue();
|
||||
}
|
||||
|
||||
private static int getNumberOfBits(final int number) {
|
||||
return Integer.SIZE - Integer.numberOfLeadingZeros(number);
|
||||
}
|
||||
|
||||
private static int getNumberOfBits(final long number) {
|
||||
return Long.SIZE - Long.numberOfLeadingZeros(number);
|
||||
}
|
||||
|
||||
public static int simpleTextSearch(char[] pattern, char[] text) {
|
||||
int patternSize = pattern.length;
|
||||
int textSize = text.length;
|
||||
|
||||
int i = 0;
|
||||
|
||||
while ((i + patternSize) <= textSize) {
|
||||
int j = 0;
|
||||
while (text[i + j] == pattern[j]) {
|
||||
j += 1;
|
||||
if (j >= patternSize)
|
||||
return i;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int RabinKarpMethod(char[] pattern, char[] text) {
|
||||
int patternSize = pattern.length; // m
|
||||
int textSize = text.length; // n
|
||||
|
||||
long prime = getBiggerPrime(patternSize);
|
||||
|
||||
long r = 1;
|
||||
for (int i = 0; i < patternSize - 1; i++) {
|
||||
r *= 2;
|
||||
r = r % prime;
|
||||
}
|
||||
|
||||
long[] t = new long[textSize];
|
||||
t[0] = 0;
|
||||
|
||||
long pfinger = 0;
|
||||
|
||||
for (int j = 0; j < patternSize; j++) {
|
||||
t[0] = (2 * t[0] + text[j]) % prime;
|
||||
pfinger = (2 * pfinger + pattern[j]) % prime;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
boolean passed = false;
|
||||
|
||||
int diff = textSize - patternSize;
|
||||
for (i = 0; i <= diff; i++) {
|
||||
if (t[i] == pfinger) {
|
||||
passed = true;
|
||||
for (int k = 0; k < patternSize; k++) {
|
||||
if (text[i + k] != pattern[k]) {
|
||||
passed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (passed) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < diff) {
|
||||
long value = 2 * (t[i] - r * text[i]) + text[i + patternSize];
|
||||
t[i + 1] = ((value % prime) + prime) % prime;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
public static int KnuthMorrisPrattSearch(char[] pattern, char[] text) {
|
||||
int patternSize = pattern.length; // m
|
||||
int textSize = text.length; // n
|
||||
|
||||
int i = 0, j = 0;
|
||||
|
||||
int[] shift = KnuthMorrisPrattShift(pattern);
|
||||
|
||||
while ((i + patternSize) <= textSize) {
|
||||
while (text[i + j] == pattern[j]) {
|
||||
j += 1;
|
||||
if (j >= patternSize)
|
||||
return i;
|
||||
}
|
||||
|
||||
if (j > 0) {
|
||||
i += shift[j - 1];
|
||||
j = Math.max(j - shift[j - 1], 0);
|
||||
} else {
|
||||
i++;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int[] KnuthMorrisPrattShift(char[] pattern) {
|
||||
int patternSize = pattern.length;
|
||||
|
||||
int[] shift = new int[patternSize];
|
||||
shift[0] = 1;
|
||||
|
||||
int i = 1, j = 0;
|
||||
|
||||
while ((i + j) < patternSize) {
|
||||
if (pattern[i + j] == pattern[j]) {
|
||||
shift[i + j] = i;
|
||||
j++;
|
||||
} else {
|
||||
if (j == 0)
|
||||
shift[i] = i + 1;
|
||||
|
||||
if (j > 0) {
|
||||
i = i + shift[j - 1];
|
||||
j = Math.max(j - shift[j - 1], 0);
|
||||
} else {
|
||||
i = i + 1;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return shift;
|
||||
}
|
||||
|
||||
public static int BoyerMooreHorspoolSimpleSearch(char[] pattern, char[] text) {
|
||||
int patternSize = pattern.length;
|
||||
int textSize = text.length;
|
||||
|
||||
int i = 0, j = 0;
|
||||
|
||||
while ((i + patternSize) <= textSize) {
|
||||
j = patternSize - 1;
|
||||
while (text[i + j] == pattern[j]) {
|
||||
j--;
|
||||
if (j < 0)
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int BoyerMooreHorspoolSearch(char[] pattern, char[] text) {
|
||||
|
||||
int shift[] = new int[256];
|
||||
|
||||
for (int k = 0; k < 256; k++) {
|
||||
shift[k] = pattern.length;
|
||||
}
|
||||
|
||||
for (int k = 0; k < pattern.length - 1; k++) {
|
||||
shift[pattern[k]] = pattern.length - 1 - k;
|
||||
}
|
||||
|
||||
int i = 0, j = 0;
|
||||
|
||||
while ((i + pattern.length) <= text.length) {
|
||||
j = pattern.length - 1;
|
||||
|
||||
while (text[i + j] == pattern[j]) {
|
||||
j -= 1;
|
||||
if (j < 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
i = i + shift[text[i + pattern.length - 1]];
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package com.baeldung.algorithms.smallestinteger;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class SmallestMissingPositiveIntegerUnitTest {
|
||||
@Test
|
||||
void givenArrayWithThreeMissing_whenSearchInSortedArray_thenThree() {
|
||||
int[] input = new int[] {0, 1, 2, 4, 5};
|
||||
|
||||
int result = SmallestMissingPositiveInteger.searchInSortedArray(input);
|
||||
|
||||
assertThat(result).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenArrayWithOneAndThreeMissing_whenSearchInSortedArray_thenOne() {
|
||||
int[] input = new int[] {0, 2, 4, 5};
|
||||
|
||||
int result = SmallestMissingPositiveInteger.searchInSortedArray(input);
|
||||
|
||||
assertThat(result).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenArrayWithoutMissingInteger_whenSearchInSortedArray_thenArrayLength() {
|
||||
int[] input = new int[] {0, 1, 2, 3, 4, 5};
|
||||
|
||||
int result = SmallestMissingPositiveInteger.searchInSortedArray(input);
|
||||
|
||||
assertThat(result).isEqualTo(input.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenArrayWithThreeMissing_whenSearchInUnsortedArraySortingFirst_thenThree() {
|
||||
int[] input = new int[] {1, 4, 0, 5, 2};
|
||||
|
||||
int result = SmallestMissingPositiveInteger.searchInUnsortedArraySortingFirst(input);
|
||||
|
||||
assertThat(result).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenArrayWithOneAndThreeMissing_whenSearchInUnsortedArraySortingFirst_thenOne() {
|
||||
int[] input = new int[] {4, 2, 0, 5};
|
||||
|
||||
int result = SmallestMissingPositiveInteger.searchInUnsortedArraySortingFirst(input);
|
||||
|
||||
assertThat(result).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenArrayWithoutMissingInteger_whenSearchInUnsortedArraySortingFirst_thenArrayLength() {
|
||||
int[] input = new int[] {4, 5, 1, 3, 0, 2};
|
||||
|
||||
int result = SmallestMissingPositiveInteger.searchInUnsortedArraySortingFirst(input);
|
||||
|
||||
assertThat(result).isEqualTo(input.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenArrayWithThreeMissing_whenSearchInUnsortedArrayBooleanArray_thenThree() {
|
||||
int[] input = new int[] {1, 4, 0, 5, 2};
|
||||
|
||||
int result = SmallestMissingPositiveInteger.searchInUnsortedArrayBooleanArray(input);
|
||||
|
||||
assertThat(result).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenArrayWithOneAndThreeMissing_whenSearchInUnsortedArrayBooleanArray_thenOne() {
|
||||
int[] input = new int[] {4, 2, 0, 5};
|
||||
|
||||
int result = SmallestMissingPositiveInteger.searchInUnsortedArrayBooleanArray(input);
|
||||
|
||||
assertThat(result).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenArrayWithoutMissingInteger_whenSearchInUnsortedArrayBooleanArray_thenArrayLength() {
|
||||
int[] input = new int[] {4, 5, 1, 3, 0, 2};
|
||||
|
||||
int result = SmallestMissingPositiveInteger.searchInUnsortedArrayBooleanArray(input);
|
||||
|
||||
assertThat(result).isEqualTo(input.length);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,13 @@
|
|||
## Relevant articles:
|
||||
## Algorithms - Miscellaneous
|
||||
|
||||
This module contains articles about algorithms. Some classes of algorithms, e.g., [sorting](/../algorithms-sorting) and
|
||||
[genetic algorithms](/../algorithms-genetic), have their own dedicated modules.
|
||||
|
||||
### Relevant articles:
|
||||
|
||||
- [Converting Between Byte Arrays and Hexadecimal Strings in Java](https://www.baeldung.com/java-byte-arrays-hex-strings)
|
||||
- [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)
|
||||
- [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)
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons-codec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-math3</artifactId>
|
||||
<version>${commons-math3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
|
@ -28,6 +33,7 @@
|
|||
<artifactId>tradukisto</artifactId>
|
||||
<version>${tradukisto.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
|
@ -52,6 +58,7 @@
|
|||
<tradukisto.version>1.0.1</tradukisto.version>
|
||||
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||
<commons-codec.version>1.11</commons-codec.version>
|
||||
<commons-math3.version>3.6.1</commons-math3.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,33 @@
|
|||
package com.baeldung.algorithms.balancedbinarytree;
|
||||
|
||||
public class BalancedBinaryTree {
|
||||
|
||||
public static boolean isBalanced(Tree tree) {
|
||||
return isBalancedRecursive(tree, -1).isBalanced;
|
||||
}
|
||||
|
||||
private static Result isBalancedRecursive(Tree tree, int depth) {
|
||||
if (tree == null) {
|
||||
return new Result(true, -1);
|
||||
}
|
||||
|
||||
Result leftSubtreeResult = isBalancedRecursive(tree.left(), depth + 1);
|
||||
Result rightSubtreeResult = isBalancedRecursive(tree.right(), depth + 1);
|
||||
|
||||
boolean isBalanced = Math.abs(leftSubtreeResult.height - rightSubtreeResult.height) <= 1;
|
||||
boolean subtreesAreBalanced = leftSubtreeResult.isBalanced && rightSubtreeResult.isBalanced;
|
||||
int height = Math.max(leftSubtreeResult.height, rightSubtreeResult.height) + 1;
|
||||
|
||||
return new Result(isBalanced && subtreesAreBalanced, height);
|
||||
}
|
||||
|
||||
private static final class Result {
|
||||
private final boolean isBalanced;
|
||||
private final int height;
|
||||
|
||||
private Result(boolean isBalanced, int height) {
|
||||
this.isBalanced = isBalanced;
|
||||
this.height = height;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.algorithms.balancedbinarytree;
|
||||
|
||||
public class Tree {
|
||||
private final int value;
|
||||
private final Tree left;
|
||||
private final Tree right;
|
||||
|
||||
public Tree(int value, Tree left, Tree right) {
|
||||
this.value = value;
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Tree left() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public Tree right() {
|
||||
return right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%s, %s, %s]",
|
||||
value,
|
||||
left == null ? "null" : left.toString(),
|
||||
right == null ? "null" : right.toString()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung.algorithms.binarygap;
|
||||
|
||||
public class BinaryGap {
|
||||
static int calculateBinaryGap(int n) {
|
||||
return calculateBinaryGap(n >>> Integer.numberOfTrailingZeros(n), 0, 0);
|
||||
}
|
||||
|
||||
static int calculateBinaryGap(int n, int current, int maximum) {
|
||||
if (n == 0) {
|
||||
return maximum;
|
||||
} else if ((n & 1) == 0) {
|
||||
return calculateBinaryGap(n >>> 1, current + 1, maximum);
|
||||
} else {
|
||||
return calculateBinaryGap(n >>> 1, 0, Math.max(maximum, current));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.baeldung.algorithms.combinatorics;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static java.util.Collections.swap;
|
||||
|
||||
public class Combinatorics {
|
||||
|
||||
public static List<List<Integer>> permutations(List<Integer> sequence) {
|
||||
List<List<Integer>> results = new ArrayList<>();
|
||||
permutationsInternal(sequence, results, 0);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void permutationsInternal(List<Integer> sequence, List<List<Integer>> results, int index) {
|
||||
if (index == sequence.size() - 1) {
|
||||
results.add(new ArrayList<>(sequence));
|
||||
}
|
||||
|
||||
for (int i = index; i < sequence.size(); i++) {
|
||||
swap(sequence, i, index);
|
||||
permutationsInternal(sequence, results, index + 1);
|
||||
swap(sequence, i, index);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<List<Integer>> combinations(List<Integer> inputSet, int k) {
|
||||
List<List<Integer>> results = new ArrayList<>();
|
||||
combinationsInternal(inputSet, k, results, new ArrayList<>(), 0);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void combinationsInternal(
|
||||
List<Integer> inputSet, int k, List<List<Integer>> results, ArrayList<Integer> accumulator, int index) {
|
||||
int leftToAccumulate = k - accumulator.size();
|
||||
int possibleToAcculumate = inputSet.size() - index;
|
||||
|
||||
if (accumulator.size() == k) {
|
||||
results.add(new ArrayList<>(accumulator));
|
||||
} else if (leftToAccumulate <= possibleToAcculumate) {
|
||||
combinationsInternal(inputSet, k, results, accumulator, index + 1);
|
||||
|
||||
accumulator.add(inputSet.get(index));
|
||||
combinationsInternal(inputSet, k, results, accumulator, index + 1);
|
||||
accumulator.remove(accumulator.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<List<Character>> powerSet(List<Character> sequence) {
|
||||
List<List<Character>> results = new ArrayList<>();
|
||||
powerSetInternal(sequence, results, new ArrayList<>(), 0);
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void powerSetInternal(
|
||||
List<Character> set, List<List<Character>> powerSet, List<Character> accumulator, int index) {
|
||||
if (index == set.size()) {
|
||||
powerSet.add(new ArrayList<>(accumulator));
|
||||
} else {
|
||||
accumulator.add(set.get(index));
|
||||
|
||||
powerSetInternal(set, powerSet, accumulator, index + 1);
|
||||
accumulator.remove(accumulator.size() - 1);
|
||||
powerSetInternal(set, powerSet, accumulator, index + 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.baeldung.algorithms.knapsack;
|
||||
|
||||
public class Knapsack {
|
||||
|
||||
public int knapsackRec(int[] w, int[] v, int n, int W) {
|
||||
if (n <= 0) {
|
||||
return 0;
|
||||
} else if (w[n - 1] > W) {
|
||||
return knapsackRec(w, v, n - 1, W);
|
||||
} else {
|
||||
return Math.max(knapsackRec(w, v, n - 1, W), v[n - 1] + knapsackRec(w, v, n - 1, W - w[n - 1]));
|
||||
}
|
||||
}
|
||||
|
||||
public int knapsackDP(int[] w, int[] v, int n, int W) {
|
||||
if (n <= 0 || W <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int[][] m = new int[n + 1][W + 1];
|
||||
for (int j = 0; j <= W; j++) {
|
||||
m[0][j] = 0;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j <= W; j++) {
|
||||
if (w[i - 1] > j) {
|
||||
m[i][j] = m[i - 1][j];
|
||||
} else {
|
||||
m[i][j] = Math.max(m[i - 1][j], m[i - 1][j - w[i - 1]] + v[i - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return m[n][W];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.baeldung.algorithms.balancedbinarytree;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
public class BalancedBinaryTreeUnitTest extends BinaryTreeDataProvider {
|
||||
|
||||
@Test
|
||||
public void givenBalancedTrees_whenCallingIsBalanced_ShouldReturnTrue() {
|
||||
for (Tree tree : balancedTrees()) {
|
||||
assertTrue(toString(tree) + " should be balanced", BalancedBinaryTree.isBalanced(tree));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnbalancedTrees_whenCallingIsBalanced_ShouldReturnFalse() {
|
||||
for (Tree tree : unbalancedTrees()) {
|
||||
assertFalse(toString(tree) + " should not be balanced", BalancedBinaryTree.isBalanced(tree));
|
||||
}
|
||||
}
|
||||
|
||||
private String toString(Tree tree) {
|
||||
return tree != null ? tree.toString() : "null";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package com.baeldung.algorithms.balancedbinarytree;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
class BinaryTreeDataProvider {
|
||||
|
||||
static Collection<Tree> balancedTrees() {
|
||||
return Arrays.asList(
|
||||
null,
|
||||
leaf(1),
|
||||
tree(1, leaf(2), leaf(3)),
|
||||
tree(
|
||||
1,
|
||||
leaf(2),
|
||||
tree(3, leaf(4), null)
|
||||
),
|
||||
tree(
|
||||
1,
|
||||
tree(
|
||||
2,
|
||||
tree(3, leaf(4), null),
|
||||
leaf(5)
|
||||
),
|
||||
tree(
|
||||
6,
|
||||
leaf(7),
|
||||
tree(8, null, leaf(9))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static Collection<Tree> unbalancedTrees() {
|
||||
return Arrays.asList(
|
||||
tree(
|
||||
1,
|
||||
tree(2, leaf(3), null),
|
||||
null
|
||||
),
|
||||
tree(
|
||||
1,
|
||||
tree(
|
||||
2,
|
||||
tree(3, leaf(4), leaf(5)),
|
||||
null
|
||||
),
|
||||
tree(6, leaf(7), null)
|
||||
),
|
||||
tree(
|
||||
1,
|
||||
tree(2, leaf(3), null),
|
||||
tree(
|
||||
4,
|
||||
tree(5, leaf(6), leaf(7)),
|
||||
null
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static Tree leaf(int value) {
|
||||
return new Tree(value, null, null);
|
||||
}
|
||||
|
||||
private static Tree tree(int value, Tree left, Tree right) {
|
||||
return new Tree(value, left, right);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.algorithms.binarygap;
|
||||
|
||||
import static com.baeldung.algorithms.binarygap.BinaryGap.calculateBinaryGap;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class BinaryGapUnitTest {
|
||||
|
||||
@Test public void givenNoOccurrenceOfBoundedZeros_whenCalculateBinaryGap_thenOutputCorrectResult() {
|
||||
|
||||
int result = calculateBinaryGap(63);
|
||||
assertEquals(0, result);
|
||||
}
|
||||
|
||||
@Test public void givenTrailingZeros_whenCalculateBinaryGap_thenOutputCorrectResult() {
|
||||
|
||||
int result = calculateBinaryGap(40);
|
||||
assertEquals(1, result);
|
||||
}
|
||||
|
||||
@Test public void givenSingleOccurrenceOfBoundedZeros_whenCalculateBinaryGap_thenOutputCorrectResult() {
|
||||
|
||||
int result = calculateBinaryGap(9);
|
||||
assertEquals(2, result);
|
||||
}
|
||||
|
||||
@Test public void givenMultipleOccurrenceOfBoundedZeros_whenCalculateBinaryGap_thenOutputCorrectResult() {
|
||||
|
||||
int result = calculateBinaryGap(145);
|
||||
assertEquals(3, result);
|
||||
}
|
||||
|
||||
}
|
|
@ -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,80 @@
|
|||
package com.baeldung.algorithms.combinatorics;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
public class CombinatoricsUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenEmptySequence_whenCallingPermutations_ShouldReturnEmptyList() {
|
||||
List<Integer> sequence = Arrays.asList();
|
||||
|
||||
List<List<Integer>> permutations = Combinatorics.permutations(sequence);
|
||||
|
||||
assertEquals(0, permutations.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOneElementSequence_whenCallingPermutations_ShouldReturnPermutations() {
|
||||
List<Integer> sequence = Arrays.asList(1);
|
||||
|
||||
List<List<Integer>> permutations = Combinatorics.permutations(sequence);
|
||||
|
||||
assertEquals(1, permutations.size());
|
||||
assertEquals(1, permutations.get(0).size());
|
||||
assertSame(1, permutations.get(0).get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFourElementsSequence_whenCallingPermutations_ShouldReturnPermutations() {
|
||||
List<Integer> sequence = Arrays.asList(1, 2, 3, 4);
|
||||
|
||||
List<List<Integer>> permutations = Combinatorics.permutations(sequence);
|
||||
|
||||
assertEquals(24, permutations.size());
|
||||
assertEquals(24, new HashSet<>(permutations).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTwoElements_whenCalling3Combinations_ShouldReturnEmptyList() {
|
||||
List<Integer> set = Arrays.asList(1, 2);
|
||||
|
||||
List<List<Integer>> combinations = Combinatorics.combinations(set, 3);
|
||||
|
||||
assertEquals(0, combinations.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenThreeElements_whenCalling3Combinations_ShouldReturnOneCombination() {
|
||||
List<Integer> set = Arrays.asList(1, 2, 3);
|
||||
|
||||
List<List<Integer>> combinations = Combinatorics.combinations(set, 3);
|
||||
|
||||
assertEquals(1, combinations.size());
|
||||
assertEquals(combinations.get(0), Arrays.asList(1, 2, 3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFourElements_whenCalling2Combinations_ShouldReturnCombinations() {
|
||||
List<Integer> set = Arrays.asList(1, 2, 3, 4);
|
||||
|
||||
List<List<Integer>> combinations = Combinatorics.combinations(set, 2);
|
||||
|
||||
assertEquals(6, combinations.size());
|
||||
assertEquals(6, new HashSet<>(combinations).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFourElements_whenCallingPowerSet_ShouldReturn15Sets() {
|
||||
List<Character> sequence = Arrays.asList('a', 'b', 'c', 'd');
|
||||
|
||||
List<List<Character>> combinations = Combinatorics.powerSet(sequence);
|
||||
|
||||
assertEquals(16, combinations.size());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.baeldung.algorithms.knapsack;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class KnapsackUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenWeightsandValues_whenCalculateMax_thenOutputCorrectResult() {
|
||||
final int[] w = new int[] { 23, 26, 20, 18, 32, 27, 29, 26, 30, 27 };
|
||||
final int[] v = new int[] { 505, 352, 458, 220, 354, 414, 498, 545, 473, 543 };
|
||||
final int n = 10;
|
||||
final int W = 67;
|
||||
final Knapsack knapsack = new Knapsack();
|
||||
|
||||
assertEquals(1270, knapsack.knapsackRec(w, v, n, W));
|
||||
assertEquals(1270, knapsack.knapsackDP(w, v, n, W));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenZeroItems_whenCalculateMax_thenOutputZero() {
|
||||
final int[] w = new int[] {};
|
||||
final int[] v = new int[] {};
|
||||
final int n = 0;
|
||||
final int W = 67;
|
||||
final Knapsack knapsack = new Knapsack();
|
||||
|
||||
assertEquals(0, knapsack.knapsackRec(w, v, n, W));
|
||||
assertEquals(0, knapsack.knapsackDP(w, v, n, W));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenZeroWeightLimit_whenCalculateMax_thenOutputZero() {
|
||||
final int[] w = new int[] { 23, 26, 20, 18, 32, 27, 29, 26, 30, 27 };
|
||||
final int[] v = new int[] { 505, 352, 458, 220, 354, 414, 498, 545, 473, 543 };
|
||||
final int n = 10;
|
||||
final int W = 0;
|
||||
final Knapsack knapsack = new Knapsack();
|
||||
|
||||
assertEquals(0, knapsack.knapsackRec(w, v, n, W));
|
||||
assertEquals(0, knapsack.knapsackDP(w, v, n, W));
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -0,0 +1,54 @@
|
|||
package com.baeldung.algorithms.breadthfirstsearch;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class BreadthFirstSearchAlgorithm {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(BreadthFirstSearchAlgorithm.class);
|
||||
|
||||
public static <T> Optional<Tree<T>> search(T value, Tree<T> root) {
|
||||
Queue<Tree<T>> queue = new ArrayDeque<>();
|
||||
queue.add(root);
|
||||
|
||||
Tree<T> currentNode;
|
||||
while (!queue.isEmpty()) {
|
||||
currentNode = queue.remove();
|
||||
LOGGER.info("Visited node with value: {}", currentNode.getValue());
|
||||
|
||||
if (currentNode.getValue().equals(value)) {
|
||||
return Optional.of(currentNode);
|
||||
} else {
|
||||
queue.addAll(currentNode.getChildren());
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static <T> Optional<Node<T>> search(T value, Node<T> start) {
|
||||
Queue<Node<T>> queue = new ArrayDeque<>();
|
||||
queue.add(start);
|
||||
|
||||
Node<T> currentNode;
|
||||
Set<Node<T>> alreadyVisited = new HashSet<>();
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
currentNode = queue.remove();
|
||||
LOGGER.info("Visited node with value: {}", currentNode.getValue());
|
||||
|
||||
if (currentNode.getValue().equals(value)) {
|
||||
return Optional.of(currentNode);
|
||||
} else {
|
||||
alreadyVisited.add(currentNode);
|
||||
queue.addAll(currentNode.getNeighbors());
|
||||
queue.removeAll(alreadyVisited);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.baeldung.algorithms.breadthfirstsearch;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class Node<T> {
|
||||
|
||||
private T value;
|
||||
private Set<Node<T>> neighbors;
|
||||
|
||||
public Node(T value) {
|
||||
this.value = value;
|
||||
this.neighbors = new HashSet<>();
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Set<Node<T>> getNeighbors() {
|
||||
return Collections.unmodifiableSet(neighbors);
|
||||
}
|
||||
|
||||
public void connect(Node<T> node) {
|
||||
if (this == node) throw new IllegalArgumentException("Can't connect node to itself");
|
||||
this.neighbors.add(node);
|
||||
node.neighbors.add(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.algorithms.breadthfirstsearch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class Tree<T> {
|
||||
|
||||
private T value;
|
||||
private List<Tree<T>> children;
|
||||
|
||||
private Tree(T value) {
|
||||
this.value = value;
|
||||
this.children = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static <T> Tree<T> of(T value) {
|
||||
return new Tree<>(value);
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public List<Tree<T>> getChildren() {
|
||||
return Collections.unmodifiableList(children);
|
||||
}
|
||||
|
||||
public Tree<T> addChild(T value) {
|
||||
Tree<T> newChild = new Tree<>(value);
|
||||
children.add(newChild);
|
||||
return newChild;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package com.baeldung.algorithms.dfs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
public class Graph {
|
||||
|
||||
private Map<Integer, List<Integer>> adjVertices;
|
||||
|
||||
public Graph() {
|
||||
this.adjVertices = new HashMap<Integer, List<Integer>>();
|
||||
}
|
||||
|
||||
public void addVertex(int vertex) {
|
||||
adjVertices.putIfAbsent(vertex, new ArrayList<>());
|
||||
}
|
||||
|
||||
public void addEdge(int src, int dest) {
|
||||
adjVertices.get(src).add(dest);
|
||||
}
|
||||
|
||||
public void dfsWithoutRecursion(int start) {
|
||||
Stack<Integer> stack = new Stack<Integer>();
|
||||
boolean[] isVisited = new boolean[adjVertices.size()];
|
||||
stack.push(start);
|
||||
while (!stack.isEmpty()) {
|
||||
int current = stack.pop();
|
||||
isVisited[current] = true;
|
||||
visit(current);
|
||||
for (int dest : adjVertices.get(current)) {
|
||||
if (!isVisited[dest])
|
||||
stack.push(dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dfs(int start) {
|
||||
boolean[] isVisited = new boolean[adjVertices.size()];
|
||||
dfsRecursive(start, isVisited);
|
||||
}
|
||||
|
||||
private void dfsRecursive(int current, boolean[] isVisited) {
|
||||
isVisited[current] = true;
|
||||
visit(current);
|
||||
for (int dest : adjVertices.get(current)) {
|
||||
if (!isVisited[dest])
|
||||
dfsRecursive(dest, isVisited);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Integer> topologicalSort(int start) {
|
||||
LinkedList<Integer> result = new LinkedList<Integer>();
|
||||
boolean[] isVisited = new boolean[adjVertices.size()];
|
||||
topologicalSortRecursive(start, isVisited, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void topologicalSortRecursive(int current, boolean[] isVisited, LinkedList<Integer> result) {
|
||||
isVisited[current] = true;
|
||||
for (int dest : adjVertices.get(current)) {
|
||||
if (!isVisited[dest])
|
||||
topologicalSortRecursive(dest, isVisited, result);
|
||||
}
|
||||
result.addFirst(current);
|
||||
}
|
||||
|
||||
private void visit(int value) {
|
||||
System.out.print(" " + value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
package com.baeldung.algorithms.textsearch;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
public class TextSearchAlgorithms {
|
||||
public static long getBiggerPrime(int m) {
|
||||
BigInteger prime = BigInteger.probablePrime(getNumberOfBits(m) + 1, new Random());
|
||||
return prime.longValue();
|
||||
}
|
||||
|
||||
public static long getLowerPrime(long number) {
|
||||
BigInteger prime = BigInteger.probablePrime(getNumberOfBits(number) - 1, new Random());
|
||||
return prime.longValue();
|
||||
}
|
||||
|
||||
private static int getNumberOfBits(final int number) {
|
||||
return Integer.SIZE - Integer.numberOfLeadingZeros(number);
|
||||
}
|
||||
|
||||
private static int getNumberOfBits(final long number) {
|
||||
return Long.SIZE - Long.numberOfLeadingZeros(number);
|
||||
}
|
||||
|
||||
public static int simpleTextSearch(char[] pattern, char[] text) {
|
||||
int patternSize = pattern.length;
|
||||
int textSize = text.length;
|
||||
|
||||
int i = 0;
|
||||
|
||||
while ((i + patternSize) <= textSize) {
|
||||
int j = 0;
|
||||
while (text[i + j] == pattern[j]) {
|
||||
j += 1;
|
||||
if (j >= patternSize)
|
||||
return i;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int RabinKarpMethod(char[] pattern, char[] text) {
|
||||
int patternSize = pattern.length; // m
|
||||
int textSize = text.length; // n
|
||||
|
||||
long prime = getBiggerPrime(patternSize);
|
||||
|
||||
long r = 1;
|
||||
for (int i = 0; i < patternSize - 1; i++) {
|
||||
r *= 2;
|
||||
r = r % prime;
|
||||
}
|
||||
|
||||
long[] t = new long[textSize];
|
||||
t[0] = 0;
|
||||
|
||||
long pfinger = 0;
|
||||
|
||||
for (int j = 0; j < patternSize; j++) {
|
||||
t[0] = (2 * t[0] + text[j]) % prime;
|
||||
pfinger = (2 * pfinger + pattern[j]) % prime;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
boolean passed = false;
|
||||
|
||||
int diff = textSize - patternSize;
|
||||
for (i = 0; i <= diff; i++) {
|
||||
if (t[i] == pfinger) {
|
||||
passed = true;
|
||||
for (int k = 0; k < patternSize; k++) {
|
||||
if (text[i + k] != pattern[k]) {
|
||||
passed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (passed) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < diff) {
|
||||
long value = 2 * (t[i] - r * text[i]) + text[i + patternSize];
|
||||
t[i + 1] = ((value % prime) + prime) % prime;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
public static int KnuthMorrisPrattSearch(char[] pattern, char[] text) {
|
||||
int patternSize = pattern.length; // m
|
||||
int textSize = text.length; // n
|
||||
|
||||
int i = 0, j = 0;
|
||||
|
||||
int[] shift = KnuthMorrisPrattShift(pattern);
|
||||
|
||||
while ((i + patternSize) <= textSize) {
|
||||
while (text[i + j] == pattern[j]) {
|
||||
j += 1;
|
||||
if (j >= patternSize)
|
||||
return i;
|
||||
}
|
||||
|
||||
if (j > 0) {
|
||||
i += shift[j - 1];
|
||||
j = Math.max(j - shift[j - 1], 0);
|
||||
} else {
|
||||
i++;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int[] KnuthMorrisPrattShift(char[] pattern) {
|
||||
int patternSize = pattern.length;
|
||||
|
||||
int[] shift = new int[patternSize];
|
||||
shift[0] = 1;
|
||||
|
||||
int i = 1, j = 0;
|
||||
|
||||
while ((i + j) < patternSize) {
|
||||
if (pattern[i + j] == pattern[j]) {
|
||||
shift[i + j] = i;
|
||||
j++;
|
||||
} else {
|
||||
if (j == 0)
|
||||
shift[i] = i + 1;
|
||||
|
||||
if (j > 0) {
|
||||
i = i + shift[j - 1];
|
||||
j = Math.max(j - shift[j - 1], 0);
|
||||
} else {
|
||||
i = i + 1;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return shift;
|
||||
}
|
||||
|
||||
public static int BoyerMooreHorspoolSimpleSearch(char[] pattern, char[] text) {
|
||||
int patternSize = pattern.length;
|
||||
int textSize = text.length;
|
||||
|
||||
int i = 0, j = 0;
|
||||
|
||||
while ((i + patternSize) <= textSize) {
|
||||
j = patternSize - 1;
|
||||
while (text[i + j] == pattern[j]) {
|
||||
j--;
|
||||
if (j < 0)
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int BoyerMooreHorspoolSearch(char[] pattern, char[] text) {
|
||||
|
||||
int shift[] = new int[256];
|
||||
|
||||
for (int k = 0; k < 256; k++) {
|
||||
shift[k] = pattern.length;
|
||||
}
|
||||
|
||||
for (int k = 0; k < pattern.length - 1; k++) {
|
||||
shift[pattern[k]] = pattern.length - 1 - k;
|
||||
}
|
||||
|
||||
int i = 0, j = 0;
|
||||
|
||||
while ((i + pattern.length) <= text.length) {
|
||||
j = pattern.length - 1;
|
||||
|
||||
while (text[i + j] == pattern[j]) {
|
||||
j -= 1;
|
||||
if (j < 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
i = i + shift[text[i + pattern.length - 1]];
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
|
@ -2,10 +2,8 @@ package com.baeldung.algorithms.binarysearch;
|
|||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import com.baeldung.algorithms.binarysearch.BinarySearch;
|
||||
|
||||
public class BinarySearchUnitTest {
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package com.baeldung.algorithms.breadthfirstsearch;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class BreadthFirstSearchAlgorithmUnitTest {
|
||||
|
||||
private Tree<Integer> root;
|
||||
private Tree<Integer> rootFirstChild;
|
||||
private Tree<Integer> depthMostChild;
|
||||
private Tree<Integer> rootSecondChild;
|
||||
|
||||
private Node<Integer> start;
|
||||
private Node<Integer> firstNeighbor;
|
||||
private Node<Integer> firstNeighborNeighbor;
|
||||
private Node<Integer> secondNeighbor;
|
||||
|
||||
@Test
|
||||
void givenTree_whenSearchTen_thenRoot() {
|
||||
initTree();
|
||||
assertThat(BreadthFirstSearchAlgorithm.search(10, root)).isPresent().contains(root);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenTree_whenSearchThree_thenDepthMostValue() {
|
||||
initTree();
|
||||
assertThat(BreadthFirstSearchAlgorithm.search(3, root)).isPresent().contains(depthMostChild);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenTree_whenSearchFour_thenRootSecondChild() {
|
||||
initTree();
|
||||
assertThat(BreadthFirstSearchAlgorithm.search(4, root)).isPresent().contains(rootSecondChild);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenTree_whenSearchFive_thenNotFound() {
|
||||
initTree();
|
||||
assertThat(BreadthFirstSearchAlgorithm.search(5, root)).isEmpty();
|
||||
}
|
||||
|
||||
private void initTree() {
|
||||
root = Tree.of(10);
|
||||
rootFirstChild = root.addChild(2);
|
||||
depthMostChild = rootFirstChild.addChild(3);
|
||||
rootSecondChild = root.addChild(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNode_whenSearchTen_thenStart() {
|
||||
initNode();
|
||||
assertThat(BreadthFirstSearchAlgorithm.search(10, firstNeighborNeighbor)).isPresent().contains(start);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNode_whenSearchThree_thenNeighborNeighbor() {
|
||||
initNode();
|
||||
assertThat(BreadthFirstSearchAlgorithm.search(3, firstNeighborNeighbor)).isPresent().contains(firstNeighborNeighbor);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNode_whenSearchFour_thenSecondNeighbor() {
|
||||
initNode();
|
||||
assertThat(BreadthFirstSearchAlgorithm.search(4, firstNeighborNeighbor)).isPresent().contains(secondNeighbor);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNode_whenSearchFive_thenNotFound() {
|
||||
initNode();
|
||||
assertThat(BreadthFirstSearchAlgorithm.search(5, firstNeighborNeighbor)).isEmpty();
|
||||
}
|
||||
|
||||
private void initNode() {
|
||||
start = new Node<>(10);
|
||||
firstNeighbor = new Node<>(2);
|
||||
start.connect(firstNeighbor);
|
||||
|
||||
firstNeighborNeighbor = new Node<>(3);
|
||||
firstNeighbor.connect(firstNeighborNeighbor);
|
||||
firstNeighborNeighbor.connect(start);
|
||||
|
||||
secondNeighbor = new Node<>(4);
|
||||
start.connect(secondNeighbor);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package com.baeldung.algorithms.dfs;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class BinaryTreeUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenAddingElements_ThenTreeNotEmpty() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
assertTrue(!bt.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenAddingElements_ThenTreeContainsThoseElements() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
assertTrue(bt.containsNode(6));
|
||||
assertTrue(bt.containsNode(4));
|
||||
|
||||
assertFalse(bt.containsNode(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenAddingExistingElement_ThenElementIsNotAdded() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
int initialSize = bt.getSize();
|
||||
|
||||
assertTrue(bt.containsNode(3));
|
||||
bt.add(3);
|
||||
assertEquals(initialSize, bt.getSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenLookingForNonExistingElement_ThenReturnsFalse() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
assertFalse(bt.containsNode(99));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenDeletingElements_ThenTreeDoesNotContainThoseElements() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
assertTrue(bt.containsNode(9));
|
||||
bt.delete(9);
|
||||
assertFalse(bt.containsNode(9));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenDeletingNonExistingElement_ThenTreeDoesNotDelete() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
int initialSize = bt.getSize();
|
||||
|
||||
assertFalse(bt.containsNode(99));
|
||||
bt.delete(99);
|
||||
assertFalse(bt.containsNode(99));
|
||||
assertEquals(initialSize, bt.getSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void it_deletes_the_root() {
|
||||
int value = 12;
|
||||
BinaryTree bt = new BinaryTree();
|
||||
bt.add(value);
|
||||
|
||||
assertTrue(bt.containsNode(value));
|
||||
bt.delete(value);
|
||||
assertFalse(bt.containsNode(value));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenTraversingInOrder_ThenPrintValues() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
bt.traverseInOrder(bt.root);
|
||||
System.out.println();
|
||||
bt.traverseInOrderWithoutRecursion();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenTraversingPreOrder_ThenPrintValues() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
bt.traversePreOrder(bt.root);
|
||||
System.out.println();
|
||||
bt.traversePreOrderWithoutRecursion();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenTraversingPostOrder_ThenPrintValues() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
bt.traversePostOrder(bt.root);
|
||||
System.out.println();
|
||||
bt.traversePostOrderWithoutRecursion();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenTraversingLevelOrder_ThenPrintValues() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
bt.traverseLevelOrder();
|
||||
}
|
||||
|
||||
private BinaryTree createBinaryTree() {
|
||||
BinaryTree bt = new BinaryTree();
|
||||
|
||||
bt.add(6);
|
||||
bt.add(4);
|
||||
bt.add(8);
|
||||
bt.add(3);
|
||||
bt.add(5);
|
||||
bt.add(7);
|
||||
bt.add(9);
|
||||
|
||||
return bt;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
package com.baeldung.graph;
|
||||
package com.baeldung.algorithms.dfs;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.baeldung.algorithms.dfs.Graph;
|
||||
import org.junit.Test;
|
||||
|
||||
public class GraphUnitTest {
|
|
@ -1,10 +1,10 @@
|
|||
package com.baeldung.algorithms.interpolationsearch;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class InterpolationSearchUnitTest {
|
||||
|
||||
private int[] myData;
|
|
@ -0,0 +1,23 @@
|
|||
package com.baeldung.algorithms.textsearch;
|
||||
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TextSearchAlgorithmsUnitTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void testStringSearchAlgorithms() {
|
||||
String text = "This is some nice text.";
|
||||
String pattern = "some";
|
||||
|
||||
int realPosition = text.indexOf(pattern);
|
||||
Assert.assertTrue(realPosition == TextSearchAlgorithms.simpleTextSearch(pattern.toCharArray(), text.toCharArray()));
|
||||
Assert.assertTrue(realPosition == TextSearchAlgorithms.RabinKarpMethod(pattern.toCharArray(), text.toCharArray()));
|
||||
Assert.assertTrue(realPosition == TextSearchAlgorithms.KnuthMorrisPrattSearch(pattern.toCharArray(), text.toCharArray()));
|
||||
Assert.assertTrue(realPosition == TextSearchAlgorithms.BoyerMooreHorspoolSimpleSearch(pattern.toCharArray(), text.toCharArray()));
|
||||
Assert.assertTrue(realPosition == TextSearchAlgorithms.BoyerMooreHorspoolSearch(pattern.toCharArray(), text.toCharArray()));
|
||||
}
|
||||
|
||||
}
|
|
@ -12,3 +12,9 @@ This module contains articles about sorting algorithms.
|
|||
- [Shell Sort in Java](https://www.baeldung.com/java-shell-sort)
|
||||
- [Counting Sort in Java](https://www.baeldung.com/java-counting-sort)
|
||||
- [Sorting Strings by Contained Numbers in Java](https://www.baeldung.com/java-sort-strings-contained-numbers)
|
||||
- [How an In-Place Sorting Algorithm Works](https://www.baeldung.com/java-in-place-sorting)
|
||||
- [Selection Sort in Java](https://www.baeldung.com/java-selection-sort)
|
||||
- [Sorting Strings by Contained Numbers in Java](https://www.baeldung.com/java-sort-strings-contained-numbers)
|
||||
- [Radix Sort in Java](https://www.baeldung.com/java-radix-sort)
|
||||
- [Sorting a String Alphabetically in Java](https://www.baeldung.com/java-sort-string-alphabetically)
|
||||
- [Bucket Sort in Java](https://www.baeldung.com/java-bucket-sort)
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
<version>${lombok.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit-jupiter-api.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
|
@ -52,6 +58,7 @@
|
|||
<commons-math3.version>3.6.1</commons-math3.version>
|
||||
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||
<commons-codec.version>1.11</commons-codec.version>
|
||||
<junit-jupiter-api.version>5.3.1</junit-jupiter-api.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.string.sorting;
|
||||
package com.baeldung.algorithms.stringsort;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
package com.baeldung.string.sorting;
|
||||
package com.baeldung.algorithms.stringsort;
|
||||
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.string.sorting.AnagramValidator;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class AnagramValidatorUnitTest {
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package com.baeldung.string.sorting;
|
||||
|
||||
import java.util.Arrays;
|
||||
package com.baeldung.algorithms.stringsort;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class SortStringUnitTest {
|
|
@ -1,7 +1,6 @@
|
|||
<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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>animal-sniffer-mvn-plugin</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>animal-sniffer-mvn-plugin</name>
|
||||
|
|
|
@ -14,12 +14,6 @@
|
|||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
|
@ -46,15 +40,6 @@
|
|||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.avro</groupId>
|
||||
<artifactId>avro-maven-plugin</artifactId>
|
||||
|
@ -79,8 +64,6 @@
|
|||
</build>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<compiler-plugin.version>3.5</compiler-plugin.version>
|
||||
<avro.version>1.8.2</avro.version>
|
||||
<slf4j.version>1.7.25</slf4j.version>
|
||||
</properties>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<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>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>apache-fop</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>apache-fop</name>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -19,26 +19,8 @@
|
|||
<artifactId>geode-core</artifactId>
|
||||
<version>${geode.core}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<geode.core>1.6.0</geode.core>
|
||||
</properties>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<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>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>apache-meecrowave</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<name>apache-meecrowave</name>
|
||||
|
@ -38,13 +37,6 @@
|
|||
<version>${meecrowave-junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/junit/junit -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.baeldung.examples.olingo2</groupId>
|
||||
<artifactId>olingo2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>olingo2</name>
|
||||
<description>Sample Olingo 2 Project</description>
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<pulsar-client.version>2.1.1-incubating</pulsar-client.version>
|
||||
</properties>
|
||||
</project>
|
||||
|
|
|
@ -5,3 +5,5 @@ This module contains articles about Apache Shiro
|
|||
### Relevant articles:
|
||||
|
||||
- [Introduction to Apache Shiro](https://www.baeldung.com/apache-shiro)
|
||||
- [Permissions-Based Access Control with Apache Shiro](https://www.baeldung.com/apache-shiro-access-control)
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<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>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>apache-solrj</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>apache-solrj</name>
|
||||
|
|
|
@ -6,3 +6,5 @@ This module contains articles about Apache Spark
|
|||
|
||||
- [Introduction to Apache Spark](https://www.baeldung.com/apache-spark)
|
||||
- [Building a Data Pipeline with Kafka, Spark Streaming and Cassandra](https://www.baeldung.com/kafka-spark-data-pipeline)
|
||||
- [Machine Learning with Spark MLlib](https://www.baeldung.com/spark-mlib-machine-learning)
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
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>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>apache-spark</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>apache-spark</name>
|
||||
|
@ -59,15 +58,6 @@
|
|||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
|
@ -95,7 +85,6 @@
|
|||
<org.apache.spark.spark-streaming-kafka.version>2.3.0</org.apache.spark.spark-streaming-kafka.version>
|
||||
<com.datastax.spark.spark-cassandra-connector.version>2.3.0</com.datastax.spark.spark-cassandra-connector.version>
|
||||
<com.datastax.spark.spark-cassandra-connector-java.version>1.5.2</com.datastax.spark.spark-cassandra-connector-java.version>
|
||||
<maven-compiler-plugin.version>3.2</maven-compiler-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>apache-tapestry</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
<name>apache-tapestry</name>
|
||||
<dependencies>
|
||||
<!-- To set up an application with a database, change the artifactId below to
|
||||
tapestry-hibernate, and add a dependency on your JDBC driver. You'll also
|
||||
need to add Hibernate configuration files, such as hibernate.cfg.xml. -->
|
||||
<dependency>
|
||||
<groupId>org.apache.tapestry</groupId>
|
||||
<artifactId>tapestry-core</artifactId>
|
||||
<version>${tapestry-release-version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Include the Log4j implementation for the SLF4J logging framework -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j-release-version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.tapestry</groupId>
|
||||
<artifactId>tapestry-webresources</artifactId>
|
||||
<version>${tapestry-release-version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Uncomment this to add support for file uploads: -->
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.apache.tapestry</groupId>
|
||||
<artifactId>tapestry-upload</artifactId>
|
||||
<version>${tapestry-release-version}</version>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<!-- A dependency on either JUnit or TestNG is required, or the surefire plugin (which runs the tests)
|
||||
will fail, preventing Maven from packaging the WAR. Tapestry includes a large number
|
||||
of testing facilities designed for use with TestNG (http://testng.org/), so it's recommended. -->
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<version>${testng-release-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.tapestry</groupId>
|
||||
<artifactId>tapestry-test</artifactId>
|
||||
<version>${tapestry-release-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided by the servlet container, but sometimes referenced in the application
|
||||
code. -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>${servlet-api-release-version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Provide dependency to the Tapestry javadoc taglet which replaces the Maven component report -->
|
||||
<dependency>
|
||||
<groupId>org.apache.tapestry</groupId>
|
||||
<artifactId>tapestry-javadoc</artifactId>
|
||||
<version>${tapestry-release-version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>apache-tapestry</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<optimize>true</optimize>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.7.2</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<tapestry.execution-mode>Qa</tapestry.execution-mode>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Run the application using "mvn jetty:run" -->
|
||||
<plugin>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>maven-jetty-plugin</artifactId>
|
||||
<version>6.1.16</version>
|
||||
<configuration>
|
||||
<!-- Log to the console. -->
|
||||
<requestLog implementation="org.mortbay.jetty.NCSARequestLog">
|
||||
<!-- This doesn't do anything for Jetty, but is a workaround for a Maven bug
|
||||
that prevents the requestLog from being set. -->
|
||||
<append>true</append>
|
||||
</requestLog>
|
||||
<systemProperties>
|
||||
<systemProperty>
|
||||
<name>tapestry.execution-mode</name>
|
||||
<value>development</value>
|
||||
</systemProperty>
|
||||
</systemProperties>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<reporting/>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jboss</id>
|
||||
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
|
||||
</repository>
|
||||
|
||||
<!-- This repository is only needed when the Tapestry version is a preview release, rather
|
||||
than a final release. -->
|
||||
<repository>
|
||||
<id>apache-staging</id>
|
||||
<url>https://repository.apache.org/content/groups/staging/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<tapestry-release-version>5.4.5</tapestry-release-version>
|
||||
<servlet-api-release-version>2.5</servlet-api-release-version>
|
||||
<testng-release-version>6.8.21</testng-release-version>
|
||||
<slf4j-release-version>1.7.19</slf4j-release-version>
|
||||
|
||||
</properties>
|
||||
</project>
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.tapestry.components;
|
||||
|
||||
import org.apache.tapestry5.BindingConstants;
|
||||
import org.apache.tapestry5.annotations.Parameter;
|
||||
import org.apache.tapestry5.annotations.Property;
|
||||
|
||||
/**
|
||||
* Layout component for pages of application.
|
||||
*/
|
||||
public class Layout {
|
||||
|
||||
@Property
|
||||
@Parameter(required = true, defaultPrefix = BindingConstants.LITERAL)
|
||||
private String title;
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.baeldung.tapestry.pages;
|
||||
|
||||
public class Error404 {
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.baeldung.tapestry.pages;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.tapestry5.Block;
|
||||
import org.apache.tapestry5.annotations.Log;
|
||||
import org.apache.tapestry5.annotations.Property;
|
||||
import org.apache.tapestry5.ioc.annotations.Inject;
|
||||
import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class Home {
|
||||
|
||||
@Property
|
||||
private String appName = "apache-tapestry";
|
||||
|
||||
public Date getCurrentTime() {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
@Inject
|
||||
private Logger logger;
|
||||
|
||||
@Inject
|
||||
private AjaxResponseRenderer ajaxResponseRenderer;
|
||||
|
||||
@Inject
|
||||
private Block ajaxBlock;
|
||||
|
||||
@Log
|
||||
void onCallAjax() {
|
||||
logger.info("Ajax call");
|
||||
ajaxResponseRenderer.addRender("ajaxZone", ajaxBlock);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.baeldung.tapestry.pages;
|
||||
|
||||
|
||||
import org.apache.tapestry5.Block;
|
||||
import org.apache.tapestry5.EventContext;
|
||||
import org.apache.tapestry5.SymbolConstants;
|
||||
import org.apache.tapestry5.annotations.InjectPage;
|
||||
import org.apache.tapestry5.annotations.Log;
|
||||
import org.apache.tapestry5.annotations.Property;
|
||||
import org.apache.tapestry5.ioc.annotations.Inject;
|
||||
import org.apache.tapestry5.ioc.annotations.Symbol;
|
||||
import org.apache.tapestry5.services.HttpError;
|
||||
import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Start page of application apache-tapestry.
|
||||
*/
|
||||
public class Index {
|
||||
@Inject
|
||||
private Logger logger;
|
||||
|
||||
@Inject
|
||||
private AjaxResponseRenderer ajaxResponseRenderer;
|
||||
|
||||
@Property
|
||||
@Inject
|
||||
@Symbol(SymbolConstants.TAPESTRY_VERSION)
|
||||
private String tapestryVersion;
|
||||
|
||||
@Inject
|
||||
private Block block;
|
||||
|
||||
// Handle call with an unwanted context
|
||||
Object onActivate(EventContext eventContext) {
|
||||
return eventContext.getCount() > 0 ?
|
||||
new HttpError(404, "Resource not found") :
|
||||
null;
|
||||
}
|
||||
|
||||
@Log
|
||||
void onComplete() {
|
||||
logger.info("Complete call on Index page");
|
||||
}
|
||||
|
||||
@Log
|
||||
void onAjax() {
|
||||
logger.info("Ajax call on Index page");
|
||||
|
||||
ajaxResponseRenderer.addRender("middlezone", block);
|
||||
}
|
||||
|
||||
public Date getCurrentTime() {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.baeldung.tapestry.pages;
|
||||
|
||||
import org.apache.tapestry5.alerts.AlertManager;
|
||||
import org.apache.tapestry5.annotations.InjectComponent;
|
||||
import org.apache.tapestry5.annotations.Property;
|
||||
import org.apache.tapestry5.corelib.components.Form;
|
||||
import org.apache.tapestry5.ioc.annotations.Inject;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class Login {
|
||||
@Inject
|
||||
private Logger logger;
|
||||
|
||||
@Inject
|
||||
private AlertManager alertManager;
|
||||
|
||||
@InjectComponent
|
||||
private Form login;
|
||||
|
||||
@Property
|
||||
private String email;
|
||||
|
||||
@Property
|
||||
private String password;
|
||||
|
||||
void onValidateFromLogin() {
|
||||
if(email == null || password == null) {
|
||||
alertManager.error("Email/Password is null");
|
||||
login.recordError("Validation failed");
|
||||
}
|
||||
}
|
||||
|
||||
Object onSuccessFromLogin() {
|
||||
alertManager.success("Welcome! Login Successful");
|
||||
return Home.class;
|
||||
}
|
||||
|
||||
void onFailureFromLogin() {
|
||||
alertManager.error("Please try again with correct credentials");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package com.baeldung.tapestry.services;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.tapestry5.SymbolConstants;
|
||||
import org.apache.tapestry5.ioc.MappedConfiguration;
|
||||
import org.apache.tapestry5.ioc.OrderedConfiguration;
|
||||
import org.apache.tapestry5.ioc.ServiceBinder;
|
||||
import org.apache.tapestry5.ioc.annotations.Contribute;
|
||||
import org.apache.tapestry5.ioc.annotations.Local;
|
||||
import org.apache.tapestry5.ioc.services.ApplicationDefaults;
|
||||
import org.apache.tapestry5.ioc.services.SymbolProvider;
|
||||
import org.apache.tapestry5.services.Request;
|
||||
import org.apache.tapestry5.services.RequestFilter;
|
||||
import org.apache.tapestry5.services.RequestHandler;
|
||||
import org.apache.tapestry5.services.Response;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* This module is automatically included as part of the Tapestry IoC Registry, it's a good place to
|
||||
* configure and extend Tapestry, or to place your own service definitions.
|
||||
*/
|
||||
public class AppModule {
|
||||
public static void bind(ServiceBinder binder) {
|
||||
// binder.bind(MyServiceInterface.class, MyServiceImpl.class);
|
||||
|
||||
// Make bind() calls on the binder object to define most IoC services.
|
||||
// Use service builder methods (example below) when the implementation
|
||||
// is provided inline, or requires more initialization than simply
|
||||
// invoking the constructor.
|
||||
}
|
||||
|
||||
public static void contributeFactoryDefaults(
|
||||
MappedConfiguration<String, Object> configuration) {
|
||||
// The values defined here (as factory default overrides) are themselves
|
||||
// overridden with application defaults by DevelopmentModule and QaModule.
|
||||
|
||||
// The application version is primarily useful as it appears in
|
||||
// any exception reports (HTML or textual).
|
||||
configuration.override(SymbolConstants.APPLICATION_VERSION, "0.0.1-SNAPSHOT");
|
||||
|
||||
// This is something that should be removed when going to production, but is useful
|
||||
// in the early stages of development.
|
||||
configuration.override(SymbolConstants.PRODUCTION_MODE, false);
|
||||
}
|
||||
|
||||
public static void contributeApplicationDefaults(
|
||||
MappedConfiguration<String, Object> configuration) {
|
||||
// Contributions to ApplicationDefaults will override any contributions to
|
||||
// FactoryDefaults (with the same key). Here we're restricting the supported
|
||||
// locales to just "en" (English). As you add localised message catalogs and other assets,
|
||||
// you can extend this list of locales (it's a comma separated series of locale names;
|
||||
// the first locale name is the default when there's no reasonable match).
|
||||
configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en");
|
||||
|
||||
// You should change the passphrase immediately; the HMAC passphrase is used to secure
|
||||
// the hidden field data stored in forms to encrypt and digitally sign client-side data.
|
||||
configuration.add(SymbolConstants.HMAC_PASSPHRASE, "change this immediately");
|
||||
}
|
||||
|
||||
/**
|
||||
* Use annotation or method naming convention: <code>contributeApplicationDefaults</code>
|
||||
*/
|
||||
@Contribute(SymbolProvider.class)
|
||||
@ApplicationDefaults
|
||||
public static void setupEnvironment(MappedConfiguration<String, Object> configuration) {
|
||||
// Support for jQuery is new in Tapestry 5.4 and will become the only supported
|
||||
// option in 5.5.
|
||||
configuration.add(SymbolConstants.JAVASCRIPT_INFRASTRUCTURE_PROVIDER, "jquery");
|
||||
configuration.add(SymbolConstants.BOOTSTRAP_ROOT, "context:mybootstrap");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is a service definition, the service will be named "TimingFilter". The interface,
|
||||
* RequestFilter, is used within the RequestHandler service pipeline, which is built from the
|
||||
* RequestHandler service configuration. Tapestry IoC is responsible for passing in an
|
||||
* appropriate Logger instance. Requests for static resources are handled at a higher level, so
|
||||
* this filter will only be invoked for Tapestry related requests.
|
||||
*
|
||||
*
|
||||
* Service builder methods are useful when the implementation is inline as an inner class
|
||||
* (as here) or require some other kind of special initialization. In most cases,
|
||||
* use the static bind() method instead.
|
||||
*
|
||||
*
|
||||
* If this method was named "build", then the service id would be taken from the
|
||||
* service interface and would be "RequestFilter". Since Tapestry already defines
|
||||
* a service named "RequestFilter" we use an explicit service id that we can reference
|
||||
* inside the contribution method.
|
||||
*/
|
||||
public RequestFilter buildTimingFilter(final Logger log) {
|
||||
return new RequestFilter() {
|
||||
public boolean service(Request request, Response response, RequestHandler handler)
|
||||
throws IOException {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
// The responsibility of a filter is to invoke the corresponding method
|
||||
// in the handler. When you chain multiple filters together, each filter
|
||||
// received a handler that is a bridge to the next filter.
|
||||
|
||||
return handler.service(request, response);
|
||||
} finally {
|
||||
long elapsed = System.currentTimeMillis() - startTime;
|
||||
|
||||
log.info("Request time: {} ms", elapsed);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a contribution to the RequestHandler service configuration. This is how we extend
|
||||
* Tapestry using the timing filter. A common use for this kind of filter is transaction
|
||||
* management or security. The @Local annotation selects the desired service by type, but only
|
||||
* from the same module. Without @Local, there would be an error due to the other service(s)
|
||||
* that implement RequestFilter (defined in other modules).
|
||||
*/
|
||||
@Contribute(RequestHandler.class)
|
||||
public void addTimingFilter(OrderedConfiguration<RequestFilter> configuration, @Local RequestFilter filter) {
|
||||
// Each contribution to an ordered configuration has a name, When necessary, you may
|
||||
// set constraints to precisely control the invocation order of the contributed filter
|
||||
// within the pipeline.
|
||||
|
||||
configuration.add("Timing", filter);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.baeldung.tapestry.services;
|
||||
|
||||
import org.apache.tapestry5.SymbolConstants;
|
||||
import org.apache.tapestry5.ioc.MappedConfiguration;
|
||||
|
||||
/**
|
||||
* This module is automatically included as part of the Tapestry IoC Registry if <em>tapestry.execution-mode</em>
|
||||
* includes <code>development</code>.
|
||||
*/
|
||||
public class DevelopmentModule {
|
||||
public static void contributeApplicationDefaults(
|
||||
MappedConfiguration<String, Object> configuration) {
|
||||
// The factory default is true but during the early stages of an application
|
||||
// overriding to false is a good idea. In addition, this is often overridden
|
||||
// on the command line as -Dtapestry.production-mode=false
|
||||
configuration.add(SymbolConstants.PRODUCTION_MODE, false);
|
||||
|
||||
// The application version number is incorprated into URLs for some
|
||||
// assets. Web browsers will cache assets because of the far future expires
|
||||
// header. If existing assets are changed, the version number should also
|
||||
// change, to force the browser to download new versions.
|
||||
configuration.add(SymbolConstants.APPLICATION_VERSION, "0.0.1-SNAPSHOT-DEV");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.tapestry.services;
|
||||
|
||||
import org.apache.tapestry5.SymbolConstants;
|
||||
import org.apache.tapestry5.ioc.MappedConfiguration;
|
||||
import org.apache.tapestry5.ioc.ServiceBinder;
|
||||
|
||||
/**
|
||||
* This module is automatically included as part of the Tapestry IoC Registry if <em>tapestry.execution-mode</em>
|
||||
* includes <code>qa</code> ("quality assurance").
|
||||
*/
|
||||
public class QaModule
|
||||
{
|
||||
public static void bind(ServiceBinder binder)
|
||||
{
|
||||
// Bind any services needed by the QA team to produce their reports
|
||||
// binder.bind(MyServiceMonitorInterface.class, MyServiceMonitorImpl.class);
|
||||
}
|
||||
|
||||
|
||||
public static void contributeApplicationDefaults(
|
||||
MappedConfiguration<String, Object> configuration)
|
||||
{
|
||||
// The factory default is true but during the early stages of an application
|
||||
// overriding to false is a good idea. In addition, this is often overridden
|
||||
// on the command line as -Dtapestry.production-mode=false
|
||||
configuration.add(SymbolConstants.PRODUCTION_MODE, false);
|
||||
|
||||
// The application version number is incorprated into URLs for some
|
||||
// assets. Web browsers will cache assets because of the far future expires
|
||||
// header. If existing assets are changed, the version number should also
|
||||
// change, to force the browser to download new versions.
|
||||
configuration.add(SymbolConstants.APPLICATION_VERSION, "0.0.1-SNAPSHOT-QA");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
|
||||
<head>
|
||||
<title>${title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<t:alerts/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<t:body />
|
||||
<hr />
|
||||
<footer>
|
||||
<p>© Your Company</p>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="com.baeldung.tapestry" level="TRACE"/>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
</configuration>
|
|
@ -0,0 +1,11 @@
|
|||
<html t:type="layout" title="Not found apache-tapestry"
|
||||
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd"
|
||||
xmlns:p="tapestry:parameter">
|
||||
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<h1>Requested page not found!</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
introMsg=Welcome to the Apache Tapestry Tutorial
|
|
@ -0,0 +1,14 @@
|
|||
<html t:type="layout" title="apache-tapestry Home" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
|
||||
|
||||
<h1>Home! ${appName}</h1>
|
||||
<h2>${message:introMsg}</h2>
|
||||
<h3>${currentTime}</h3>
|
||||
<p><t:eventlink event="callAjax" zone="ajaxZone" class="btn btn-default">Call Ajax</t:eventlink></p>
|
||||
<t:zone t:id="ajaxZone" class="span4"></t:zone>
|
||||
<t:block t:id="ajaxBlock">
|
||||
<hr/>
|
||||
<h2>Rendered through Ajax</h2>
|
||||
<p>The current time is: <strong>${currentTime}</strong></p>
|
||||
</t:block>
|
||||
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
greeting=Welcome to Tapestry 5! We hope that this project template will get you going in style.
|
|
@ -0,0 +1,46 @@
|
|||
<html t:type="layout" title="apache-tapestry Index"
|
||||
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd"
|
||||
>
|
||||
|
||||
<!-- Most of the page content, including <head>, <body>, etc. tags, comes from Layout.tml -->
|
||||
|
||||
<!-- Main hero unit for a primary marketing message or call to action -->
|
||||
<div class="hero-unit">
|
||||
<p>
|
||||
<img src="${asset:context:images/tapestry.png}"
|
||||
alt="${message:greeting}" title="${message:greeting}"/>
|
||||
</p>
|
||||
<h3>${message:greeting}</h3>
|
||||
<p>The current time is: <strong>${currentTime}</strong></p>
|
||||
<p>
|
||||
This is a template for a simple marketing or informational website. It includes a large callout called
|
||||
the hero unit and three supporting pieces of content. Use it as a starting point to create something
|
||||
more unique.
|
||||
</p>
|
||||
<p><t:actionlink t:id="learnmore" class="btn btn-primary btn-large">Learn more »</t:actionlink></p>
|
||||
</div>
|
||||
|
||||
<!-- Example row of columns -->
|
||||
<div class="row">
|
||||
<div class="span4">
|
||||
<h2>Normal link</h2>
|
||||
<p>Clink the bottom link and the page refresh with event <code>complete</code></p>
|
||||
<p><t:eventlink event="complete" class="btn btn-default">Complete»</t:eventlink></p>
|
||||
</div>
|
||||
<t:zone t:id="middlezone" class="span4">
|
||||
|
||||
</t:zone>
|
||||
<div class="span4">
|
||||
<h2>Ajax link</h2>
|
||||
<p>Click the bottom link to update just the middle column with Ajax call with event <code>ajax</code></p>
|
||||
<p><t:eventlink event="ajax" zone="middlezone" class="btn btn-default">Ajax»</t:eventlink></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<t:block t:id="block">
|
||||
<h2>Ajax updated</h2>
|
||||
<p>I'v been updated through AJAX call</p>
|
||||
<p>The current time is: <strong>${currentTime}</strong></p>
|
||||
</t:block>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<html t:type="layout" title="apache-tapestry com.example"
|
||||
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
|
||||
xmlns:p="tapestry:parameter">
|
||||
|
||||
<div class="row">
|
||||
<div class="span4 offset3">
|
||||
<t:form t:id="login">
|
||||
<h2>Please sign in</h2>
|
||||
<t:textfield t:id="email" class="input-block-level" placeholder="Email address"/>
|
||||
<t:passwordfield t:id="password" class="input-block-level" placeholder="Password"/>
|
||||
<t:submit class="btn btn-large btn-primary" value="Sign in"/>
|
||||
</t:form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,44 @@
|
|||
# Default to info level output; this is very handy if you eventually use Hibernate as well.
|
||||
log4j.rootCategory=info, A1
|
||||
|
||||
# A1 is set to be a ConsoleAppender.
|
||||
log4j.appender.A1=org.apache.log4j.ConsoleAppender
|
||||
|
||||
# A1 uses PatternLayout.
|
||||
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.A1.layout.ConversionPattern=[%p] %c{2} %m%n
|
||||
|
||||
# Service category names are the name of the defining module class
|
||||
# and then the service id.
|
||||
log4j.category.com.baeldung.tapestry.services.AppModule.TimingFilter=info
|
||||
|
||||
# Outputs a list of pages, components and mixins at startup.
|
||||
log4j.category.org.apache.tapestry5.modules.TapestryModule.ComponentClassResolver=info
|
||||
|
||||
# Outputs startup statistics; elapsed time to setup and initialize the registry, a list of
|
||||
# available services, and a launch banner that includes the Tapestry version number.
|
||||
log4j.category.org.apache.tapestry5.TapestryFilter=info
|
||||
|
||||
|
||||
# Turning on debug mode for a page's or component's transformer logger
|
||||
# will show all of the code changes that occur when the
|
||||
# class is loaded.
|
||||
|
||||
# log4j.category.tapestry.transformer.com.baeldung.tapestry.pages.Index=debug
|
||||
|
||||
# Turning on debug mode for a component's events logger will show all the events triggered on the
|
||||
# component, and which component methods are invoked as a result.
|
||||
|
||||
# log4j.category.tapestry.events.com.baeldung.tapestry.pages.Index=debug
|
||||
|
||||
# Turning on trace mode for a page's render logger provides extended information about every step
|
||||
# in rendering (this is not generally helpful). Turning on debug mode will add a one-line
|
||||
# summary that includes the elapsed render time, which can be useful in tracking down
|
||||
# performance issues.
|
||||
|
||||
# log4j.category.tapestry.render.com.baeldung.tapestry.pages.Index=debug
|
||||
|
||||
# Turn on some verbose debugging about everything in the application. This is nice initially,
|
||||
# while getting everything set up. You'll probably want to remove this once you are
|
||||
# up and running, replacing it with more selective debugging output.
|
||||
log4j.category.com.baeldung.tapestry=debug
|
|
@ -0,0 +1,4 @@
|
|||
# This is where global application properties go.
|
||||
# You can also have individual message catalogs for each page and each
|
||||
# component that override these defaults.
|
||||
# The name of this file is based on the <filter-name> element in web.
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
|
||||
version="2.4">
|
||||
|
||||
<display-name>apache-tapestry Tapestry 5 Application</display-name>
|
||||
<context-param>
|
||||
<!--
|
||||
The only significant configuration for Tapestry 5, this informs Tapestry
|
||||
of where to look for pages, components and mixins.
|
||||
-->
|
||||
<param-name>tapestry.app-package</param-name>
|
||||
<param-value>com.baeldung.tapestry</param-value>
|
||||
</context-param>
|
||||
|
||||
<!--
|
||||
Specify some additional Modules for two different execution
|
||||
modes: development and qa.
|
||||
Remember that the default execution mode is production
|
||||
-->
|
||||
<context-param>
|
||||
<param-name>tapestry.development-modules</param-name>
|
||||
<param-value>
|
||||
com.baeldung.tapestry.services.DevelopmentModule
|
||||
</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>tapestry.qa-modules</param-name>
|
||||
<param-value>
|
||||
com.baeldung.tapestry.services.QaModule
|
||||
</param-value>
|
||||
</context-param>
|
||||
|
||||
|
||||
<!-- Filter configuration -->
|
||||
<filter>
|
||||
<filter-name>app</filter-name>
|
||||
<filter-class>org.apache.tapestry5.TapestryFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>app</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<dispatcher>REQUEST</dispatcher>
|
||||
<dispatcher>ERROR</dispatcher>
|
||||
</filter-mapping>
|
||||
|
||||
<error-page>
|
||||
<error-code>404</error-code>
|
||||
<location>/error404</location>
|
||||
</error-page>
|
||||
|
||||
</web-app>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue