Advertisement
aaaaaa123456789

JV programming challenges, week 3, challenge 1

Dec 3rd, 2013
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.29 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. struct block {
  6.   unsigned start;
  7.   unsigned count;
  8.   struct block * next;
  9. };
  10.  
  11. unsigned get_number(void);
  12. char ** get_lines(unsigned);
  13. char * get_line(void);
  14. char * check_line(char *, unsigned, unsigned);
  15. struct block parse_column(char **, unsigned, unsigned);
  16. char ** generate_result(struct block *, unsigned);
  17. void free_lines_array(char **, unsigned);
  18.  
  19. int main (void) {
  20.   unsigned size = get_number();
  21.   if (!size) {
  22.     fprintf(stderr, "Invalid amount of lines entered\n");
  23.     return 1;
  24.   }
  25.   char ** lines = get_lines(size);
  26.   unsigned line;
  27.   for (line = 0; line < size; line ++) lines[line] = check_line(lines[line], size, line + 1);
  28.   struct block * columns = malloc(sizeof(struct block) * size);
  29.   for (line = 0; line < size; line ++) columns[line] = parse_column(lines, size, line);
  30.   free_lines_array(lines, size);
  31.   lines = generate_result(columns, size);
  32.   for (line = 0; line < size; line ++) {
  33.     struct block * current = columns[line].next;
  34.     struct block * previous = NULL;
  35.     while (current) {
  36.       previous = current;
  37.       current = current -> next;
  38.       free(previous);
  39.     }
  40.     printf("%s\n", lines[line]);
  41.   }
  42.   free(columns);
  43.   free_lines_array(lines, size);
  44.   return 0;
  45. }
  46.  
  47. unsigned get_number (void) {
  48.   char * line = get_line();
  49.   if (!*line) {
  50.     free(line);
  51.     return 0;
  52.   }
  53.   char * end;
  54.   unsigned number = strtoul(line, &end, 10);
  55.   if (*end) number = 0;
  56.   free(line);
  57.   return number;
  58. }
  59.  
  60. char ** get_lines (unsigned lines) {
  61.   char ** result = malloc(sizeof(char *) * lines);
  62.   unsigned line;
  63.   for (line = 0; line < lines; line ++) result[line] = get_line();
  64.   return result;
  65. }
  66.  
  67. char * get_line (void) {
  68.   char * line = NULL;
  69.   unsigned length = 0;
  70.   char newchar;
  71.   for (newchar = getchar(); (newchar != EOF) && (newchar != '\n'); newchar = getchar()) {
  72.     line = realloc(line, ++ length);
  73.     line[length - 1] = newchar;
  74.   }
  75.   line = realloc(line, length + 1);
  76.   line[length] = 0;
  77.   return line;
  78. }
  79.  
  80. char * check_line (char * line, unsigned size, unsigned line_number) {
  81.   unsigned length = strlen(line);
  82.   unsigned pos;
  83.   if (length > size) {
  84.     fprintf(stderr, "Line %u is %u characters long (expected: %u), truncating\n", line_number, length, size);
  85.     line = realloc(line, size + 1);
  86.     line[size] = 0;
  87.   } else if (length < size) {
  88.     fprintf(stderr, "Line %u is %u characters long (expected: %u), padding with spaces\n", line_number, length, size);
  89.     line = realloc(line, size + 1);
  90.     memset(line + length, ' ', size - length);
  91.     line[size] = 0;
  92.   }
  93.   for (pos = 0; pos < size; pos ++) {
  94.     if ((line[pos] == ' ') || (line[pos] == '#') || (line[pos] == '.')) continue;
  95.     fprintf(stderr, "Line %u: spurious character 0x%02x at column %u, inserting space\n", line_number, (int) (line[pos]), pos + 1);
  96.     line[pos] = ' ';
  97.   }
  98.   return line;
  99. }
  100.  
  101. struct block parse_column (char ** lines, unsigned size, unsigned column) {
  102.   struct block result = {.start = 0, .count = 0, .next = NULL};
  103.   struct block * current = &result;
  104.   unsigned line;
  105.   for (line = 0; line < size; line ++)
  106.     switch (lines[size - 1 - line][column]) {
  107.       case '.':
  108.         (current -> count) ++;
  109.         break;
  110.       case '#':
  111.         current = (current -> next = malloc(sizeof(struct block)));
  112.         current -> start = line + 1;
  113.         current -> count = 0;
  114.         current -> next = NULL;
  115.     }
  116.   return result;
  117. }
  118.  
  119. char ** generate_result (struct block * columns, unsigned size) {
  120.   char ** result = malloc(sizeof(char *) * size);
  121.   unsigned line, pos;
  122.   struct block * current_block;
  123.   for (line = 0; line < size; line ++) {
  124.     result[line] = malloc(size + 1);
  125.     memset(result[line], ' ', size);
  126.     result[line][size] = 0;
  127.   }
  128.   for (line = 0; line < size; line ++)
  129.     for (current_block = columns + line; current_block; current_block = current_block -> next) {
  130.       if (current_block -> start) result[size - current_block -> start][line] = '#';
  131.       for (pos = 1; pos <= (current_block -> count); pos ++)
  132.         result[size - (current_block -> start + pos)][line] = '.';
  133.     }
  134.   return result;
  135. }
  136.  
  137. void free_lines_array (char ** lines, unsigned size) {
  138.   unsigned line;
  139.   for (line = 0; line < size; line ++) free(lines[line]);
  140.   free(lines);
  141. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement