-
Notifications
You must be signed in to change notification settings - Fork 2
Prolly needs refactoring #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| #include <fstream> | ||
| #include <iostream> | ||
| #include <unordered_set> | ||
| #include <string> | ||
|
|
||
|
|
||
| class Dictionary { | ||
| public: | ||
| Dictionary(); | ||
| Dictionary(std::string); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even if nod needed by the compiler, putting names for the parameters helps readers understand what parameters are. |
||
| ~Dictionary(); | ||
| void Fill(std::string); | ||
| bool isPrefix(const std::string&); | ||
|
|
||
| std::unordered_set<std::string> words; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those probably don't need to be public. |
||
| std::unordered_set<std::string> prefixes; | ||
| std::string path; | ||
| }; | ||
|
|
||
| Dictionary::Dictionary() {}; | ||
| Dictionary::Dictionary(std::string path): | ||
| path(path) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It helps readability having different naming conventions for fields and parameters. On the Google Style for example, we end fields with '_'. |
||
| {} | ||
| // Load the word dictionary and prefixes dictionary from a given file | ||
| void Dictionary::Fill(std::string path) | ||
| { | ||
| std::string line; | ||
| std::ifstream file(path); | ||
| if (file.is_open()) { | ||
| while (std::getline(file, line)) { | ||
| // Add to word dictionary | ||
| this->words.insert(line); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| // Add to prefixes dictionary | ||
| this->prefixes.insert(line); | ||
| for (size_t i = 1; i < line.length(); i++) { | ||
| this->prefixes.insert(line.substr(0, i)); | ||
| } | ||
| } | ||
| } | ||
| file.close(); | ||
| } | ||
| Dictionary::~Dictionary() {}; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| #include <map> | ||
| #include <string> | ||
| #include <unordered_set> | ||
| #include <vector> | ||
| #include "Dictionary.hpp" | ||
|
|
||
| // prolly not the best solution to store it like that | ||
| int rows = 2; | ||
| int cols = 3; | ||
|
|
||
| class Main { | ||
| private: | ||
| struct cell { | ||
| std::string value; | ||
| int row; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's ok to store them, but they are technically not needed. |
||
| int col; | ||
| std::vector<int> neighbours; | ||
| cell(int row, int col); | ||
| }; | ||
| std::vector<cell> board; | ||
| Dictionary dict; | ||
| std::unordered_set<std::string> found_words; | ||
| void Words(int pos, std::string str = "", std::unordered_set<int> visited = std::unordered_set<int>()); | ||
|
|
||
| public: | ||
| Main(Dictionary dict); | ||
| ~Main(); | ||
|
|
||
| void Load(std::string letters); | ||
| void Print(); | ||
| std::unordered_set<std::string> Result(); | ||
| }; | ||
|
|
||
| // Main board constructor | ||
| Main::Main(Dictionary dict) | ||
| { | ||
| this->dict = dict; | ||
| int row = 0; | ||
| int col = 0; | ||
|
|
||
|
|
||
| for (int i = 0; i < rows; i++) { | ||
| row = i / rows; | ||
| for ( int j = 0; j < cols; j++) { | ||
| col = j % cols; | ||
| board.push_back(cell(row, col)); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (*) |
||
| } | ||
| } | ||
|
|
||
| //get all neighbours of a cell | ||
| std::vector<int> shift {-1, 0, 1}; | ||
| for (cell &sq : board) { | ||
| for (int row_shift : shift) { | ||
| for (int col_shift : shift) { | ||
| row = sq.row + row_shift; | ||
| col = sq.col + col_shift; | ||
| if (row >= 0 & row < rows & col >= 0 & col < cols & !(row_shift == 0 & col_shift == 0)) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it works, but you probably should use logical and |
||
| sq.neighbours.push_back(row * rows + col); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (*) |
||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Main::~Main() {} | ||
|
|
||
| Main::cell::cell(int row, int col): | ||
| row(row), | ||
| col(col) | ||
| {} | ||
|
|
||
| // Load a string of letters into the board | ||
| void Main::Load(std::string letters) { | ||
| int i = 0; | ||
| for (cell &it : board) { | ||
| it.value = letters[i]; | ||
| i += 1; | ||
| } | ||
| // Clear any previously found words | ||
| found_words.clear(); | ||
| } | ||
|
|
||
| // Print the board | ||
| void Main::Print() { | ||
| for (const cell &sq : board) { | ||
| std::cout << sq.value << " "; | ||
| if (sq.col == cols - 1) { | ||
| std::cout << std::endl; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| std::unordered_set<std::string> Main::Result() | ||
| { | ||
| // a | ||
| // Find words for all cells on the board | ||
| for (size_t i = 0; i < board.size(); i++) | ||
| { | ||
| Words(i); | ||
| } | ||
| return found_words; | ||
| } | ||
|
|
||
| // Find all words starting at a given position | ||
| void Main::Words(int position, std::string string, std::unordered_set<int> visited) { | ||
|
|
||
| cell &sq = board[position]; | ||
| string += sq.value; | ||
| visited.insert(position); | ||
|
|
||
| // If the string is a word, add it to the found words | ||
| if (dict.words.find(string) != dict.words.end()) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be a function |
||
| found_words.insert(string); | ||
| } | ||
|
|
||
| // If the string is a prefix, continue looking | ||
| if (dict.prefixes.find(string) != dict.prefixes.end()) { | ||
| for (const int &neighbour : sq.neighbours) { | ||
| if (visited.find(neighbour) == visited.end()) { | ||
| Words(neighbour, string, visited); | ||
| } | ||
| } | ||
| } | ||
| visited.erase(position); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| #include "Main.hpp" | ||
|
|
||
| int main() { | ||
| const std::string path = "dict.txt"; | ||
| std::string board = "aartcd"; | ||
| Dictionary dict(path); | ||
| dict.Fill(path); | ||
| Main m(dict); | ||
| m.Load(board); | ||
| m.Print(); | ||
| std::unordered_set<std::string> res = m.Result(); | ||
| std::cout << std::endl; | ||
| for (auto it = res.begin(); it != res.end(); ++it) | ||
| { | ||
| std::cout << *it << std::endl; | ||
| } | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| #include "Unit_tests.h" | ||
|
|
||
| void test_IsWord(Dictionary &d){ | ||
| EXPECT_TRUE(d.words.find("cat") != d.words.end()); | ||
| EXPECT_TRUE(d.words.find("car") != d.words.end()); | ||
| EXPECT_FALSE(d.words.find("rat") != d.words.end()); | ||
| EXPECT_FALSE(d.words.find("ca") != d.words.end()); | ||
| EXPECT_FALSE(d.words.find("CAT") != d.words.end()); | ||
| } | ||
|
|
||
| void test_IsPrefix(Dictionary& d){ | ||
| EXPECT_TRUE(d.prefixes.find("c") != d.prefixes.end()); | ||
| EXPECT_TRUE(d.prefixes.find("ca") != d.prefixes.end()); | ||
| EXPECT_TRUE(d.prefixes.find("cat") != d.prefixes.end()); | ||
| EXPECT_TRUE(d.prefixes.find("card") != d.prefixes.end()); | ||
| EXPECT_FALSE(d.prefixes.find("") != d.prefixes.end()); | ||
| EXPECT_FALSE(d.prefixes.find("a") != d.prefixes.end()); | ||
| EXPECT_FALSE(d.prefixes.find("Ra") != d.prefixes.end()); | ||
| } | ||
|
|
||
| void test_IsWordAfterRemoval(Dictionary & d){ | ||
| d.words.erase("car"); | ||
| EXPECT_FALSE(d.words.find("car") != d.words.end()); | ||
| } | ||
|
|
||
| void test_IsPrefixAfterRemoval(Dictionary & d){ | ||
| EXPECT_TRUE(d.prefixes.find("c") != d.prefixes.end()); | ||
| EXPECT_TRUE(d.prefixes.find("ca") != d.prefixes.end()); | ||
| EXPECT_TRUE(d.prefixes.find("car") != d.prefixes.end()); | ||
| d.prefixes.erase("card"); | ||
| EXPECT_FALSE(d.prefixes.find("card") != d.prefixes.end()); | ||
|
|
||
| d.words.erase("bicycle"); | ||
| EXPECT_FALSE(d.prefixes.find("b") != d.prefixes.end()); | ||
| EXPECT_FALSE(d.prefixes.find("bi") != d.prefixes.end()); | ||
| EXPECT_FALSE(d.prefixes.find("bic") != d.prefixes.end()); | ||
| } | ||
|
|
||
| int main (){ | ||
| Dictionary d("dict.txt"); | ||
| d.Fill("dict.txt"); | ||
| test_IsWord(d); | ||
| test_IsPrefix(d); | ||
| test_IsWordAfterRemoval(d); | ||
| test_IsPrefixAfterRemoval(d); | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| #include "codeu_test_lib.h" | ||
| #include "Dictionary.hpp" | ||
|
|
||
| #ifndef UNIT_TESTS | ||
| #define UNIT_TESTS | ||
|
|
||
| void test_IsWord(const Dictionary& d); | ||
|
|
||
| void test_IsPrefix(const Dictionary& d); | ||
|
|
||
| void test_IsWordAfterRemoval(Dictionary& d); | ||
|
|
||
| void test_IsPrefixAfterRemoval(Dictionary& d); | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| #include <iostream> | ||
| #include <vector> | ||
|
|
||
| // Some convenient macros for simple testing. | ||
| // If expectation is fulfilled, prints nothing; | ||
| // If expectation is not fulfilled, prints what went wrong (expectation vs. | ||
| // actual value) with the filename and line number for convenience. | ||
|
|
||
| #define EXPECT_TRUE(statement) \ | ||
| if (!(statement)) { \ | ||
| std::cout << __FILE__ << ":" << __LINE__ << " Failed: " \ | ||
| << "Statement (" #statement << ") is false, expected true." \ | ||
| << std::endl; \ | ||
| } | ||
|
|
||
| #define EXPECT_FALSE(statement) \ | ||
| if (statement) { \ | ||
| std::cout << __FILE__ << ":" << __LINE__ << " Failed: " \ | ||
| << "Statement (" #statement << ") is true, expected false." \ | ||
| << std::endl; \ | ||
| } | ||
|
|
||
| #define EXPECT_EQ(expected, actual) \ | ||
| if ((expected) != (actual)) { \ | ||
| std::cout << __FILE__ << ":" << __LINE__ << " Failed: " \ | ||
| << "Statement (" << #actual << ") is " << actual \ | ||
| << ", expected " << (expected) << " (" << #expected << ")." \ | ||
| << std::endl; \ | ||
| } | ||
|
|
||
| #define EXPECT_NULL(statement) \ | ||
| if (statement != nullptr) { \ | ||
| std::cout << __FILE__ << ":" << __LINE__ << " Failed: " \ | ||
| << "Statement (" << #statement \ | ||
| << ") is not null, expected null." << std::endl; \ | ||
| } | ||
|
|
||
| // Print operator for vectors. Must be defined in order to use EXPECT_EQ macro | ||
| // with vectors (see example below). | ||
| /* | ||
| template <class T> | ||
| inline std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) { | ||
| os << "{"; | ||
| for (int i = 0; i < v.size(); i++) { | ||
| if (i > 0) { | ||
| os << ", "; | ||
| } | ||
| os << v[i]; | ||
| } | ||
| os << "}"; | ||
| } | ||
| */ | ||
| // Example usage: | ||
|
|
||
| // EXPECT_TRUE(1 < 3); // Prints nothing. | ||
| // EXPECT_TRUE(5 < 3); // main.cpp:53 Failed: Statement (5 < 3) is | ||
| // // false, expected true. | ||
| // EXPECT_TRUE(true); // Prints nothing. | ||
| // EXPECT_TRUE(false); // Prints: tests.cpp:56 Failed: Statement (false) is | ||
| // // false, expected true. | ||
| // EXPECT_FALSE(5 > 6); | ||
| // EXPECT_FALSE(5 > 0); // Prints: tests.cpp:59 Failed: Statement (5 > 0) is | ||
| // // true, expected false. | ||
| // EXPECT_EQ(4, 2 + 2); | ||
| // EXPECT_EQ(4, 3 + 1); | ||
| // EXPECT_EQ(10 * 10, 50 + 51); // tests:37 Failed: Statement (50 + 51) is 101, | ||
| // // expected 100 (10 * 10). | ||
| // EXPECT_EQ("pizza", std::string("pizz") + "a"); | ||
| // EXPECT_EQ("pizza", std::string("pizz") + "aaaa"); | ||
| // // tests.cpp:39 Failed: Statement (std::string("pizz")+"aaaa") is pizzaaaa, | ||
| // // expected pizza ("pizza"). | ||
| // | ||
| // int x; | ||
| // EXPECT_NULL(&x); // main.cpp:71 Failed: Statement (&x) is not null, | ||
| // // expected null. | ||
| // | ||
| // std::vector<int> expected_vec{1, 2, 3}; | ||
| // std::vector<int> actual_vec{4, 5, 6}; | ||
| // EXPECT_EQ(expected_vec, actual_vec); | ||
| // // main.cpp:77 Failed: Statement (actual_vec) is {4, 5, 6}, expected | ||
| // // {1, 2, 3} (expected_vec). |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| car | ||
| card | ||
| cart | ||
| cat |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please try to keep indentation consistent.