#include <iostream> #include <algorithm> #include <vector> template <typename T> class matrix { public: size_t cols; size_t rows; private: std::vector<T> data; public: matrix() : cols(0), rows(0) { } matrix(const size_t cols, const size_t rows) : cols(cols), rows(rows) { data = std::vector<T>(cols * rows); } matrix(const size_t cols, const size_t rows, const T val) : cols(cols), rows(rows) { data = std::vector<T>(cols * rows, val); } T& operator()(const size_t col, const size_t row) { return data[col * rows + row]; } const T& operator()(const size_t col, const size_t row) const { return data[col * rows + row]; } matrix<T> rotate() const { matrix<T> new_mat; new_mat = matrix(rows, cols); for (size_t col = 0; col < new_mat.cols; col++) { for (size_t row = 0; row < new_mat.rows; row++) { new_mat(col, row) = operator()(row, (rows - 1) - col); } } return new_mat; } matrix<T> copy(const size_t c_col, const size_t c_row, size_t c_cols, size_t c_rows) const { if (c_col + c_cols > cols - 1) { c_cols = cols - c_col; } if (c_row + c_rows > rows - 1) { c_rows = rows - c_row; } matrix<T> new_mat = matrix(c_cols, c_rows); for (size_t col = 0; col < c_cols; col++) { for (size_t row = 0; row < c_rows; row++) { //std::cout << "(" << c_col + col << ", " << c_row + row << ") --> (" << col << ", " << row << ")" << std::endl; new_mat(col, row) = operator()(c_col + col, c_row + row); //std::cout << "(" << col << ", " << row << ") = " << i << std::endl; } } return new_mat; } // You should change this to use a predicate to decide whether or not a value should be cropped. matrix<T> crop(const T empty_val) const { matrix<T> new_mat = *this; // Use rotation to help crop! int i = 4; while (i --> 0) { bool do_break = false; for (size_t col = 0; col < new_mat.cols; col++) { if (do_break) { break; } for (size_t row = 0; row < new_mat.rows; row++) { if (new_mat(col, row) != empty_val) { new_mat = new_mat.copy(col, 0, new_mat.cols - col, new_mat.rows).rotate(); do_break = true; break; } } } } return new_mat; } // You have to go first by rows and then by columns since printing is sort of "row major". void print() const { for (size_t row = 0; row < rows; row++) { for (size_t col = 0; col < cols; col++) { std::cout << this->operator()(col, row) << ' '; } std::cout << std::endl; } std::cout << std::endl; } }; int main() { std::vector<std::string> words = { "colorful", "dividend", "fourteen", "alsatian" }; size_t side_size = 28; matrix<char> empty_mat(side_size, side_size, ' '); matrix<char> best_mat(side_size, side_size, ' '); // Try each possible sequence of words. For each word that you try, try every possible place that word can fit. std::sort(words.begin(), words.end()); do { matrix<char> mat(empty_mat); for (std::string s : words) { size_t this_col = 0; size_t this_row = 0; bool good = true; bool do_break = false; int r = 4; while (r--> 0) { if (do_break == true) break; // Rotate the matrix ninety degrees each time and only deal with the forward horizontal case. mat = mat.rotate(); // Find a place to try the word. for (size_t i = 0; i < s.size(); i++) { char& c = s[i]; if (do_break == true) break; for (size_t col = 0; col < mat.cols; col++) { if (do_break == true) break; for (size_t row = 0; row < mat.rows; row++) { good = false; if (mat(col, row) == c) { good = true; // Make sure that the word isn't colliding with anything already there. for (size_t k = col - i; k < col - i + s.size(); k++) { for (size_t q = row - 1; q <= row + 1; q++) { if (q == 0) { if ((mat(k, row) != ' ') && (mat(k, row) != s[(k) - (col - i)])) { good = false; break; } } else if (k != col) { if (mat(k, q) != ' ') { good = false; break; } } } } } if (good) { this_col = col - i; this_row = row; do_break = true; break; } } } } } if (this_col == 0 && this_row == 0) { this_col = side_size / 2; this_row = side_size / 2; } for (char c : s) { mat(this_col++, this_row) = c; } } // for (std::string s : words) { // std::cout << s << ' '; // } std::cout << std::endl; mat.crop(' ').print(); } while (std::next_permutation(words.begin(), words.end())); return 0; }
Standard input is empty
l
u
f o u r t e e n
r
o d
a l s a t i a n
o v
c i
d
e
n
d
n
a
d i v i d e n d
t
a
s
l u f r o l o c
o a
u
r
t
e
e
n
d
n
e
d
c i
o v
a l s a t i a n
o d
r
f o u r t e e n
u
l
f
c o l o r f u l
u
r n
t a
d n e d i v i d
e t
n a
s
l
a
d i v i d e n d
a
i c
n e e t r u o f
a l
s o
l r
a f
u
l
n
d n e d i v i d
e
a l s a t i a n
r
u
c o l o r f u l
f
l
u
f o u r t e e n
r
d o
n a i t a s l a
v o
i c
d
e
n
d
l
f u
o f
u r
r o
n a i t a s l a
e o
d i v i d e n d c
n
a
l
s
a
t
d n e d i v i d
a
f o u r t e e n
f
o
u
r
t
d n e d i v i d
e
a l s a t i a n
a
l
s l
a u
n e e t r u o f
i r
a o
d i v i d e n d l
o
c
d
i
v
i a l s a t i a n
d u
n e e t r u o f
n r
d o
l
o
c
d
n
e
d
i c
v o
n a i t a s l a
d o
r
f o u r t e e n
u
l
f
o d
c o l o r f u l n
r e
t d
e i
e v
n a i t a s l a
d
a
l u f r o l o c
s
a
f o u r t e e n
i
a
n
l u f r o l o c
o
u
r
a l s a t i a n
e
e
n
a
c o l o r f u l
s
a
t
i d
a n
n e e t r u o f
d
i
v
i
d
d
n c
n e e t r u o f
d l
i o
v r
i f
d u
a l s a t i a n
n
d i v i d e n d c
e o
n a i t a s l a
r o
u r
o f
f u
l
d
i
v
i n
d e
e e
n a i t a s l a
d r
u
c o l o r f u l
f
n
e
e
t
r
a u
l u f r o l o c
s f
a
t
d i v i d e n d
a
n
f
c o l o r f u l
u
r
a l s a t i a n
e
d n e d i v i d
n
a
l
s
n a
e t
d n e d i v i d
t a
r n
u
c o l o r f u l
f
f
l u f r o l o c
u
r
t
d i v i d e n d
e
a l s a t i a n