JAVA-12097: renamed algorithms-module to algorithms-modules

This commit is contained in:
sampadawagde
2022-05-20 22:07:32 +05:30
parent 2d7de1343f
commit 93b93417e0
324 changed files with 31 additions and 20 deletions
@@ -0,0 +1,28 @@
package com.baeldung.algorithms;
import java.util.Scanner;
import com.baeldung.algorithms.slope_one.SlopeOne;
public class RunAlgorithm {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Scanner in = new Scanner(System.in);
System.out.println("1 - Slope One");
System.out.println("2 - Dijkstra");
int decision = in.nextInt();
switch (decision) {
case 1:
SlopeOne.slopeOne(3);
break;
case 2:
System.out.println("Please run the DijkstraAlgorithmLongRunningUnitTest.");
break;
default:
System.out.println("Unknown option");
break;
}
in.close();
}
}
@@ -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,57 @@
package com.baeldung.algorithms.ga.dijkstra;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Set;
public class Dijkstra {
public static Graph calculateShortestPathFromSource(Graph graph, Node source) {
source.setDistance(0);
Set<Node> settledNodes = new HashSet<>();
Set<Node> unsettledNodes = new HashSet<>();
unsettledNodes.add(source);
while (unsettledNodes.size() != 0) {
Node currentNode = getLowestDistanceNode(unsettledNodes);
unsettledNodes.remove(currentNode);
for (Entry<Node, Integer> adjacencyPair : currentNode.getAdjacentNodes().entrySet()) {
Node adjacentNode = adjacencyPair.getKey();
Integer edgeWeigh = adjacencyPair.getValue();
if (!settledNodes.contains(adjacentNode)) {
CalculateMinimumDistance(adjacentNode, edgeWeigh, currentNode);
unsettledNodes.add(adjacentNode);
}
}
settledNodes.add(currentNode);
}
return graph;
}
private static void CalculateMinimumDistance(Node evaluationNode, Integer edgeWeigh, Node sourceNode) {
Integer sourceDistance = sourceNode.getDistance();
if (sourceDistance + edgeWeigh < evaluationNode.getDistance()) {
evaluationNode.setDistance(sourceDistance + edgeWeigh);
LinkedList<Node> shortestPath = new LinkedList<>(sourceNode.getShortestPath());
shortestPath.add(sourceNode);
evaluationNode.setShortestPath(shortestPath);
}
}
private static Node getLowestDistanceNode(Set<Node> unsettledNodes) {
Node lowestDistanceNode = null;
int lowestDistance = Integer.MAX_VALUE;
for (Node node : unsettledNodes) {
int nodeDistance = node.getDistance();
if (nodeDistance < lowestDistance) {
lowestDistance = nodeDistance;
lowestDistanceNode = node;
}
}
return lowestDistanceNode;
}
}
@@ -0,0 +1,21 @@
package com.baeldung.algorithms.ga.dijkstra;
import java.util.HashSet;
import java.util.Set;
public class Graph {
private Set<Node> nodes = new HashSet<>();
public void addNode(Node nodeA) {
nodes.add(nodeA);
}
public Set<Node> getNodes() {
return nodes;
}
public void setNodes(Set<Node> nodes) {
this.nodes = nodes;
}
}
@@ -0,0 +1,58 @@
package com.baeldung.algorithms.ga.dijkstra;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class Node {
private String name;
private LinkedList<Node> shortestPath = new LinkedList<>();
private Integer distance = Integer.MAX_VALUE;
private Map<Node, Integer> adjacentNodes = new HashMap<>();
public Node(String name) {
this.name = name;
}
public void addDestination(Node destination, int distance) {
adjacentNodes.put(destination, distance);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<Node, Integer> getAdjacentNodes() {
return adjacentNodes;
}
public void setAdjacentNodes(Map<Node, Integer> adjacentNodes) {
this.adjacentNodes = adjacentNodes;
}
public Integer getDistance() {
return distance;
}
public void setDistance(Integer distance) {
this.distance = distance;
}
public List<Node> getShortestPath() {
return shortestPath;
}
public void setShortestPath(LinkedList<Node> shortestPath) {
this.shortestPath = shortestPath;
}
}
@@ -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,35 @@
package com.baeldung.algorithms.slope_one;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.Data;
@Data
public class InputData {
protected static List<Item> items = Arrays.asList(new Item("Candy"), new Item("Drink"), new Item("Soda"), new Item("Popcorn"), new Item("Snacks"));
public static Map<User, HashMap<Item, Double>> initializeData(int numberOfUsers) {
Map<User, HashMap<Item, Double>> data = new HashMap<>();
HashMap<Item, Double> newUser;
Set<Item> newRecommendationSet;
for (int i = 0; i < numberOfUsers; i++) {
newUser = new HashMap<Item, Double>();
newRecommendationSet = new HashSet<>();
for (int j = 0; j < 3; j++) {
newRecommendationSet.add(items.get((int) (Math.random() * 5)));
}
for (Item item : newRecommendationSet) {
newUser.put(item, Math.random());
}
data.put(new User("User " + i), newUser);
}
return data;
}
}
@@ -0,0 +1,13 @@
package com.baeldung.algorithms.slope_one;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Item {
private String itemName;
}
@@ -0,0 +1,124 @@
package com.baeldung.algorithms.slope_one;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
/**
* Slope One algorithm implementation
*/
public class SlopeOne {
private static Map<Item, Map<Item, Double>> diff = new HashMap<>();
private static Map<Item, Map<Item, Integer>> freq = new HashMap<>();
private static Map<User, HashMap<Item, Double>> inputData;
private static Map<User, HashMap<Item, Double>> outputData = new HashMap<>();
public static void slopeOne(int numberOfUsers) {
inputData = InputData.initializeData(numberOfUsers);
System.out.println("Slope One - Before the Prediction\n");
buildDifferencesMatrix(inputData);
System.out.println("\nSlope One - With Predictions\n");
predict(inputData);
}
/**
* Based on the available data, calculate the relationships between the
* items and number of occurences
*
* @param data
* existing user data and their items' ratings
*/
private static void buildDifferencesMatrix(Map<User, HashMap<Item, Double>> data) {
for (HashMap<Item, Double> user : data.values()) {
for (Entry<Item, Double> e : user.entrySet()) {
if (!diff.containsKey(e.getKey())) {
diff.put(e.getKey(), new HashMap<Item, Double>());
freq.put(e.getKey(), new HashMap<Item, Integer>());
}
for (Entry<Item, Double> e2 : user.entrySet()) {
int oldCount = 0;
if (freq.get(e.getKey()).containsKey(e2.getKey())) {
oldCount = freq.get(e.getKey()).get(e2.getKey()).intValue();
}
double oldDiff = 0.0;
if (diff.get(e.getKey()).containsKey(e2.getKey())) {
oldDiff = diff.get(e.getKey()).get(e2.getKey()).doubleValue();
}
double observedDiff = e.getValue() - e2.getValue();
freq.get(e.getKey()).put(e2.getKey(), oldCount + 1);
diff.get(e.getKey()).put(e2.getKey(), oldDiff + observedDiff);
}
}
}
for (Item j : diff.keySet()) {
for (Item i : diff.get(j).keySet()) {
double oldValue = diff.get(j).get(i).doubleValue();
int count = freq.get(j).get(i).intValue();
diff.get(j).put(i, oldValue / count);
}
}
printData(data);
}
/**
* Based on existing data predict all missing ratings. If prediction is not
* possible, the value will be equal to -1
*
* @param data
* existing user data and their items' ratings
*/
private static void predict(Map<User, HashMap<Item, Double>> data) {
HashMap<Item, Double> uPred = new HashMap<Item, Double>();
HashMap<Item, Integer> uFreq = new HashMap<Item, Integer>();
for (Item j : diff.keySet()) {
uFreq.put(j, 0);
uPred.put(j, 0.0);
}
for (Entry<User, HashMap<Item, Double>> e : data.entrySet()) {
for (Item j : e.getValue().keySet()) {
for (Item k : diff.keySet()) {
try {
double predictedValue = diff.get(k).get(j).doubleValue() + e.getValue().get(j).doubleValue();
double finalValue = predictedValue * freq.get(k).get(j).intValue();
uPred.put(k, uPred.get(k) + finalValue);
uFreq.put(k, uFreq.get(k) + freq.get(k).get(j).intValue());
} catch (NullPointerException e1) {
}
}
}
HashMap<Item, Double> clean = new HashMap<Item, Double>();
for (Item j : uPred.keySet()) {
if (uFreq.get(j) > 0) {
clean.put(j, uPred.get(j).doubleValue() / uFreq.get(j).intValue());
}
}
for (Item j : InputData.items) {
if (e.getValue().containsKey(j)) {
clean.put(j, e.getValue().get(j));
} else if (!clean.containsKey(j)) {
clean.put(j, -1.0);
}
}
outputData.put(e.getKey(), clean);
}
printData(outputData);
}
private static void printData(Map<User, HashMap<Item, Double>> data) {
for (User user : data.keySet()) {
System.out.println(user.getUsername() + ":");
print(data.get(user));
}
}
private static void print(HashMap<Item, Double> hashMap) {
NumberFormat formatter = new DecimalFormat("#0.000");
for (Item j : hashMap.keySet()) {
System.out.println(" " + j.getItemName() + " --> " + formatter.format(hashMap.get(j).doubleValue()));
}
}
}
@@ -0,0 +1,14 @@
package com.baeldung.algorithms.slope_one;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String username;
}
@@ -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;
}
}
@@ -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>
@@ -0,0 +1,12 @@
S ########
# #
# ### ## #
# # # #
# # # # #
# ## #####
# # #
# # # # #
##### ####
# # E
# # # #
##########
@@ -0,0 +1,22 @@
S ##########################
# # # #
# # #### ############### #
# # # # # #
# # #### # # ###############
# # # # # # #
# # # #### ### ########### #
# # # # # #
# ################## #
######### # # # # #
# # #### # ####### # #
# # ### ### # # # # #
# # ## # ##### # #
##### ####### # # # # #
# # ## ## #### # #
# ##### ####### # #
# # ############
####### ######### # #
# # ######## #
# ####### ###### ## # E
# # # ## #
############################