Actual model
| 91 | }; |
| 92 | /// Actual model |
| 93 | Crossword(const SizeOptions& opt) |
| 94 | : Script(opt), |
| 95 | w(grids[opt.size()][0]), h(grids[opt.size()][1]), |
| 96 | letters(*this,w*h,'a','z') { |
| 97 | // Pointer into the grid specification (width and height already skipped) |
| 98 | const int* g = &grids[opt.size()][2]; |
| 99 | |
| 100 | // Matrix for letters |
| 101 | Matrix<IntVarArray> ml(letters, w, h); |
| 102 | |
| 103 | // Set black fields to 0 |
| 104 | { |
| 105 | IntVar z(*this,0,0); |
| 106 | for (int n = *g++; n--; ) { |
| 107 | int x=*g++, y=*g++; |
| 108 | ml(x,y)=z; |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | // Array of all words |
| 113 | IntVarArgs allwords; |
| 114 | |
| 115 | switch (opt.model()) { |
| 116 | case MODEL_ELEMENT: |
| 117 | // While words of length w_l to process |
| 118 | while (int w_l=*g++) { |
| 119 | // Number of words of that length in the dictionary |
| 120 | int n_w = dict.words(w_l); |
| 121 | // Number of words of that length in the puzzle |
| 122 | int n=*g++; |
| 123 | |
| 124 | if (n > n_w) { |
| 125 | fail(); |
| 126 | } else { |
| 127 | // Array of all words of length w_l |
| 128 | IntVarArgs words(*this,n,0,n_w-1); |
| 129 | allwords << words; |
| 130 | |
| 131 | // All words of same length must be different |
| 132 | distinct(*this, words, opt.ipl()); |
| 133 | |
| 134 | for (int d=0; d<w_l; d++) { |
| 135 | // Array that maps words to a letter at a certain position (shared among all element constraints) |
| 136 | IntSharedArray w2l(n_w); |
| 137 | // Initialize word to letter map |
| 138 | for (int i=n_w; i--; ) |
| 139 | w2l[i] = dict.word(w_l,i)[d]; |
| 140 | // Link word to letter variable |
| 141 | for (int i=0; i<n; i++) { |
| 142 | // Get (x,y) coordinate where word begins |
| 143 | int x=g[3*i+0], y=g[3*i+1]; |
| 144 | // Whether word is horizontal |
| 145 | bool h=(g[3*i+2] == 0); |
| 146 | // Constrain the letters to the words' letters |
| 147 | element(*this, w2l, words[i], h ? ml(x+d,y) : ml(x,y+d)); |
| 148 | } |
| 149 | } |
| 150 | // Skip word coordinates |
nothing calls this directly
no test coverage detected