[BAEL-9551] - Splitted algorithms into 4 modules
This commit is contained in:
4
algorithms-miscellaneous-2/.gitignore
vendored
Normal file
4
algorithms-miscellaneous-2/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/target/
|
||||
.settings/
|
||||
.classpath
|
||||
.project
|
||||
20
algorithms-miscellaneous-2/README.md
Normal file
20
algorithms-miscellaneous-2/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
## Relevant articles:
|
||||
|
||||
- [Dijkstra Algorithm in Java](http://www.baeldung.com/java-dijkstra)
|
||||
- [Introduction to Cobertura](http://www.baeldung.com/cobertura)
|
||||
- [Test a Linked List for Cyclicity](http://www.baeldung.com/java-linked-list-cyclicity)
|
||||
- [Introduction to JGraphT](http://www.baeldung.com/jgrapht)
|
||||
- [A Maze Solver in Java](http://www.baeldung.com/java-solve-maze)
|
||||
- [Create a Sudoku Solver in Java](http://www.baeldung.com/java-sudoku)
|
||||
- [Displaying Money Amounts in Words](http://www.baeldung.com/java-money-into-words)
|
||||
- [A Collaborative Filtering Recommendation System in Java](http://www.baeldung.com/java-collaborative-filtering-recommendations)
|
||||
- [Converting Between Roman and Arabic Numerals in Java](http://www.baeldung.com/java-convert-roman-arabic)
|
||||
- [Practical Java Examples of the Big O Notation](http://www.baeldung.com/java-algorithm-complexity)
|
||||
- [Find the Middle Element of a Linked List](http://www.baeldung.com/java-linked-list-middle-element)
|
||||
- [An Introduction to the Theory of Big-O Notation](http://www.baeldung.com/big-o-notation)
|
||||
- [Check If Two Rectangles Overlap In Java](https://www.baeldung.com/java-check-if-two-rectangles-overlap)
|
||||
- [Calculate the Distance Between Two Points in Java](https://www.baeldung.com/java-distance-between-two-points)
|
||||
- [Find the Intersection of Two Lines in Java](https://www.baeldung.com/java-intersection-of-two-lines)
|
||||
- [Round Up to the Nearest Hundred](https://www.baeldung.com/java-round-up-nearest-hundred)
|
||||
- [Calculate Percentage in Java](https://www.baeldung.com/java-calculate-percentage)
|
||||
- [Converting Between Byte Arrays and Hexadecimal Strings in Java](https://www.baeldung.com/java-byte-arrays-hex-strings)
|
||||
96
algorithms-miscellaneous-2/pom.xml
Normal file
96
algorithms-miscellaneous-2/pom.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<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>algorithms-miscellaneous-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-math3</artifactId>
|
||||
<version>${commons-math3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons-codec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jenetics</groupId>
|
||||
<artifactId>jenetics</artifactId>
|
||||
<version>${io.jenetics.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jgrapht</groupId>
|
||||
<artifactId>jgrapht-core</artifactId>
|
||||
<version>${org.jgrapht.core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>pl.allegro.finance</groupId>
|
||||
<artifactId>tradukisto</artifactId>
|
||||
<version>${tradukisto.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${org.assertj.core.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<version>2.7</version>
|
||||
<configuration>
|
||||
<instrumentation>
|
||||
<ignores>
|
||||
<ignore>com/baeldung/algorithms/dijkstra/*</ignore>
|
||||
</ignores>
|
||||
<excludes>
|
||||
<exclude>com/baeldung/algorithms/dijkstra/*</exclude>
|
||||
</excludes>
|
||||
</instrumentation>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
<properties>
|
||||
<lombok.version>1.16.12</lombok.version>
|
||||
<commons-math3.version>3.6.1</commons-math3.version>
|
||||
<tradukisto.version>1.0.1</tradukisto.version>
|
||||
<io.jenetics.version>3.7.0</io.jenetics.version>
|
||||
<org.jgrapht.core.version>1.0.1</org.jgrapht.core.version>
|
||||
<org.assertj.core.version>3.9.0</org.assertj.core.version>
|
||||
<commons-codec.version>1.11</commons-codec.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
1
algorithms-miscellaneous-2/roundUpToHundred/.gitignore
vendored
Normal file
1
algorithms-miscellaneous-2/roundUpToHundred/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/bin/
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.java.src;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
public class RoundUpToHundred {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
double input = scanner.nextDouble();
|
||||
scanner.close();
|
||||
|
||||
RoundUpToHundred.round(input);
|
||||
}
|
||||
|
||||
static long round(double input) {
|
||||
long i = (long) Math.ceil(input);
|
||||
return ((i + 99) / 100) * 100;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.java.src;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class RoundUpToHundredTest {
|
||||
@Test
|
||||
public void givenInput_whenRound_thenRoundUpToTheNearestHundred() {
|
||||
assertEquals("Rounded up to hundred", 100, RoundUpToHundred.round(99));
|
||||
assertEquals("Rounded up to three hundred ", 300, RoundUpToHundred.round(200.2));
|
||||
assertEquals("Returns same rounded value", 400, RoundUpToHundred.round(400));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.baeldung.algorithms.conversion;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
|
||||
public class HexStringConverter {
|
||||
|
||||
/**
|
||||
* Create a byte Array from String of hexadecimal digits using Character conversion
|
||||
* @param hexString - Hexadecimal digits as String
|
||||
* @return Desired byte Array
|
||||
*/
|
||||
public byte[] decodeHexString(String hexString) {
|
||||
if (hexString.length() % 2 == 1) {
|
||||
throw new IllegalArgumentException("Invalid hexadecimal String supplied.");
|
||||
}
|
||||
byte[] bytes = new byte[hexString.length() / 2];
|
||||
|
||||
for (int i = 0; i < hexString.length(); i += 2) {
|
||||
bytes[i / 2] = hexToByte(hexString.substring(i, i + 2));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a String of hexadecimal digits from a byte Array using Character conversion
|
||||
* @param byteArray - The byte Array
|
||||
* @return Desired String of hexadecimal digits in lower case
|
||||
*/
|
||||
public String encodeHexString(byte[] byteArray) {
|
||||
StringBuffer hexStringBuffer = new StringBuffer();
|
||||
for (int i = 0; i < byteArray.length; i++) {
|
||||
hexStringBuffer.append(byteToHex(byteArray[i]));
|
||||
}
|
||||
return hexStringBuffer.toString();
|
||||
}
|
||||
|
||||
public String byteToHex(byte num) {
|
||||
char[] hexDigits = new char[2];
|
||||
hexDigits[0] = Character.forDigit((num >> 4) & 0xF, 16);
|
||||
hexDigits[1] = Character.forDigit((num & 0xF), 16);
|
||||
return new String(hexDigits);
|
||||
}
|
||||
|
||||
public byte hexToByte(String hexString) {
|
||||
int firstDigit = toDigit(hexString.charAt(0));
|
||||
int secondDigit = toDigit(hexString.charAt(1));
|
||||
return (byte) ((firstDigit << 4) + secondDigit);
|
||||
}
|
||||
|
||||
private int toDigit(char hexChar) {
|
||||
int digit = Character.digit(hexChar, 16);
|
||||
if(digit == -1) {
|
||||
throw new IllegalArgumentException("Invalid Hexadecimal Character: "+ hexChar);
|
||||
}
|
||||
return digit;
|
||||
}
|
||||
|
||||
public String encodeUsingBigIntegerToString(byte[] bytes) {
|
||||
BigInteger bigInteger = new BigInteger(1, bytes);
|
||||
return bigInteger.toString(16);
|
||||
}
|
||||
|
||||
public String encodeUsingBigIntegerStringFormat(byte[] bytes) {
|
||||
BigInteger bigInteger = new BigInteger(1, bytes);
|
||||
return String.format("%0" + (bytes.length << 1) + "x", bigInteger);
|
||||
}
|
||||
|
||||
public byte[] decodeUsingBigInteger(String hexString) {
|
||||
byte[] byteArray = new BigInteger(hexString, 16).toByteArray();
|
||||
if (byteArray[0] == 0) {
|
||||
byte[] output = new byte[byteArray.length - 1];
|
||||
System.arraycopy(byteArray, 1, output, 0, output.length);
|
||||
return output;
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
public String encodeUsingDataTypeConverter(byte[] bytes) {
|
||||
return DatatypeConverter.printHexBinary(bytes);
|
||||
}
|
||||
|
||||
public byte[] decodeUsingDataTypeConverter(String hexString) {
|
||||
return DatatypeConverter.parseHexBinary(hexString);
|
||||
}
|
||||
|
||||
public String encodeUsingApacheCommons(byte[] bytes) throws DecoderException {
|
||||
return Hex.encodeHexString(bytes);
|
||||
}
|
||||
|
||||
public byte[] decodeUsingApacheCommons(String hexString) throws DecoderException {
|
||||
return Hex.decodeHex(hexString);
|
||||
}
|
||||
|
||||
public String encodeUsingGuava(byte[] bytes) {
|
||||
return BaseEncoding.base16()
|
||||
.encode(bytes);
|
||||
}
|
||||
|
||||
public byte[] decodeUsingGuava(String hexString) {
|
||||
return BaseEncoding.base16()
|
||||
.decode(hexString.toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.algorithms.distancebetweenpoints;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
public class DistanceBetweenPointsService {
|
||||
|
||||
public double calculateDistanceBetweenPoints(
|
||||
double x1,
|
||||
double y1,
|
||||
double x2,
|
||||
double y2) {
|
||||
|
||||
return Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));
|
||||
}
|
||||
|
||||
public double calculateDistanceBetweenPointsWithHypot(
|
||||
double x1,
|
||||
double y1,
|
||||
double x2,
|
||||
double y2) {
|
||||
|
||||
double ac = Math.abs(y2 - y1);
|
||||
double cb = Math.abs(x2 - x1);
|
||||
|
||||
return Math.hypot(ac, cb);
|
||||
}
|
||||
|
||||
public double calculateDistanceBetweenPointsWithPoint2D(
|
||||
double x1,
|
||||
double y1,
|
||||
double x2,
|
||||
double y2) {
|
||||
|
||||
return Point2D.distance(x1, y1, x2, y2);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.algorithms.editdistance;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class EditDistanceBase {
|
||||
|
||||
static int costOfSubstitution(char a, char b) {
|
||||
return a == b ? 0 : 1;
|
||||
}
|
||||
|
||||
static int min(int... numbers) {
|
||||
return Arrays.stream(numbers)
|
||||
.min().orElse(Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.algorithms.editdistance;
|
||||
|
||||
public class EditDistanceDynamicProgramming extends EditDistanceBase {
|
||||
|
||||
static int calculate(String x, String y) {
|
||||
int[][] dp = new int[x.length() + 1][y.length() + 1];
|
||||
|
||||
for (int i = 0; i <= x.length(); i++) {
|
||||
for (int j = 0; j <= y.length(); j++) {
|
||||
if (i == 0)
|
||||
dp[i][j] = j;
|
||||
|
||||
else if (j == 0)
|
||||
dp[i][j] = i;
|
||||
|
||||
else {
|
||||
dp[i][j] = min(dp[i - 1][j - 1]
|
||||
+ costOfSubstitution(x.charAt(i - 1), y.charAt(j - 1)),
|
||||
dp[i - 1][j] + 1, dp[i][j - 1] + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dp[x.length()][y.length()];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.algorithms.editdistance;
|
||||
|
||||
public class EditDistanceRecursive extends EditDistanceBase {
|
||||
|
||||
static int calculate(String x, String y) {
|
||||
|
||||
if (x.isEmpty()) {
|
||||
return y.length();
|
||||
}
|
||||
|
||||
if (y.isEmpty()) {
|
||||
return x.length();
|
||||
}
|
||||
|
||||
int substitution = calculate(x.substring(1), y.substring(1)) + costOfSubstitution(x.charAt(0), y.charAt(0));
|
||||
int insertion = calculate(x, y.substring(1)) + 1;
|
||||
int deletion = calculate(x.substring(1), y) + 1;
|
||||
|
||||
return min(substitution, insertion, deletion);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
public class CycleDetectionBruteForce {
|
||||
|
||||
public static <T> CycleDetectionResult<T> detectCycle(Node<T> head) {
|
||||
if (head == null) {
|
||||
return new CycleDetectionResult<>(false, null);
|
||||
}
|
||||
|
||||
Node<T> it1 = head;
|
||||
int nodesTraversedByOuter = 0;
|
||||
while (it1 != null && it1.next != null) {
|
||||
it1 = it1.next;
|
||||
nodesTraversedByOuter++;
|
||||
|
||||
int x = nodesTraversedByOuter;
|
||||
Node<T> it2 = head;
|
||||
int noOfTimesCurrentNodeVisited = 0;
|
||||
|
||||
while (x > 0) {
|
||||
it2 = it2.next;
|
||||
|
||||
if (it2 == it1) {
|
||||
noOfTimesCurrentNodeVisited++;
|
||||
}
|
||||
|
||||
if (noOfTimesCurrentNodeVisited == 2) {
|
||||
return new CycleDetectionResult<>(true, it1);
|
||||
}
|
||||
|
||||
x--;
|
||||
}
|
||||
}
|
||||
|
||||
return new CycleDetectionResult<>(false, null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
public class CycleDetectionByFastAndSlowIterators {
|
||||
|
||||
public static <T> CycleDetectionResult<T> detectCycle(Node<T> head) {
|
||||
if (head == null) {
|
||||
return new CycleDetectionResult<>(false, null);
|
||||
}
|
||||
|
||||
Node<T> slow = head;
|
||||
Node<T> fast = head;
|
||||
|
||||
while (fast != null && fast.next != null) {
|
||||
slow = slow.next;
|
||||
fast = fast.next.next;
|
||||
|
||||
if (slow == fast) {
|
||||
return new CycleDetectionResult<>(true, fast);
|
||||
}
|
||||
}
|
||||
|
||||
return new CycleDetectionResult<>(false, null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class CycleDetectionByHashing {
|
||||
|
||||
public static <T> CycleDetectionResult<T> detectCycle(Node<T> head) {
|
||||
if (head == null) {
|
||||
return new CycleDetectionResult<>(false, null);
|
||||
}
|
||||
|
||||
Set<Node<T>> set = new HashSet<>();
|
||||
Node<T> node = head;
|
||||
|
||||
while (node != null) {
|
||||
if (set.contains(node)) {
|
||||
return new CycleDetectionResult<>(true, node);
|
||||
}
|
||||
set.add(node);
|
||||
node = node.next;
|
||||
}
|
||||
|
||||
return new CycleDetectionResult<>(false, null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
public class CycleDetectionResult<T> {
|
||||
boolean cycleExists;
|
||||
Node<T> node;
|
||||
|
||||
public CycleDetectionResult(boolean cycleExists, Node<T> node) {
|
||||
super();
|
||||
this.cycleExists = cycleExists;
|
||||
this.node = node;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
public class CycleRemovalBruteForce {
|
||||
|
||||
public static <T> boolean detectAndRemoveCycle(Node<T> head) {
|
||||
CycleDetectionResult<T> result = CycleDetectionByFastAndSlowIterators.detectCycle(head);
|
||||
|
||||
if (result.cycleExists) {
|
||||
removeCycle(result.node, head);
|
||||
}
|
||||
|
||||
return result.cycleExists;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param loopNodeParam - reference to the node where Flyods cycle
|
||||
* finding algorithm ends, i.e. the fast and the slow iterators
|
||||
* meet.
|
||||
* @param head - reference to the head of the list
|
||||
*/
|
||||
private static <T> void removeCycle(Node<T> loopNodeParam, Node<T> head) {
|
||||
Node<T> it = head;
|
||||
|
||||
while (it != null) {
|
||||
if (isNodeReachableFromLoopNode(it, loopNodeParam)) {
|
||||
Node<T> loopStart = it;
|
||||
findEndNodeAndBreakCycle(loopStart);
|
||||
break;
|
||||
}
|
||||
it = it.next;
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> boolean isNodeReachableFromLoopNode(Node<T> it, Node<T> loopNodeParam) {
|
||||
Node<T> loopNode = loopNodeParam;
|
||||
|
||||
do {
|
||||
if (it == loopNode) {
|
||||
return true;
|
||||
}
|
||||
loopNode = loopNode.next;
|
||||
} while (loopNode.next != loopNodeParam);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static <T> void findEndNodeAndBreakCycle(Node<T> loopStartParam) {
|
||||
Node<T> loopStart = loopStartParam;
|
||||
|
||||
while (loopStart.next != loopStartParam) {
|
||||
loopStart = loopStart.next;
|
||||
}
|
||||
|
||||
loopStart.next = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
public class CycleRemovalByCountingLoopNodes {
|
||||
|
||||
public static <T> boolean detectAndRemoveCycle(Node<T> head) {
|
||||
CycleDetectionResult<T> result = CycleDetectionByFastAndSlowIterators.detectCycle(head);
|
||||
|
||||
if (result.cycleExists) {
|
||||
removeCycle(result.node, head);
|
||||
}
|
||||
|
||||
return result.cycleExists;
|
||||
}
|
||||
|
||||
private static <T> void removeCycle(Node<T> loopNodeParam, Node<T> head) {
|
||||
int cycleLength = calculateCycleLength(loopNodeParam);
|
||||
Node<T> cycleLengthAdvancedIterator = head;
|
||||
Node<T> it = head;
|
||||
|
||||
for (int i = 0; i < cycleLength; i++) {
|
||||
cycleLengthAdvancedIterator = cycleLengthAdvancedIterator.next;
|
||||
}
|
||||
|
||||
while (it.next != cycleLengthAdvancedIterator.next) {
|
||||
it = it.next;
|
||||
cycleLengthAdvancedIterator = cycleLengthAdvancedIterator.next;
|
||||
}
|
||||
|
||||
cycleLengthAdvancedIterator.next = null;
|
||||
}
|
||||
|
||||
private static <T> int calculateCycleLength(Node<T> loopNodeParam) {
|
||||
Node<T> loopNode = loopNodeParam;
|
||||
int length = 1;
|
||||
|
||||
while (loopNode.next != loopNodeParam) {
|
||||
length++;
|
||||
loopNode = loopNode.next;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
public class CycleRemovalWithoutCountingLoopNodes {
|
||||
|
||||
public static <T> boolean detectAndRemoveCycle(Node<T> head) {
|
||||
CycleDetectionResult<T> result = CycleDetectionByFastAndSlowIterators.detectCycle(head);
|
||||
|
||||
if (result.cycleExists) {
|
||||
removeCycle(result.node, head);
|
||||
}
|
||||
|
||||
return result.cycleExists;
|
||||
}
|
||||
|
||||
private static <T> void removeCycle(Node<T> meetingPointParam, Node<T> head) {
|
||||
Node<T> loopNode = meetingPointParam;
|
||||
Node<T> it = head;
|
||||
|
||||
while (loopNode.next != it.next) {
|
||||
it = it.next;
|
||||
loopNode = loopNode.next;
|
||||
}
|
||||
|
||||
loopNode.next = null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
public class Node<T> {
|
||||
T data;
|
||||
Node<T> next;
|
||||
|
||||
public static <T> Node<T> createNewNode(T data, Node<T> next) {
|
||||
Node<T> node = new Node<T>();
|
||||
node.data = data;
|
||||
node.next = next;
|
||||
return node;
|
||||
}
|
||||
|
||||
public static <T> void traverseList(Node<T> root) {
|
||||
if (root == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node<T> node = root;
|
||||
while (node != null) {
|
||||
System.out.println(node.data);
|
||||
node = node.next;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> Node<T> getTail(Node<T> root) {
|
||||
if (root == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Node<T> node = root;
|
||||
while (node.next != null) {
|
||||
node = node.next;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.baeldung.algorithms.maze.solver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class BFSMazeSolver {
|
||||
private static final int[][] DIRECTIONS = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
|
||||
|
||||
public List<Coordinate> solve(Maze maze) {
|
||||
LinkedList<Coordinate> nextToVisit = new LinkedList<>();
|
||||
Coordinate start = maze.getEntry();
|
||||
nextToVisit.add(start);
|
||||
|
||||
while (!nextToVisit.isEmpty()) {
|
||||
Coordinate cur = nextToVisit.remove();
|
||||
|
||||
if (!maze.isValidLocation(cur.getX(), cur.getY()) || maze.isExplored(cur.getX(), cur.getY())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (maze.isWall(cur.getX(), cur.getY())) {
|
||||
maze.setVisited(cur.getX(), cur.getY(), true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (maze.isExit(cur.getX(), cur.getY())) {
|
||||
return backtrackPath(cur);
|
||||
}
|
||||
|
||||
for (int[] direction : DIRECTIONS) {
|
||||
Coordinate coordinate = new Coordinate(cur.getX() + direction[0], cur.getY() + direction[1], cur);
|
||||
nextToVisit.add(coordinate);
|
||||
maze.setVisited(cur.getX(), cur.getY(), true);
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private List<Coordinate> backtrackPath(Coordinate cur) {
|
||||
List<Coordinate> path = new ArrayList<>();
|
||||
Coordinate iter = cur;
|
||||
|
||||
while (iter != null) {
|
||||
path.add(iter);
|
||||
iter = iter.parent;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.algorithms.maze.solver;
|
||||
|
||||
public class Coordinate {
|
||||
int x;
|
||||
int y;
|
||||
Coordinate parent;
|
||||
|
||||
public Coordinate(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.parent = null;
|
||||
}
|
||||
|
||||
public Coordinate(int x, int y, Coordinate parent) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
Coordinate getParent() {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.baeldung.algorithms.maze.solver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class DFSMazeSolver {
|
||||
private static final int[][] DIRECTIONS = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
|
||||
|
||||
public List<Coordinate> solve(Maze maze) {
|
||||
List<Coordinate> path = new ArrayList<>();
|
||||
if (explore(maze, maze.getEntry()
|
||||
.getX(),
|
||||
maze.getEntry()
|
||||
.getY(),
|
||||
path)) {
|
||||
return path;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private boolean explore(Maze maze, int row, int col, List<Coordinate> path) {
|
||||
if (!maze.isValidLocation(row, col) || maze.isWall(row, col) || maze.isExplored(row, col)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
path.add(new Coordinate(row, col));
|
||||
maze.setVisited(row, col, true);
|
||||
|
||||
if (maze.isExit(row, col)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int[] direction : DIRECTIONS) {
|
||||
Coordinate coordinate = getNextCoordinate(row, col, direction[0], direction[1]);
|
||||
if (explore(maze, coordinate.getX(), coordinate.getY(), path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
path.remove(path.size() - 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
private Coordinate getNextCoordinate(int row, int col, int i, int j) {
|
||||
return new Coordinate(row + i, col + j);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.baeldung.algorithms.maze.solver;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Maze {
|
||||
private static final int ROAD = 0;
|
||||
private static final int WALL = 1;
|
||||
private static final int START = 2;
|
||||
private static final int EXIT = 3;
|
||||
private static final int PATH = 4;
|
||||
|
||||
private int[][] maze;
|
||||
private boolean[][] visited;
|
||||
private Coordinate start;
|
||||
private Coordinate end;
|
||||
|
||||
public Maze(File maze) throws FileNotFoundException {
|
||||
String fileText = "";
|
||||
try (Scanner input = new Scanner(maze)) {
|
||||
while (input.hasNextLine()) {
|
||||
fileText += input.nextLine() + "\n";
|
||||
}
|
||||
}
|
||||
initializeMaze(fileText);
|
||||
}
|
||||
|
||||
private void initializeMaze(String text) {
|
||||
if (text == null || (text = text.trim()).length() == 0) {
|
||||
throw new IllegalArgumentException("empty lines data");
|
||||
}
|
||||
|
||||
String[] lines = text.split("[\r]?\n");
|
||||
maze = new int[lines.length][lines[0].length()];
|
||||
visited = new boolean[lines.length][lines[0].length()];
|
||||
|
||||
for (int row = 0; row < getHeight(); row++) {
|
||||
if (lines[row].length() != getWidth()) {
|
||||
throw new IllegalArgumentException("line " + (row + 1) + " wrong length (was " + lines[row].length() + " but should be " + getWidth() + ")");
|
||||
}
|
||||
|
||||
for (int col = 0; col < getWidth(); col++) {
|
||||
if (lines[row].charAt(col) == '#')
|
||||
maze[row][col] = WALL;
|
||||
else if (lines[row].charAt(col) == 'S') {
|
||||
maze[row][col] = START;
|
||||
start = new Coordinate(row, col);
|
||||
} else if (lines[row].charAt(col) == 'E') {
|
||||
maze[row][col] = EXIT;
|
||||
end = new Coordinate(row, col);
|
||||
} else
|
||||
maze[row][col] = ROAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return maze.length;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return maze[0].length;
|
||||
}
|
||||
|
||||
public Coordinate getEntry() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public Coordinate getExit() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public boolean isExit(int x, int y) {
|
||||
return x == end.getX() && y == end.getY();
|
||||
}
|
||||
|
||||
public boolean isStart(int x, int y) {
|
||||
return x == start.getX() && y == start.getY();
|
||||
}
|
||||
|
||||
public boolean isExplored(int row, int col) {
|
||||
return visited[row][col];
|
||||
}
|
||||
|
||||
public boolean isWall(int row, int col) {
|
||||
return maze[row][col] == WALL;
|
||||
}
|
||||
|
||||
public void setVisited(int row, int col, boolean value) {
|
||||
visited[row][col] = value;
|
||||
}
|
||||
|
||||
public boolean isValidLocation(int row, int col) {
|
||||
if (row < 0 || row >= getHeight() || col < 0 || col >= getWidth()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void printPath(List<Coordinate> path) {
|
||||
int[][] tempMaze = Arrays.stream(maze)
|
||||
.map(int[]::clone)
|
||||
.toArray(int[][]::new);
|
||||
for (Coordinate coordinate : path) {
|
||||
if (isStart(coordinate.getX(), coordinate.getY()) || isExit(coordinate.getX(), coordinate.getY())) {
|
||||
continue;
|
||||
}
|
||||
tempMaze[coordinate.getX()][coordinate.getY()] = PATH;
|
||||
}
|
||||
System.out.println(toString(tempMaze));
|
||||
}
|
||||
|
||||
public String toString(int[][] maze) {
|
||||
StringBuilder result = new StringBuilder(getWidth() * (getHeight() + 1));
|
||||
for (int row = 0; row < getHeight(); row++) {
|
||||
for (int col = 0; col < getWidth(); col++) {
|
||||
if (maze[row][col] == ROAD) {
|
||||
result.append(' ');
|
||||
} else if (maze[row][col] == WALL) {
|
||||
result.append('#');
|
||||
} else if (maze[row][col] == START) {
|
||||
result.append('S');
|
||||
} else if (maze[row][col] == EXIT) {
|
||||
result.append('E');
|
||||
} else {
|
||||
result.append('.');
|
||||
}
|
||||
}
|
||||
result.append('\n');
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
for (int i = 0; i < visited.length; i++)
|
||||
Arrays.fill(visited[i], false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.baeldung.algorithms.maze.solver;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
public class MazeDriver {
|
||||
public static void main(String[] args) throws Exception {
|
||||
File maze1 = new File("src/main/resources/maze/maze1.txt");
|
||||
File maze2 = new File("src/main/resources/maze/maze2.txt");
|
||||
|
||||
execute(maze1);
|
||||
execute(maze2);
|
||||
}
|
||||
|
||||
private static void execute(File file) throws Exception {
|
||||
Maze maze = new Maze(file);
|
||||
dfs(maze);
|
||||
bfs(maze);
|
||||
}
|
||||
|
||||
private static void bfs(Maze maze) {
|
||||
BFSMazeSolver bfs = new BFSMazeSolver();
|
||||
List<Coordinate> path = bfs.solve(maze);
|
||||
maze.printPath(path);
|
||||
maze.reset();
|
||||
}
|
||||
|
||||
private static void dfs(Maze maze) {
|
||||
DFSMazeSolver dfs = new DFSMazeSolver();
|
||||
List<Coordinate> path = dfs.solve(maze);
|
||||
maze.printPath(path);
|
||||
maze.reset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.baeldung.algorithms.numberwordconverter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import pl.allegro.finance.tradukisto.MoneyConverters;
|
||||
|
||||
public class NumberWordConverter {
|
||||
|
||||
public static final String INVALID_INPUT_GIVEN = "Invalid input given";
|
||||
|
||||
public static final String[] ones = { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
|
||||
|
||||
public static final String[] tens = {
|
||||
"", // 0
|
||||
"", // 1
|
||||
"twenty", // 2
|
||||
"thirty", // 3
|
||||
"forty", // 4
|
||||
"fifty", // 5
|
||||
"sixty", // 6
|
||||
"seventy", // 7
|
||||
"eighty", // 8
|
||||
"ninety" // 9
|
||||
};
|
||||
|
||||
public static String getMoneyIntoWords(String input) {
|
||||
MoneyConverters converter = MoneyConverters.ENGLISH_BANKING_MONEY_VALUE;
|
||||
return converter.asWords(new BigDecimal(input));
|
||||
}
|
||||
|
||||
public static String getMoneyIntoWords(final double money) {
|
||||
long dollar = (long) money;
|
||||
long cents = Math.round((money - dollar) * 100);
|
||||
if (money == 0D) {
|
||||
return "";
|
||||
}
|
||||
if (money < 0) {
|
||||
return INVALID_INPUT_GIVEN;
|
||||
}
|
||||
String dollarPart = "";
|
||||
if (dollar > 0) {
|
||||
dollarPart = convert(dollar) + " dollar" + (dollar == 1 ? "" : "s");
|
||||
}
|
||||
String centsPart = "";
|
||||
if (cents > 0) {
|
||||
if (dollarPart.length() > 0) {
|
||||
centsPart = " and ";
|
||||
}
|
||||
centsPart += convert(cents) + " cent" + (cents == 1 ? "" : "s");
|
||||
}
|
||||
return dollarPart + centsPart;
|
||||
}
|
||||
|
||||
private static String convert(final long n) {
|
||||
if (n < 0) {
|
||||
return INVALID_INPUT_GIVEN;
|
||||
}
|
||||
if (n < 20) {
|
||||
return ones[(int) n];
|
||||
}
|
||||
if (n < 100) {
|
||||
return tens[(int) n / 10] + ((n % 10 != 0) ? " " : "") + ones[(int) n % 10];
|
||||
}
|
||||
if (n < 1000) {
|
||||
return ones[(int) n / 100] + " hundred" + ((n % 100 != 0) ? " " : "") + convert(n % 100);
|
||||
}
|
||||
if (n < 1_000_000) {
|
||||
return convert(n / 1000) + " thousand" + ((n % 1000 != 0) ? " " : "") + convert(n % 1000);
|
||||
}
|
||||
if (n < 1_000_000_000) {
|
||||
return convert(n / 1_000_000) + " million" + ((n % 1_000_000 != 0) ? " " : "") + convert(n % 1_000_000);
|
||||
}
|
||||
return convert(n / 1_000_000_000) + " billion" + ((n % 1_000_000_000 != 0) ? " " : "") + convert(n % 1_000_000_000);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.baeldung.algorithms.rectanglesoverlap;
|
||||
|
||||
public class Point {
|
||||
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
public Point(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setY(int y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.baeldung.algorithms.rectanglesoverlap;
|
||||
|
||||
public class Rectangle {
|
||||
|
||||
private Point bottomLeft;
|
||||
private Point topRight;
|
||||
|
||||
public Rectangle(Point bottomLeft, Point topRight) {
|
||||
this.bottomLeft = bottomLeft;
|
||||
this.topRight = topRight;
|
||||
}
|
||||
|
||||
public Point getBottomLeft() {
|
||||
return bottomLeft;
|
||||
}
|
||||
|
||||
public void setBottomLeft(Point bottomLeft) {
|
||||
this.bottomLeft = bottomLeft;
|
||||
}
|
||||
|
||||
public Point getTopRight() {
|
||||
return topRight;
|
||||
}
|
||||
|
||||
public void setTopRight(Point topRight) {
|
||||
this.topRight = topRight;
|
||||
}
|
||||
|
||||
public boolean isOverlapping(Rectangle other) {
|
||||
// one rectangle is to the top of the other
|
||||
if (this.topRight.getY() < other.bottomLeft.getY() || this.bottomLeft.getY() > other.topRight.getY()) {
|
||||
return false;
|
||||
}
|
||||
// one rectangle is to the left of the other
|
||||
if (this.topRight.getX() < other.bottomLeft.getX() || this.bottomLeft.getX() > other.topRight.getX()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.baeldung.algorithms.romannumerals;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class RomanArabicConverter {
|
||||
|
||||
public static int romanToArabic(String input) {
|
||||
String romanNumeral = input.toUpperCase();
|
||||
int result = 0;
|
||||
|
||||
List<RomanNumeral> romanNumerals = RomanNumeral.getReverseSortedValues();
|
||||
|
||||
int i = 0;
|
||||
|
||||
while ((romanNumeral.length() > 0) && (i < romanNumerals.size())) {
|
||||
RomanNumeral symbol = romanNumerals.get(i);
|
||||
if (romanNumeral.startsWith(symbol.name())) {
|
||||
result += symbol.getValue();
|
||||
romanNumeral = romanNumeral.substring(symbol.name().length());
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (romanNumeral.length() > 0) {
|
||||
throw new IllegalArgumentException(input + " cannot be converted to a Roman Numeral");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String arabicToRoman(int number) {
|
||||
if ((number <= 0) || (number > 4000)) {
|
||||
throw new IllegalArgumentException(number + " is not in range (0,4000]");
|
||||
}
|
||||
|
||||
List<RomanNumeral> romanNumerals = RomanNumeral.getReverseSortedValues();
|
||||
|
||||
int i = 0;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
while (number > 0 && i < romanNumerals.size()) {
|
||||
RomanNumeral currentSymbol = romanNumerals.get(i);
|
||||
if (currentSymbol.getValue() <= number) {
|
||||
sb.append(currentSymbol.name());
|
||||
number -= currentSymbol.getValue();
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.algorithms.romannumerals;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
enum RomanNumeral {
|
||||
I(1), IV(4), V(5), IX(9), X(10), XL(40), L(50), XC(90), C(100), CD(400), D(500), CM(900), M(1000);
|
||||
|
||||
private int value;
|
||||
|
||||
RomanNumeral(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static List<RomanNumeral> getReverseSortedValues() {
|
||||
return Arrays.stream(values())
|
||||
.sorted(Comparator.comparing((RomanNumeral e) -> e.value).reversed())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.baeldung.algorithms.sudoku;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class BacktrackingAlgorithm {
|
||||
|
||||
private static final int BOARD_SIZE = 9;
|
||||
private static final int SUBSECTION_SIZE = 3;
|
||||
private static final int BOARD_START_INDEX = 0;
|
||||
|
||||
private static final int NO_VALUE = 0;
|
||||
private static final int MIN_VALUE = 1;
|
||||
private static final int MAX_VALUE = 9;
|
||||
|
||||
private static int[][] board = {
|
||||
{8, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 3, 6, 0, 0, 0, 0, 0},
|
||||
{0, 7, 0, 0, 9, 0, 2, 0, 0},
|
||||
{0, 5, 0, 0, 0, 7, 0, 0, 0},
|
||||
{0, 0, 0, 0, 4, 5, 7, 0, 0},
|
||||
{0, 0, 0, 1, 0, 0, 0, 3, 0},
|
||||
{0, 0, 1, 0, 0, 0, 0, 6, 8},
|
||||
{0, 0, 8, 5, 0, 0, 0, 1, 0},
|
||||
{0, 9, 0, 0, 0, 0, 4, 0, 0}
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
BacktrackingAlgorithm solver = new BacktrackingAlgorithm();
|
||||
solver.solve(board);
|
||||
solver.printBoard();
|
||||
}
|
||||
|
||||
private void printBoard() {
|
||||
for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) {
|
||||
for (int column = BOARD_START_INDEX; column < BOARD_SIZE; column++) {
|
||||
System.out.print(board[row][column] + " ");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean solve(int[][] board) {
|
||||
for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) {
|
||||
for (int column = BOARD_START_INDEX; column < BOARD_SIZE; column++) {
|
||||
if (board[row][column] == NO_VALUE) {
|
||||
for (int k = MIN_VALUE; k <= MAX_VALUE; k++) {
|
||||
board[row][column] = k;
|
||||
if (isValid(board, row, column) && solve(board)) {
|
||||
return true;
|
||||
}
|
||||
board[row][column] = NO_VALUE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValid(int[][] board, int row, int column) {
|
||||
return rowConstraint(board, row) &&
|
||||
columnConstraint(board, column) &&
|
||||
subsectionConstraint(board, row, column);
|
||||
}
|
||||
|
||||
private boolean subsectionConstraint(int[][] board, int row, int column) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
int subsectionRowStart = (row / SUBSECTION_SIZE) * SUBSECTION_SIZE;
|
||||
int subsectionRowEnd = subsectionRowStart + SUBSECTION_SIZE;
|
||||
|
||||
int subsectionColumnStart = (column / SUBSECTION_SIZE) * SUBSECTION_SIZE;
|
||||
int subsectionColumnEnd = subsectionColumnStart + SUBSECTION_SIZE;
|
||||
|
||||
for (int r = subsectionRowStart; r < subsectionRowEnd; r++) {
|
||||
for (int c = subsectionColumnStart; c < subsectionColumnEnd; c++) {
|
||||
if (!checkConstraint(board, r, constraint, c)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean columnConstraint(int[][] board, int column) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
return IntStream.range(BOARD_START_INDEX, BOARD_SIZE)
|
||||
.allMatch(row -> checkConstraint(board, row, constraint, column));
|
||||
}
|
||||
|
||||
private boolean rowConstraint(int[][] board, int row) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
return IntStream.range(BOARD_START_INDEX, BOARD_SIZE)
|
||||
.allMatch(column -> checkConstraint(board, row, constraint, column));
|
||||
}
|
||||
|
||||
private boolean checkConstraint(int[][] board, int row, boolean[] constraint, int column) {
|
||||
if (board[row][column] != NO_VALUE) {
|
||||
if (!constraint[board[row][column] - 1]) {
|
||||
constraint[board[row][column] - 1] = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.baeldung.algorithms.sudoku;
|
||||
|
||||
class ColumnNode extends DancingNode {
|
||||
int size;
|
||||
String name;
|
||||
|
||||
ColumnNode(String n) {
|
||||
super();
|
||||
size = 0;
|
||||
name = n;
|
||||
C = this;
|
||||
}
|
||||
|
||||
void cover() {
|
||||
unlinkLR();
|
||||
for (DancingNode i = this.D; i != this; i = i.D) {
|
||||
for (DancingNode j = i.R; j != i; j = j.R) {
|
||||
j.unlinkUD();
|
||||
j.C.size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uncover() {
|
||||
for (DancingNode i = this.U; i != this; i = i.U) {
|
||||
for (DancingNode j = i.L; j != i; j = j.L) {
|
||||
j.C.size++;
|
||||
j.relinkUD();
|
||||
}
|
||||
}
|
||||
relinkLR();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package com.baeldung.algorithms.sudoku;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class DancingLinks {
|
||||
|
||||
private ColumnNode header;
|
||||
private List<DancingNode> answer;
|
||||
|
||||
private void search(int k) {
|
||||
if (header.R == header) {
|
||||
handleSolution(answer);
|
||||
} else {
|
||||
ColumnNode c = selectColumnNodeHeuristic();
|
||||
c.cover();
|
||||
|
||||
for (DancingNode r = c.D; r != c; r = r.D) {
|
||||
answer.add(r);
|
||||
|
||||
for (DancingNode j = r.R; j != r; j = j.R) {
|
||||
j.C.cover();
|
||||
}
|
||||
|
||||
search(k + 1);
|
||||
|
||||
r = answer.remove(answer.size() - 1);
|
||||
c = r.C;
|
||||
|
||||
for (DancingNode j = r.L; j != r; j = j.L) {
|
||||
j.C.uncover();
|
||||
}
|
||||
}
|
||||
c.uncover();
|
||||
}
|
||||
}
|
||||
|
||||
private ColumnNode selectColumnNodeHeuristic() {
|
||||
int min = Integer.MAX_VALUE;
|
||||
ColumnNode ret = null;
|
||||
for (ColumnNode c = (ColumnNode) header.R; c != header; c = (ColumnNode) c.R) {
|
||||
if (c.size < min) {
|
||||
min = c.size;
|
||||
ret = c;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private ColumnNode makeDLXBoard(boolean[][] grid) {
|
||||
final int COLS = grid[0].length;
|
||||
|
||||
ColumnNode headerNode = new ColumnNode("header");
|
||||
List<ColumnNode> columnNodes = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < COLS; i++) {
|
||||
ColumnNode n = new ColumnNode(Integer.toString(i));
|
||||
columnNodes.add(n);
|
||||
headerNode = (ColumnNode) headerNode.hookRight(n);
|
||||
}
|
||||
headerNode = headerNode.R.C;
|
||||
|
||||
for (boolean[] aGrid : grid) {
|
||||
DancingNode prev = null;
|
||||
for (int j = 0; j < COLS; j++) {
|
||||
if (aGrid[j]) {
|
||||
ColumnNode col = columnNodes.get(j);
|
||||
DancingNode newNode = new DancingNode(col);
|
||||
if (prev == null)
|
||||
prev = newNode;
|
||||
col.U.hookDown(newNode);
|
||||
prev = prev.hookRight(newNode);
|
||||
col.size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
headerNode.size = COLS;
|
||||
|
||||
return headerNode;
|
||||
}
|
||||
|
||||
DancingLinks(boolean[][] cover) {
|
||||
header = makeDLXBoard(cover);
|
||||
}
|
||||
|
||||
public void runSolver() {
|
||||
answer = new LinkedList<>();
|
||||
search(0);
|
||||
}
|
||||
|
||||
private void handleSolution(List<DancingNode> answer) {
|
||||
int[][] result = parseBoard(answer);
|
||||
printSolution(result);
|
||||
}
|
||||
|
||||
private int size = 9;
|
||||
|
||||
private int[][] parseBoard(List<DancingNode> answer) {
|
||||
int[][] result = new int[size][size];
|
||||
for (DancingNode n : answer) {
|
||||
DancingNode rcNode = n;
|
||||
int min = Integer.parseInt(rcNode.C.name);
|
||||
for (DancingNode tmp = n.R; tmp != n; tmp = tmp.R) {
|
||||
int val = Integer.parseInt(tmp.C.name);
|
||||
if (val < min) {
|
||||
min = val;
|
||||
rcNode = tmp;
|
||||
}
|
||||
}
|
||||
int ans1 = Integer.parseInt(rcNode.C.name);
|
||||
int ans2 = Integer.parseInt(rcNode.R.C.name);
|
||||
int r = ans1 / size;
|
||||
int c = ans1 % size;
|
||||
int num = (ans2 % size) + 1;
|
||||
result[r][c] = num;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void printSolution(int[][] result) {
|
||||
int size = result.length;
|
||||
for (int[] aResult : result) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
for (int j = 0; j < size; j++) {
|
||||
ret.append(aResult[j]).append(" ");
|
||||
}
|
||||
System.out.println(ret);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.baeldung.algorithms.sudoku;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class DancingLinksAlgorithm {
|
||||
private static final int BOARD_SIZE = 9;
|
||||
private static final int SUBSECTION_SIZE = 3;
|
||||
private static final int NO_VALUE = 0;
|
||||
private static final int CONSTRAINTS = 4;
|
||||
private static final int MIN_VALUE = 1;
|
||||
private static final int MAX_VALUE = 9;
|
||||
private static final int COVER_START_INDEX = 1;
|
||||
|
||||
private static int[][] board = {
|
||||
{8, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 3, 6, 0, 0, 0, 0, 0},
|
||||
{0, 7, 0, 0, 9, 0, 2, 0, 0},
|
||||
{0, 5, 0, 0, 0, 7, 0, 0, 0},
|
||||
{0, 0, 0, 0, 4, 5, 7, 0, 0},
|
||||
{0, 0, 0, 1, 0, 0, 0, 3, 0},
|
||||
{0, 0, 1, 0, 0, 0, 0, 6, 8},
|
||||
{0, 0, 8, 5, 0, 0, 0, 1, 0},
|
||||
{0, 9, 0, 0, 0, 0, 4, 0, 0}
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
DancingLinksAlgorithm solver = new DancingLinksAlgorithm();
|
||||
solver.solve(board);
|
||||
}
|
||||
|
||||
private void solve(int[][] board) {
|
||||
boolean[][] cover = initializeExactCoverBoard(board);
|
||||
DancingLinks dlx = new DancingLinks(cover);
|
||||
dlx.runSolver();
|
||||
}
|
||||
|
||||
private int getIndex(int row, int column, int num) {
|
||||
return (row - 1) * BOARD_SIZE * BOARD_SIZE + (column - 1) * BOARD_SIZE + (num - 1);
|
||||
}
|
||||
|
||||
private boolean[][] createExactCoverBoard() {
|
||||
boolean[][] coverBoard = new boolean[BOARD_SIZE * BOARD_SIZE * MAX_VALUE][BOARD_SIZE * BOARD_SIZE * CONSTRAINTS];
|
||||
|
||||
int hBase = 0;
|
||||
hBase = checkCellConstraint(coverBoard, hBase);
|
||||
hBase = checkRowConstraint(coverBoard, hBase);
|
||||
hBase = checkColumnConstraint(coverBoard, hBase);
|
||||
checkSubsectionConstraint(coverBoard, hBase);
|
||||
|
||||
return coverBoard;
|
||||
}
|
||||
|
||||
private int checkSubsectionConstraint(boolean[][] coverBoard, int hBase) {
|
||||
for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row += SUBSECTION_SIZE) {
|
||||
for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column += SUBSECTION_SIZE) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
|
||||
for (int rowDelta = 0; rowDelta < SUBSECTION_SIZE; rowDelta++) {
|
||||
for (int columnDelta = 0; columnDelta < SUBSECTION_SIZE; columnDelta++) {
|
||||
int index = getIndex(row + rowDelta, column + columnDelta, n);
|
||||
coverBoard[index][hBase] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hBase;
|
||||
}
|
||||
|
||||
private int checkColumnConstraint(boolean[][] coverBoard, int hBase) {
|
||||
for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
|
||||
for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
|
||||
int index = getIndex(row, column, n);
|
||||
coverBoard[index][hBase] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hBase;
|
||||
}
|
||||
|
||||
private int checkRowConstraint(boolean[][] coverBoard, int hBase) {
|
||||
for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
|
||||
for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++) {
|
||||
int index = getIndex(row, column, n);
|
||||
coverBoard[index][hBase] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hBase;
|
||||
}
|
||||
|
||||
private int checkCellConstraint(boolean[][] coverBoard, int hBase) {
|
||||
for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
|
||||
for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++, hBase++) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++) {
|
||||
int index = getIndex(row, column, n);
|
||||
coverBoard[index][hBase] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hBase;
|
||||
}
|
||||
|
||||
private boolean[][] initializeExactCoverBoard(int[][] board) {
|
||||
boolean[][] coverBoard = createExactCoverBoard();
|
||||
for (int row = COVER_START_INDEX; row <= BOARD_SIZE; row++) {
|
||||
for (int column = COVER_START_INDEX; column <= BOARD_SIZE; column++) {
|
||||
int n = board[row - 1][column - 1];
|
||||
if (n != NO_VALUE) {
|
||||
for (int num = MIN_VALUE; num <= MAX_VALUE; num++) {
|
||||
if (num != n) {
|
||||
Arrays.fill(coverBoard[getIndex(row, column, num)], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return coverBoard;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.baeldung.algorithms.sudoku;
|
||||
|
||||
class DancingNode {
|
||||
DancingNode L, R, U, D;
|
||||
ColumnNode C;
|
||||
|
||||
DancingNode hookDown(DancingNode node) {
|
||||
assert (this.C == node.C);
|
||||
node.D = this.D;
|
||||
node.D.U = node;
|
||||
node.U = this;
|
||||
this.D = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
DancingNode hookRight(DancingNode node) {
|
||||
node.R = this.R;
|
||||
node.R.L = node;
|
||||
node.L = this;
|
||||
this.R = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
void unlinkLR() {
|
||||
this.L.R = this.R;
|
||||
this.R.L = this.L;
|
||||
}
|
||||
|
||||
void relinkLR() {
|
||||
this.L.R = this.R.L = this;
|
||||
}
|
||||
|
||||
void unlinkUD() {
|
||||
this.U.D = this.D;
|
||||
this.D.U = this.U;
|
||||
}
|
||||
|
||||
void relinkUD() {
|
||||
this.U.D = this.D.U = this;
|
||||
}
|
||||
|
||||
DancingNode() {
|
||||
L = R = U = D = this;
|
||||
}
|
||||
|
||||
DancingNode(ColumnNode c) {
|
||||
this();
|
||||
C = c;
|
||||
}
|
||||
}
|
||||
13
algorithms-miscellaneous-2/src/main/resources/logback.xml
Normal file
13
algorithms-miscellaneous-2/src/main/resources/logback.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
12
algorithms-miscellaneous-2/src/main/resources/maze/maze1.txt
Normal file
12
algorithms-miscellaneous-2/src/main/resources/maze/maze1.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
S ########
|
||||
# #
|
||||
# ### ## #
|
||||
# # # #
|
||||
# # # # #
|
||||
# ## #####
|
||||
# # #
|
||||
# # # # #
|
||||
##### ####
|
||||
# # E
|
||||
# # # #
|
||||
##########
|
||||
22
algorithms-miscellaneous-2/src/main/resources/maze/maze2.txt
Normal file
22
algorithms-miscellaneous-2/src/main/resources/maze/maze2.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
S ##########################
|
||||
# # # #
|
||||
# # #### ############### #
|
||||
# # # # # #
|
||||
# # #### # # ###############
|
||||
# # # # # # #
|
||||
# # # #### ### ########### #
|
||||
# # # # # #
|
||||
# ################## #
|
||||
######### # # # # #
|
||||
# # #### # ####### # #
|
||||
# # ### ### # # # # #
|
||||
# # ## # ##### # #
|
||||
##### ####### # # # # #
|
||||
# # ## ## #### # #
|
||||
# ##### ####### # #
|
||||
# # ############
|
||||
####### ######### # #
|
||||
# # ######## #
|
||||
# ####### ###### ## # E
|
||||
# # # ## #
|
||||
############################
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.baeldung.algorithms.analysis;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class AnalysisRunnerLiveTest {
|
||||
|
||||
int n = 10;
|
||||
int total = 0;
|
||||
|
||||
@Test
|
||||
public void whenConstantComplexity_thenConstantRuntime() {
|
||||
|
||||
System.out.println("**** n = " + n + " ****");
|
||||
System.out.println();
|
||||
|
||||
// Constant Time
|
||||
System.out.println("**** Constant time ****");
|
||||
|
||||
System.out.println("Hey - your input is: " + n);
|
||||
System.out.println("Running time not dependent on input size!");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenLogarithmicComplexity_thenLogarithmicRuntime() {
|
||||
// Logarithmic Time
|
||||
System.out.println("**** Logarithmic Time ****");
|
||||
for (int i = 1; i < n; i = i * 2) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i);
|
||||
total++;
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenLinearComplexity_thenLinearRuntime() {
|
||||
// Linear Time
|
||||
System.out.println("**** Linear Time ****");
|
||||
for (int i = 0; i < n; i++) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i);
|
||||
total++;
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNLogNComplexity_thenNLogNRuntime() {
|
||||
// N Log N Time
|
||||
System.out.println("**** nlogn Time ****");
|
||||
total = 0;
|
||||
for (
|
||||
|
||||
int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j < n; j = j * 2) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i + " and " + j);
|
||||
total++;
|
||||
}
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenQuadraticComplexity_thenQuadraticRuntime() {
|
||||
// Quadratic Time
|
||||
System.out.println("**** Quadratic Time ****");
|
||||
total = 0;
|
||||
for (
|
||||
|
||||
int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j <= n; j++) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i + " and " + j);
|
||||
total++;
|
||||
}
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCubicComplexity_thenCubicRuntime() {
|
||||
// Cubic Time
|
||||
System.out.println("**** Cubic Time ****");
|
||||
total = 0;
|
||||
for (
|
||||
|
||||
int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j <= n; j++) {
|
||||
for (int k = 1; k <= n; k++) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i + " and " + j + " and " + k);
|
||||
total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenExponentialComplexity_thenExponentialRuntime() {
|
||||
// Exponential Time
|
||||
System.out.println("**** Exponential Time ****");
|
||||
total = 0;
|
||||
for (
|
||||
|
||||
int i = 1; i <= Math.pow(2, n); i++) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i);
|
||||
total++;
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenFactorialComplexity_thenFactorialRuntime() {
|
||||
// Factorial Time
|
||||
System.out.println("**** Factorial Time ****");
|
||||
total = 0;
|
||||
for (
|
||||
|
||||
int i = 1; i <=
|
||||
|
||||
factorial(n); i++) {
|
||||
// System.out.println("Hey - I'm busy looking at: " + i);
|
||||
total++;
|
||||
}
|
||||
System.out.println("Total amount of times run: " + total);
|
||||
}
|
||||
|
||||
static int factorial(int n) {
|
||||
if (n == 0 || n == 1)
|
||||
return 1;
|
||||
else
|
||||
return n * factorial(n - 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package com.baeldung.algorithms.conversion;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.hamcrest.text.IsEqualIgnoringCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.algorithms.conversion.HexStringConverter;
|
||||
|
||||
public class ByteArrayConverterUnitTest {
|
||||
|
||||
private HexStringConverter hexStringConverter;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
hexStringConverter = new HexStringConverter();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncodeByteArrayToHexStringUsingBigIntegerToString() {
|
||||
byte[] bytes = getSampleBytes();
|
||||
String hexString = getSampleHexString();
|
||||
if(hexString.charAt(0) == '0') {
|
||||
hexString = hexString.substring(1);
|
||||
}
|
||||
String output = hexStringConverter.encodeUsingBigIntegerToString(bytes);
|
||||
assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncodeByteArrayToHexStringUsingBigIntegerStringFormat() {
|
||||
byte[] bytes = getSampleBytes();
|
||||
String hexString = getSampleHexString();
|
||||
String output = hexStringConverter.encodeUsingBigIntegerStringFormat(bytes);
|
||||
assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDecodeHexStringToByteArrayUsingBigInteger() {
|
||||
byte[] bytes = getSampleBytes();
|
||||
String hexString = getSampleHexString();
|
||||
byte[] output = hexStringConverter.decodeUsingBigInteger(hexString);
|
||||
assertArrayEquals(bytes, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncodeByteArrayToHexStringUsingCharacterConversion() {
|
||||
byte[] bytes = getSampleBytes();
|
||||
String hexString = getSampleHexString();
|
||||
String output = hexStringConverter.encodeHexString(bytes);
|
||||
assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDecodeHexStringToByteArrayUsingCharacterConversion() {
|
||||
byte[] bytes = getSampleBytes();
|
||||
String hexString = getSampleHexString();
|
||||
byte[] output = hexStringConverter.decodeHexString(hexString);
|
||||
assertArrayEquals(bytes, output);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void shouldDecodeHexToByteWithInvalidHexCharacter() {
|
||||
hexStringConverter.hexToByte("fg");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncodeByteArrayToHexStringDataTypeConverter() {
|
||||
byte[] bytes = getSampleBytes();
|
||||
String hexString = getSampleHexString();
|
||||
String output = hexStringConverter.encodeUsingDataTypeConverter(bytes);
|
||||
assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDecodeHexStringToByteArrayUsingDataTypeConverter() {
|
||||
byte[] bytes = getSampleBytes();
|
||||
String hexString = getSampleHexString();
|
||||
byte[] output = hexStringConverter.decodeUsingDataTypeConverter(hexString);
|
||||
assertArrayEquals(bytes, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncodeByteArrayToHexStringUsingGuava() {
|
||||
byte[] bytes = getSampleBytes();
|
||||
String hexString = getSampleHexString();
|
||||
String output = hexStringConverter.encodeUsingGuava(bytes);
|
||||
assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDecodeHexStringToByteArrayUsingGuava() {
|
||||
byte[] bytes = getSampleBytes();
|
||||
String hexString = getSampleHexString();
|
||||
byte[] output = hexStringConverter.decodeUsingGuava(hexString);
|
||||
assertArrayEquals(bytes, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncodeByteArrayToHexStringUsingApacheCommons() throws DecoderException {
|
||||
byte[] bytes = getSampleBytes();
|
||||
String hexString = getSampleHexString();
|
||||
String output = hexStringConverter.encodeUsingApacheCommons(bytes);
|
||||
assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDecodeHexStringToByteArrayUsingApacheCommons() throws DecoderException {
|
||||
byte[] bytes = getSampleBytes();
|
||||
String hexString = getSampleHexString();
|
||||
byte[] output = hexStringConverter.decodeUsingApacheCommons(hexString);
|
||||
assertArrayEquals(bytes, output);
|
||||
}
|
||||
|
||||
private String getSampleHexString() {
|
||||
return "0af50c0e2d10";
|
||||
}
|
||||
|
||||
private byte[] getSampleBytes() {
|
||||
return new byte[] { 10, -11, 12, 14, 45, 16 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.baeldung.algorithms.distancebetweenpoints;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.algorithms.distancebetweenpoints.DistanceBetweenPointsService;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class DistanceBetweenPointsServiceUnitTest {
|
||||
|
||||
private DistanceBetweenPointsService service = new DistanceBetweenPointsService();
|
||||
|
||||
@Test
|
||||
public void givenTwoPoints_whenCalculateDistanceByFormula_thenCorrect() {
|
||||
|
||||
double x1 = 3;
|
||||
double y1 = 4;
|
||||
double x2 = 7;
|
||||
double y2 = 1;
|
||||
|
||||
double distance = service.calculateDistanceBetweenPoints(x1, y1, x2, y2);
|
||||
|
||||
assertEquals(distance, 5, 0.001);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTwoPoints_whenCalculateDistanceWithHypot_thenCorrect() {
|
||||
|
||||
double x1 = 3;
|
||||
double y1 = 4;
|
||||
double x2 = 7;
|
||||
double y2 = 1;
|
||||
|
||||
double distance = service.calculateDistanceBetweenPointsWithHypot(x1, y1, x2, y2);
|
||||
|
||||
assertEquals(distance, 5, 0.001);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTwoPoints_whenCalculateDistanceWithPoint2D_thenCorrect() {
|
||||
|
||||
double x1 = 3;
|
||||
double y1 = 4;
|
||||
double x2 = 7;
|
||||
double y2 = 1;
|
||||
|
||||
double distance = service.calculateDistanceBetweenPointsWithPoint2D(x1, y1, x2, y2);
|
||||
|
||||
assertEquals(distance, 5, 0.001);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.algorithms.editdistance;
|
||||
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
public class EditDistanceDataProvider {
|
||||
|
||||
@Parameters
|
||||
public static Collection<Object[]> getLists() {
|
||||
return Arrays.asList(new Object[][] {
|
||||
{ "", "", 0 },
|
||||
{ "ago", "", 3 },
|
||||
{ "", "do", 2 },
|
||||
{ "abc", "adc", 1 },
|
||||
{ "peek", "pesek", 1 },
|
||||
{ "sunday", "saturday", 3 }
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.baeldung.algorithms.editdistance;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class EditDistanceUnitTest extends EditDistanceDataProvider {
|
||||
|
||||
private String x;
|
||||
private String y;
|
||||
private int result;
|
||||
|
||||
public EditDistanceUnitTest(String a, String b, int res) {
|
||||
super();
|
||||
x = a;
|
||||
y = b;
|
||||
result = res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditDistance_RecursiveImplementation() {
|
||||
assertEquals(result, EditDistanceRecursive.calculate(x, y));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditDistance_givenDynamicProgrammingImplementation() {
|
||||
assertEquals(result, EditDistanceDynamicProgramming.calculate(x, y));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(value = Parameterized.class)
|
||||
public class CycleDetectionBruteForceUnitTest extends CycleDetectionTestBase {
|
||||
boolean cycleExists;
|
||||
Node<Integer> head;
|
||||
|
||||
public CycleDetectionBruteForceUnitTest(Node<Integer> head, boolean cycleExists) {
|
||||
super();
|
||||
this.cycleExists = cycleExists;
|
||||
this.head = head;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenList_detectLoop() {
|
||||
Assert.assertEquals(cycleExists, CycleDetectionBruteForce.detectCycle(head).cycleExists);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(value = Parameterized.class)
|
||||
public class CycleDetectionByFastAndSlowIteratorsUnitTest extends CycleDetectionTestBase {
|
||||
boolean cycleExists;
|
||||
Node<Integer> head;
|
||||
|
||||
public CycleDetectionByFastAndSlowIteratorsUnitTest(Node<Integer> head, boolean cycleExists) {
|
||||
super();
|
||||
this.cycleExists = cycleExists;
|
||||
this.head = head;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenList_detectLoop() {
|
||||
Assert.assertEquals(cycleExists, CycleDetectionByFastAndSlowIterators.detectCycle(head).cycleExists);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(value = Parameterized.class)
|
||||
public class CycleDetectionByHashingUnitTest extends CycleDetectionTestBase {
|
||||
boolean cycleExists;
|
||||
Node<Integer> head;
|
||||
|
||||
public CycleDetectionByHashingUnitTest(Node<Integer> head, boolean cycleExists) {
|
||||
super();
|
||||
this.cycleExists = cycleExists;
|
||||
this.head = head;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenList_detectLoop() {
|
||||
Assert.assertEquals(cycleExists, CycleDetectionByHashing.detectCycle(head).cycleExists);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
public class CycleDetectionTestBase {
|
||||
|
||||
@Parameters
|
||||
public static Collection<Object[]> getLists() {
|
||||
return Arrays.asList(new Object[][] {
|
||||
{ createList(), false },
|
||||
{ createListWithLoop(), true },
|
||||
{ createListWithFullCycle(), true },
|
||||
{ createListWithSingleNodeInCycle(), true }
|
||||
});
|
||||
}
|
||||
|
||||
public static Node<Integer> createList() {
|
||||
Node<Integer> root = Node.createNewNode(10, null);
|
||||
|
||||
for (int i = 9; i >= 1; --i) {
|
||||
Node<Integer> current = Node.createNewNode(i, root);
|
||||
root = current;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public static Node<Integer> createListWithLoop() {
|
||||
Node<Integer> node = createList();
|
||||
createLoop(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
public static Node<Integer> createListWithFullCycle() {
|
||||
Node<Integer> head = createList();
|
||||
Node<Integer> tail = Node.getTail(head);
|
||||
tail.next = head;
|
||||
return head;
|
||||
}
|
||||
|
||||
public static Node<Integer> createListWithSingleNodeInCycle() {
|
||||
Node<Integer> head = createList();
|
||||
Node<Integer> tail = Node.getTail(head);
|
||||
tail.next = tail;
|
||||
return head;
|
||||
}
|
||||
|
||||
public static void createLoop(Node<Integer> root) {
|
||||
Node<Integer> tail = Node.getTail(root);
|
||||
|
||||
Node<Integer> middle = root;
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
middle = middle.next;
|
||||
}
|
||||
|
||||
tail.next = middle;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(value = Parameterized.class)
|
||||
public class CycleRemovalBruteForceUnitTest extends CycleDetectionTestBase {
|
||||
boolean cycleExists;
|
||||
Node<Integer> head;
|
||||
|
||||
public CycleRemovalBruteForceUnitTest(Node<Integer> head, boolean cycleExists) {
|
||||
super();
|
||||
this.cycleExists = cycleExists;
|
||||
this.head = head;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenList_ifLoopExists_thenDetectAndRemoveLoop() {
|
||||
Assert.assertEquals(cycleExists, CycleRemovalBruteForce.detectAndRemoveCycle(head));
|
||||
Assert.assertFalse(CycleDetectionByFastAndSlowIterators.detectCycle(head).cycleExists);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(value = Parameterized.class)
|
||||
public class CycleRemovalByCountingLoopNodesUnitTest extends CycleDetectionTestBase {
|
||||
boolean cycleExists;
|
||||
Node<Integer> head;
|
||||
|
||||
public CycleRemovalByCountingLoopNodesUnitTest(Node<Integer> head, boolean cycleExists) {
|
||||
super();
|
||||
this.cycleExists = cycleExists;
|
||||
this.head = head;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenList_ifLoopExists_thenDetectAndRemoveLoop() {
|
||||
Assert.assertEquals(cycleExists, CycleRemovalByCountingLoopNodes.detectAndRemoveCycle(head));
|
||||
Assert.assertFalse(CycleDetectionByFastAndSlowIterators.detectCycle(head).cycleExists);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.algorithms.linkedlist;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(value = Parameterized.class)
|
||||
public class CycleRemovalWithoutCountingLoopNodesUnitTest extends CycleDetectionTestBase {
|
||||
boolean cycleExists;
|
||||
Node<Integer> head;
|
||||
|
||||
public CycleRemovalWithoutCountingLoopNodesUnitTest(Node<Integer> head, boolean cycleExists) {
|
||||
super();
|
||||
this.cycleExists = cycleExists;
|
||||
this.head = head;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenList_ifLoopExists_thenDetectAndRemoveLoop() {
|
||||
Assert.assertEquals(cycleExists, CycleRemovalWithoutCountingLoopNodes.detectAndRemoveCycle(head));
|
||||
Assert.assertFalse(CycleDetectionByFastAndSlowIterators.detectCycle(head).cycleExists);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.baeldung.algorithms.moneywords;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.algorithms.numberwordconverter.NumberWordConverter;
|
||||
|
||||
public class NumberWordConverterUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenMoneyNegative_thenReturnInvalidInput() {
|
||||
assertEquals(NumberWordConverter.INVALID_INPUT_GIVEN, NumberWordConverter.getMoneyIntoWords(-13));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenZeroDollarsGiven_thenReturnEmptyString() {
|
||||
assertEquals("", NumberWordConverter.getMoneyIntoWords(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOnlyDollarsGiven_thenReturnWords() {
|
||||
assertEquals("one dollar", NumberWordConverter.getMoneyIntoWords(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOnlyCentsGiven_thenReturnWords() {
|
||||
assertEquals("sixty cents", NumberWordConverter.getMoneyIntoWords(0.6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAlmostAMillioDollarsGiven_thenReturnWords() {
|
||||
String expectedResult = "nine hundred ninety nine thousand nine hundred ninety nine dollars";
|
||||
assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(999_999));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenThirtyMillionDollarsGiven_thenReturnWords() {
|
||||
String expectedResult = "thirty three million three hundred forty eight thousand nine hundred seventy eight dollars";
|
||||
assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(33_348_978));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenTwoBillionDollarsGiven_thenReturnWords() {
|
||||
String expectedResult = "two billion one hundred thirty three million two hundred forty seven thousand eight hundred ten dollars";
|
||||
assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(2_133_247_810));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGivenDollarsAndCents_thenReturnWords() {
|
||||
String expectedResult = "nine hundred twenty four dollars and sixty cents";
|
||||
assertEquals(expectedResult, NumberWordConverter.getMoneyIntoWords(924.6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenOneDollarAndNoCents_thenReturnDollarSingular() {
|
||||
assertEquals("one dollar", NumberWordConverter.getMoneyIntoWords(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNoDollarsAndOneCent_thenReturnCentSingular() {
|
||||
assertEquals("one cent", NumberWordConverter.getMoneyIntoWords(0.01));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNoDollarsAndTwoCents_thenReturnCentsPlural() {
|
||||
assertEquals("two cents", NumberWordConverter.getMoneyIntoWords(0.02));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNoDollarsAndNinetyNineCents_thenReturnWords() {
|
||||
assertEquals("ninety nine cents", NumberWordConverter.getMoneyIntoWords(0.99));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNoDollarsAndNineFiveNineCents_thenCorrectRounding() {
|
||||
assertEquals("ninety six cents", NumberWordConverter.getMoneyIntoWords(0.959));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGivenDollarsAndCents_thenReturnWordsVersionTwo() {
|
||||
assertEquals("three hundred ten £ 00/100", NumberWordConverter.getMoneyIntoWords("310"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.algorithms.rectanglesoverlap;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.algorithms.rectanglesoverlap.Point;
|
||||
import com.baeldung.algorithms.rectanglesoverlap.Rectangle;
|
||||
|
||||
public class RectangleUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenTwoOverlappingRectangles_whenisOverlappingCalled_shouldReturnTrue() {
|
||||
Rectangle rectangle1 = new Rectangle(new Point(2, 1), new Point(4, 3));
|
||||
Rectangle rectangle2 = new Rectangle(new Point(1, 1), new Point(6, 4));
|
||||
assertTrue(rectangle1.isOverlapping(rectangle2));
|
||||
|
||||
rectangle1 = new Rectangle(new Point(-5, -2), new Point(2, 3));
|
||||
rectangle2 = new Rectangle(new Point(-2, -1), new Point(5, 2));
|
||||
assertTrue(rectangle1.isOverlapping(rectangle2));
|
||||
|
||||
rectangle1 = new Rectangle(new Point(-5, 1), new Point(2, 4));
|
||||
rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, 5));
|
||||
assertTrue(rectangle1.isOverlapping(rectangle2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTwoNonOverlappingRectangles_whenisOverlappingCalled_shouldReturnFalse() {
|
||||
Rectangle rectangle1 = new Rectangle(new Point(-5, 1), new Point(-3, 4));
|
||||
Rectangle rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, 5));
|
||||
assertFalse(rectangle1.isOverlapping(rectangle2));
|
||||
|
||||
rectangle1 = new Rectangle(new Point(-5, 1), new Point(3, 4));
|
||||
rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, -1));
|
||||
assertFalse(rectangle1.isOverlapping(rectangle2));
|
||||
|
||||
rectangle1 = new Rectangle(new Point(-2, 1), new Point(0, 3));
|
||||
rectangle2 = new Rectangle(new Point(3, 1), new Point(5, 4));
|
||||
assertFalse(rectangle1.isOverlapping(rectangle2));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.baeldung.algorithms.romannumerals;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class RomanArabicConverterUnitTest {
|
||||
|
||||
@Test
|
||||
public void given2018Roman_WhenConvertingToArabic_ThenReturn2018() {
|
||||
|
||||
String roman2018 = "MMXVIII";
|
||||
|
||||
int result = RomanArabicConverter.romanToArabic(roman2018);
|
||||
|
||||
assertThat(result).isEqualTo(2018);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void given1999Arabic_WhenConvertingToRoman_ThenReturnMCMXCIX() {
|
||||
|
||||
int arabic1999 = 1999;
|
||||
|
||||
String result = RomanArabicConverter.arabicToRoman(arabic1999);
|
||||
|
||||
assertThat(result).isEqualTo("MCMXCIX");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.baeldung.jgrapht;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jgrapht.VertexFactory;
|
||||
import org.jgrapht.alg.HamiltonianCycle;
|
||||
import org.jgrapht.generate.CompleteGraphGenerator;
|
||||
import org.jgrapht.graph.DefaultEdge;
|
||||
import org.jgrapht.graph.SimpleWeightedGraph;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CompleteGraphUnitTest {
|
||||
|
||||
static SimpleWeightedGraph<String, DefaultEdge> completeGraph;
|
||||
static int size = 10;
|
||||
|
||||
@Before
|
||||
public void createCompleteGraph() {
|
||||
completeGraph = new SimpleWeightedGraph<>(DefaultEdge.class);
|
||||
CompleteGraphGenerator<String, DefaultEdge> completeGenerator = new CompleteGraphGenerator<String, DefaultEdge>(size);
|
||||
VertexFactory<String> vFactory = new VertexFactory<String>() {
|
||||
private int id = 0;
|
||||
public String createVertex() {
|
||||
return "v" + id++;
|
||||
}
|
||||
};
|
||||
completeGenerator.generateGraph(completeGraph, vFactory, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCompleteGraph_whenGetHamiltonianCyclePath_thenGetVerticeListInSequence() {
|
||||
List<String> verticeList = HamiltonianCycle.getApproximateOptimalForCompleteGraph(completeGraph);
|
||||
assertEquals(verticeList.size(), completeGraph.vertexSet().size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.baeldung.jgrapht;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.jgrapht.DirectedGraph;
|
||||
import org.jgrapht.GraphPath;
|
||||
import org.jgrapht.alg.CycleDetector;
|
||||
import org.jgrapht.alg.KosarajuStrongConnectivityInspector;
|
||||
import org.jgrapht.alg.interfaces.StrongConnectivityAlgorithm;
|
||||
import org.jgrapht.alg.shortestpath.AllDirectedPaths;
|
||||
import org.jgrapht.alg.shortestpath.BellmanFordShortestPath;
|
||||
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
|
||||
import org.jgrapht.graph.DefaultDirectedGraph;
|
||||
import org.jgrapht.graph.DefaultEdge;
|
||||
import org.jgrapht.graph.DirectedSubgraph;
|
||||
import org.jgrapht.traverse.BreadthFirstIterator;
|
||||
import org.jgrapht.traverse.DepthFirstIterator;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DirectedGraphUnitTest {
|
||||
DirectedGraph<String, DefaultEdge> directedGraph;
|
||||
|
||||
@Before
|
||||
public void createDirectedGraph() {
|
||||
directedGraph = new DefaultDirectedGraph<String, DefaultEdge>(DefaultEdge.class);
|
||||
IntStream.range(1, 10).forEach(i -> {
|
||||
directedGraph.addVertex("v" + i);
|
||||
});
|
||||
directedGraph.addEdge("v1", "v2");
|
||||
directedGraph.addEdge("v2", "v4");
|
||||
directedGraph.addEdge("v4", "v3");
|
||||
directedGraph.addEdge("v3", "v1");
|
||||
directedGraph.addEdge("v5", "v4");
|
||||
directedGraph.addEdge("v5", "v6");
|
||||
directedGraph.addEdge("v6", "v7");
|
||||
directedGraph.addEdge("v7", "v5");
|
||||
directedGraph.addEdge("v8", "v5");
|
||||
directedGraph.addEdge("v9", "v8");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDirectedGraph_whenGetStronglyConnectedSubgraphs_thenPathExistsBetweenStronglyconnectedVertices() {
|
||||
StrongConnectivityAlgorithm<String, DefaultEdge> scAlg = new KosarajuStrongConnectivityInspector<>(directedGraph);
|
||||
List<DirectedSubgraph<String, DefaultEdge>> stronglyConnectedSubgraphs = scAlg.stronglyConnectedSubgraphs();
|
||||
List<String> stronglyConnectedVertices = new ArrayList<>(stronglyConnectedSubgraphs.get(3).vertexSet());
|
||||
|
||||
String randomVertex1 = stronglyConnectedVertices.get(0);
|
||||
String randomVertex2 = stronglyConnectedVertices.get(3);
|
||||
AllDirectedPaths<String, DefaultEdge> allDirectedPaths = new AllDirectedPaths<>(directedGraph);
|
||||
|
||||
List<GraphPath<String, DefaultEdge>> possiblePathList = allDirectedPaths.getAllPaths(randomVertex1, randomVertex2, false, stronglyConnectedVertices.size());
|
||||
assertTrue(possiblePathList.size() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDirectedGraphWithCycle_whenCheckCycles_thenDetectCycles() {
|
||||
CycleDetector<String, DefaultEdge> cycleDetector = new CycleDetector<String, DefaultEdge>(directedGraph);
|
||||
assertTrue(cycleDetector.detectCycles());
|
||||
Set<String> cycleVertices = cycleDetector.findCycles();
|
||||
assertTrue(cycleVertices.size() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDirectedGraph_whenCreateInstanceDepthFirstIterator_thenGetIterator() {
|
||||
DepthFirstIterator depthFirstIterator = new DepthFirstIterator<>(directedGraph);
|
||||
assertNotNull(depthFirstIterator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDirectedGraph_whenCreateInstanceBreadthFirstIterator_thenGetIterator() {
|
||||
BreadthFirstIterator breadthFirstIterator = new BreadthFirstIterator<>(directedGraph);
|
||||
assertNotNull(breadthFirstIterator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDirectedGraph_whenGetDijkstraShortestPath_thenGetNotNullPath() {
|
||||
DijkstraShortestPath dijkstraShortestPath = new DijkstraShortestPath(directedGraph);
|
||||
List<String> shortestPath = dijkstraShortestPath.getPath("v1", "v4").getVertexList();
|
||||
assertNotNull(shortestPath);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDirectedGraph_whenGetBellmanFordShortestPath_thenGetNotNullPath() {
|
||||
BellmanFordShortestPath bellmanFordShortestPath = new BellmanFordShortestPath(directedGraph);
|
||||
List<String> shortestPath = bellmanFordShortestPath.getPath("v1", "v4").getVertexList();
|
||||
assertNotNull(shortestPath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.jgrapht;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.jgrapht.GraphPath;
|
||||
import org.jgrapht.alg.cycle.HierholzerEulerianCycle;
|
||||
import org.jgrapht.graph.DefaultEdge;
|
||||
import org.jgrapht.graph.SimpleWeightedGraph;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class EulerianCircuitUnitTest {
|
||||
SimpleWeightedGraph<String, DefaultEdge> simpleGraph;
|
||||
|
||||
@Before
|
||||
public void createGraphWithEulerianCircuit() {
|
||||
simpleGraph = new SimpleWeightedGraph<>(DefaultEdge.class);
|
||||
IntStream.range(1, 6).forEach(i -> {
|
||||
simpleGraph.addVertex("v" + i);
|
||||
});
|
||||
IntStream.range(1, 6).forEach(i -> {
|
||||
int endVertexNo = (i + 1) > 5 ? 1 : i + 1;
|
||||
simpleGraph.addEdge("v" + i, "v" + endVertexNo);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGraph_whenCheckEluerianCycle_thenGetResult() {
|
||||
HierholzerEulerianCycle eulerianCycle = new HierholzerEulerianCycle<>();
|
||||
assertTrue(eulerianCycle.isEulerian(simpleGraph));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGraphWithEulerianCircuit_whenGetEulerianCycle_thenGetGraphPath() {
|
||||
HierholzerEulerianCycle eulerianCycle = new HierholzerEulerianCycle<>();
|
||||
GraphPath path = eulerianCycle.getEulerianCycle(simpleGraph);
|
||||
assertTrue(path.getEdgeList().containsAll(simpleGraph.edgeSet()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user