#include #include #include 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); }