С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
3 / 3 / 0
Регистрация: 20.07.2018
Сообщений: 249
1

Крисс-кросс, этюды для программистов

03.12.2022, 21:24. Показов 1631. Ответов 33
Метки c++ (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, пытаюсь решить задачу из книги Уэзерелла Чарльза "Этюды для программистов". Задача крисс - кросс. Нужно по заданному списку слов построить сетку. В местах пересечения слова имеют одинаковые буквы. Я написал вот такую программу:

main.cpp:
C++
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
#include <iostream>
#include "crisscross.h"
#include <vector>
using namespace std;
 
int main()
{
 
    vector<Word> mass;
    vector<Word>a not_visited_words;
    mass.push_back(Word("cat"));
    mass.push_back(Word("fbad"));
    mass.push_back(Word("forest"));
    mass.push_back(Word("eagle"));
   // mass.push_back(Word("lose"));
    mass.push_back(Word("siedge"));
    not_visited_words = mass;
    Cell c;
    //for(int i = 0; i < mass.size(); i++) {
        Word w;
        w = mass[0];
        w.set_coord_X(0);
        w.set_coord_Y(c.get_cell_coord_Y()/2);
        w.set_horizontal(1);
        c.add_word(w);
        not_visited_words.erase(not_visited_words.begin());
        c.backtracking(not_visited_words, w, 0);
        c.delete_word(w);
        //cout << not_visited_words[0].get_string() << endl;
 
    //}
 
    //c.backtracking(mass, mass[0], 0);
    c.print_matrix();
   // c.delete_word(w);
    //c.print_matrix();
}
crisscross.h:
C++
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
#ifndef CRISSCROSS_H_INCLUDED
#define CRISSCROSS_H_INCLUDED
 
#include <vector>
#include <string>
#include <tuple>
 
using namespace std;
 
class Word {
private:
    string value;
    int len;
    bool horizontal;
    int coord_X;
    int coord_Y;
public:
    Word();
    Word(string value);
    void set_horizontal(bool horizontal);
    void set_coord_X(int coord);
    void set_coord_Y(int coord);
    bool get_horizontal();
    int get_coord_X();
    int get_coord_Y();
    int get_len();
    string get_string();
};
 
class Cell {
private:
    char** matrix;
    int dx;
    int dy;
    vector<bool> table_with_laters;
    vector<bool> used_words;
    tuple<int,int> check_in_table(Word& word_a, Word& word_b);
    int index_in1word;
public:
    Cell();
    int get_cell_coord_X();
    int get_cell_coord_Y();
    void add_word( Word& word_to_add);
    bool check(int X, int Y, bool horiz);
    void delete_word(Word& word_to_delete);
    int backtracking(vector<Word>& list_of_wirds, Word& current_word, int iteration);
    void print_matrix();
};
#endif // CRISSCROSS_H_INCLUDED
crisscross.cpp:
C++
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#include <string>
#include <iostream>
#include "crisscross.h"
#include <tuple>
using namespace std;
 
Word::Word() {
 
    this->value = "";
    this->coord_X = 0;
    this->coord_Y = 0;
    this->len = 0;
    this->horizontal = 1;
}
Word::Word(string value) {
    this->value = value;
    this->len = value.length();
    this->coord_X = 0;
    this->coord_Y = 0;
    this->horizontal = 1;
}
void Word::set_coord_X(int coord) {
    this->coord_X = coord;
}
void Word::set_coord_Y(int coord) {
    this->coord_Y = coord;
}
void Word::set_horizontal(bool horizontal) {
    this->horizontal = horizontal;
}
bool Word::get_horizontal() {
    return this->horizontal;
}
int Word::get_coord_X() {
    return this->coord_X;
}
int Word::get_coord_Y() {
    return this->coord_Y;
}
int Word::get_len() {
    return this->len;
}
 
string Word::get_string() {
    return this->value;
}
 
Cell::Cell(){
    this->dx = 50;
    this->dy = 50;
    matrix = new char* [dx];
    for(int i = 0; i < dx; i++) {
        matrix[i] = new char [dy];
    }
    for(int i = 0; i < dx; i++) {
        for(int j = 0; j < dy; j++) {
            matrix[i][j] = ' ';
        }
    }
 
}
 
bool Cell::check(int X, int Y, bool horiz) {
    if(horiz == true) {
        if(matrix[X][Y+1] == ' ' && matrix[X][Y-1] == ' ' && matrix[X][Y] == ' ')
            return true;
        else
            return false;
    }
    else if(horiz == false) {
        if(matrix[X+1][Y] == ' ' && matrix[X][Y] == ' ') {
            if( X > 0 && matrix[X-1][Y] == ' ')
                return true;
            return true;
        }
        else
            return false;
    }
    else
        return false;
}
 
void Cell::add_word( Word& word_to_add) {
    string value = word_to_add.get_string();
    int iter = 0;
    int max_value = 0;
 
    if(word_to_add.get_horizontal() == true)
        max_value = word_to_add.get_coord_X();
    else
        max_value = word_to_add.get_coord_Y();
    while(iter != value.length()) {
        if(word_to_add.get_horizontal() == true && check(max_value, word_to_add.get_coord_Y(), true)) {
            matrix[word_to_add.get_coord_Y()][max_value] = value[iter];
            iter += 1;
            max_value += 1;
        }
        else if(word_to_add.get_horizontal() == false && check(word_to_add.get_coord_X(), max_value, false)){
            matrix[max_value][word_to_add.get_coord_X()] = value[iter];
            iter += 1;
            max_value += 1;
        }
        else {
            cout << "error";
            delete_word(word_to_add);
        }
    }
}
 
 
void Cell::delete_word(Word& word_to_delete) {
    if(word_to_delete.get_horizontal() == true) {
        int iter = 0;
        int i = word_to_delete.get_coord_X();
        while(iter < word_to_delete.get_len()) {
            if(matrix[word_to_delete.get_coord_Y() + 1][i] != ' ' || matrix[word_to_delete.get_coord_Y() - 1][i] != ' ')
                continue;
            else {
                matrix[word_to_delete.get_coord_Y()][i] = ' ';
                iter+=1;
                i+=1;
            }
        }
    }
 
    else if(word_to_delete.get_horizontal() == false) {
        int iter = 0;
        int i = word_to_delete.get_coord_Y();
        while(iter < word_to_delete.get_len()) {
            if(matrix[i][word_to_delete.get_coord_X() - 1] != ' ' || matrix[i][word_to_delete.get_coord_X() + 1] != ' ')
                continue;
            else {
                matrix[i][word_to_delete.get_coord_X()] = ' ';
                iter+=1;
                i+=1;
            }
        }
    }
    else
        cout << "error" << endl;
}
 
void Cell::print_matrix() {
    for(int i = 0; i < dx; i++) {
        for(int j = 0; j < dy; j++) {
            cout << matrix[i][j];
            if(i == dx - 1)
                cout << '-';
        }
        cout << '|' << endl;
    }
}
 
tuple<int,int> Cell::check_in_table(Word& word_a, Word& word_b) {
    table_with_laters.resize(128);
    table_with_laters.clear();
    for (const char *p = word_a.get_string().c_str(); *p != '\0'; ++p)
        table_with_laters[(unsigned char) *p] = true;
 
    for (unsigned int i = 0; i < word_b.get_string().length(); i++) {
        if (table_with_laters[(unsigned char) word_b.get_string()[i]]) {
            for(int j = 0; j < word_a.get_string().length(); j++) {
                if(word_a.get_string()[j] != (unsigned char)word_b.get_string()[i])
                    continue;
                else {
                    table_with_laters.resize(0);
                    table_with_laters.clear();
                    return make_tuple(i, j);
                }
            }
        }
    }
    table_with_laters.resize(0);
    table_with_laters.clear();
    return make_tuple(-1, -1);
}
 
int Cell::get_cell_coord_X() {
    return this->dx;
}
 
int Cell::get_cell_coord_Y() {
    return this->dy;
}
 
int Cell::backtracking(vector<Word>& list_of_words, Word& current_word, int iteration)
{
    print_matrix();
    vector<Word> not_visited_words = list_of_words;
    for(int i = 0; i < list_of_words.size(); i++)
    {
        int tmp = 0;
        int same_latter_1, same_latter_2;
        tie(same_latter_2, same_latter_1) = check_in_table(current_word, list_of_words[i]);
        if(same_latter_1 >= 0 && same_latter_2 >= 0) {
        Word new_word;
        new_word = list_of_words[i];
        bool new_horiz;
        if(current_word.get_horizontal())
            new_horiz = false;
        else
            new_horiz = true;
 
        new_word.set_horizontal(new_horiz);
 
        new_word.set_coord_X(current_word.get_coord_X() + same_latter_1);
        new_word.set_coord_Y(current_word.get_coord_Y() - same_latter_2);
        add_word(new_word);
        for(int j = 0; j < not_visited_words.size()+1; j++) {
            if(not_visited_words[j].get_string() == new_word.get_string()) {
                tmp = j;
                not_visited_words.erase(not_visited_words.begin() + tmp);
                break;
            }
        }
 
        backtracking(not_visited_words, new_word, iteration+1);
        not_visited_words.insert(not_visited_words.begin()+tmp, new_word);
        delete_word(new_word);
        new_word.set_horizontal(true);
        new_word.set_coord_X(0);
        new_word.set_coord_Y(0);
        iteration -= 1;
        }
 
    }
}
Пояснение к коду: отдельный класс Word хранит в себе слово (которое в будущем будет считано из текстового файла), а класс Cell хранит сетку в матрице mass. У каждого слова есть своя координата для отрисовки. Идея такова: взять слово из списка, найти одинаковые буквы в другом слове, нарисовать это новое слово, запустить метод для нового слова, используя список еще не использованных слов. Собственно в чем проблема: я совсем не понимаю почему иногда слова вписываются СОВСЕМ не туда, куда надо, например как на скришотах. Также программа почему то не завершается (нет сообщения, что программа завершилась с каким либо кодом), даже если я добавляю условие выхода (if(list...size() == 0){return 1;}). Очень прошу помочь, если будут вопросы по коду - с радостью постараюсь объяснить что я пытался написать
Миниатюры
Крисс-кросс, этюды для программистов   Крисс-кросс, этюды для программистов  
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
03.12.2022, 21:24
Ответы с готовыми решениями:

Кроссворд крисс-кросс в делфи
Помогите создать кроссворд крисс-кросс в дельфи

Задание по книге "Этюды для программистов"
Ссылка на полную статью: http://programming-lang.com/ru/comp_programming/uezerell/0/j6.html

Реализация Игры "Жизнь" из книги Уэзерелл Ч. "Этюды для программистов"
Кто нибудь встречал ее нга с#??? Если у кого-то есть, вы не могли бы выложить исходник?

Ищу программистов Cocos2d-x для разработки игр, Ищу программистов C++
Привет всем. Ищу разработчиков С++ для мобильной игры (iOS, Android и WP в перспективе)....

Кросс-компиляция для raspberry
Читал серию публикаций про raspberry. Так и не понял, как осуществить кросс-компиляцию. Если кто...

33
3 / 3 / 0
Регистрация: 20.07.2018
Сообщений: 249
06.12.2022, 21:05  [ТС] 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от SmallEvil Посмотреть сообщение
Это тоже у вас так совпало красиво или же не допускаете прикасание слов при вставке ?
Тоже просто совпало) Но сейчас как раз хочу добавить условие исключения соприкасания
0
3 / 3 / 0
Регистрация: 20.07.2018
Сообщений: 249
06.12.2022, 22:03  [ТС] 22
Этот результат пока наилучшее, что у меня получилось
Изображения
 
1
3718 / 2647 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
06.12.2022, 22:49 23
Так же создал новую версию класса Сетки, добавил в метод проверки фильтр на соприкасание.
Вот так вот получилось. Телескопу толком места не осталось.
Хотя если ограничить поле размерами, то он бы упаковался к слову cosmonaut.
Хотя еще можно изменить порядок выбора мест не по добавлению слов, а по расстоянию к центру кроссворда (его первого слова)
Код
       c  p          
       ogalaxy       
       l  a          
       o  n          
      universe       
       i  t p        
 t     s    a        
meteorite   cosmonaut
 l          e        
 e                   
 s                   
 c                   
 o                   
 p                   
 e
Моя песочница.
Последний код, со скудными комментариями, без оптимизаций, и излишними контейнерами.
C++17

C++
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <functional>
#include <memory>
#include <set>
#include <list>
#include <algorithm>
 
using std::string;
using std::pair;
using std::vector;
using std::ref;
template <typename T>
using ref_t = std::reference_wrapper<T>;
template <typename T>
using cref_t = std::reference_wrapper<const T>;
 
// универсальный hash дл¤ pair
struct pair_hash
{
    template <class T1, class T2>
    std::size_t operator() (const std::pair<T1, T2> &pair) const {
        return (std::hash<T1>()(pair.first) + std::hash<T2>()(pair.second)) ^ std::hash<T2>()(pair.second);
    }
};
 
// это просто Data класс, он хранит только данные, и не ¤вл¤етс¤ самосто¤тельной единицей.
// поэтому нет инкапсул¤ции полей.
struct CWord{
    CWord(const string &word):word{word}{
    }
    enum class Dir{Hor, Vert};
    struct CWordLink{
        CWordLink(CWord &cword, int pos):cword{cword}, pos{pos}{
        }
        bool operator==(const CWordLink &rhs){
            return (pos == rhs.pos) && (&cword.get() == &rhs.cword.get());
        }
        ref_t<CWord> cword; // ссыкла на cross - слово
        int pos; // номер буквы пересечени¤ с данным словом
    };
    int x{},y{}; // начало слова
    Dir dir{}; // ориентаци¤
    short pn{}; // ѕ/Ќ - пор¤дковый номер // если нужно
    cref_t<string> word; // слово
    std::map<int, CWordLink> links; // число - позици¤ буквы пересечени¤, с кемой буквой
    // danger !!!
    bool Linked() const{
        return links.size()!=0;
    }
    bool Link(int pos, CWord& to, int pos_to){
        if (pos < word.get().size() && pos_to < to.word.get().size()){
            links.emplace(pos, CWordLink(to, pos_to));
            return true;
        }
        return false;
    }
    void break_links(){
        for(auto& [pos, link] : links)
            link.cword.get().links.erase(pos);
        links.clear();
    }
};
 
// сетка (виртуальна¤), отвечает за расположение в ней слов.
// правила их расстановок, отступы , правила пересечений и т.д
struct Grid{
    using cells_t = std::map<pair<int,int>, vector<CWord::CWordLink>>;
    //using available_cells_t = std::unordered_map<pair<int,int>, CWord::CWordLink, pair_hash>;
    using available_cells_t = std::map<pair<int,int>, CWord::CWordLink>;
    using available_queued_cells_t = std::list<CWord::CWordLink>;   
    // максимальна¤ ширина и высота пол¤.
    // -1 - резинова¤
//      Grid(int max_width=-1, int max_height=-1)
         Grid()
      :width{0}, height{0}{
    }
    // одна из самых важных функций-членов Cетки
    // с отступами между словами
    bool CanBurn(const CWord & cword){
        if (cword.word.get().empty())
            return false;
        int dx = (cword.dir == CWord::Dir::Hor );
        int dy = (cword.dir == CWord::Dir::Vert);
        int x = cword.x, y = cword.y;
        auto cells_end = cells.end();
        for (int i = 0, end = cword.word.get().size(); i != end ; ++i){
            auto search = cells.find({x, y});
 
            if (search != cells_end){
                const auto& links = search->second;
                if (links.size()==2)
                    return false;
                else if ( links.size()==1){
                        if ( links[0].cword.get().word.get()[links[0].pos] != cword.word.get()[i]) 
                            return false;
                }
            }else{
                // проверка прилегаемости
                switch(cword.dir){
                    case CWord::Dir::Hor  : 
                        if (cells.find({x, y-1}) != cells_end || cells.find({x, y+1}) != cells_end)
                            return false;
                        break;
                    case CWord::Dir::Vert : 
                        if (cells.find({x-1, y}) != cells_end || cells.find({x+1, y}) != cells_end)
                            return false;
                        break;
                    default : break;
                }
            }
            x+=dx, y+=dy;
        }
        return true;
    }
    // прожиг слова на —етке
    bool Burn(CWord &cword){
        if (!CanBurn(cword))
            return false;
 
        int dx = (cword.dir == CWord::Dir::Hor );
        int dy = (cword.dir == CWord::Dir::Vert);
        int x = cword.x, y = cword.y;
        top_left_x = std::min(top_left_x, x);
        top_left_y = std::min(top_left_y, y);
        bottom_right_x = std::max(bottom_right_x, x + dx * int(cword.word.get().size()-1));
        bottom_right_y = std::max(bottom_right_y, y + dy * int(cword.word.get().size()-1));
 
        for (int i = 0, end = cword.word.get().size(); i != end ; ++i){
            cells_t::mapped_type & links = cells[{x,y}];
            links.emplace_back(cword, i);
            if (links.size()==1){
                available_cells.emplace(std::make_pair(x,y), CWord::CWordLink(cword, i) );
                available_queued_cells.push_back(CWord::CWordLink(cword, i));
            }
            else{
                available_queued_cells.erase(std::find(available_queued_cells.begin(), available_queued_cells.end(),
                    CWord::CWordLink(links[0].cword,links[0].pos))
                );
                cword.Link(i, links[0].cword, links[0].pos);
                available_cells.erase(std::make_pair(x,y));
                
            }
            x+=dx; y+=dy;
        }
        return true;
    }
    
    bool Excision (const CWord &cword);
    
    vector<string> MakeRows(){
        if (cells.size()!=0){
            int w = GetWidth();
            int h = GetHeight();
            vector<string> rows(h, string(w, ' '));
            for(auto& cell : cells){
                rows[cell.first.second - top_left_y][cell.first.first - top_left_x] = cell.second[0].cword.get().word.get()[cell.second[0].pos];
            }
            return rows;
        }
        return {};
    }
    
    int GetWidth() const{
        return bottom_right_x - top_left_x + 1;
    }
    int GetHeight() const{
        return bottom_right_y - top_left_y + 1;
    }
    const cells_t& Cells() const{
        return cells;
    }
    const available_cells_t& AvailableCells() const{
        return available_cells;
    }
    const available_queued_cells_t& AvailableQueuedCells() const{
        return available_queued_cells;
    }
private:
    // карта клеток, можно определить к какому слову/словам относитс¤ клетка
    cells_t cells;
    available_cells_t available_cells;
    available_queued_cells_t available_queued_cells;
    // bounds
    int top_left_x{0}, top_left_y{0};
    int bottom_right_x{0}, bottom_right_y{0};
    
    int width;  // текуща¤ ширина
    int height; // текуща¤ высота
    int max_width;
    int max_hegiht;
};
 
// главный класс, хран¤щий слова, св¤зи между ними и сетку дл¤ слов.
template <typename TGrid>
class CrossWord{
    //std::unique_ptr<TGrid> grid;  // сетка
    TGrid grid;
    std::set<string> words; // сами слова
    std::list<CWord> cwords; // crossed words
    std::map<pair<int, int>, ref_t<CWord>> table; // таблица cross-слов
    int horizontal_words = 0;
    int vertical_words = 0;
public:
    CrossWord(const CrossWord &) = delete;
    CrossWord(CrossWord&&) = delete;
    CrossWord& operator=(const CrossWord&) = delete;
    CrossWord& operator=(CrossWord&&) = delete;
    CrossWord() = default;
    ~CrossWord() = default;
    
    bool AddWord(const string &word){
        //const auto &cells  = grid.Cells();
        //const auto &acells = grid.AvailableCells();
        if (words.size() == 0){
            auto inserted_word = words.insert(word);
            if (inserted_word.second == false)
                return false;
            cwords.emplace_back(*(inserted_word.first));
            auto& cword = cwords.back();
            cword.dir = CWord::Dir::Hor;
            if (grid.Burn(cword)){
                cword.pn = ++horizontal_words;
                table.emplace(std::make_pair(cword.pn, 0), cword); 
                return true;
            }
            words.erase(inserted_word.first);
            cwords.pop_back();
            return false;
        }
        const auto &acells = grid.AvailableQueuedCells();
        if (acells.size() == 0)
            return false;
        
        auto inserted_word = words.insert(word);
        if (inserted_word.second == false)
            return false;
        cwords.emplace_back(*(inserted_word.first));
        auto& cword = cwords.back();
 
        for(const auto& wordlink : acells){
            for(int i = 0, end = word.size(); i != end; ++i){
                auto dir = wordlink.cword.get().dir;
                auto coord = std::make_pair(wordlink.cword.get().x + (dir == CWord::Dir::Hor)  * wordlink.pos ,
                                            wordlink.cword.get().y + (dir == CWord::Dir::Vert) * wordlink.pos);
                if (word[i] != wordlink.cword.get().word.get()[wordlink.pos])
                    continue;
                cword.x = coord.first  - (dir == CWord::Dir::Vert ? i : 0);
                cword.y = coord.second - (dir == CWord::Dir::Hor  ? i : 0);
                cword.dir = (dir == CWord::Dir::Hor ? CWord::Dir::Vert : CWord::Dir::Hor);
                if (grid.Burn(cword)){
                    if (cword.dir == CWord::Dir::Hor){
                        cword.pn = ++horizontal_words;
                        table.emplace(std::make_pair(cword.pn, 0), cword);
                    }
                    if (cword.dir == CWord::Dir::Vert){
                        cword.pn = ++vertical_words;
                        table.emplace(std::make_pair(0, cword.pn), cword);
                    }
                    return true;
                }
                
            }
        }
        words.erase(inserted_word.first);
        cwords.pop_back();
        return false;
    }
    
    vector<string> MakeCrossField(){
        return grid.MakeRows();
    };
};
 
int main(){
    CrossWord<Grid> cross;
    vector<string> words{
        "universe", "colonist", "planet", "space", "galaxy",
        "meteorite", "cosmonaut", "telescope",
    };
    for (const auto& w : words)
        std::cout << "Add word \"" << w << "\" - " 
                  << (cross.AddWord(w) ? "success" : "fail") << std::endl;
    auto cw_paper{cross.MakeCrossField()};
    for(const auto& line : cw_paper)
       std::cout << line << std::endl;
}


Добавлено через 1 минуту
Точно, в коде нет проверок на размеры сетки.
То есть пока сетка только "резиновая".
0
3 / 3 / 0
Регистрация: 20.07.2018
Сообщений: 249
06.12.2022, 23:18  [ТС] 24
У меня есть какой то странный момент: если у меня не осталось не использованных слов, то я вывожу полученную сетку. Первая такая сетка - та что выше, а все последующие имеют странную особенность: слово universe стирается. Ладно стирается, так оно убирается не полностью, а счетчик слов указывает, что оно все еще в сетке. Чудеса
Миниатюры
Крисс-кросс, этюды для программистов  
0
3 / 3 / 0
Регистрация: 20.07.2018
Сообщений: 249
06.12.2022, 23:20  [ТС] 25
А все, проблема решена, я не до конца проверял соприкасание между словами)
Миниатюры
Крисс-кросс, этюды для программистов  
0
3718 / 2647 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
06.12.2022, 23:25 26
_lUserl_, а вы позади слова проверяете соприкасание?
Я вот пропустил, добавил уже, но засорять не хочу своими правками.
В моем посте #23, слово galaxy прилепилось к другому
0
3 / 3 / 0
Регистрация: 20.07.2018
Сообщений: 249
06.12.2022, 23:26  [ТС] 27
Теперь надо бы решить проблему со связанностью и компактность решетки. Можно ли как то вычислить максимальный размер сетки имея только набор слов?
0
3718 / 2647 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
06.12.2022, 23:26 28
_lUserl_, в общем поздравляю, за упорность вашу, все таки доделали (хоть так)
1
3 / 3 / 0
Регистрация: 20.07.2018
Сообщений: 249
06.12.2022, 23:28  [ТС] 29
Цитата Сообщение от SmallEvil Посмотреть сообщение
_lUserl_, а вы позади слова проверяете соприкасание?
Я вот пропустил, добавил уже, но засорять не хочу своими правками.
В моем посте #23, слово galaxy прилепилось к другому
Да, и как раз из за этого у меня и стиралась вселенная)

Добавлено через 42 секунды
Цитата Сообщение от SmallEvil Посмотреть сообщение
_lUserl_, в общем поздравляю, за упорность вашу, все таки доделали (хоть так)
Спасибо вам тоже, вы подали много хороших идей!
0
3718 / 2647 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
06.12.2022, 23:28 30
Цитата Сообщение от _lUserl_ Посмотреть сообщение
Теперь надо бы решить проблему со связанностью и компактность решетки. Можно ли как то вычислить максимальный размер сетки имея только набор слов?
Даже не знаю что на это ответить. На глаз, оно такое не нужно.
У меня такой проблемы нет
0
3 / 3 / 0
Регистрация: 20.07.2018
Сообщений: 249
06.12.2022, 23:30  [ТС] 31
Просто изначально я создаю матрицу фиксированного заведомо большего размера, хотелось бы как нибудь этого избежать
0
3718 / 2647 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
06.12.2022, 23:39 32
Цитата Сообщение от _lUserl_ Посмотреть сообщение
решить проблему со связанностью и компактность решетки
Ну это зависит от набора слов.
И как я уже писал, начинать выбирать буквы для вставки, начиная с выбранного центра кроссворда (например центра первого слова.).
А связность, это особый случай.
То есть при переборе мест вставки, искать все варианты, и выбирать тот, где наибольше пересечений с другими словами.

Цитата Сообщение от _lUserl_ Посмотреть сообщение
Просто изначально я создаю матрицу фиксированного заведомо большего размера, хотелось бы как нибудь этого избежать
Так и делается, создается размер ожидаемого кроссворда, составили сетку.
Не нравится, увеличили/уменьшили размеры поля. И заново составляем сетку.

Например в моем коде добавить ограничение сетки довольно просто, так же как и метод ее расширения, с сохранением текущего расположения слов.
Сужать же более сложно, для этого придется удалять слова и связи, но так же возможно.
Лучше этим не заморачиваться, если вы заранее об этом не подумали.

Добавлено через 4 минуты
Edit : добавлено несколько важных правок в пост!
0
3 / 3 / 0
Регистрация: 20.07.2018
Сообщений: 249
06.12.2022, 23:41  [ТС] 33
Хорошо, я попробую сделать еще что нибудь. Большое спасибо за помощь, это, наверное, одна из самых трудоемких задач из тех, что мне приходилось решать

Добавлено через 1 минуту
В книге написано так:

Качество схем крисс-кросса пропорционально их «связанности», т. е., чем теснее в среднем слова переплетены с соседями, тем интереснее головоломка. Связанность можно измерять по-разному: как отношение площади схемы к площади наименьшего объемлющего прямоугольника; как среднее число пересечений на слово; как среднее число пересечений на букву; как минимальное число пересечений на слово. При генерации головоломок крисс-кросс для массовых изданий использовалась коммерческая программа, но головоломки получались неинтересные — слишком длинные и извилистые. Когда ваша программа заработает, позаботьтесь об увеличении связанности.

Буду пытаться решить эту задачу
1
3718 / 2647 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
07.12.2022, 00:24 34
Попытался скомпоновать плотнее, пока только очередностью выбора потенциальных мест вставки (от своего центра, относительного, (0,0)).
Также слова из вектора, берутся до тех пор, пока хотя бы одно слово на каждом проходе, было вставлено.
То-есть, если не получилось вставить, оставляю слово на след. круг.
Если ни одного слова не было вставлено из всего вектора, прерываю цикл.
Более-менее смотрится, но еще есть над чем подумать.
Хотя я пока наигрался

Код
Add word "universe" - success
Add word "colonist" - success
Add word "planet" - success
Add word "space" - success
Add word "galaxy" - fail
Add word "meteorite" - success
Add word "cosmonaut" - fail
Add word "telescope" - success
Add word "comet" - success
Add word "eclipse" - success
Add word "gravity" - fail
Add word "observatory" - success
Add word "galaxy" - success
Add word "cosmonaut" - success
Add word "gravity" - success

 space               
    o  m  c          
   planet observatory
    o  t  m          
   universe          
    i  o  t          
    s  r g           
    t  i a           
       telescope     
 eclipse a           
  o      x           
  s      y           
  m                  
  o                  
  n                  
gravity              
  u                  
  t
Удачи.
0
07.12.2022, 00:24
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
07.12.2022, 00:24
Помогаю со студенческими работами здесь

Макрос для кросс журнала
Всем здравствуйте. Помогите пожалуйста создать маркос для заполнения кроссировочного журнала. сам...

Кросс компиляция для Raspberry Pi 3
Добрый день. Пытаюсь собрать QT, опираюсь на мануал...

EntityFramework для кросс-платформенного приложения
Доброго времени суток товарищи! Есть две либы: Model и ViewModel, обе на .NET Standard 2.0....

Кросс-сборка ядра для powerpc
Прошу помощи, пожалуйста пару строк по поводу кросс компиляции ядра под powerpc: целевая система:...

Кросс-компиляция из Windows для Linux, MacOS
Доброго времени суток! Имеется проект написанный на C++ в Qt, скомпилирован под Windows...

В поисках идеального кросс-платформенного GUI для C#
Добрый день. Сразу оговорюсь, я не профессиональный разработчик. Но по ходу моей деятельности мне...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
34
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru