123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- #include <errno.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- static int lineWidth = 0;
- static FILE* file = NULL;
- static char** words = NULL;
- static int wordAmount = 0;
- static int wordCapacity = 0;
- static int randA = 0;
- static int randB = 0;
- static const char* afterWord = "";
- static int afterWordLength = 0;
- static const char* afterLine = "";
- static int afterLineLength = 0;
- static void addWord(char* word) {
- if(wordAmount >= wordCapacity) {
- wordCapacity = wordCapacity * 2 + 1;
- words = (char**)realloc(words, (size_t)wordCapacity * sizeof(char*));
- }
- words[wordAmount++] = word;
- }
- static void parseFile(void) {
- while(true) {
- int c = fgetc(file);
- while(c == ' ' || c == '\n') {
- c = fgetc(file);
- }
- if(c == EOF) {
- break;
- }
- int capacity = 8;
- int index = 0;
- char* word = (char*)malloc((size_t)capacity * sizeof(char));
- while(c != ' ' && c != EOF && c != '\n') {
- if(index >= capacity) {
- capacity *= 2;
- word = (char*)realloc(word, (size_t)capacity);
- }
- word[index++] = (char)c;
- c = fgetc(file);
- }
- if(index >= capacity) {
- capacity *= 2;
- word = (char*)realloc(word, (size_t)capacity);
- }
- word[index++] = '\0';
- addWord(word);
- }
- }
- static void clean(void) {
- if(words != NULL) {
- for(int i = 0; i < wordAmount; i++) {
- free(words[i]);
- }
- free(words);
- }
- }
- static int getScore(void) {
- int score = 0;
- int length = 0;
- for(int i = 0; i < wordAmount; i++) {
- int l = (int)strlen(words[i]) + afterWordLength;
- if(length + l <= lineWidth - afterLineLength) {
- length += l;
- } else {
- score += lineWidth - length;
- length = l;
- }
- }
- return score;
- }
- static void print(void) {
- for(int i = 0; i < lineWidth; i++) {
- putchar('0' + (i % 10));
- }
- putchar('\n');
- int length = 0;
- for(int i = 0; i < wordAmount; i++) {
- int l = (int)strlen(words[i]) + afterWordLength;
- if(length + l <= lineWidth - afterLineLength) {
- printf("%s%s", words[i], afterWord);
- length += l;
- } else {
- length = l;
- printf("%s\n%s%s", afterLine, words[i], afterWord);
- }
- }
- }
- static void generateRandom(void) {
- randA = rand() % wordAmount;
- randB = rand() % wordAmount;
- }
- static void swap(void) {
- char* tmp = words[randA];
- words[randA] = words[randB];
- words[randB] = tmp;
- }
- static void optimize(void) {
- int globalMin = getScore();
- for(int k = 0; k < 5000; k++) {
- int minScore = getScore();
- for(int i = 0; i < 100000; i++) {
- generateRandom();
- swap();
- int score = getScore();
- if(score < minScore) {
- minScore = score;
- } else {
- swap();
- }
- }
- if(minScore < globalMin) {
- globalMin = minScore;
- print();
- printf("\nscore: %d\n", minScore);
- }
- for(int i = 0; i < 50; i++) {
- generateRandom();
- swap();
- }
- }
- }
- int main(int argAmount, const char* const* args) {
- if(argAmount <= 0) {
- puts("... <width> <file> <after> <line>");
- return 0;
- } else if(argAmount < 5) {
- printf("%s <width> <file> <after> <line>\n", args[0]);
- return 0;
- }
- lineWidth = atoi(args[1]);
- if(lineWidth <= 0) {
- printf("%s is an invalid line width\n", args[1]);
- return 0;
- }
- file = fopen(args[2], "rb");
- if(file == NULL) {
- printf("%s is an invalid file: %s\n", args[2], strerror(errno));
- return 0;
- }
- afterWord = args[3];
- afterWordLength = (int)strlen(args[3]);
- afterLine = args[4];
- afterLineLength = (int)strlen(args[4]);
- parseFile();
- optimize();
- clean();
- if(fclose(file)) {
- printf("close error: %s\n", strerror(errno));
- }
- return 0;
- }
|