Skip to content

Instantly share code, notes, and snippets.

@FireBanana
Last active April 3, 2019 05:29
Show Gist options
  • Save FireBanana/40b75a05caae2717985c6d5c36a2669e to your computer and use it in GitHub Desktop.
Save FireBanana/40b75a05caae2717985c6d5c36a2669e to your computer and use it in GitHub Desktop.
A prefix tree for scrabble or other word games.
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