//-------------- cartelle.cpp ------------------------------ #include <stdlib.h> #include <string.h> #include "cartelle.h" //-------------------------------------------------- const int MAX_RANGE = 11;// l'ultima riga va da 80 a 90, quindi usa 11 numeri const int TOT_ROW = 3; // righe della cartella const int TOT_COLUMN = 9; // colonne della cartella const int TOT_CART = (TOT_ROW * TOT_COLUMN); const int MAX_NUMB_ROW = 5; // numeri possibili per riga const int MAX_NUMB_CART = (MAX_NUMB_ROW * TOT_ROW); // se si desiderano avere ordinati i numeri sulla colonna //#define ORDINATI //-------------------------------------------------- class ten { public: ten(tRange low, tRange hight); // Preleva il primo valore di threeVal e fa salire gli altri. // Se il nuovo primo valore è zero, ricarica dal buffer e se è // ancora zero, cioè è finito il buffer richiama reload() tRange getNumber(); // torna il numero di elementi totali disponibili int getTotNumber(); // riporta il contenuto di threeVal in buff, ricarica // threeVal con tre valori casuali togliendoli da buff e li ordina (se // è attiva ORDINATI). // Da richiamare prima della generazione della cartella void shuffle(); private: // tre valori casuali estratti da buff tRange threeVal[TOT_ROW]; tRange Buff[MAX_RANGE]; // numero di elementi contenuti in Buff (esclusi quelli in threeVal) int Tot; tRange Low; tRange Hight; // ricarica buffer e richiama shuffle() void reload(); }; //-------------------------------------------------- //-------------------------------------------------- ten::ten(tRange low, tRange hight) : Low(low), Hight(hight) { reload(); } //-------------------------------------------------- void ten::reload() { int j; for(Tot = 0, j = Low; j <= Hight; ++j, ++Tot) Buff[Tot] = j; memset(threeVal, 0, sizeof(threeVal)); shuffle(); } //-------------------------------------------------- int ten::getTotNumber() { int i; for(i = 0; i < TOT_ROW; ++i) if(!threeVal[i]) break; return i + Tot; } //-------------------------------------------------- tRange ten::getNumber() { tRange ret = threeVal[0]; int i; for(i=0; i < TOT_ROW-1; ++i) threeVal[i] = threeVal[i+1]; threeVal[i]=0; if(!threeVal[0]) { shuffle(); if(!threeVal[0]) reload(); } return ret; } //-------------------------------------------------- void ten::shuffle() { int i; for(i=0; i < TOT_ROW; ++i) if(threeVal[i]) { Buff[Tot++] = threeVal[i]; threeVal[i] = 0; } else break; for(i=0; i < TOT_ROW && Tot; ++i) { int pos = rand() % Tot; threeVal[i] = Buff[pos]; --Tot; Buff[pos] = Buff[Tot]; #if 0 Buff[Tot]=0; // può servire per un debug #endif } #ifdef ORDINATI // riordina i due/tre valori if(i ==2) { if(threeVal[0] > threeVal[1]) { tRange t = threeVal[0]; threeVal[0] = threeVal[1]; threeVal[1] = t; } } else if(i == 3) { for(int i = 1; i < 3; ++i) { tRange t = threeVal[i]; // elemento da inserire int j; for(j = i - 1 ; j >= 0 && t < threeVal[j]; --j) threeVal[j + 1]=threeVal[j]; threeVal[j + 1]=t; } } #endif } //-------------------------------------------------- //-------------------------------------------------- //-------------------------------------------------- class cartella { public: cartella(); ~cartella(); // buff deve avere dimensione almeno TOT_CART void make(tRange *buff); private: class ten **Ten; int Tot; int PosTmp; int Row[TOT_ROW][MAX_NUMB_ROW]; int Numb[TOT_COLUMN]; int NumbTmp[TOT_COLUMN]; // carica in numb i sei oggetti ten che hanno il numeri più alto di elementi void getTopSix(int *numb); // calcola se occupati i bit vicini a pos e ne ritorna il peso int best_of(int pos, int bit); // calcola quale bit dà il peso maggiore int bestOf(int bit0, int bit1); // esegue lo spostamento di un elemento da una riga all'altra per evitare // di avere più di tre numeri vicini nella direzione orizzontale void move(int rowBit_0, int rowBit_1, int *row_0, int *row_1); // crea la riga in modo casuale void makeRow(int *row); // verifica se ci sono più di tre elementi vicini ed in caso affermativo // scambia con le altre righe void checkIfTooNear(); // estrae i numeri da Ten alle posizioni date da Row void extract(tRange *buff); }; //------------------------------------------------- cartella::cartella() { Ten = new ten*[TOT_COLUMN]; const tRange range[] = { 0, 9, 19, 29, 39, 49, 59, 69, 79, 90 }; for(int i = 0; i < TOT_COLUMN; ++i) Ten[i] = new ten(range[i]+1,range[i+1]); } //-------------------------------------------------- cartella::~cartella() { for(int i = 0; i < TOT_COLUMN; ++i) delete Ten[i]; delete []Ten; } //-------------------------------------------------- void cartella::getTopSix(int *numb) { int top[TOT_COLUMN]; for(int i = 0; i < TOT_COLUMN; ++i) top[i] = Ten[i]->getTotNumber(); for(int i = 0; i < TOT_COLUMN; ++i) { --top[numb[i]]; numb[i] = i; } for(int i = 1; i < TOT_COLUMN; ++i) { int t = top[i]; // elemento da inserire tRange n = numb[i]; int j; for(j = i - 1 ; j >= 0 && t > top[j]; --j) { top[j + 1] = top[j]; numb[j + 1] = numb[j]; } top[j + 1] = t; numb[j + 1] = n; } int j=0; for(int i = MAX_NUMB_CART - TOT_COLUMN - 1; i; --i) { if(!top[i]) numb[i] = numb[j++]; else break; } } //--------------------------------------------------- int cartella::best_of(int pos, int bit) { int bestLow = 0; int bestHight = 0; int side = 0; if(pos > 0) { bestLow += (bit & (1 << (pos-1))) != 0; if(pos > 1) bestLow += (bit & (1 << (pos-2))) != 0; else if(bestLow) ++side; } else side = 2; if(pos < TOT_COLUMN-1) { bestHight += (bit & (1 << (pos+1))) != 0; if(pos < TOT_COLUMN-2) bestHight += (bit & (1 << (pos+2))) != 0; else if(bestHight) ++side; } else side = 2; if(2 == side) return (bestLow + bestHight) << 1; return bestLow + bestHight + side; } //--------------------------------------------------- int cartella::bestOf(int bit0, int bit1) { int bit = bit0 ^ bit1; int bit_0 = bit0 & bit; int best = 0; int bestVal = 0; for(int i = 0; i < TOT_COLUMN; ++i) { if(bit_0 & (1 << i)) { // solo quelli che possono essere trasferiti int result = best_of(i, bit0); if(result >= bestVal) { bestVal = result; best = i; } } } return best; } //--------------------------------------------------- void cartella::move(int rowBit_0, int rowBit_1, int *row_0, int *row_1) { int best_0 = bestOf(rowBit_0, rowBit_1); int best_1 = bestOf(rowBit_1, rowBit_0); for(int i = 0; i < MAX_NUMB_ROW; ++i) if(row_0[i] == best_0) { best_0 = i; break; } for(int i = 0; i < MAX_NUMB_ROW; ++i) if(row_1[i] == best_1) { best_1 = i; break; } int t = row_0[best_0]; row_0[best_0] = row_1[best_1]; row_1[best_1] = t; } //----------------------------------------------------- void cartella::makeRow(int* row) { for(int j = 0; j < MAX_NUMB_ROW; ++j) { int pos; if(PosTmp >= 0) { pos = rand() % Tot; row[j] = Numb[pos]; NumbTmp[PosTmp++] = Numb[pos]; } else { for(;;) { pos = rand() % Tot; int k; for(k = 0; k < j; ++k) if(row[k] == Numb[pos]) break; if(k == j) break; } } row[j] = Numb[pos]; if(!--Tot) { memcpy(Numb, NumbTmp, TOT_COLUMN * sizeof(Numb[0])); getTopSix(Numb); Tot = MAX_NUMB_CART - TOT_COLUMN; PosTmp = -1; } else { Numb[pos] = Numb[Tot]; Numb[Tot] = 0; } } } //----------------------------------------------------- #define MASK_CONS 0x8000 #define MAX_REPEAT 10 void cartella::checkIfTooNear() { int maxRepeat = 0; int last = -1; for(;;) { int rowBit[TOT_ROW]; for(int i = 0; i < TOT_ROW; ++i) { rowBit[i] = 0; for(int j = 0; j < MAX_NUMB_ROW; ++j) { int bit = Row[i][j]; rowBit[i] |= 1 << bit; } int cons = 0; for(int j = 0; j < TOT_COLUMN-1; ++j) { if((rowBit[i] & (3 << j)) == (3 << j)) { if(++cons >= 3) { rowBit[i] |= MASK_CONS; break; } } else cons = 0; } } if(MAX_REPEAT <= maxRepeat++) break; #define MOVE(a,b) move(rowBit[a], rowBit[b], Row[a], Row[b]) if(rowBit[0] & MASK_CONS) { int t = 0 == last ? 2 : 1; MOVE(0, t); last = 0 == last ? 2 : 0; continue; } if(rowBit[1] & MASK_CONS) { int t = 1 == last ? 0 : 2; MOVE(1, t); last = 1 == last ? 0 : 1; continue; } if(rowBit[2] & MASK_CONS) { int t = 2 == last ? 1 : 0; MOVE(2, t); last = 2 == last ? 1 : 2; continue; } break; } } //----------------------------------------------------- void cartella::extract(tRange *buff) { int pos_row = 0; for(int i = 0; i < TOT_ROW; ++i, pos_row += TOT_COLUMN) { for(int j = 0; j < MAX_NUMB_ROW; ++j) { int column = Row[i][j]; int pos = pos_row + column; buff[pos] = Ten[column]->getNumber(); } } } //----------------------------------------------------- void cartella::make(tRange *buff) { memset(buff, 0, sizeof(*buff) * TOT_CART); PosTmp = 0; Tot = TOT_COLUMN; for(int i = 0; i < TOT_COLUMN; ++i) { Numb[i] = i; Ten[i]->shuffle(); } for(int i = 0; i < TOT_ROW; ++i) makeRow(Row[i]); checkIfTooNear(); extract(buff); } //------------------------------------------------------- //------------------------------------------------------- //------------------------------------------------------- #define RESULT "Result.txt" Gest_Cart::Gest_Cart() : Curr(0), File(0) { C = new cartella; } //------------------------------------------------------- Gest_Cart::~Gest_Cart() { if(File) fclose(File); delete C; } //------------------------------------------------------- #define BREAK1 "---------------" #define BREAK2 "---------------\r\n" bool Gest_Cart::run(int numCart, bool tabbed, int seme) { if(File) fclose(File); File = fopen(RESULT, "wb+"); if(!seme) randomize(); else srand(seme); Curr=0; //#define MAKE_FIELD #ifdef MAKE_FIELD if(tabbed) { char t[6] = "N"; int i; for(i = 0; i < TOT_CART-1; ++i) { itoa(i+1,t+1,10); strcat(t,"\t"); fwrite(t, strlen(t), 1, File); } itoa(i+1,t+1,10); strcat(t,"\r\n"); fwrite(t, strlen(t), 1, File); } #endif for(int i = 0; i < numCart; ++i) { ++Curr; showCurr(Curr); tRange numb[TOT_CART+1]; C->make(numb); if(tabbed) saveTabbed(numb); else save(numb); if(get_break()) { fclose(File); return false; } } fclose(File); return true; } //------------------------------------------------------- void Gest_Cart::save(tRange *numb) { char buff[100]; int pos=0; sprintf(buff, "%s[%4d]%s", BREAK1, Curr, BREAK2); fwrite(buff, strlen(buff), 1, File); for(int i = 0;i < TOT_ROW; ++i) { for(int j=0; j < TOT_COLUMN; ++j,++pos) { if(numb[pos]) sprintf(buff,"%4d",static_cast<int>(numb[pos])); else sprintf(buff," "); fwrite(buff, strlen(buff), 1, File); } fwrite("\r\n", 2, 1, File); } sprintf(buff,"%s------%s",BREAK1,BREAK2); fwrite(buff, strlen(buff), 1, File); } //------------------------------------------------------- void Gest_Cart::saveTabbed(tRange *numb) { char buff[100]; int pos=0; for(int i = 0;i < TOT_ROW; ++i) { for(int j=0; j < TOT_COLUMN; ++j,++pos) { if(numb[pos]) sprintf(buff,"%d\t",static_cast<int>(numb[pos])); else sprintf(buff," \t"); fwrite(buff, strlen(buff), 1, File); } } fwrite("\r\n", 2, 1, File); } //-------------------------------------------------------