Formatter.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include <errno.h>
  2. #include <stdbool.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. static int lineWidth = 0;
  7. static FILE* file = NULL;
  8. static char** words = NULL;
  9. static int wordAmount = 0;
  10. static int wordCapacity = 0;
  11. static int randA = 0;
  12. static int randB = 0;
  13. static const char* afterWord = "";
  14. static int afterWordLength = 0;
  15. static const char* afterLine = "";
  16. static int afterLineLength = 0;
  17. static void addWord(char* word) {
  18. if(wordAmount >= wordCapacity) {
  19. wordCapacity = wordCapacity * 2 + 1;
  20. words = (char**)realloc(words, (size_t)wordCapacity * sizeof(char*));
  21. }
  22. words[wordAmount++] = word;
  23. }
  24. static void parseFile(void) {
  25. while(true) {
  26. int c = fgetc(file);
  27. while(c == ' ' || c == '\n') {
  28. c = fgetc(file);
  29. }
  30. if(c == EOF) {
  31. break;
  32. }
  33. int capacity = 8;
  34. int index = 0;
  35. char* word = (char*)malloc((size_t)capacity * sizeof(char));
  36. while(c != ' ' && c != EOF && c != '\n') {
  37. if(index >= capacity) {
  38. capacity *= 2;
  39. word = (char*)realloc(word, (size_t)capacity);
  40. }
  41. word[index++] = (char)c;
  42. c = fgetc(file);
  43. }
  44. if(index >= capacity) {
  45. capacity *= 2;
  46. word = (char*)realloc(word, (size_t)capacity);
  47. }
  48. word[index++] = '\0';
  49. addWord(word);
  50. }
  51. }
  52. static void clean(void) {
  53. if(words != NULL) {
  54. for(int i = 0; i < wordAmount; i++) {
  55. free(words[i]);
  56. }
  57. free(words);
  58. }
  59. }
  60. static int getScore(void) {
  61. int score = 0;
  62. int length = 0;
  63. for(int i = 0; i < wordAmount; i++) {
  64. int l = (int)strlen(words[i]) + afterWordLength;
  65. if(length + l <= lineWidth - afterLineLength) {
  66. length += l;
  67. } else {
  68. score += lineWidth - length;
  69. length = l;
  70. }
  71. }
  72. return score;
  73. }
  74. static void print(void) {
  75. for(int i = 0; i < lineWidth; i++) {
  76. putchar('0' + (i % 10));
  77. }
  78. putchar('\n');
  79. int length = 0;
  80. for(int i = 0; i < wordAmount; i++) {
  81. int l = (int)strlen(words[i]) + afterWordLength;
  82. if(length + l <= lineWidth - afterLineLength) {
  83. printf("%s%s", words[i], afterWord);
  84. length += l;
  85. } else {
  86. length = l;
  87. printf("%s\n%s%s", afterLine, words[i], afterWord);
  88. }
  89. }
  90. }
  91. static void generateRandom(void) {
  92. randA = rand() % wordAmount;
  93. randB = rand() % wordAmount;
  94. }
  95. static void swap(void) {
  96. char* tmp = words[randA];
  97. words[randA] = words[randB];
  98. words[randB] = tmp;
  99. }
  100. static void optimize(void) {
  101. int globalMin = getScore();
  102. for(int k = 0; k < 5000; k++) {
  103. int minScore = getScore();
  104. for(int i = 0; i < 100000; i++) {
  105. generateRandom();
  106. swap();
  107. int score = getScore();
  108. if(score < minScore) {
  109. minScore = score;
  110. } else {
  111. swap();
  112. }
  113. }
  114. if(minScore < globalMin) {
  115. globalMin = minScore;
  116. print();
  117. printf("\nscore: %d\n", minScore);
  118. }
  119. for(int i = 0; i < 50; i++) {
  120. generateRandom();
  121. swap();
  122. }
  123. }
  124. }
  125. int main(int argAmount, const char* const* args) {
  126. if(argAmount <= 0) {
  127. puts("... <width> <file> <after> <line>");
  128. return 0;
  129. } else if(argAmount < 5) {
  130. printf("%s <width> <file> <after> <line>\n", args[0]);
  131. return 0;
  132. }
  133. lineWidth = atoi(args[1]);
  134. if(lineWidth <= 0) {
  135. printf("%s is an invalid line width\n", args[1]);
  136. return 0;
  137. }
  138. file = fopen(args[2], "rb");
  139. if(file == NULL) {
  140. printf("%s is an invalid file: %s\n", args[2], strerror(errno));
  141. return 0;
  142. }
  143. afterWord = args[3];
  144. afterWordLength = (int)strlen(args[3]);
  145. afterLine = args[4];
  146. afterLineLength = (int)strlen(args[4]);
  147. parseFile();
  148. optimize();
  149. clean();
  150. if(fclose(file)) {
  151. printf("close error: %s\n", strerror(errno));
  152. }
  153. return 0;
  154. }