#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