Last active
April 3, 2019 05:29
-
-
Save FireBanana/40b75a05caae2717985c6d5c36a2669e to your computer and use it in GitHub Desktop.
A prefix tree for scrabble or other word games.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
/* | |
A 'dictionary' for scrabble or other games where you can add words and retrieve them with results such as: | |
input: "app" | |
result: "apple", "application"... | |
*/ | |
public class ScrabbleTrie | |
{ | |
delegate void OnWordCallback(string word); | |
public struct Node | |
{ | |
public Dictionary<char, Node> Children; | |
public bool IsEnd; | |
public char Character; | |
public Node[] Parent; //Must contain 1 | |
} | |
private Node _root; | |
private int _size; | |
public ScrabbleTrie() | |
{ | |
_root = new Node(); | |
_root.Parent = new Node[0]; | |
_root.Children = new Dictionary<char, Node>(); | |
} | |
public void Add(string word) | |
{ | |
var nodeIncrement = _root; | |
int count = 1; | |
foreach (var ch in word) | |
{ | |
if (nodeIncrement.Children.ContainsKey(ch)) | |
{ | |
if (count == word.Length) | |
{ | |
var temp = nodeIncrement.Children[ch]; | |
temp.IsEnd = true; | |
nodeIncrement.Children[ch] = temp; | |
} | |
nodeIncrement = nodeIncrement.Children[ch]; | |
} | |
else | |
{ | |
var newNode = new Node(); | |
newNode.Character = ch; | |
newNode.IsEnd = count == word.Length; | |
newNode.Parent = new[] {nodeIncrement}; | |
newNode.Children = new Dictionary<char, Node>(); | |
nodeIncrement.Children.Add(ch, newNode); | |
nodeIncrement = newNode; | |
} | |
count++; | |
} | |
_size++; | |
} | |
public List<string> GetWords(string word) | |
{ | |
List<string> words = new List<string>(); | |
Node traverseNode = _root; | |
bool wordFound = false; | |
foreach (var ch in word) | |
{ | |
if (traverseNode.Children.ContainsKey(ch)) | |
{ | |
if (wordFound == false) | |
wordFound = true; | |
traverseNode = traverseNode.Children[ch]; | |
} | |
else | |
{ | |
break; | |
} | |
} | |
if (wordFound) | |
Get(traverseNode, x => { words.Add(Reverse(x)); }); | |
return words; | |
} | |
public int GetSize() | |
{ | |
return _size; | |
} | |
void Get(Node node, OnWordCallback callback) | |
{ | |
if (node.IsEnd) | |
callback.Invoke(Pop(node)); | |
foreach (var child in node.Children) | |
{ | |
if (child.Value.IsEnd) | |
{ | |
callback.Invoke(Pop(child.Value)); | |
} | |
foreach (var subChild in child.Value.Children) | |
{ | |
Get(subChild.Value, callback); | |
} | |
} | |
} | |
string Pop(Node startNode) | |
{ | |
string word = ""; | |
Node traverseNode = startNode; | |
while (traverseNode.Parent.Length != 0) | |
{ | |
word += traverseNode.Character; | |
traverseNode = traverseNode.Parent[0]; | |
} | |
return word; | |
} | |
string Reverse(string word) | |
{ | |
string newString = ""; | |
for (int i = word.Length - 1; i >= 0; i--) | |
{ | |
newString += word[i]; | |
} | |
return newString; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment