Input consuming.
It's possible that this commit contains errors, since I'm writing this on a Windows machine and the compiler seems bad. I'll compile this in a Linux machine and fix any errors present in the following commit.
This commit is contained in:
parent
bc3125dcc8
commit
fe3d00a5f5
|
@ -0,0 +1,4 @@
|
|||
3
|
||||
1 1 -1
|
||||
555 0.9 +2
|
||||
-55 2 1555
|
3
make.py
3
make.py
|
@ -7,8 +7,9 @@ from sane import *
|
|||
|
||||
COMPILER = 'gcc'
|
||||
COMPILE_FLAGS = ['-g',
|
||||
'-Wall',
|
||||
'--std=c99',
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
'-fopenmp']
|
||||
LINK_FLAGS = []
|
||||
OBJ_DIR = 'obj'
|
||||
|
|
172
src/main.c
172
src/main.c
|
@ -1,11 +1,177 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define STB_DS_IMPLEMENTATION
|
||||
#include "../contrib/stb/stb_ds.h"
|
||||
// #define STB_DS_IMPLEMENTATION
|
||||
// #define STBDS_NO_SHORT_NAMES
|
||||
// #include "../contrib/stb/stb_ds.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
#define PRIgridDATA PRIiFAST32
|
||||
typedef int_fast32_t grid_data_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Number of elements in one row.
|
||||
size_t row_len;
|
||||
// Pointer to the buffer containing the matrix's characters.
|
||||
// The data is organized as <string length> <chars...>, such that the `char`s
|
||||
// are casted to `int_fast32_t` to allow for the mixed types.
|
||||
grid_data_t *data_head;
|
||||
// Array of pointers to the start of each entry string.
|
||||
grid_data_t **entries_head;
|
||||
// Number of elements.
|
||||
size_t data_len;
|
||||
} grid_t;
|
||||
|
||||
// Parameters for `increase_input_buffers`.
|
||||
typedef struct
|
||||
{
|
||||
size_t data_cap;
|
||||
grid_data_t *data_head;
|
||||
grid_data_t **entries_head;
|
||||
} increase_input_buffers_params_t;
|
||||
|
||||
// Prints a debug view of a `grid_t` to standard output.
|
||||
void debug_print_grid(grid_t *grid)
|
||||
{
|
||||
printf("Grid { row_len: %zu, data_head: %p, entries_head: %p, data_len: %zu }",
|
||||
(grid->row_len), (void*)(grid->data_head), (void*)(grid->entries_head),
|
||||
(grid->data_len));
|
||||
}
|
||||
|
||||
// Increases the data buffers used in `parse_input`.
|
||||
//
|
||||
// As reallocation will happen, the updated pointers and capacity are returned
|
||||
// in an updated parameters object.
|
||||
increase_input_buffers_params_t increase_input_buffers(increase_input_buffers_params_t params)
|
||||
{
|
||||
params.data_cap *= 2;
|
||||
params.data_head = realloc(params.data_head, params.data_cap * sizeof(grid_data_t));
|
||||
params.entries_head = realloc(params.entries_head, params.data_cap * sizeof(grid_data_t *));
|
||||
if ((params.data_head == NULL) || (params.entries_head == NULL))
|
||||
{
|
||||
printf(
|
||||
"Failed to reallocate bigger buffer for input data. Was trying to "
|
||||
"allocate %zu entries, aborting.",
|
||||
params.data_cap);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
// Parse the input from standard input.
|
||||
//
|
||||
// This function parses an extended matrix (C|l), where C is an n×m matrix, and
|
||||
// l is an m-sized column vector. This input is given in standard input as
|
||||
//
|
||||
// <row length> <whitespace separated entries>
|
||||
//
|
||||
// Parsing the entries of the matrix as numeric is unnecessary, since we just
|
||||
// want to check equality of rows under certain permutations. Therefore, the
|
||||
// matrix is stored as literal characters.
|
||||
//
|
||||
// To make data access O(1), we store both the literal characters, as well as
|
||||
// indices to the start of each entry. See the `Grid` struct. In particular,
|
||||
// what we have is contiguous blocks of strings, structured as
|
||||
//
|
||||
// <string length> <characters...>
|
||||
grid_t parse_input(void)
|
||||
{
|
||||
size_t row_len;
|
||||
scanf("%zu", &row_len);
|
||||
|
||||
size_t data_cap = 32; // Initial value is arbitrary.
|
||||
size_t data_len = 0; // Number of characters written so far.
|
||||
size_t str_len = 0; // Number of strings written so far.
|
||||
grid_data_t *data_head = malloc(data_cap * sizeof(grid_data_t));
|
||||
size_t *entries_head = malloc(data_cap * sizeof(size_t));
|
||||
|
||||
_Bool spaces = 1;
|
||||
char scanned;
|
||||
while ((scanned = scanf("%c", &scanned)) != EOF)
|
||||
{
|
||||
if (isspace(scanned))
|
||||
{
|
||||
spaces = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// A little input sanitization.
|
||||
if (scanned == '+')
|
||||
{
|
||||
// We can ignore plus signs, assuming we have (\+|\-)?\d+(\.\d+)?(E\d+)?
|
||||
continue;
|
||||
}
|
||||
if (!(isdigit(scanned) || (scanned == '-') || (scanned == '.')))
|
||||
{
|
||||
printf(
|
||||
"Foreign character %c found when processing input, aborting.",
|
||||
scanned);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (spaces)
|
||||
{
|
||||
// New row
|
||||
str_len += 1;
|
||||
data_len += 1; // The byte for the string length
|
||||
// data_head[data_len] is already correctly initialized to 0.
|
||||
entries_head[str_len - 1] = data_len - 1;
|
||||
}
|
||||
spaces = 0;
|
||||
|
||||
// We're about to write a new character.
|
||||
data_len += 1;
|
||||
|
||||
// Check if we need to resize the buffer.
|
||||
if (data_len > data_cap)
|
||||
{
|
||||
increase_input_buffers_params_t params = {
|
||||
.data_cap = data_cap,
|
||||
.data_head = data_head,
|
||||
.entries_head = entries_head,
|
||||
};
|
||||
params = increase_input_buffers(params);
|
||||
data_cap = params.data_cap;
|
||||
data_head = params.data_head;
|
||||
entries_head = params.entries_head;
|
||||
}
|
||||
|
||||
// Write the character
|
||||
data_head[data_len - 1] = scanned;
|
||||
|
||||
// Increase the length of current string
|
||||
grid_data_t *cur_len = entries_head[str_len - 1];
|
||||
*cur_len += 1;
|
||||
}
|
||||
} // End of scan loop
|
||||
|
||||
// Input sanitization: confirm that the number of entries read is a multiple
|
||||
// of the number of entries in a row.
|
||||
if (!((str_len % row_len) == 0))
|
||||
{
|
||||
printf("Number of entries is not consistent with provided row length. "
|
||||
"Got row length of %zu, and read %zu entries. Aborting.",
|
||||
row_len, str_len);
|
||||
// No need to free the buffers.
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
grid_t grid = {
|
||||
.row_len = row_len,
|
||||
.data_head = data_head,
|
||||
.entries_head = entries_head,
|
||||
.data_len = data_len,
|
||||
};
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
grid_t grid = parse_input();
|
||||
debug_print_grid(&grid);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue