aaaaaa123456789 icon

JV programming challenges, week 3, challenge 1

aaaaaa123456789 | PRO | 12/03/13 07:33:36 AM UTC | 0 ⭐ | 399 👁️ | Never ⏰ | []
C |

4.29 KB

|

None

|

0 👍

/

0 👎

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
struct block {
  unsigned start;
  unsigned count;
  struct block * next;
};
 
unsigned get_number(void);
char ** get_lines(unsigned);
char * get_line(void);
char * check_line(char *, unsigned, unsigned);
struct block parse_column(char **, unsigned, unsigned);
char ** generate_result(struct block *, unsigned);
void free_lines_array(char **, unsigned);
 
int main (void) {
  unsigned size = get_number();
  if (!size) {
    fprintf(stderr, "Invalid amount of lines entered\n");
    return 1;
  }
  char ** lines = get_lines(size);
  unsigned line;
  for (line = 0; line < size; line ++) lines[line] = check_line(lines[line], size, line + 1);
  struct block * columns = malloc(sizeof(struct block) * size);
  for (line = 0; line < size; line ++) columns[line] = parse_column(lines, size, line);
  free_lines_array(lines, size);
  lines = generate_result(columns, size);
  for (line = 0; line < size; line ++) {
    struct block * current = columns[line].next;
    struct block * previous = NULL;
    while (current) {
      previous = current;
      current = current -> next;
      free(previous);
    }
    printf("%s\n", lines[line]);
  }
  free(columns);
  free_lines_array(lines, size);
  return 0;
}
 
unsigned get_number (void) {
  char * line = get_line();
  if (!*line) {
    free(line);
    return 0;
  }
  char * end;
  unsigned number = strtoul(line, &end, 10);
  if (*end) number = 0;
  free(line);
  return number;
}
 
char ** get_lines (unsigned lines) {
  char ** result = malloc(sizeof(char *) * lines);
  unsigned line;
  for (line = 0; line < lines; line ++) result[line] = get_line();
  return result;
}
 
char * get_line (void) {
  char * line = NULL;
  unsigned length = 0;
  char newchar;
  for (newchar = getchar(); (newchar != EOF) && (newchar != '\n'); newchar = getchar()) {
    line = realloc(line, ++ length);
    line[length - 1] = newchar;
  }
  line = realloc(line, length + 1);
  line[length] = 0;
  return line;
}
 
char * check_line (char * line, unsigned size, unsigned line_number) {
  unsigned length = strlen(line);
  unsigned pos;
  if (length > size) {
    fprintf(stderr, "Line %u is %u characters long (expected: %u), truncating\n", line_number, length, size);
    line = realloc(line, size + 1);
    line[size] = 0;
  } else if (length < size) {
    fprintf(stderr, "Line %u is %u characters long (expected: %u), padding with spaces\n", line_number, length, size);
    line = realloc(line, size + 1);
    memset(line + length, ' ', size - length);
    line[size] = 0;
  }
  for (pos = 0; pos < size; pos ++) {
    if ((line[pos] == ' ') || (line[pos] == '#') || (line[pos] == '.')) continue;
    fprintf(stderr, "Line %u: spurious character 0x%02x at column %u, inserting space\n", line_number, (int) (line[pos]), pos + 1);
    line[pos] = ' ';
  }
  return line;
}
 
struct block parse_column (char ** lines, unsigned size, unsigned column) {
  struct block result = {.start = 0, .count = 0, .next = NULL};
  struct block * current = &result;
  unsigned line;
  for (line = 0; line < size; line ++)
    switch (lines[size - 1 - line][column]) {
      case '.':
        (current -> count) ++;
        break;
      case '#':
        current = (current -> next = malloc(sizeof(struct block)));
        current -> start = line + 1;
        current -> count = 0;
        current -> next = NULL;
    }
  return result;
}
 
char ** generate_result (struct block * columns, unsigned size) {
  char ** result = malloc(sizeof(char *) * size);
  unsigned line, pos;
  struct block * current_block;
  for (line = 0; line < size; line ++) {
    result[line] = malloc(size + 1);
    memset(result[line], ' ', size);
    result[line][size] = 0;
  }
  for (line = 0; line < size; line ++)
    for (current_block = columns + line; current_block; current_block = current_block -> next) {
      if (current_block -> start) result[size - current_block -> start][line] = '#';
      for (pos = 1; pos <= (current_block -> count); pos ++)
        result[size - (current_block -> start + pos)][line] = '.';
    }
  return result;
}
 
void free_lines_array (char ** lines, unsigned size) {
  unsigned line;
  for (line = 0; line < size; line ++) free(lines[line]);
  free(lines);
}

Comments