Change project structure to a Maven Java project + Refactor (#2816)

This commit is contained in:
Aitor Fidalgo Sánchez
2021-11-12 07:59:36 +01:00
committed by GitHub
parent 8e533d2617
commit 9fb3364ccc
642 changed files with 26570 additions and 25488 deletions

View File

@ -0,0 +1,94 @@
package com.thealgorithms.searches;
import static java.lang.String.format;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;
import com.thealgorithms.devutils.searches.SearchAlgorithm;
/**
* Binary search is one of the most popular algorithms The algorithm finds the
* position of a target value within a sorted array
*
* <p>
* Worst-case performance O(log n) Best-case performance O(1) Average
* performance O(log n) Worst-case space complexity O(1)
*
* @author Varun Upadhyay (https://github.com/varunu28)
* @author Podshivalov Nikita (https://github.com/nikitap492)
* @see SearchAlgorithm
* @see IterativeBinarySearch
*/
class BinarySearch implements SearchAlgorithm {
/**
* @param array is an array where the element should be found
* @param key is an element which should be found
* @param <T> is any comparable type
* @return index of the element
*/
@Override
public <T extends Comparable<T>> int find(T[] array, T key) {
return search(array, key, 0, array.length);
}
/**
* This method implements the Generic Binary Search
*
* @param array The array to make the binary search
* @param key The number you are looking for
* @param left The lower bound
* @param right The upper bound
* @return the location of the key
*/
private <T extends Comparable<T>> int search(T array[], T key, int left, int right) {
if (right < left) {
return -1; // this means that the key not found
}
// find median
int median = (left + right) >>> 1;
int comp = key.compareTo(array[median]);
if (comp == 0) {
return median;
} else if (comp < 0) {
return search(array, key, left, median - 1);
} else {
return search(array, key, median + 1, right);
}
}
// Driver Program
public static void main(String[] args) {
// Just generate data
Random r = ThreadLocalRandom.current();
int size = 100;
int maxElement = 100000;
Integer[] integers
= IntStream.generate(() -> r.nextInt(maxElement))
.limit(size)
.sorted()
.boxed()
.toArray(Integer[]::new);
// The element that should be found
int shouldBeFound = integers[r.nextInt(size - 1)];
BinarySearch search = new BinarySearch();
int atIndex = search.find(integers, shouldBeFound);
System.out.println(
format(
"Should be found: %d. Found %d at index %d. An array length %d",
shouldBeFound, integers[atIndex], atIndex, size));
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
System.out.println(
format(
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
}
}

View File

@ -0,0 +1,80 @@
package com.thealgorithms.searches;
import com.thealgorithms.searches.DepthFirstSearch.Node;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* @author: caos321
* @date: 31 October 2021 (Sunday)
*/
public class BreadthFirstSearch {
public static Optional<Node> search(final Node node, final String name) {
if (node.getName().equals(name)) {
return Optional.of(node);
}
List<Node> queue = new ArrayList<>(node.getSubNodes());
while (!queue.isEmpty()) {
final Node current = queue.get(0);
if (current.getName().equals(name)) {
return Optional.of(current);
}
queue.addAll(current.getSubNodes());
queue.remove(0);
}
return Optional.empty();
}
public static void assertThat(final Object actual, final Object expected) {
if (!Objects.equals(actual, expected)) {
throw new AssertionError(String.format("expected=%s but was actual=%s", expected, actual));
}
}
public static void main(final String[] args) {
final Node rootNode = new Node("A", List.of(
new Node("B", List.of(new Node("D"), new Node("F", List.of(
new Node("H"), new Node("I")
)))),
new Node("C", List.of(new Node("G"))),
new Node("E")
));
{
final String expected = "I";
final Node result = search(rootNode, expected)
.orElseThrow(() -> new AssertionError("Node not found!"));
assertThat(result.getName(), expected);
}
{
final String expected = "G";
final Node result = search(rootNode, expected)
.orElseThrow(() -> new AssertionError("Node not found!"));
assertThat(result.getName(), expected);
}
{
final String expected = "E";
final Node result = search(rootNode, expected)
.orElseThrow(() -> new AssertionError("Node not found!"));
assertThat(result.getName(), expected);
}
}
}

View File

@ -0,0 +1,92 @@
package com.thealgorithms.searches;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* @author: caos321
* @date: 31 October 2021 (Sunday)
*/
public class DepthFirstSearch {
static class Node {
private final String name;
private final List<Node> subNodes;
public Node(final String name) {
this.name = name;
this.subNodes = new ArrayList<>();
}
public Node(final String name, final List<Node> subNodes) {
this.name = name;
this.subNodes = subNodes;
}
public String getName() {
return name;
}
public List<Node> getSubNodes() {
return subNodes;
}
}
public static Optional<Node> search(final Node node, final String name) {
if (node.getName().equals(name)) {
return Optional.of(node);
}
return node.getSubNodes()
.stream()
.map(value -> search(value, name))
.flatMap(Optional::stream)
.findAny();
}
public static void assertThat(final Object actual, final Object expected) {
if (!Objects.equals(actual, expected)) {
throw new AssertionError(String.format("expected=%s but was actual=%s", expected, actual));
}
}
public static void main(final String[] args) {
final Node rootNode = new Node("A", List.of(
new Node("B", List.of(new Node("D"), new Node("F", List.of(
new Node("H"), new Node("I")
)))),
new Node("C", List.of(new Node("G"))),
new Node("E")
));
{
final String expected = "I";
final Node result = search(rootNode, expected)
.orElseThrow(() -> new AssertionError("Node not found!"));
assertThat(result.getName(), expected);
}
{
final String expected = "G";
final Node result = search(rootNode, expected)
.orElseThrow(() -> new AssertionError("Node not found!"));
assertThat(result.getName(), expected);
}
{
final String expected = "E";
final Node result = search(rootNode, expected)
.orElseThrow(() -> new AssertionError("Node not found!"));
assertThat(result.getName(), expected);
}
}
}

View File

@ -0,0 +1,61 @@
package com.thealgorithms.searches;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;
import com.thealgorithms.devutils.searches.SearchAlgorithm;
import static java.lang.String.format;
class ExponentialSearch implements SearchAlgorithm {
public static void main(String[] args) {
Random r = ThreadLocalRandom.current();
int size = 100;
int maxElement = 100000;
Integer[] integers
= IntStream.generate(() -> r.nextInt(maxElement))
.limit(size)
.sorted()
.boxed()
.toArray(Integer[]::new);
// The element that should be found
int shouldBeFound = integers[r.nextInt(size - 1)];
ExponentialSearch search = new ExponentialSearch();
int atIndex = search.find(integers, shouldBeFound);
System.out.println(
format(
"Should be found: %d. Found %d at index %d. An array length %d",
shouldBeFound, integers[atIndex], atIndex, size));
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
System.out.println(
format(
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
}
@Override
public <T extends Comparable<T>> int find(T[] array, T key) {
if (array[0] == key) {
return 0;
}
if (array[array.length - 1] == key) {
return array.length;
}
int range = 1;
while (range < array.length && array[range].compareTo(key) <= -1) {
range = range * 2;
}
return Arrays.binarySearch(array, range / 2, Math.min(range, array.length), key);
}
}

View File

@ -0,0 +1,73 @@
package com.thealgorithms.searches;
import com.thealgorithms.devutils.searches.SearchAlgorithm;
/*
* Fibonacci Search is a popular algorithm which finds the position of a target value in
* a sorted array
*
* The time complexity for this search algorithm is O(log3(n))
* The space complexity for this search algorithm is O(1)
* @author Kanakalatha Vemuru (https://github.com/KanakalathaVemuru)
*/
public class FibonacciSearch implements SearchAlgorithm {
/**
* @param array is a sorted array where the element has to be searched
* @param key is an element whose position has to be found
* @param <T> is any comparable type
* @return index of the element
*/
@Override
public <T extends Comparable<T>> int find(T[] array, T key) {
int fibMinus1 = 1;
int fibMinus2 = 0;
int fibNumber = fibMinus1 + fibMinus2;
int n = array.length;
while (fibNumber < n) {
fibMinus2 = fibMinus1;
fibMinus1 = fibNumber;
fibNumber = fibMinus2 + fibMinus1;
}
int offset = -1;
while (fibNumber > 1) {
int i = Math.min(offset + fibMinus2, n - 1);
if (array[i].compareTo(key) < 0) {
fibNumber = fibMinus1;
fibMinus1 = fibMinus2;
fibMinus2 = fibNumber - fibMinus1;
offset = i;
} else if (array[i].compareTo(key) > 0) {
fibNumber = fibMinus2;
fibMinus1 = fibMinus1 - fibMinus2;
fibMinus2 = fibNumber - fibMinus1;
} else {
return i;
}
}
if (fibMinus1 == 1 && array[offset + 1] == key) {
return offset + 1;
}
return -1;
}
// Driver Program
public static void main(String[] args) {
Integer[] integers = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512};
int size = integers.length;
Integer shouldBeFound = 128;
FibonacciSearch fsearch = new FibonacciSearch();
int atIndex = fsearch.find(integers, shouldBeFound);
System.out.println(
"Should be found: " + shouldBeFound + ". Found " + integers[atIndex] + " at index " + atIndex + ". An array length " + size);
}
}

View File

@ -0,0 +1,60 @@
package com.thealgorithms.searches;
import java.util.*;
/*
Problem Statement:
Given an array, find out how many times it has to been rotated
from its initial sorted position.
Input-Output:
Eg. [11,12,15,18,2,5,6,8]
It has been rotated: 4 times
(One rotation means putting the first element to the end)
Note: The array cannot contain duplicates
Logic:
The position of the minimum element will give the number of times the array has been rotated
from its initial sorted position.
Eg. For [2,5,6,8,11,12,15,18], 1 rotation gives [5,6,8,11,12,15,18,2], 2 rotations [6,8,11,12,15,18,2,5] and so on.
Finding the minimum element will take O(N) time but, we can use Binary Search to find the mimimum element, we can reduce the complexity to O(log N).
If we look at the rotated array, to identify the minimum element (say a[i]), we observe that a[i-1]>a[i]<a[i+1].
Some other test cases:
1. [1,2,3,4] Number of rotations: 0 or 4(Both valid)
2. [15,17,2,3,5] Number of rotations: 3
*/
class HowManyTimesRotated {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
System.out.println("The array has been rotated " + rotated(a) + " times");
sc.close();
}
public static int rotated(int[] a) {
int low = 0;
int high = a.length - 1;
int mid = 0; // low + (high-low)/2 = (low + high)/2
while (low <= high) {
mid = low + (high - low) / 2;
if (a[mid] < a[mid - 1] && a[mid] < a[mid + 1]) {
break;
} else if (a[mid] > a[mid - 1] && a[mid] < a[mid + 1]) {
high = mid + 1;
} else if (a[mid] > a[mid - 1] && a[mid] > a[mid + 1]) {
low = mid - 1;
}
}
return mid;
}
}

View File

@ -0,0 +1,76 @@
package com.thealgorithms.searches;
import static java.lang.String.format;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.IntStream;
/**
* Interpolation search algorithm implementation
*
* <p>
* Worst-case performance O(n) Best-case performance O(1) Average performance
* O(log(log(n))) if the elements are uniformly distributed if not O(n)
* Worst-case space complexity O(1)
*
* @author Podshivalov Nikita (https://github.com/nikitap492)
*/
class InterpolationSearch {
/**
* @param array is a sorted array
* @param key is a value what shoulb be found in the array
* @return an index if the array contains the key unless -1
*/
public int find(int array[], int key) {
// Find indexes of two corners
int start = 0, end = (array.length - 1);
// Since array is sorted, an element present
// in array must be in range defined by corner
while (start <= end && key >= array[start] && key <= array[end]) {
// Probing the position with keeping
// uniform distribution in mind.
int pos = start + (((end - start) / (array[end] - array[start])) * (key - array[start]));
// Condition of target found
if (array[pos] == key) {
return pos;
}
// If key is larger, key is in upper part
if (array[pos] < key) {
start = pos + 1;
} // If key is smaller, x is in lower part
else {
end = pos - 1;
}
}
return -1;
}
// Driver method
public static void main(String[] args) {
Random r = new Random();
int size = 100;
int maxElement = 100000;
int[] integers = IntStream.generate(() -> r.nextInt(maxElement)).limit(size).sorted().toArray();
// the element that should be found
Integer shouldBeFound = integers[r.nextInt(size - 1)];
InterpolationSearch search = new InterpolationSearch();
int atIndex = search.find(integers, shouldBeFound);
System.out.println(
String.format(
"Should be found: %d. Found %d at index %d. An array length %d",
shouldBeFound, integers[atIndex], atIndex, size));
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
System.out.println(
format(
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
}
}

View File

@ -0,0 +1,82 @@
package com.thealgorithms.searches;
import static java.lang.String.format;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.Stream;
import com.thealgorithms.devutils.searches.SearchAlgorithm;
/**
* Binary search is one of the most popular algorithms This class represents
* iterative version {@link BinarySearch} Iterative binary search is likely to
* have lower constant factors because it doesn't involve the overhead of
* manipulating the call stack. But in java the recursive version can be
* optimized by the compiler to this version.
*
* <p>
* Worst-case performance O(log n) Best-case performance O(1) Average
* performance O(log n) Worst-case space complexity O(1)
*
* @author Gabriele La Greca : https://github.com/thegabriele97
* @author Podshivalov Nikita (https://github.com/nikitap492)
* @see SearchAlgorithm
* @see BinarySearch
*/
public final class IterativeBinarySearch implements SearchAlgorithm {
/**
* This method implements an iterative version of binary search algorithm
*
* @param array a sorted array
* @param key the key to search in array
* @return the index of key in the array or -1 if not found
*/
@Override
public <T extends Comparable<T>> int find(T[] array, T key) {
int l, r, k, cmp;
l = 0;
r = array.length - 1;
while (l <= r) {
k = (l + r) >>> 1;
cmp = key.compareTo(array[k]);
if (cmp == 0) {
return k;
} else if (cmp < 0) {
r = --k;
} else {
l = ++k;
}
}
return -1;
}
// Only a main method for test purpose
public static void main(String[] args) {
Random r = new Random();
int size = 100;
int maxElement = 100000;
Integer[] integers
= Stream.generate(() -> r.nextInt(maxElement)).limit(size).sorted().toArray(Integer[]::new);
// the element that should be found
Integer shouldBeFound = integers[r.nextInt(size - 1)];
IterativeBinarySearch search = new IterativeBinarySearch();
int atIndex = search.find(integers, shouldBeFound);
System.out.println(
String.format(
"Should be found: %d. Found %d at index %d. An array length %d",
shouldBeFound, integers[atIndex], atIndex, size));
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
System.out.println(
format(
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
}
}

View File

@ -0,0 +1,81 @@
package com.thealgorithms.searches;
import static java.lang.String.format;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.Stream;
import com.thealgorithms.devutils.searches.SearchAlgorithm;
/**
* A iterative version of a ternary search algorithm This is better way to
* implement the ternary search, because a recursive version adds some overhead
* to a stack. But in java the compile can transform the recursive version to
* iterative implicitly, so there are no much differences between these two
* algorithms
*
* <p>
* Worst-case performance Θ(log3(N)) Best-case performance O(1) Average
* performance Θ(log3(N)) Worst-case space complexity O(1)
*
* @author Podshivalov Nikita (https://github.com/nikitap492)
* @see SearchAlgorithm
* @see TernarySearch
* @since 2018-04-13
*/
public class IterativeTernarySearch implements SearchAlgorithm {
@Override
public <T extends Comparable<T>> int find(T[] array, T key) {
int left = 0;
int right = array.length - 1;
while (right > left) {
int leftCmp = array[left].compareTo(key);
int rightCmp = array[right].compareTo(key);
if (leftCmp == 0) {
return left;
}
if (rightCmp == 0) {
return right;
}
int leftThird = left + (right - left) / 3 + 1;
int rightThird = right - (right - left) / 3 - 1;
if (array[leftThird].compareTo(key) <= 0) {
left = leftThird;
} else {
right = rightThird;
}
}
return -1;
}
public static void main(String[] args) {
// just generate data
Random r = new Random();
int size = 100;
int maxElement = 100000;
Integer[] integers
= Stream.generate(() -> r.nextInt(maxElement)).limit(size).sorted().toArray(Integer[]::new);
// the element that should be found
Integer shouldBeFound = integers[r.nextInt(size - 1)];
IterativeTernarySearch search = new IterativeTernarySearch();
int atIndex = search.find(integers, shouldBeFound);
System.out.println(
format(
"Should be found: %d. Found %d at index %d. An array length %d",
shouldBeFound, integers[atIndex], atIndex, size));
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
System.out.println(
format(
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
}
}

View File

@ -0,0 +1,45 @@
package com.thealgorithms.searches;
import com.thealgorithms.devutils.searches.SearchAlgorithm;
public class JumpSearch implements SearchAlgorithm {
public static void main(String[] args) {
JumpSearch jumpSearch = new JumpSearch();
Integer[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int i = 0; i < array.length; i++) {
assert jumpSearch.find(array, i) == i;
}
assert jumpSearch.find(array, -1) == -1;
assert jumpSearch.find(array, 11) == -1;
}
/**
* Jump Search algorithm implements
*
* @param array the array contains elements
* @param key to be searched
* @return index of {@code key} if found, otherwise <tt>-1</tt>
*/
@Override
public <T extends Comparable<T>> int find(T[] array, T key) {
int length = array.length;
/* length of array */
int blockSize = (int) Math.sqrt(length);
/* block size to be jumped */
int limit = blockSize;
while (key.compareTo(array[limit]) > 0 && limit < array.length - 1) {
limit = Math.min(limit + blockSize, array.length - 1);
}
for (int i = limit - blockSize; i <= limit; i++) {
if (array[i] == key) {
/* execute linear search */
return i;
}
}
return -1;
/* not found */
}
}

View File

@ -0,0 +1,59 @@
package com.thealgorithms.searches;
import java.util.Random;
import java.util.stream.Stream;
import com.thealgorithms.devutils.searches.SearchAlgorithm;
/**
* Linear search is the easiest search algorithm It works with sorted and
* unsorted arrays (an binary search works only with sorted array) This
* algorithm just compares all elements of an array to find a value
*
* <p>
* Worst-case performance O(n) Best-case performance O(1) Average performance
* O(n) Worst-case space complexity
*
* @author Varun Upadhyay (https://github.com/varunu28)
* @author Podshivalov Nikita (https://github.com/nikitap492)
* @see BinarySearch
* @see SearchAlgorithm
*/
public class LinearSearch implements SearchAlgorithm {
/**
* Generic Linear search method
*
* @param array List to be searched
* @param value Key being searched for
* @return Location of the key
*/
@Override
public <T extends Comparable<T>> int find(T[] array, T value) {
for (int i = 0; i < array.length; i++) {
if (array[i].compareTo(value) == 0) {
return i;
}
}
return -1;
}
public static void main(String[] args) {
// just generate data
Random r = new Random();
int size = 200;
int maxElement = 100;
Integer[] integers
= Stream.generate(() -> r.nextInt(maxElement)).limit(size).toArray(Integer[]::new);
// the element that should be found
Integer shouldBeFound = integers[r.nextInt(size - 1)];
LinearSearch search = new LinearSearch();
int atIndex = search.find(integers, shouldBeFound);
System.out.println(
String.format(
"Should be found: %d. Found %d at index %d. An array length %d",
shouldBeFound, integers[atIndex], atIndex, size));
}
}

View File

@ -0,0 +1,101 @@
package com.thealgorithms.searches;
import static java.lang.String.format;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;
import com.thealgorithms.devutils.searches.SearchAlgorithm;
/**
* The LowerBound method is used to return an index pointing to the first
* element in the range [first, last) which has a value not less than val, i.e.
* the index of the next smallest number just greater than or equal to that
* number. If there are multiple values that are equal to val it returns the
* index of the first such value.
*
* <p>
* This is an extension of BinarySearch.
*
* <p>
* Worst-case performance O(log n) Best-case performance O(1) Average
* performance O(log n) Worst-case space complexity O(1)
*
* @author Pratik Padalia (https://github.com/15pratik)
* @see SearchAlgorithm
* @see BinarySearch
*/
class LowerBound implements SearchAlgorithm {
// Driver Program
public static void main(String[] args) {
// Just generate data
Random r = ThreadLocalRandom.current();
int size = 100;
int maxElement = 100000;
Integer[] integers
= IntStream.generate(() -> r.nextInt(maxElement))
.limit(size)
.sorted()
.boxed()
.toArray(Integer[]::new);
// The element for which the lower bound is to be found
int val = integers[r.nextInt(size - 1)] + 1;
LowerBound search = new LowerBound();
int atIndex = search.find(integers, val);
System.out.println(
format(
"Val: %d. Lower Bound Found %d at index %d. An array length %d",
val, integers[atIndex], atIndex, size));
boolean toCheck = integers[atIndex] >= val || integers[size - 1] < val;
System.out.println(
format(
"Lower Bound found at an index: %d. Is greater or max element: %b", atIndex, toCheck));
}
/**
* @param array is an array where the LowerBound value is to be found
* @param key is an element for which the LowerBound is to be found
* @param <T> is any comparable type
* @return index of the LowerBound element
*/
@Override
public <T extends Comparable<T>> int find(T[] array, T key) {
return search(array, key, 0, array.length - 1);
}
/**
* This method implements the Generic Binary Search
*
* @param array The array to make the binary search
* @param key The number you are looking for
* @param left The lower bound
* @param right The upper bound
* @return the location of the key
*/
private <T extends Comparable<T>> int search(T[] array, T key, int left, int right) {
if (right <= left) {
return left;
}
// find median
int median = (left + right) >>> 1;
int comp = key.compareTo(array[median]);
if (comp == 0) {
return median;
} else if (comp < 0) {
// median position can be a possible solution
return search(array, key, left, median);
} else {
// key we are looking is greater, so we must look on the right of median position
return search(array, key, median + 1, right);
}
}
}

View File

@ -0,0 +1,182 @@
package com.thealgorithms.searches;
import java.util.Collections;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Random;
/**
* Monte Carlo Tree Search (MCTS) is a heuristic search algorithm used in
* decition taking problems especially games.
*
* See more: https://en.wikipedia.org/wiki/Monte_Carlo_tree_search,
* https://www.baeldung.com/java-monte-carlo-tree-search
*/
public class MonteCarloTreeSearch {
public class Node {
Node parent;
ArrayList<Node> childNodes;
boolean isPlayersTurn; // True if it is the player's turn.
boolean playerWon; // True if the player won; false if the opponent won.
int score;
int visitCount;
public Node() {
}
public Node(Node parent, boolean isPlayersTurn) {
this.parent = parent;
childNodes = new ArrayList<>();
this.isPlayersTurn = isPlayersTurn;
playerWon = false;
score = 0;
visitCount = 0;
}
}
static final int WIN_SCORE = 10;
static final int TIME_LIMIT = 500; // Time the algorithm will be running for (in milliseconds).
public static void main(String[] args) {
MonteCarloTreeSearch mcts = new MonteCarloTreeSearch();
mcts.monteCarloTreeSearch(mcts.new Node(null, true));
}
/**
* Explores a game tree using Monte Carlo Tree Search (MCTS) and returns the
* most promising node.
*
* @param rootNode Root node of the game tree.
* @return The most promising child of the root node.
*/
public Node monteCarloTreeSearch(Node rootNode) {
Node winnerNode;
double timeLimit;
// Expand the root node.
addChildNodes(rootNode, 10);
timeLimit = System.currentTimeMillis() + TIME_LIMIT;
// Explore the tree until the time limit is reached.
while (System.currentTimeMillis() < timeLimit) {
Node promisingNode;
// Get a promising node using UCT.
promisingNode = getPromisingNode(rootNode);
// Expand the promising node.
if (promisingNode.childNodes.size() == 0) {
addChildNodes(promisingNode, 10);
}
simulateRandomPlay(promisingNode);
}
winnerNode = getWinnerNode(rootNode);
printScores(rootNode);
System.out.format("\nThe optimal node is: %02d\n", rootNode.childNodes.indexOf(winnerNode) + 1);
return winnerNode;
}
public void addChildNodes(Node node, int childCount) {
for (int i = 0; i < childCount; i++) {
node.childNodes.add(new Node(node, !node.isPlayersTurn));
}
}
/**
* Uses UCT to find a promising child node to be explored.
*
* UCT: Upper Confidence bounds applied to Trees.
*
* @param rootNode Root node of the tree.
* @return The most promising node according to UCT.
*/
public Node getPromisingNode(Node rootNode) {
Node promisingNode = rootNode;
// Iterate until a node that hasn't been expanded is found.
while (promisingNode.childNodes.size() != 0) {
double uctIndex = Double.MIN_VALUE;
int nodeIndex = 0;
// Iterate through child nodes and pick the most promising one
// using UCT (Upper Confidence bounds applied to Trees).
for (int i = 0; i < promisingNode.childNodes.size(); i++) {
Node childNode = promisingNode.childNodes.get(i);
double uctTemp;
// If child node has never been visited
// it will have the highest uct value.
if (childNode.visitCount == 0) {
nodeIndex = i;
break;
}
uctTemp = ((double) childNode.score / childNode.visitCount)
+ 1.41 * Math.sqrt(Math.log(promisingNode.visitCount) / (double) childNode.visitCount);
if (uctTemp > uctIndex) {
uctIndex = uctTemp;
nodeIndex = i;
}
}
promisingNode = promisingNode.childNodes.get(nodeIndex);
}
return promisingNode;
}
/**
* Simulates a random play from a nodes current state and back propagates
* the result.
*
* @param promisingNode Node that will be simulated.
*/
public void simulateRandomPlay(Node promisingNode) {
Random rand = new Random();
Node tempNode = promisingNode;
boolean isPlayerWinner;
// The following line randomly determines whether the simulated play is a win or loss.
// To use the MCTS algorithm correctly this should be a simulation of the nodes' current
// state of the game until it finishes (if possible) and use an evaluation function to
// determine how good or bad the play was.
// e.g. Play tic tac toe choosing random squares until the game ends.
promisingNode.playerWon = (rand.nextInt(6) == 0);
isPlayerWinner = promisingNode.playerWon;
// Back propagation of the random play.
while (tempNode != null) {
tempNode.visitCount++;
// Add wining scores to bouth player and opponent depending on the turn.
if ((tempNode.isPlayersTurn && isPlayerWinner)
|| (!tempNode.isPlayersTurn && !isPlayerWinner)) {
tempNode.score += WIN_SCORE;
}
tempNode = tempNode.parent;
}
}
public Node getWinnerNode(Node rootNode) {
return Collections.max(rootNode.childNodes, Comparator.comparing(c -> c.score));
}
public void printScores(Node rootNode) {
System.out.println("N.\tScore\t\tVisits");
for (int i = 0; i < rootNode.childNodes.size(); i++) {
System.out.println(String.format("%02d\t%d\t\t%d", i + 1,
rootNode.childNodes.get(i).score, rootNode.childNodes.get(i).visitCount));
}
}
}

View File

@ -0,0 +1,29 @@
package com.thealgorithms.searches;
class PerfectBinarySearch {
static int binarySearch(int[] arr, int target) {
int low = 0;
int high = arr.length - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
public static void main(String[] args) {
PerfectBinarySearch BinarySearch = new PerfectBinarySearch();
int[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
assert BinarySearch.binarySearch(array, -1) == -1;
assert BinarySearch.binarySearch(array, 11) == -1;
}
}

View File

@ -0,0 +1,72 @@
package com.thealgorithms.searches;
import java.util.Scanner;
/**
* Program to perform Saddleback Search Given a sorted 2D array(elements are
* sorted across every row and column, assuming ascending order) of size n*m we
* can search a given element in O(n+m)
*
* <p>
* we start from bottom left corner if the current element is greater than the
* given element then we move up else we move right Sample Input: 5 5
* ->Dimensions -10 -5 -3 4 9 -6 -2 0 5 10 -4 -1 1 6 12 2 3 7 8 13 100 120 130
* 140 150 140 ->element to be searched output: 4 3 // first value is row,
* second one is column
*
* @author Nishita Aggarwal
*/
public class SaddlebackSearch {
/**
* This method performs Saddleback Search
*
* @param arr The **Sorted** array in which we will search the element.
* @param row the current row.
* @param col the current column.
* @param key the element that we want to search for.
* @return The index(row and column) of the element if found. Else returns
* -1 -1.
*/
private static int[] find(int arr[][], int row, int col, int key) {
// array to store the answer row and column
int ans[] = {-1, -1};
if (row < 0 || col >= arr[row].length) {
return ans;
}
if (arr[row][col] == key) {
ans[0] = row;
ans[1] = col;
return ans;
} // if the current element is greater than the given element then we move up
else if (arr[row][col] > key) {
return find(arr, row - 1, col, key);
}
// else we move right
return find(arr, row, col + 1, key);
}
/**
* Main method
*
* @param args Command line arguments
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int arr[][];
int i, j, rows = sc.nextInt(), col = sc.nextInt();
arr = new int[rows][col];
for (i = 0; i < rows; i++) {
for (j = 0; j < col; j++) {
arr[i][j] = sc.nextInt();
}
}
int ele = sc.nextInt();
// we start from bottom left corner
int ans[] = find(arr, rows - 1, 0, ele);
System.out.println(ans[0] + " " + ans[1]);
sc.close();
}
}

View File

@ -0,0 +1,60 @@
package com.thealgorithms.searches;
import java.util.Scanner;
/**
* Given an integer x, find the square root of x. If x is not a perfect square,
* then return floor(√x).
* <p>
* For example, if x = 5, The answer should be 2 which is the floor value of √5.
* <p>
* The approach that will be used for solving the above problem is not going to
* be a straight forward Math.sqrt(). Instead we will be using Binary Search to
* find the square root of a number in the most optimised way.
*
* @author sahil
*/
public class SquareRootBinarySearch {
/**
* This is the driver method.
*
* @param args Command line arguments
*/
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter a number you want to calculate square root of : ");
int num = sc.nextInt();
long ans = squareRoot(num);
System.out.println("The square root is : " + ans);
}
/**
* This function calculates the floor of square root of a number. We use
* Binary Search algorithm to calculate the square root in a more optimised
* way.
*
* @param num Number
* @return answer
*/
private static long squareRoot(long num) {
if (num == 0 || num == 1) {
return num;
}
long l = 1;
long r = num;
long ans = 0;
while (l <= r) {
long mid = l + (r - l) / 2;
if (mid == num / mid) {
return mid;
} else if (mid < num / mid) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
return ans;
}
}

View File

@ -0,0 +1,90 @@
package com.thealgorithms.searches;
import static java.lang.String.format;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.Stream;
import com.thealgorithms.devutils.searches.SearchAlgorithm;
/**
* A ternary search algorithm is a technique in computer science for finding the
* minimum or maximum of a unimodal function The algorithm determines either
* that the minimum or maximum cannot be in the first third of the domain or
* that it cannot be in the last third of the domain, then repeats on the
* remaining third.
*
* <p>
* Worst-case performance Θ(log3(N)) Best-case performance O(1) Average
* performance Θ(log3(N)) Worst-case space complexity O(1)
*
* @author Podshivalov Nikita (https://github.com/nikitap492)
* @see SearchAlgorithm
* @see IterativeBinarySearch
*/
public class TernarySearch implements SearchAlgorithm {
/**
* @param arr The **Sorted** array in which we will search the element.
* @param value The value that we want to search for.
* @return The index of the element if found. Else returns -1.
*/
@Override
public <T extends Comparable<T>> int find(T[] arr, T value) {
return ternarySearch(arr, value, 0, arr.length - 1);
}
/**
* @param arr The **Sorted** array in which we will search the element.
* @param key The value that we want to search for.
* @param start The starting index from which we will start Searching.
* @param end The ending index till which we will Search.
* @return Returns the index of the Element if found. Else returns -1.
*/
private <T extends Comparable<T>> int ternarySearch(T[] arr, T key, int start, int end) {
if (start > end) {
return -1;
}
/* First boundary: add 1/3 of length to start */
int mid1 = start + (end - start) / 3;
/* Second boundary: add 2/3 of length to start */
int mid2 = start + 2 * (end - start) / 3;
if (key.compareTo(arr[mid1]) == 0) {
return mid1;
} else if (key.compareTo(arr[mid2]) == 0) {
return mid2;
} /* Search the first (1/3) rd part of the array.*/ else if (key.compareTo(arr[mid1]) < 0) {
return ternarySearch(arr, key, start, --mid1);
} /* Search 3rd (1/3)rd part of the array */ else if (key.compareTo(arr[mid2]) > 0) {
return ternarySearch(arr, key, ++mid2, end);
} /* Search middle (1/3)rd part of the array */ else {
return ternarySearch(arr, key, mid1, mid2);
}
}
public static void main(String[] args) {
// just generate data
Random r = new Random();
int size = 100;
int maxElement = 100000;
Integer[] integers
= Stream.generate(() -> r.nextInt(maxElement)).limit(size).sorted().toArray(Integer[]::new);
// the element that should be found
Integer shouldBeFound = integers[r.nextInt(size - 1)];
TernarySearch search = new TernarySearch();
int atIndex = search.find(integers, shouldBeFound);
System.out.println(
format(
"Should be found: %d. Found %d at index %d. An array length %d",
shouldBeFound, integers[atIndex], atIndex, size));
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
System.out.println(
format(
"Found by system method at an index: %d. Is equal: %b", toCheck, toCheck == atIndex));
}
}

View File

@ -0,0 +1,82 @@
package com.thealgorithms.searches;
import java.util.*;
public class UnionFind {
private int[] p;
private int[] r;
public UnionFind(int n) {
p = new int[n];
r = new int[n];
for (int i = 0; i < n; i++) {
p[i] = i;
}
}
public int find(int i) {
int parent = p[i];
if (i == parent) {
return i;
}
return p[i] = find(parent);
}
public void union(int x, int y) {
int r0 = find(x);
int r1 = find(y);
if (r1 == r0) {
return;
}
if (r[r0] > r[r1]) {
p[r1] = r0;
} else if (r[r1] > r[r0]) {
p[r0] = r1;
} else {
p[r1] = r0;
r[r0]++;
}
}
public int count() {
List parents = new ArrayList();
for (int i = 0; i < p.length; i++) {
if (!parents.contains(find(i))) {
parents.add(find(i));
}
}
return parents.size();
}
public String toString() {
return "p " + Arrays.toString(p) + " r " + Arrays.toString(r) + "\n";
}
// Tests
public static void main(String[] args) {
UnionFind uf = new UnionFind(5);
System.out.println("init /w 5 (should print 'p [0, 1, 2, 3, 4] r [0, 0, 0, 0, 0]'):");
System.out.println(uf);
uf.union(1, 2);
System.out.println("union 1 2 (should print 'p [0, 1, 1, 3, 4] r [0, 1, 0, 0, 0]'):");
System.out.println(uf);
uf.union(3, 4);
System.out.println("union 3 4 (should print 'p [0, 1, 1, 3, 3] r [0, 1, 0, 1, 0]'):");
System.out.println(uf);
uf.find(4);
System.out.println("find 4 (should print 'p [0, 1, 1, 3, 3] r [0, 1, 0, 1, 0]'):");
System.out.println(uf);
System.out.println("count (should print '3'):");
System.out.println(uf.count());
}
}

View File

@ -0,0 +1,99 @@
package com.thealgorithms.searches;
import static java.lang.String.format;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;
import com.thealgorithms.devutils.searches.SearchAlgorithm;
/**
* The UpperBound method is used to return an index pointing to the first
* element in the range [first, last) which has a value greater than val, or the
* last index if no such element exists i.e. the index of the next smallest
* number just greater than that number. If there are multiple values that are
* equal to val it returns the index of the first such value.
*
* <p>
* This is an extension of BinarySearch.
*
* <p>
* Worst-case performance O(log n) Best-case performance O(1) Average
* performance O(log n) Worst-case space complexity O(1)
*
* @author Pratik Padalia (https://github.com/15pratik)
* @see SearchAlgorithm
* @see BinarySearch
*/
class UpperBound implements SearchAlgorithm {
// Driver Program
public static void main(String[] args) {
// Just generate data
Random r = ThreadLocalRandom.current();
int size = 100;
int maxElement = 100000;
Integer[] integers
= IntStream.generate(() -> r.nextInt(maxElement))
.limit(size)
.sorted()
.boxed()
.toArray(Integer[]::new);
// The element for which the upper bound is to be found
int val = integers[r.nextInt(size - 1)] + 1;
UpperBound search = new UpperBound();
int atIndex = search.find(integers, val);
System.out.println(
format(
"Val: %d. Upper Bound Found %d at index %d. An array length %d",
val, integers[atIndex], atIndex, size));
boolean toCheck = integers[atIndex] > val || integers[size - 1] < val;
System.out.println(
format(
"Upper Bound found at an index: %d. Is greater or max element: %b", atIndex, toCheck));
}
/**
* @param array is an array where the UpperBound value is to be found
* @param key is an element for which the UpperBound is to be found
* @param <T> is any comparable type
* @return index of the UpperBound element
*/
@Override
public <T extends Comparable<T>> int find(T[] array, T key) {
return search(array, key, 0, array.length - 1);
}
/**
* This method implements the Generic Binary Search
*
* @param array The array to make the binary search
* @param key The number you are looking for
* @param left The lower bound
* @param right The upper bound
* @return the location of the key
*/
private <T extends Comparable<T>> int search(T[] array, T key, int left, int right) {
if (right <= left) {
return left;
}
// find median
int median = (left + right) >>> 1;
int comp = key.compareTo(array[median]);
if (comp < 0) {
// key is smaller, median position can be a possible solution
return search(array, key, left, median);
} else {
// key we are looking is greater, so we must look on the right of median position
return search(array, key, median + 1, right);
}
}
}