Main.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct {
  4. int fitness;
  5. int* data;
  6. } Square;
  7. Square* squares;
  8. int size = 0;
  9. int population = 0;
  10. int (*fitness)(int*) = NULL;
  11. int compare(const void* a, const void* b) {
  12. int ia = ((Square*)a)->fitness;
  13. int ib = ((Square*)b)->fitness;
  14. return ia < ib ? -1 : (ia > ib ? 1 : 0);
  15. }
  16. void sort() {
  17. qsort(squares, population, sizeof(Square), compare);
  18. }
  19. void mutate(int* data) {
  20. int a = rand() % (size * size);
  21. int b = rand() % (size * size);
  22. while(b == a) {
  23. b = rand() % (size * size);
  24. }
  25. int tmp = data[a];
  26. data[a] = data[b];
  27. data[b] = tmp;
  28. }
  29. void reproduce(const int* parent, Square* child) {
  30. int end = size * size;
  31. for(int i = 0; i < end; i++) {
  32. child->data[i] = parent[i];
  33. }
  34. mutate(child->data);
  35. child->fitness = fitness(child->data);
  36. }
  37. void init() {
  38. squares = malloc(sizeof(Square) * population);
  39. int end = size * size;
  40. for(int i = 0; i < population; i++) {
  41. squares[i].data = malloc(sizeof(int) * end);
  42. for(int k = 0; k < end; k++) {
  43. squares[i].data[k] = k + 1;
  44. }
  45. for(int k = 0; k < end; k++) {
  46. mutate(squares[i].data);
  47. }
  48. squares[i].fitness = fitness(squares[i].data);
  49. }
  50. }
  51. void clear() {
  52. for(int i = 0; i < population; i++) {
  53. free(squares[i].data);
  54. }
  55. free(squares);
  56. }
  57. int get(int* data, int x, int y) {
  58. return data[y * size + x];
  59. }
  60. int errorFactor(int e) {
  61. return e * e;
  62. }
  63. int getWanted() {
  64. return (size * (size * size + 1)) / 2;
  65. }
  66. int getSemiFitness(int* data) {
  67. int fitness = 0;
  68. int wanted = getWanted();
  69. for(int y = 0; y < size; y++) {
  70. int sum = 0;
  71. for(int x = 0; x < size; x++) {
  72. sum += get(data, x, y);
  73. }
  74. fitness += errorFactor(sum - wanted);
  75. }
  76. for(int x = 0; x < size; x++) {
  77. int sum = 0;
  78. for(int y = 0; y < size; y++) {
  79. sum += get(data, x, y);
  80. }
  81. fitness += errorFactor(sum - wanted);
  82. }
  83. return fitness;
  84. }
  85. int getDiagonalBase(int* data) {
  86. int diaA = 0;
  87. int diaB = 0;
  88. for(int i = 0; i < size; i++) {
  89. diaA += get(data, i, i);
  90. diaB += get(data, i, (size - 1) - i);
  91. }
  92. int wanted = getWanted();
  93. int fitness = errorFactor(diaA - wanted);
  94. fitness += errorFactor(diaB - wanted);
  95. return fitness;
  96. }
  97. int getNormalFitness(int* data) {
  98. return getSemiFitness(data) + getDiagonalBase(data);
  99. }
  100. int getPandiagonalBase(int* data) {
  101. int fitness = 0;
  102. int wanted = getWanted();
  103. for(int x = 0; x < size; x++) {
  104. int sumA = 0;
  105. int sumB = 0;
  106. for(int y = 0; y < size; y++) {
  107. sumA += get(data, (x + y) % size, y);
  108. sumB += get(data, (x - y + size) % size, y);
  109. }
  110. fitness += errorFactor(sumA - wanted);
  111. fitness += errorFactor(sumB - wanted);
  112. }
  113. return fitness;
  114. }
  115. int getAssociativeBase(int* data) {
  116. int fitness = 0;
  117. int wanted = size * size + 1;
  118. for(int x = 0; x < size; x++) {
  119. for(int y = 0; y < size; y++) {
  120. int sum = get(data, x, y) + get(data, size - x - 1, size - y - 1);
  121. fitness += errorFactor(sum - wanted);
  122. }
  123. }
  124. return fitness;
  125. }
  126. int getUltraFitness(int* data) {
  127. return getSemiFitness(data) + getPandiagonalBase(data) +
  128. getAssociativeBase(data);
  129. }
  130. int get2x2SquareBase(int* data) {
  131. int fitness = 0;
  132. int wanted = 2 * (size * size + 1);
  133. for(int x = 0; x < size; x++) {
  134. for(int y = 0; y < size; y++) {
  135. if(x % 2 == 0 && y % 2 == 0) {
  136. int sum = get(data, x, y) + get(data, x + 1, y) +
  137. get(data, x, y + 1) + get(data, x + 1, y + 1);
  138. fitness += errorFactor(sum - wanted);
  139. }
  140. }
  141. }
  142. return fitness;
  143. }
  144. int getPerfectDiagonalBase(int* data) {
  145. int fitness = 0;
  146. int wanted = size * size + 1;
  147. for(int x = 0; x < size / 2; x++) {
  148. for(int y = 0; y < size; y++) {
  149. int sum = get(data, x, y) +
  150. get(data, (x + size / 2) % size, (y + size / 2) % size);
  151. fitness += errorFactor(sum - wanted);
  152. }
  153. }
  154. return fitness;
  155. }
  156. int getMostPerfectFitness(int* data) {
  157. return getSemiFitness(data) + getPandiagonalBase(data) +
  158. get2x2SquareBase(data) + getPerfectDiagonalBase(data);
  159. }
  160. void print(Square* s) {
  161. printf("Fitness: %d\n", s->fitness);
  162. for(int y = 0; y < size; y++) {
  163. for(int x = 0; x < size; x++) {
  164. printf("%2d ", get(s->data, x, y));
  165. }
  166. putchar('\n');
  167. }
  168. putchar('\n');
  169. }
  170. int main(int argAmount, char** args) {
  171. if(argAmount < 4) {
  172. if(argAmount <= 0) {
  173. printf("... <type> <size> <population>\n");
  174. } else {
  175. printf("%s <type> <size> <population>\n", args[0]);
  176. }
  177. return 0;
  178. }
  179. int type = atoi(args[1]);
  180. size = atoi(args[2]);
  181. population = atoi(args[3]);
  182. if(population < 4) {
  183. population = 4;
  184. }
  185. switch(type) {
  186. case 1: fitness = getNormalFitness; break;
  187. case 2: fitness = getUltraFitness; break;
  188. case 3: fitness = getMostPerfectFitness; break;
  189. default: puts("unknown type"); return 0;
  190. }
  191. for(int h = 0; h < 5; h++) {
  192. init();
  193. int half = population / 2;
  194. int run = 1;
  195. while(run) {
  196. sort();
  197. for(int k = half; k < population; k++) {
  198. int parent = rand() % half;
  199. reproduce(squares[parent].data, squares + k);
  200. if(squares[k].fitness == 0) {
  201. run = 0;
  202. break;
  203. }
  204. }
  205. }
  206. sort();
  207. print(squares);
  208. clear();
  209. }
  210. return 0;
  211. }