Skip to content

Added new File WordBoggle.java in Java/Misc #2007

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 4, 2021
82 changes: 82 additions & 0 deletions Misc/RangeInSortedArray.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package Misc;

import java.util.*;

public class RangeInSortedArray {

public static void main(String[] args) {
// Testcases
assert Arrays.equals(sortedRange(new int[] {1, 2, 3, 3, 3, 4, 5}, 3), new int[] {2, 4});
assert Arrays.equals(sortedRange(new int[] {1, 2, 3, 3, 3, 4, 5}, 4), new int[] {5, 5});
assert Arrays.equals(sortedRange(new int[] {0, 1, 2}, 3), new int[] {-1, -1});
}

// Get the 1st and last occurrence index of a number 'key' in a non-decreasing array 'nums'
// Gives [-1, -1] in case element doesn't exist in array
public static int[] sortedRange(int[] nums, int key) {
int[] range = new int[] {-1, -1};
alteredBinSearchIter(nums, key, 0, nums.length - 1, range, true);
alteredBinSearchIter(nums, key, 0, nums.length - 1, range, false);
return range;
}

// Recursive altered binary search which searches for leftmost as well as rightmost occurrence of
// 'key'
public static void alteredBinSearch(
int[] nums, int key, int left, int right, int[] range, boolean goLeft) {
if (left > right) return;
int mid = (left + right) / 2;
if (nums[mid] > key) alteredBinSearch(nums, key, left, mid - 1, range, goLeft);
else if (nums[mid] < key) alteredBinSearch(nums, key, mid + 1, right, range, goLeft);
else {
if (goLeft) {
if (mid == 0 || nums[mid - 1] != key) range[0] = mid;
else alteredBinSearch(nums, key, left, mid - 1, range, goLeft);
} else {
if (mid == nums.length - 1 || nums[mid + 1] != key) range[1] = mid;
else alteredBinSearch(nums, key, mid + 1, right, range, goLeft);
}
}
}

// Iterative altered binary search which searches for leftmost as well as rightmost occurrence of
// 'key'
public static void alteredBinSearchIter(
int[] nums, int key, int left, int right, int[] range, boolean goLeft) {
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] > key) right = mid - 1;
else if (nums[mid] < key) left = mid + 1;
else {
if (goLeft) {
if (mid == 0 || nums[mid - 1] != key) {
range[0] = mid;
return;
} else right = mid - 1;
} else {
if (mid == nums.length - 1 || nums[mid + 1] != key) {
range[1] = mid;
return;
} else left = mid + 1;
}
}
}
}

public static int getCountLessThan(int[] nums, int key) {
return getLessThan(nums, key, 0, nums.length - 1);
}

public static int getLessThan(int[] nums, int key, int left, int right) {
int count = 0;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] > key) right = mid - 1;
else if (nums[mid] <= key) {
count = mid + 1; // Atleast mid+1 elements exist which are <= key
left = mid + 1;
}
}
return count;
}
}
130 changes: 130 additions & 0 deletions Misc/WordBoggle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import java.util.*;

public class WordBoggle {

/**
* O(nm * 8^s + ws) time where n=width of boggle board, m=height of boggle board, s=length of
* longest word in string array, w= length of string array, 8 is due to 8 explorable neighbours
* O(nm + ws) space.
*/
public static List<String> boggleBoard(char[][] board, String[] words) {
Trie trie = new Trie();
for (String word : words) trie.add(word);
Set<String> finalWords = new HashSet<>();
boolean[][] visited = new boolean[board.length][board.length];
for (int i = 0; i < board.length; i++)
for (int j = 0; j < board[i].length; j++)
explore(i, j, board, trie.root, visited, finalWords);
return new ArrayList<>(finalWords);
}

public static void main(String[] args) {
// Testcase
List<String> ans =
new ArrayList<>(
Arrays.asList("a", "boggle", "this", "NOTRE_PEATED", "is", "simple", "board"));
assert (boggleBoard(
new char[][] {
{'t', 'h', 'i', 's', 'i', 's', 'a'},
{'s', 'i', 'm', 'p', 'l', 'e', 'x'},
{'b', 'x', 'x', 'x', 'x', 'e', 'b'},
{'x', 'o', 'g', 'g', 'l', 'x', 'o'},
{'x', 'x', 'x', 'D', 'T', 'r', 'a'},
{'R', 'E', 'P', 'E', 'A', 'd', 'x'},
{'x', 'x', 'x', 'x', 'x', 'x', 'x'},
{'N', 'O', 'T', 'R', 'E', '_', 'P'},
{'x', 'x', 'D', 'E', 'T', 'A', 'E'},
},
new String[] {
"this",
"is",
"not",
"a",
"simple",
"test",
"boggle",
"board",
"REPEATED",
"NOTRE_PEATED",
})
.equals(ans));
}

public static void explore(
int i,
int j,
char[][] board,
TrieNode trieNode,
boolean[][] visited,
Set<String> finalWords) {
if (visited[i][j]) return;

char letter = board[i][j];
if (!trieNode.children.containsKey(letter)) {
return;
}
visited[i][j] = true;
trieNode = trieNode.children.get(letter);
if (trieNode.children.containsKey('*')) finalWords.add(trieNode.word);

List<Integer[]> neighbors = getNeighbors(i, j, board);
for (Integer[] neighbor : neighbors)
explore(neighbor[0], neighbor[1], board, trieNode, visited, finalWords);

visited[i][j] = false;
}

public static List<Integer[]> getNeighbors(int i, int j, char[][] board) {
List<Integer[]> neighbors = new ArrayList<>();
if (i > 0 && j > 0) neighbors.add(new Integer[] {i - 1, j - 1});

if (i > 0 && j < board[0].length - 1) neighbors.add(new Integer[] {i - 1, j + 1});

if (i < board.length - 1 && j < board[0].length - 1)
neighbors.add(new Integer[] {i + 1, j + 1});

if (i < board.length - 1 && j > 0) neighbors.add(new Integer[] {i + 1, j - 1});

if (i > 0) neighbors.add(new Integer[] {i - 1, j});

if (i < board.length - 1) neighbors.add(new Integer[] {i + 1, j});

if (j > 0) neighbors.add(new Integer[] {i, j - 1});

if (j < board[0].length - 1) neighbors.add(new Integer[] {i, j + 1});

return neighbors;
}
}

// Trie used to optimize string search
class TrieNode {

Map<Character, TrieNode> children = new HashMap<>();
String word = "";
}

class Trie {

TrieNode root;
char endSymbol;

public Trie() {
this.root = new TrieNode();
this.endSymbol = '*';
}

public void add(String str) {
TrieNode node = this.root;
for (int i = 0; i < str.length(); i++) {
char letter = str.charAt(i);
if (!node.children.containsKey(letter)) {
TrieNode newNode = new TrieNode();
node.children.put(letter, newNode);
}
node = node.children.get(letter);
}
node.children.put(this.endSymbol, null);
node.word = str;
}
}