Technical test for a job interview.
1#include <iostream>
2#include "numeral_manager.hpp"
3
4bool NumeralManager::add(std::string word, int value, bool exclusive)
5{
6 bool success = false;
7 if (exclusive)
8 {
9 success = _numeral_exclusive.insert(word);
10 }
11 else
12 {
13 success = _context_dependent.insert(word);
14 }
15
16 _values[word] = value;
17 return success;
18}
19
20bool NumeralManager::add(std::string word, NumeralModifier::Join joiner, bool exclusive)
21{
22 bool success = false;
23 if (exclusive)
24 {
25 success = _numeral_exclusive.insert(word);
26 }
27 else
28 {
29 success = _context_dependent.insert(word);
30 }
31
32 _modifiers[word] = joiner;
33 return success;
34}
35
36bool NumeralManager::isNumeralWord(std::string word)
37{
38 bool exclusive_find = _numeral_exclusive.search(word);
39
40 return exclusive_find || (_numeral_context && _context_dependent.search(word));
41}
42
43NumeralWord *NumeralManager::analyze_numeral(std::string &text, int &pos, bool &alnum_state, bool &is_alnum, int &last_val)
44{
45 std::string word = "";
46 NumeralWord *numeral = nullptr;
47 int val = last_val;
48 int old_pos = pos;
49 alnum_state = std::isalnum(text[pos]);
50 is_alnum = std::isalnum(text[pos]);
51
52 while (pos < text.length())
53 {
54 word = "";
55
56 while (pos < text.length() && is_alnum == alnum_state)
57 {
58 word += text[pos];
59 pos++;
60 is_alnum = std::isalnum(text[pos]);
61 }
62
63 if (alnum_state == true && !word.empty())
64 {
65 // If we have read an alphanumeric chunk of characters
66 if (_modifiers.find(word) != _modifiers.end())
67 {
68 if (numeral == nullptr)
69 {
70 numeral = new NumeralModifier(word, _modifiers[word]);
71 }
72 else
73 {
74 NumeralModifier *mod = new NumeralModifier(word, numeral, _modifiers[word]);
75 NumeralWord *next_numeral = analyze_numeral(text, pos, alnum_state, is_alnum, val);
76 mod->setChild(next_numeral);
77
78 numeral = mod;
79 }
80 }
81 else if (_values.find(word) != _values.end())
82 {
83 val = _values[word];
84
85 if (numeral == nullptr)
86 {
87 numeral = new NumeralNumber(word, val);
88 }
89 else if (val >= last_val)
90 {
91 // Assumes eurocentric property where bigger values
92 // following smaller values is a multiplication
93 // (like in "two hundred")
94 NumeralNumber *num = new NumeralNumber(word, val);
95 numeral->setChild(num);
96 }
97 else
98 {
99 // Assumes eurocentric property where smaller values
100 // following bigger values is a sum (like in "forty two")
101 NumeralModifier *mod = new NumeralModifier("+", numeral, NumeralModifier::ADD);
102
103 NumeralWord *next_numeral = analyze_numeral(text, old_pos, alnum_state, is_alnum, val);
104 pos = old_pos;
105 mod->setChild(next_numeral);
106
107 numeral = mod;
108 }
109
110 last_val = val;
111 }
112 }
113
114 old_pos = pos;
115
116 alnum_state = std::isalnum(text[pos]);
117 }
118
119 return numeral;
120}
121
122NumeralWord *NumeralManager::analyze(std::string &text)
123{ // We assume that this is called on a text that we already know is entirely a numeral
124 std::string word = "";
125 int pos = 0;
126 bool alnum_state = std::isalnum(text[pos]);
127 bool is_alnum = std::isalnum(text[pos]);
128 int last_val = 0;
129
130 return analyze_numeral(text, pos, alnum_state, is_alnum, last_val);
131}