Open In App

Boggle using Trie

Improve
Improve
Like Article
Like
Save
Share
Report

Given a dictionary, a method to do a lookup in the dictionary and a M x N board where every cell has one character. Find all possible words that can be formed by a sequence of adjacent characters. Note that we can move to any of 8 adjacent characters, but a word should not have multiple instances of the same cell.
Example: 
 

Input: dictionary[] = {"GEEKS", "FOR", "QUIZ", "GO"};
       boggle[][]   = {{'G', 'I', 'Z'},
                       {'U', 'E', 'K'},
                       {'Q', 'S', 'E'}};

Output: Following words of the dictionary are present
         GEEKS
         QUIZ

Explanation:

Input: dictionary[] = {"GEEKS", "ABCFIHGDE"};
       boggle[][]   = {{'A', 'B', 'C'},
                       {'D', 'E', 'F'},
                       {'G', 'H', 'I'}};
Output: Following words of the dictionary are present
         ABCFIHGDE     
Explanation:

 
Recommended Practice

We have discussed a Graph DFS based solution in below post. 
Boggle (Find all possible words in a board of characters) | Set 1
Here we discuss a Trie based solution which is better than DFS based solution. 
Given Dictionary dictionary[] = {“GEEKS”, “FOR”, “QUIZ”, “GO”} 
1. Create an Empty trie and insert all words of given dictionary into trie 
 

After insertion, Trie looks like(leaf nodes are in RED)
                       root
                    /       
                    G   F     Q
                 /  |   |     |
                O   E   O     U
                    |   |     |
                    E    R     I
                    |         |  
                    K         Z 
                    |   
                    S   

2. After that we have pick only those character in boggle[][] which are child of root of Trie 
Let for above we pick ‘G’ boggle[0][0], ‘Q’ boggle[2][0] (they both are present in boggle matrix) 
3. search a word in a trie which start with character that we pick in step 2 
 

1) Create bool visited boolean matrix (Visited[M][N] = false )
2) Call SearchWord() for every cell (i, j) which has one of the
   first characters of dictionary words. In above example,
   we have 'G' and 'Q' as first characters.

SearchWord(Trie *root, i, j, visited[][N])
if root->leaf == true 
   print word 

if we have seen this element first time then make it visited.
   visited[i][j] = true
   do
      traverse all child of current root 
      k goes (0 to 26 ) [there are only 26 Alphabet] 
      add current char and search for next character 

      find next character which is adjacent to boggle[i][j]
      they are 8 adjacent cells of boggle[i][j] (i+1, j+1), 
      (i+1, j) (i-1, j) and so on.
   
   make it unvisited visited[i][j] = false 

Below is the implementation of above idea: 
 

C++




// C++ program for Boggle game
#include <bits/stdc++.h>
using namespace std;
 
// Converts key current character into index
// use only 'A' through 'Z'
#define char_int(c) ((int)c - (int)'A')
 
// Alphabet size
#define SIZE (26)
 
#define M 3
#define N 3
 
// trie Node
struct TrieNode {
    TrieNode* Child[SIZE];
 
    // isLeaf is true if the node represents
    // end of a word
    bool leaf;
};
 
// Returns new trie node (initialized to NULLs)
TrieNode* getNode()
{
    TrieNode* newNode = new TrieNode;
    newNode->leaf = false;
    for (int i = 0; i < SIZE; i++)
        newNode->Child[i] = NULL;
    return newNode;
}
 
// If not present, inserts a key into the trie
// If the key is a prefix of trie node, just
// marks leaf node
void insert(TrieNode* root, char* Key)
{
    int n = strlen(Key);
    TrieNode* pChild = root;
 
    for (int i = 0; i < n; i++) {
        int index = char_int(Key[i]);
 
        if (pChild->Child[index] == NULL)
            pChild->Child[index] = getNode();
 
        pChild = pChild->Child[index];
    }
 
    // make last node as leaf node
    pChild->leaf = true;
}
 
// function to check that current location
// (i and j) is in matrix range
bool isSafe(int i, int j, bool visited[M][N])
{
    return (i >= 0 && i < M && j >= 0 && j < N && !visited[i][j]);
}
 
// A recursive function to print all words present on boggle
void searchWord(TrieNode* root, char boggle[M][N], int i,
                int j, bool visited[][N], string str)
{
    // if we found word in trie / dictionary
    if (root->leaf == true)
        cout << str << endl;
 
    // If both I and j in  range and we visited
    // that element of matrix first time
    if (isSafe(i, j, visited)) {
        // make it visited
        visited[i][j] = true;
 
        // traverse all childs of current root
        for (int K = 0; K < SIZE; K++) {
            if (root->Child[K] != NULL) {
                // current character
                char ch = (char)K + (char)'A';
 
                // Recursively search reaming character of word
                // in trie for all 8 adjacent cells of boggle[i][j]
                if (isSafe(i + 1, j + 1, visited)
                    && boggle[i + 1][j + 1] == ch)
                    searchWord(root->Child[K], boggle,
                               i + 1, j + 1, visited, str + ch);
                if (isSafe(i, j + 1, visited)
                    && boggle[i][j + 1] == ch)
                    searchWord(root->Child[K], boggle,
                               i, j + 1, visited, str + ch);
                if (isSafe(i - 1, j + 1, visited)
                    && boggle[i - 1][j + 1] == ch)
                    searchWord(root->Child[K], boggle,
                               i - 1, j + 1, visited, str + ch);
                if (isSafe(i + 1, j, visited)
                    && boggle[i + 1][j] == ch)
                    searchWord(root->Child[K], boggle,
                               i + 1, j, visited, str + ch);
                if (isSafe(i + 1, j - 1, visited)
                    && boggle[i + 1][j - 1] == ch)
                    searchWord(root->Child[K], boggle,
                               i + 1, j - 1, visited, str + ch);
                if (isSafe(i, j - 1, visited)
                    && boggle[i][j - 1] == ch)
                    searchWord(root->Child[K], boggle,
                               i, j - 1, visited, str + ch);
                if (isSafe(i - 1, j - 1, visited)
                    && boggle[i - 1][j - 1] == ch)
                    searchWord(root->Child[K], boggle,
                               i - 1, j - 1, visited, str + ch);
                if (isSafe(i - 1, j, visited)
                    && boggle[i - 1][j] == ch)
                    searchWord(root->Child[K], boggle,
                               i - 1, j, visited, str + ch);
            }
        }
 
        // make current element unvisited
        visited[i][j] = false;
    }
}
 
// Prints all words present in dictionary.
void findWords(char boggle[M][N], TrieNode* root)
{
    // Mark all characters as not visited
    bool visited[M][N];
    memset(visited, false, sizeof(visited));
 
    TrieNode* pChild = root;
 
    string str = "";
 
    // traverse all matrix elements
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < N; j++) {
            // we start searching for word in dictionary
            // if we found a character which is child
            // of Trie root
            if (pChild->Child[char_int(boggle[i][j])]) {
                str = str + boggle[i][j];
                searchWord(pChild->Child[char_int(boggle[i][j])],
                           boggle, i, j, visited, str);
                str = "";
            }
        }
    }
}
 
// Driver program to test above function
int main()
{
    // Let the given dictionary be following
    char* dictionary[] = { "GEEKS", "FOR", "QUIZ", "GEE" };
 
    // root Node of trie
    TrieNode* root = getNode();
 
    // insert all words of dictionary into trie
    int n = sizeof(dictionary) / sizeof(dictionary[0]);
    for (int i = 0; i < n; i++)
        insert(root, dictionary[i]);
 
    char boggle[M][N] = { { 'G', 'I', 'Z' },
                          { 'U', 'E', 'K' },
                          { 'Q', 'S', 'E' } };
 
    findWords(boggle, root);
 
    return 0;
}


Java




// Java program for Boggle game
public class Boggle {
 
    // Alphabet size
    static final int SIZE = 26;
 
    static final int M = 3;
    static final int N = 3;
 
    // trie Node
    static class TrieNode {
        TrieNode[] Child = new TrieNode[SIZE];
 
        // isLeaf is true if the node represents
        // end of a word
        boolean leaf;
 
        // constructor
        public TrieNode()
        {
            leaf = false;
            for (int i = 0; i < SIZE; i++)
                Child[i] = null;
        }
    }
 
    // If not present, inserts a key into the trie
    // If the key is a prefix of trie node, just
    // marks leaf node
    static void insert(TrieNode root, String Key)
    {
        int n = Key.length();
        TrieNode pChild = root;
 
        for (int i = 0; i < n; i++) {
            int index = Key.charAt(i) - 'A';
 
            if (pChild.Child[index] == null)
                pChild.Child[index] = new TrieNode();
 
            pChild = pChild.Child[index];
        }
 
        // make last node as leaf node
        pChild.leaf = true;
    }
 
    // function to check that current location
    // (i and j) is in matrix range
    static boolean isSafe(int i, int j, boolean visited[][])
    {
        return (i >= 0 && i < M && j >= 0
                && j < N && !visited[i][j]);
    }
 
    // A recursive function to print
    // all words present on boggle
    static void searchWord(TrieNode root, char boggle[][], int i,
                           int j, boolean visited[][], String str)
    {
        // if we found word in trie / dictionary
        if (root.leaf == true)
            System.out.println(str);
 
        // If both I and j in  range and we visited
        // that element of matrix first time
        if (isSafe(i, j, visited)) {
            // make it visited
            visited[i][j] = true;
 
            // traverse all child of current root
            for (int K = 0; K < SIZE; K++) {
                if (root.Child[K] != null) {
                    // current character
                    char ch = (char)(K + 'A');
 
                    // Recursively search reaming character of word
                    // in trie for all 8 adjacent cells of
                    // boggle[i][j]
                    if (isSafe(i + 1, j + 1, visited)
                        && boggle[i + 1][j + 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i + 1, j + 1,
                                   visited, str + ch);
                    if (isSafe(i, j + 1, visited)
                        && boggle[i][j + 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i, j + 1,
                                   visited, str + ch);
                    if (isSafe(i - 1, j + 1, visited)
                        && boggle[i - 1][j + 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i - 1, j + 1,
                                   visited, str + ch);
                    if (isSafe(i + 1, j, visited)
                        && boggle[i + 1][j] == ch)
                        searchWord(root.Child[K], boggle,
                                   i + 1, j,
                                   visited, str + ch);
                    if (isSafe(i + 1, j - 1, visited)
                        && boggle[i + 1][j - 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i + 1, j - 1,
                                   visited, str + ch);
                    if (isSafe(i, j - 1, visited)
                        && boggle[i][j - 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i, j - 1,
                                   visited, str + ch);
                    if (isSafe(i - 1, j - 1, visited)
                        && boggle[i - 1][j - 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i - 1, j - 1,
                                   visited, str + ch);
                    if (isSafe(i - 1, j, visited)
                        && boggle[i - 1][j] == ch)
                        searchWord(root.Child[K], boggle,
                                   i - 1, j,
                                   visited, str + ch);
                }
            }
 
            // make current element unvisited
            visited[i][j] = false;
        }
    }
 
    // Prints all words present in dictionary.
    static void findWords(char boggle[][], TrieNode root)
    {
        // Mark all characters as not visited
        boolean[][] visited = new boolean[M][N];
        TrieNode pChild = root;
 
        String str = "";
 
        // traverse all matrix elements
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                // we start searching for word in dictionary
                // if we found a character which is child
                // of Trie root
                if (pChild.Child[(boggle[i][j]) - 'A'] != null) {
                    str = str + boggle[i][j];
                    searchWord(pChild.Child[(boggle[i][j]) - 'A'],
                               boggle, i, j, visited, str);
                    str = "";
                }
            }
        }
    }
 
    // Driver program to test above function
    public static void main(String args[])
    {
        // Let the given dictionary be following
        String dictionary[] = { "GEEKS", "FOR", "QUIZ", "GEE" };
 
        // root Node of trie
        TrieNode root = new TrieNode();
 
        // insert all words of dictionary into trie
        int n = dictionary.length;
        for (int i = 0; i < n; i++)
            insert(root, dictionary[i]);
 
        char boggle[][] = { { 'G', 'I', 'Z' },
                            { 'U', 'E', 'K' },
                            { 'Q', 'S', 'E' } };
 
        findWords(boggle, root);
    }
}
// This code is contributed by Sumit Ghosh


Python3




# Python program for Boggle game
class TrieNode:
 
    # Trie node class
    def __init__(self):
        self.children = [None] * 26
 
        # isEndOfWord is True if node represent the end of the word
        self.isEndOfWord = False
 
M = 3
N = 3
class Boogle:
 
    # Trie data structure class
    def __init__(self):
        self.root = self.getNode()
 
    def getNode(self):
 
        # Returns new trie node (initialized to NULLs)
        return TrieNode()
 
    def _charToIndex(self, ch):
 
        # private helper function
        # Converts key current character into index
        # use only 'A' through 'Z' and upper case
        return ord(ch) - ord('A')
 
    def insert(self, key):
 
        # If not present, inserts key into trie
        # If the key is prefix of trie node,
        # just marks leaf node
        pCrawl = self.root
        length = len(key)
        for level in range(length):
            index = self._charToIndex(key[level])
 
            # if current character is not present
            if not pCrawl.children[index]:
 
                pCrawl.children[index] = self.getNode()
            pCrawl = pCrawl.children[index]
            # print('h', self.root.children)
 
        # mark last node as leaf
        pCrawl.isEndOfWord = True
 
 
def is_Safe(i, j, vis):
    return 0 <= i < M and 0 <= j < N and not vis[i][j]
 
def search_word(root, boggle, i, j, vis, string):
    if root.isEndOfWord:
        print(string)
 
    if is_Safe(i, j, vis):
        vis[i][j] = True
        for K in range(26):
            if root.children[K] is not None:
                ch = chr(K+ord('A'))
                 
                # Recursively search reaming character of word
                # in trie for all 8 adjacent cells of boggle[i][j]
                if is_Safe(i + 1, j + 1, vis) and boggle[i + 1][j + 1] == ch:
                    search_word(root.children[K], boggle,
                                i + 1, j + 1, vis, string + ch)
                if is_Safe(i, j + 1, vis) and boggle[i][j + 1] == ch:
                    search_word(root.children[K], boggle,
                                i, j + 1, vis, string + ch)
                if is_Safe(i - 1, j + 1, vis) and boggle[i - 1][j + 1] == ch:
                    search_word(root.children[K], boggle,
                                i - 1, j + 1, vis, string + ch)
                if is_Safe(i + 1, j, vis) and boggle[i + 1][j] == ch:
                    search_word(root.children[K], boggle,
                                i + 1, j, vis, string + ch)
                if is_Safe(i + 1, j - 1, vis) and boggle[i + 1][j - 1] == ch:
                    search_word(root.children[K], boggle,
                                i + 1, j - 1, vis, string + ch)
                if is_Safe(i, j - 1, vis) and boggle[i][j - 1] == ch:
                    search_word(root.children[K], boggle,
                                i, j - 1, vis, string + ch)
                if is_Safe(i - 1, j - 1, vis) and boggle[i - 1][j - 1] == ch:
                    search_word(root.children[K], boggle,
                                i - 1, j - 1, vis, string + ch)
                if is_Safe(i - 1, j, vis) and boggle[i - 1][j] == ch:
                    search_word(root.children[K], boggle,
                                i - 1, j, vis, string + ch)
                vis[i][j] = False
 
 
def char_int(ch):
   
    # private helper function
    # Converts key current character into index
    # use only 'A' through 'Z' and upper case
    return ord(ch) - ord('A')
 
 
def findWords(boggle, root):
   
    # Mark all characters as not visited
    visited = [[False for i in range(N)] for i in range(M)]
 
    pChild = root
 
    string = ""
 
    # traverse all matrix elements
    for i in range(M):
        for j in range(N):
            # we start searching for word in dictionary
            # if we found a character which is child
            # of Trie root
            if pChild.children[char_int(boggle[i][j])]:
                # print('h')
                string = string + boggle[i][j]
                search_word(pChild.children[char_int(boggle[i][j])],
                            boggle, i, j, visited, string)
                string = ""
 
dictionary = ["GEEKS", "FOR", "QUIZ", "GEE"]
 
# root Node of trie
t = Boogle()
 
# insert all words of dictionary into trie
n = len(dictionary)
for i in range(n):
 
    t.insert(dictionary[i])
root = t.root
boggle = [['G', 'I', 'Z'],
          ['U', 'E', 'K'],
          ['Q', 'S', 'E']]
 
# print(root.children)
findWords(boggle, root)
 
# This code is contributed by Yashwant Kumar


C#




// C# program for Boggle game
using System;
 
public class Boggle {
 
    // Alphabet size
    static readonly int SIZE = 26;
 
    static readonly int M = 3;
    static readonly int N = 3;
 
    // trie Node
    public class TrieNode {
        public TrieNode[] Child = new TrieNode[SIZE];
 
        // isLeaf is true if the node represents
        // end of a word
        public bool leaf;
 
        // constructor
        public TrieNode()
        {
            leaf = false;
            for (int i = 0; i < SIZE; i++)
                Child[i] = null;
        }
    }
 
    // If not present, inserts a key into the trie
    // If the key is a prefix of trie node, just
    // marks leaf node
    static void insert(TrieNode root, String Key)
    {
        int n = Key.Length;
        TrieNode pChild = root;
 
        for (int i = 0; i < n; i++) {
            int index = Key[i] - 'A';
 
            if (pChild.Child[index] == null)
                pChild.Child[index] = new TrieNode();
 
            pChild = pChild.Child[index];
        }
 
        // make last node as leaf node
        pChild.leaf = true;
    }
 
    // function to check that current location
    // (i and j) is in matrix range
    static bool isSafe(int i, int j, bool[, ] visited)
    {
        return (i >= 0 && i < M && j >= 0 && j < N && !visited[i, j]);
    }
 
    // A recursive function to print all words present on boggle
    static void searchWord(TrieNode root, char[, ] boggle, int i,
                           int j, bool[, ] visited, String str)
    {
        // if we found word in trie / dictionary
        if (root.leaf == true)
            Console.WriteLine(str);
 
        // If both I and j in range and we visited
        // that element of matrix first time
        if (isSafe(i, j, visited)) {
            // make it visited
            visited[i, j] = true;
 
            // traverse all child of current root
            for (int K = 0; K < SIZE; K++) {
                if (root.Child[K] != null) {
                    // current character
                    char ch = (char)(K + 'A');
 
                    // Recursively search reaming character of word
                    // in trie for all 8 adjacent cells of
                    // boggle[i, j]
                    if (isSafe(i + 1, j + 1, visited) && boggle[i + 1, j + 1] == ch)
                        searchWord(root.Child[K], boggle, i + 1, j + 1,
                                   visited, str + ch);
                    if (isSafe(i, j + 1, visited) && boggle[i, j + 1] == ch)
                        searchWord(root.Child[K], boggle, i, j + 1,
                                   visited, str + ch);
                    if (isSafe(i - 1, j + 1, visited) && boggle[i - 1, j + 1] == ch)
                        searchWord(root.Child[K], boggle, i - 1, j + 1,
                                   visited, str + ch);
                    if (isSafe(i + 1, j, visited) && boggle[i + 1, j] == ch)
                        searchWord(root.Child[K], boggle, i + 1, j,
                                   visited, str + ch);
                    if (isSafe(i + 1, j - 1, visited) && boggle[i + 1, j - 1] == ch)
                        searchWord(root.Child[K], boggle, i + 1, j - 1,
                                   visited, str + ch);
                    if (isSafe(i, j - 1, visited) && boggle[i, j - 1] == ch)
                        searchWord(root.Child[K], boggle, i, j - 1,
                                   visited, str + ch);
                    if (isSafe(i - 1, j - 1, visited) && boggle[i - 1, j - 1] == ch)
                        searchWord(root.Child[K], boggle, i - 1, j - 1,
                                   visited, str + ch);
                    if (isSafe(i - 1, j, visited) && boggle[i - 1, j] == ch)
                        searchWord(root.Child[K], boggle, i - 1, j,
                                   visited, str + ch);
                }
            }
 
            // make current element unvisited
            visited[i, j] = false;
        }
    }
 
    // Prints all words present in dictionary.
    static void findWords(char[, ] boggle, TrieNode root)
    {
        // Mark all characters as not visited
        bool[, ] visited = new bool[M, N];
        TrieNode pChild = root;
 
        String str = "";
 
        // traverse all matrix elements
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                // we start searching for word in dictionary
                // if we found a character which is child
                // of Trie root
                if (pChild.Child[(boggle[i, j]) - 'A'] != null) {
                    str = str + boggle[i, j];
                    searchWord(pChild.Child[(boggle[i, j]) - 'A'],
                               boggle, i, j, visited, str);
                    str = "";
                }
            }
        }
    }
 
    // Driver program to test above function
    public static void Main(String[] args)
    {
        // Let the given dictionary be following
        String[] dictionary = { "GEEKS", "FOR", "QUIZ", "GEE" };
 
        // root Node of trie
        TrieNode root = new TrieNode();
 
        // insert all words of dictionary into trie
        int n = dictionary.Length;
        for (int i = 0; i < n; i++)
            insert(root, dictionary[i]);
 
        char[, ] boggle = { { 'G', 'I', 'Z' },
                            { 'U', 'E', 'K' },
                            { 'Q', 'S', 'E' } };
        findWords(boggle, root);
    }
}
 
// This code has been contributed by 29AjayKumar


Javascript




<script>
// Javascript program for Boggle game
 
// Alphabet size
let SIZE = 26;
let M = 3;
let N = 3;
 
 // trie Node
class TrieNode
{
    constructor()
    {
        this.leaf=false;
        this.Child = new Array(SIZE);
        for (let i = 0; i < SIZE; i++)
            this.Child[i]=null;
    }
}
 
// If not present, inserts a key into the trie
    // If the key is a prefix of trie node, just
    // marks leaf node
function insert(root,Key)
{
    let n = Key.length;
        let pChild = root;
   
        for (let i = 0; i < n; i++) {
            let index = Key[i].charCodeAt(0) - 'A'.charCodeAt(0);
   
            if (pChild.Child[index] == null)
                pChild.Child[index] = new TrieNode();
   
            pChild = pChild.Child[index];
        }
   
        // make last node as leaf node
        pChild.leaf = true;
}
 
// function to check that current location
    // (i and j) is in matrix range
function isSafe(i,j,visited)
{
    return (i >= 0 && i < M && j >= 0
                && j < N && !visited[i][j]);
}
 
// A recursive function to print
    // all words present on boggle
function searchWord(root,boggle,i,j,visited,str)
{
    // if we found word in trie / dictionary
        if (root.leaf == true)
            document.write(str+" <br>");
   
        // If both I and j in  range and we visited
        // that element of matrix first time
        if (isSafe(i, j, visited)) {
            // make it visited
            visited[i][j] = true;
   
            // traverse all child of current root
            for (let K = 0; K < SIZE; K++) {
                if (root.Child[K] != null) {
                    // current character
                    let ch = String.fromCharCode(K + 'A'.charCodeAt(0));
   
                    // Recursively search reaming character of word
                    // in trie for all 8 adjacent cells of
                    // boggle[i][j]
                    if (isSafe(i + 1, j + 1, visited)
                        && boggle[i + 1][j + 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i + 1, j + 1,
                                   visited, str + ch);
                    if (isSafe(i, j + 1, visited)
                        && boggle[i][j + 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i, j + 1,
                                   visited, str + ch);
                    if (isSafe(i - 1, j + 1, visited)
                        && boggle[i - 1][j + 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i - 1, j + 1,
                                   visited, str + ch);
                    if (isSafe(i + 1, j, visited)
                        && boggle[i + 1][j] == ch)
                        searchWord(root.Child[K], boggle,
                                   i + 1, j,
                                   visited, str + ch);
                    if (isSafe(i + 1, j - 1, visited)
                        && boggle[i + 1][j - 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i + 1, j - 1,
                                   visited, str + ch);
                    if (isSafe(i, j - 1, visited)
                        && boggle[i][j - 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i, j - 1,
                                   visited, str + ch);
                    if (isSafe(i - 1, j - 1, visited)
                        && boggle[i - 1][j - 1] == ch)
                        searchWord(root.Child[K], boggle,
                                   i - 1, j - 1,
                                   visited, str + ch);
                    if (isSafe(i - 1, j, visited)
                        && boggle[i - 1][j] == ch)
                        searchWord(root.Child[K], boggle,
                                   i - 1, j,
                                   visited, str + ch);
                }
            }
   
            // make current element unvisited
            visited[i][j] = false;
        }
}
 
// Prints all words present in dictionary.
function findWords(boggle,root)
{
    // Mark all characters as not visited
        let visited = new Array(M);
        for(let i=0;i<M;i++)
        {
            visited[i]=new Array(N);
            for(let j=0;j<N;j++)
            {
                visited[i][j]=false;
            }
        }
        let pChild = root;
   
        let str = "";
   
        // traverse all matrix elements
        for (let i = 0; i < M; i++) {
            for (let j = 0; j < N; j++) {
                // we start searching for word in dictionary
                // if we found a character which is child
                // of Trie root
                if (pChild.Child[(boggle[i][j]).charCodeAt(0) - 'A'.charCodeAt(0)] != null) {
                    str = str + boggle[i][j];
                    searchWord(pChild.Child[(boggle[i][j]).charCodeAt(0) - 'A'.charCodeAt(0)],
                               boggle, i, j, visited, str);
                    str = "";
                }
            }
        }
}
 
// Driver program to test above function
let dictionary=["GEEKS", "FOR", "QUIZ", "GEE" ];
// root Node of trie
let root = new TrieNode();
 
// insert all words of dictionary into trie
let n = dictionary.length;
for (let i = 0; i < n; i++)
    insert(root, dictionary[i]);
 
let boggle = [[ 'G', 'I', 'Z' ],
[ 'U', 'E', 'K' ],
[ 'Q', 'S', 'E' ]];
 
findWords(boggle, root);
 
 
// This code is contributed by rag2127
</script>


Output

GEE
GEEKS
QUIZ

Complexity Analysis: 
 

  • Time complexity: O(4^(N^2)). 
    Even after applying trie the time complexity remains same. For every cell there are 4 directions and there are N^2 cells. So the time complexity is O(4^(N^2)).
  • Auxiliary Space: O(N^2). 
    The maximum length of recursion can be N^2, where N is the side of the matrix. So the space Complexity is O(N^2).

OPTIMIZED APPROACH WITHOUT USING TRIE ( Short and Easy to understand with a better Time and Space complexity):

  1. First, we create a Set Data Structure and add all word in it to avoid duplicate word.
  2. Then we make a new array of type String and add those set elements to it.
  3. We check word by word using a for loop whether that particular word is present in the board and if it returns true , we shall add it our ArrayList<String>.
  4. While searching for a word in the board,we shall use backtracking so that while coming back,we can alter the board as it was before.
  5. Lastly we sort the array and print it.

C++




// C++ program for word Boggle
#include <bits/stdc++.h>
using namespace std;
 
bool exist(char board[][3], string word, int r, int c);
bool search(char board[][3], string word, int len, int i,
            int j, int r, int c);
 
vector<string> wordBoggle(char board[][3],
                          vector<string> dictionary)
{
    int r = 3;
    int c = 3;
 
    vector<string> temp;
    set<string> st(dictionary.begin(), dictionary.end());
    int n = st.size();
 
    string dict[n];
 
    int id = 0;
    for (string s : st)
        dict[id++] = s;
 
    for (int i = 0; i < n; i++) {
        if (exist(board, dict[i], r, c))
            temp.push_back(dict[i]);
    }
 
    return temp;
}
 
bool exist(char board[][3], string word, int r, int c)
{
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            if (board[i][j] == word[0]
                && search(board, word, 0, i, j, r, c))
                return true;
        }
    }
    return false;
}
 
bool search(char board[][3], string word, int len, int i,
            int j, int r, int c)
{
    if (i < 0 || i >= r || j < 0 || j >= c)
        return false;
 
    if (board[i][j] != word[len])
        return false;
 
    if (len == word.length() - 1)
        return true;
 
    char ch = board[i][j];
    board[i][j] = '@';
 
    bool ans
        = search(board, word, len + 1, i - 1, j, r, c)
          || search(board, word, len + 1, i + 1, j, r, c)
          || search(board, word, len + 1, i, j - 1, r, c)
          || search(board, word, len + 1, i, j + 1, r, c)
          || search(board, word, len + 1, i - 1, j + 1, r,
                    c)
          || search(board, word, len + 1, i - 1, j - 1, r,
                    c)
          || search(board, word, len + 1, i + 1, j - 1, r,
                    c)
          || search(board, word, len + 1, i + 1, j + 1, r,
                    c);
 
    board[i][j] = ch;
    return ans;
}
 
int main()
{
    vector<string> dictionary
        = { "GEEKS", "FOR", "QUIZ", "GEE" };
 
    char boggle[][3] = { { 'G', 'I', 'Z' },
                         { 'U', 'E', 'K' },
                         { 'Q', 'S', 'E' } };
 
    vector<string> ans = wordBoggle(boggle, dictionary);
 
    if (ans.size() == 0)
        cout << "-1" << endl;
    else {
        sort(ans.begin(), ans.end());
        for (int i = 0; i < ans.size(); i++) {
            cout << ans[i] << " ";
        }
        cout << endl;
    }
    return 0;
}
 
// Contributed by adityasha4x71


Java




// Java program for word Boggle
 
import java.io.*;
import java.util.*;
 
public class Boggle {
    public static String[] wordBoggle(char board[][],
                                      String[] dictionary)
    {
        int r = board.length;
        int c = board[0].length;
 
        ArrayList<String> temp = new ArrayList<>();
        Set<String> set = new HashSet<>();
 
        for (String i : dictionary)
            set.add(i);
        int n = set.size();
 
        String dict[] = new String[n];
 
        int id = 0;
        for (String s : set)
            dict[id++] = s;
 
        for (int i = 0; i < dict.length; i++) {
            if (exist(board, dict[i], r, c))
                temp.add(dict[i]);
        }
        String[] ans = new String[temp.size()];
        int idx = 0;
 
        for (String i : temp)
            ans[idx++] = i;
 
        return ans;
    }
    public static boolean exist(char board[][], String word,
                                int r, int c)
    {
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                if (board[i][j] == word.charAt(0)
                    && search(board, word, 0, i, j, r, c))
                    return true;
            }
        }
        return false;
    }
    public static boolean search(char board[][],
                                 String word, int len,
                                 int i, int j, int r, int c)
    {
        if (i < 0 || i >= r || j < 0 || j >= c)
            return false;
 
        if (board[i][j] != word.charAt(len))
            return false;
 
        if (len == word.length() - 1)
            return true;
 
        char ch = board[i][j];
        board[i][j] = '@';
 
        boolean ans
            = search(board, word, len + 1, i - 1, j, r, c)
              || search(board, word, len + 1, i + 1, j, r,
                        c)
              || search(board, word, len + 1, i, j - 1, r,
                        c)
              || search(board, word, len + 1, i, j + 1, r,
                        c)
              || search(board, word, len + 1, i - 1, j + 1,
                        r, c)
              || search(board, word, len + 1, i - 1, j - 1,
                        r, c)
              || search(board, word, len + 1, i + 1, j - 1,
                        r, c)
              || search(board, word, len + 1, i + 1, j + 1,
                        r, c);
 
        board[i][j] = ch;
        return ans;
    }
    public static void main(String[] args)
    {
        String dictionary[]
            = { "GEEKS", "FOR", "QUIZ", "GEE" };
 
        char boggle[][] = { { 'G', 'I', 'Z' },
                            { 'U', 'E', 'K' },
                            { 'Q', 'S', 'E' } };
 
        String ans[] = wordBoggle(boggle, dictionary);
 
        if (ans.length == 0)
            System.out.println("-1");
        else {
            Arrays.sort(ans);
            for (int i = 0; i < ans.length; i++) {
                System.out.print(ans[i] + " ");
            }
            System.out.println();
        }
    }
}
 
// This code is contributed by Raunak Singh


Python3




# Python code addition
 
def exist(board, word, r, c):
    for i in range(r):
        for j in range(c):
            if board[i][j] == word[0] and search(board, word, 0, i, j, r, c):
                return True
    return False
 
def search(board, word, length, i, j, r, c):
    if i < 0 or i >= r or j < 0 or j >= c:
        return False
 
    if board[i][j] != word[length]:
        return False
 
    if length == len(word) - 1:
        return True
 
    ch = board[i][j]
    board[i][j] = '@'
 
    ans = search(board, word, length+1, i-1, j, r, c) or \
          search(board, word, length+1, i+1, j, r, c) or \
          search(board, word, length+1, i, j-1, r, c) or \
          search(board, word, length+1, i, j+1, r, c) or \
          search(board, word, length+1, i-1, j+1, r, c) or \
          search(board, word, length+1, i-1, j-1, r, c) or \
          search(board, word, length+1, i+1, j-1, r, c) or \
          search(board, word, length+1, i+1, j+1, r, c)
 
    board[i][j] = ch
    return ans
 
def word_boggle(board, dictionary):
    r, c = 3, 3
 
    temp = []
    st = set(dictionary)
    n = len(st)
 
    dict = []
    for s in st:
        dict.append(s)
 
    for i in range(n):
        if exist(board, dict[i], r, c):
            temp.append(dict[i])
 
    return temp
 
 
if __name__ == '__main__':
    dictionary = ["GEEKS", "FOR", "QUIZ", "GEE"]
 
    boggle = [['G', 'I', 'Z'],
              ['U', 'E', 'K'],
              ['Q', 'S', 'E']]
 
    ans = word_boggle(boggle, dictionary)
 
    if len(ans) == 0:
        print("-1")
    else:
        ans.sort()
        print(" ".join(ans))
         
# The code is contributed by Nidhi goel.


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
public class Boggle {
public static string[] WordBoggle(char[,] board, string[] dictionary) {
int r = board.GetLength(0);
int c = board.GetLength(1);
    var temp = new List<string>();
    var set = new HashSet<string>(dictionary);
    int n = set.Count;
 
    string[] dict = set.ToArray();
 
    for (int i = 0; i < dict.Length; i++) {
        if (Exist(board, dict[i], r, c)) {
            temp.Add(dict[i]);
        }
    }
    string[] ans = temp.ToArray();
 
    return ans;
}
public static bool Exist(char[,] board, string word, int r, int c) {
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            if (board[i, j] == word[0] && Search(board, word, 0, i, j, r, c)) {
                return true;
            }
        }
    }
    return false;
}
public static bool Search(char[,] board, string word, int len, int i, int j, int r, int c) {
    if (i < 0 || i >= r || j < 0 || j >= c) {
        return false;
    }
 
    if (board[i, j] != word[len]) {
        return false;
    }
 
    if (len == word.Length - 1) {
        return true;
    }
 
    char ch = board[i, j];
    board[i, j] = '@';
 
    bool ans = Search(board, word, len + 1, i - 1, j, r, c) ||
               Search(board, word, len + 1, i + 1, j, r, c) ||
               Search(board, word, len + 1, i, j - 1, r, c) ||
               Search(board, word, len + 1, i, j + 1, r, c) ||
               Search(board, word, len + 1, i - 1, j + 1, r, c) ||
               Search(board, word, len + 1, i - 1, j - 1, r, c) ||
               Search(board, word, len + 1, i + 1, j - 1, r, c) ||
               Search(board, word, len + 1, i + 1, j + 1, r, c);
 
    board[i, j] = ch;
    return ans;
}
public static void Main(string[] args) {
    string[] dictionary = { "GEEKS", "FOR", "QUIZ", "GEE" };
 
    char[,] boggle = { { 'G', 'I', 'Z' },
                       { 'U', 'E', 'K' },
                       { 'Q', 'S', 'E' } };
 
    string[] ans = WordBoggle(boggle, dictionary);
 
    if (ans.Length == 0) {
        Console.WriteLine("-1");
    } else {
        Array.Sort(ans);
        foreach (string word in ans) {
            Console.Write(word + " ");
        }
        Console.WriteLine();
    }
}
}


Javascript




// JavaScript program for word Boggle
function exist(board, word, r, c) {
for (let i = 0; i < r; i++) {
for (let j = 0; j < c; j++) {
if (board[i][j] === word[0] && search(board, word, 0, i, j, r, c)) {
return true;
}
}
}
return false;
}
 
function search(board, word, len, i, j, r, c) {
if (i < 0 || i >= r || j < 0 || j >= c) {
return false;
}
 
if (board[i][j] !== word[len]) {
return false;
}
 
if (len === word.length - 1) {
return true;
}
 
const ch = board[i][j];
board[i][j] = '@';
 
const ans =
search(board, word, len + 1, i - 1, j, r, c) ||
search(board, word, len + 1, i + 1, j, r, c) ||
search(board, word, len + 1, i, j - 1, r, c) ||
search(board, word, len + 1, i, j + 1, r, c) ||
search(board, word, len + 1, i - 1, j + 1, r, c) ||
search(board, word, len + 1, i - 1, j - 1, r, c) ||
search(board, word, len + 1, i + 1, j - 1, r, c) ||
search(board, word, len + 1, i + 1, j + 1, r, c);
 
board[i][j] = ch;
return ans;
}
 
function wordBoggle(board, dictionary) {
const r = 3;
const c = 3;
 
const temp = [];
const st = new Set(dictionary);
const n = st.size;
 
const dict = Array.from(st);
 
for (let i = 0; i < n; i++) {
if (exist(board, dict[i], r, c)) {
temp.push(dict[i]);
}
}
 
return temp;
}
 
const dictionary = ["GEEKS", "FOR", "QUIZ", "GEE"];
 
const boggle = [
["G", "I", "Z"],
["U", "E", "K"],
["Q", "S", "E"],
];
 
const ans = wordBoggle(boggle, dictionary);
 
if (ans.length === 0) {
console.log("-1");
} else {
ans.sort();
for (let i = 0; i < ans.length; i++) {
console.log(ans[i] + " ");
}
console.log("");
}
// This code is contributed by user_dtewbxkn77n


Output

GEE GEEKS QUIZ 

Time Complexity: O(N*W + R*C^2)
Space Complexity: O(N*W + R*C)
 



Last Updated : 20 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads