1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#include "WordTree.hpp"
#include "rlutil.h"
#include <algorithm>
#include <fstream>
#include <iterator>
#include <memory>
#include <sstream>
#include <string>
template <typename Out>
void split(const std::string& s, char delim, Out result)
{
std::istringstream iss(s);
std::string item;
while (std::getline(iss, item, delim))
{
*result++ = item;
}
}
std::vector<std::string> split(const std::string& s, char delim)
{
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
class TypeAhead
{
std::string m_sentence;
std::shared_ptr<WordTree> m_wordTree;
public:
TypeAhead() :
m_sentence(""), m_wordTree(std::make_shared<WordTree>()) {}
void constructWordTreeFromFile(std::string filename)
{
std::ifstream inFile = std::ifstream(filename, std::ios::in);
while (!inFile.eof())
{
std::string word;
std::getline(inFile, word);
// Need to consume the carriage return character for some systems, if it exists
if (!word.empty() && word[word.size() - 1] == '\r')
{
word.erase(word.end() - 1);
}
// Keep only if everything is an alphabetic character -- Have to send isalpha an unsigned char or
// it will throw exception on negative values; e.g., characters with accent marks.
if (std::all_of(word.begin(), word.end(), [](unsigned char c)
{ return std::isalpha(c); }))
{
std::transform(word.begin(), word.end(), word.begin(), [](char c)
{ return static_cast<char>(std::tolower(c)); });
m_wordTree->add(word);
}
}
}
bool update()
{
char input = rlutil::getkey();
if (input == rlutil::KEY_ESCAPE)
return false;
if (input == rlutil::KEY_BACKSPACE)
{
if (m_sentence.length() > 0)
m_sentence.pop_back();
return true;
}
m_sentence += input;
return true;
}
void draw()
{
rlutil::cls();
std::uint32_t cursorY = m_sentence.size() / rlutil::tcols() + 1;
std::uint32_t cursorX = m_sentence.length() % rlutil::tcols();
std::cout << m_sentence << std::endl;
std::cout << " --- predictions ---" << std::endl;
if (m_sentence.size() > 0 && m_sentence.back() != ' ')
{
std::vector<std::string> words = split(m_sentence, ' ');
std::string currentWord = words.back();
std::transform(currentWord.begin(), currentWord.end(), currentWord.begin(), ::tolower);
std::vector<std::string> predictions = m_wordTree->predict(currentWord, rlutil::trows() - cursorY - 2);
for (std::string prediction : predictions)
std::cout << prediction << std::endl;
}
rlutil::locate(cursorX + 1, cursorY);
}
};
int main()
{
rlutil::cls();
TypeAhead program;
program.constructWordTreeFromFile("dictionary.txt");
do
{
program.draw();
} while (program.update());
return 0;
}
|