This commit is contained in:
chirag d 2019-12-02 19:48:58 +05:30
commit 7807c24d2b
4397 changed files with 45501 additions and 174295 deletions

9
.gitignore vendored
View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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());
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.algorithms.astar;
public interface GraphNode {
String getId();
}

View File

@ -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");
}
}

View File

@ -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();
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.algorithms.astar;
public interface Scorer<T extends GraphNode> {
double computeCost(T from, T to);
}

View File

@ -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;
}
}

View File

@ -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()));
}
}

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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()));
}
}

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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>

View File

@ -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;
}
}
}

View File

@ -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()
);
}
}

View File

@ -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));
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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];
}
}

View File

@ -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";
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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));
}
}

View File

@ -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)

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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;

View File

@ -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()));
}
}

View File

@ -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)

View File

@ -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>

View File

@ -1,4 +1,4 @@
package com.baeldung.string.sorting;
package com.baeldung.algorithms.stringsort;
import java.util.Arrays;

View File

@ -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 {

View File

@ -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 {

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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)

View File

@ -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>

View File

@ -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)

View File

@ -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>

147
apache-tapestry/pom.xml Normal file
View File

@ -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>

View File

@ -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;
}

View File

@ -0,0 +1,5 @@
package com.baeldung.tapestry.pages;
public class Error404 {
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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>&copy; Your Company</p>
</footer>
</div>
</body>
</html>

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1 @@
introMsg=Welcome to the Apache Tapestry Tutorial

View File

@ -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>

View File

@ -0,0 +1 @@
greeting=Welcome to Tapestry 5! We hope that this project template will get you going in style.

View File

@ -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 &raquo;</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&raquo;</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&raquo;</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>

View File

@ -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>

View File

@ -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

View File

@ -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.

View File

@ -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