#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#define ROWS 10000
#define COLS 10000
#define COLORS_NUM 3
#define SEED 0xDEADBEEFull
#define VEC_INIT_CAPACITY 100
#define MATRIX_AT(matrix, i, j) (matrix)[(i) * COLS + (j)]
uint32_t LCGRand()
{
static uint64_t seed = SEED;
seed = seed * 6364136223846793005 + 1442695040888963407;
return seed >> 32;
}
typedef struct Node_s {
uint32_t color;
uint32_t isVisited;
} Node;
typedef struct Coords_s {
intptr_t i;
intptr_t j;
} Coords;
typedef struct Vec_s {
Coords *arr;
size_t curSize;
size_t curCapacity;
} Vec;
Vec *vec_create()
{
Vec
*vec
= malloc(sizeof(Vec
)); if (!vec) {
return NULL;
}
vec
->arr
= malloc(VEC_INIT_CAPACITY
* sizeof(Coords
)); if (!vec->arr) {
return NULL;
}
vec->curCapacity = VEC_INIT_CAPACITY;
vec->curSize = 0;
return vec;
}
int vec_push(Vec *vec, intptr_t i, intptr_t j)
{
if (vec->curSize >= vec->curCapacity) {
size_t newCapacity = vec->curCapacity * 2;
Coords *oldArr = vec->arr;
vec
->arr
= realloc(vec
->arr
, newCapacity
* sizeof(Coords
)); if (!vec->arr) {
vec->arr = oldArr;
return 0;
}
vec->curCapacity = newCapacity;
}
vec->arr[vec->curSize].i = i;
vec->arr[vec->curSize].j = j;
vec->curSize++;
return 1;
}
Coords *vec_pop(Vec *vec)
{
if (vec->curSize > 0) {
return &vec->arr[vec->curSize-- - 1];
} else {
return NULL;
}
}
void vec_clear(Vec *vec)
{
vec->curSize = 0;
}
void vec_delete(Vec *vec)
{
if (vec) {
if (vec->arr) {
}
}
}
inline int isValidCoords(intptr_t i, intptr_t j)
{
return (i >= 0) && (i < ROWS) && (j >= 0) && (j < COLS);
}
size_t visitNode(Node *matrix, intptr_t i, intptr_t j)
{
static const int MOVES[][2] = {
{ -1, 0 },
{ +1, 0 },
{ 0, -1 },
{ 0, +1 },
};
static Vec *vec = NULL;
if (!vec) {
vec = vec_create();
if (!vec) {
goto OOM;
}
}
if (!vec_push(vec, i, j)) {
goto OOM;
}
size_t blockSize = 0;
uint32_t targetColor = MATRIX_AT(matrix, i, j).color;
MATRIX_AT(matrix, i, j).isVisited = 1;
while (vec->curSize > 0) {
Coords *coords = vec_pop(vec);
i = coords->i;
j = coords->j;
blockSize++;
for (size_t moveIdx = 0; moveIdx < sizeof(MOVES) / sizeof(MOVES[0]); moveIdx++) {
intptr_t movedI = i + MOVES[moveIdx][0], movedJ = j + MOVES[moveIdx][1];
if (isValidCoords(movedI, movedJ)) {
Node *adjNode = &MATRIX_AT(matrix, movedI, movedJ);
if (adjNode->color == targetColor && !adjNode->isVisited) {
adjNode->isVisited = 1;
if (!vec_push(vec, movedI, movedJ)) {
goto OOM;
}
}
}
}
}
vec_clear(vec);
return blockSize;
OOM:
vec_delete(vec);
}
void print_matrix(Node *matrix)
{
for (size_t i = 0; i < ROWS; i++) {
for (size_t j = 0; j < COLS; j++) {
putchar(MATRIX_AT
(matrix
, i
, j
).
color + '0'); }
}
}
int main()
{
Node
*matrix
= malloc(ROWS
* COLS
* sizeof(Node
)); for (size_t i = 0; i < ROWS * COLS; i++) {
matrix[i].color = LCGRand() % COLORS_NUM;
matrix[i].isVisited = 0;
}
//print_matrix(matrix);
size_t maxAdjNodes = 0;
for (intptr_t i = 0; i < ROWS; i++) {
for (intptr_t j = 0; j < COLS; j++) {
if (!MATRIX_AT(matrix, i, j).isVisited) {
size_t adjNodes = visitNode(matrix, i, j);
if (maxAdjNodes < adjNodes) {
maxAdjNodes = adjNodes;
}
}
}
}
printf("Max block size: %zd\ntime: %ld", maxAdjNodes
, (clock() - start
) / (CLOCKS_PER_SEC
/ 1000)); return 0;
}
I2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0ZGludC5oPgojaW5jbHVkZSA8dGltZS5oPgoKI2RlZmluZSBST1dTIDEwMDAwCiNkZWZpbmUgQ09MUyAxMDAwMAojZGVmaW5lIENPTE9SU19OVU0gMwojZGVmaW5lIFNFRUQgMHhERUFEQkVFRnVsbAoKI2RlZmluZSBWRUNfSU5JVF9DQVBBQ0lUWSAxMDAKI2RlZmluZSBNQVRSSVhfQVQobWF0cml4LCBpLCBqKSAobWF0cml4KVsoaSkgKiBDT0xTICsgKGopXQoKdWludDMyX3QgTENHUmFuZCgpCnsKICAgIHN0YXRpYyB1aW50NjRfdCBzZWVkID0gU0VFRDsKICAgIHNlZWQgPSBzZWVkICogNjM2NDEzNjIyMzg0Njc5MzAwNSArIDE0NDI2OTUwNDA4ODg5NjM0MDc7CiAgICByZXR1cm4gc2VlZCA+PiAzMjsKfQoKdHlwZWRlZiBzdHJ1Y3QgTm9kZV9zIHsKICAgIHVpbnQzMl90IGNvbG9yOwogICAgdWludDMyX3QgaXNWaXNpdGVkOwp9IE5vZGU7Cgp0eXBlZGVmIHN0cnVjdCBDb29yZHNfcyB7CiAgICBpbnRwdHJfdCBpOwogICAgaW50cHRyX3QgajsKfSBDb29yZHM7Cgp0eXBlZGVmIHN0cnVjdCBWZWNfcyB7CiAgICBDb29yZHMgKmFycjsKICAgIHNpemVfdCBjdXJTaXplOwogICAgc2l6ZV90IGN1ckNhcGFjaXR5Owp9IFZlYzsKClZlYyAqdmVjX2NyZWF0ZSgpCnsKICAgIFZlYyAqdmVjID0gbWFsbG9jKHNpemVvZihWZWMpKTsKICAgIGlmICghdmVjKSB7CiAgICAgICAgcmV0dXJuIE5VTEw7CiAgICB9CiAgICB2ZWMtPmFyciA9IG1hbGxvYyhWRUNfSU5JVF9DQVBBQ0lUWSAqIHNpemVvZihDb29yZHMpKTsKICAgIGlmICghdmVjLT5hcnIpIHsKICAgICAgICBmcmVlKHZlYyk7CiAgICAgICAgcmV0dXJuIE5VTEw7CiAgICB9CiAgICB2ZWMtPmN1ckNhcGFjaXR5ID0gVkVDX0lOSVRfQ0FQQUNJVFk7CiAgICB2ZWMtPmN1clNpemUgPSAwOwogICAgcmV0dXJuIHZlYzsKfQoKaW50IHZlY19wdXNoKFZlYyAqdmVjLCBpbnRwdHJfdCBpLCBpbnRwdHJfdCBqKQp7CiAgICBpZiAodmVjLT5jdXJTaXplID49IHZlYy0+Y3VyQ2FwYWNpdHkpIHsKICAgICAgICBzaXplX3QgbmV3Q2FwYWNpdHkgPSB2ZWMtPmN1ckNhcGFjaXR5ICogMjsKICAgICAgICBDb29yZHMgKm9sZEFyciA9IHZlYy0+YXJyOwogICAgICAgIHZlYy0+YXJyID0gcmVhbGxvYyh2ZWMtPmFyciwgbmV3Q2FwYWNpdHkgKiBzaXplb2YoQ29vcmRzKSk7CiAgICAgICAgaWYgKCF2ZWMtPmFycikgewogICAgICAgICAgICB2ZWMtPmFyciA9IG9sZEFycjsKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQogICAgICAgIHZlYy0+Y3VyQ2FwYWNpdHkgPSBuZXdDYXBhY2l0eTsKICAgIH0KCiAgICB2ZWMtPmFyclt2ZWMtPmN1clNpemVdLmkgPSBpOwogICAgdmVjLT5hcnJbdmVjLT5jdXJTaXplXS5qID0gajsKICAgIHZlYy0+Y3VyU2l6ZSsrOwogICAgcmV0dXJuIDE7Cn0KCkNvb3JkcyAqdmVjX3BvcChWZWMgKnZlYykKewogICAgaWYgKHZlYy0+Y3VyU2l6ZSA+IDApIHsKICAgICAgICByZXR1cm4gJnZlYy0+YXJyW3ZlYy0+Y3VyU2l6ZS0tIC0gMV07CiAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBOVUxMOwogICAgfQp9Cgp2b2lkIHZlY19jbGVhcihWZWMgKnZlYykKewogICAgdmVjLT5jdXJTaXplID0gMDsKfQoKdm9pZCB2ZWNfZGVsZXRlKFZlYyAqdmVjKQp7CiAgICBpZiAodmVjKSB7CiAgICAgICAgaWYgKHZlYy0+YXJyKSB7CiAgICAgICAgICAgIGZyZWUodmVjLT5hcnIpOwogICAgICAgIH0KICAgICAgICBmcmVlKHZlYyk7CiAgICB9Cn0KCmlubGluZSBpbnQgaXNWYWxpZENvb3JkcyhpbnRwdHJfdCBpLCBpbnRwdHJfdCBqKQp7CiAgICByZXR1cm4gKGkgPj0gMCkgJiYgKGkgPCBST1dTKSAmJiAoaiA+PSAwKSAmJiAoaiA8IENPTFMpOwp9CgpzaXplX3QgdmlzaXROb2RlKE5vZGUgKm1hdHJpeCwgaW50cHRyX3QgaSwgaW50cHRyX3QgaikKewogICAgc3RhdGljIGNvbnN0IGludCBNT1ZFU1tdWzJdID0gewogICAgICAgIHsgLTEsIDAgfSwKICAgICAgICB7ICsxLCAwIH0sCiAgICAgICAgeyAwLCAtMSB9LAogICAgICAgIHsgMCwgKzEgfSwKICAgIH07CgogICAgc3RhdGljIFZlYyAqdmVjID0gTlVMTDsKICAgIGlmICghdmVjKSB7CiAgICAgICAgdmVjID0gdmVjX2NyZWF0ZSgpOwogICAgICAgIGlmICghdmVjKSB7CiAgICAgICAgICAgIGdvdG8gT09NOwogICAgICAgIH0KICAgIH0KCiAgICBpZiAoIXZlY19wdXNoKHZlYywgaSwgaikpIHsKICAgICAgICBnb3RvIE9PTTsKICAgIH0KCiAgICBzaXplX3QgYmxvY2tTaXplID0gMDsKICAgIHVpbnQzMl90IHRhcmdldENvbG9yID0gTUFUUklYX0FUKG1hdHJpeCwgaSwgaikuY29sb3I7CiAgICBNQVRSSVhfQVQobWF0cml4LCBpLCBqKS5pc1Zpc2l0ZWQgPSAxOwogICAgd2hpbGUgKHZlYy0+Y3VyU2l6ZSA+IDApIHsKICAgICAgICBDb29yZHMgKmNvb3JkcyA9IHZlY19wb3AodmVjKTsKICAgICAgICBpID0gY29vcmRzLT5pOwogICAgICAgIGogPSBjb29yZHMtPmo7CgogICAgICAgIGJsb2NrU2l6ZSsrOwoKICAgICAgICBmb3IgKHNpemVfdCBtb3ZlSWR4ID0gMDsgbW92ZUlkeCA8IHNpemVvZihNT1ZFUykgLyBzaXplb2YoTU9WRVNbMF0pOyBtb3ZlSWR4KyspIHsKICAgICAgICAgICAgaW50cHRyX3QgbW92ZWRJID0gaSArIE1PVkVTW21vdmVJZHhdWzBdLCBtb3ZlZEogPSBqICsgTU9WRVNbbW92ZUlkeF1bMV07CiAgICAgICAgICAgIGlmIChpc1ZhbGlkQ29vcmRzKG1vdmVkSSwgbW92ZWRKKSkgewogICAgICAgICAgICAgICAgTm9kZSAqYWRqTm9kZSA9ICZNQVRSSVhfQVQobWF0cml4LCBtb3ZlZEksIG1vdmVkSik7CiAgICAgICAgICAgICAgICBpZiAoYWRqTm9kZS0+Y29sb3IgPT0gdGFyZ2V0Q29sb3IgJiYgIWFkak5vZGUtPmlzVmlzaXRlZCkgewogICAgICAgICAgICAgICAgICAgIGFkak5vZGUtPmlzVmlzaXRlZCA9IDE7CiAgICAgICAgICAgICAgICAgICAgaWYgKCF2ZWNfcHVzaCh2ZWMsIG1vdmVkSSwgbW92ZWRKKSkgewogICAgICAgICAgICAgICAgICAgICAgICBnb3RvIE9PTTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgdmVjX2NsZWFyKHZlYyk7CiAgICByZXR1cm4gYmxvY2tTaXplOwoKT09NOgogICAgcGVycm9yKCJPT00iKTsKICAgIHZlY19kZWxldGUodmVjKTsKICAgIGV4aXQoRVhJVF9GQUlMVVJFKTsKfQoKdm9pZCBwcmludF9tYXRyaXgoTm9kZSAqbWF0cml4KQp7CiAgICBmb3IgKHNpemVfdCBpID0gMDsgaSA8IFJPV1M7IGkrKykgewogICAgICAgIGZvciAoc2l6ZV90IGogPSAwOyBqIDwgQ09MUzsgaisrKSB7CiAgICAgICAgICAgIHB1dGNoYXIoTUFUUklYX0FUKG1hdHJpeCwgaSwgaikuY29sb3IgKyAnMCcpOwogICAgICAgIH0KICAgICAgICBwdXRjaGFyKCdcbicpOwogICAgfQp9CgppbnQgbWFpbigpCnsKICAgIGNsb2NrX3Qgc3RhcnQgPSBjbG9jaygpOwogICAgTm9kZSAqbWF0cml4ID0gbWFsbG9jKFJPV1MgKiBDT0xTICogc2l6ZW9mKE5vZGUpKTsKICAgIGZvciAoc2l6ZV90IGkgPSAwOyBpIDwgUk9XUyAqIENPTFM7IGkrKykgewogICAgICAgIG1hdHJpeFtpXS5jb2xvciA9IExDR1JhbmQoKSAlIENPTE9SU19OVU07CiAgICAgICAgbWF0cml4W2ldLmlzVmlzaXRlZCA9IDA7CiAgICB9CiAgICAvL3ByaW50X21hdHJpeChtYXRyaXgpOwoKICAgIHNpemVfdCBtYXhBZGpOb2RlcyA9IDA7CiAgICBmb3IgKGludHB0cl90IGkgPSAwOyBpIDwgUk9XUzsgaSsrKSB7CiAgICAgICAgZm9yIChpbnRwdHJfdCBqID0gMDsgaiA8IENPTFM7IGorKykgewogICAgICAgICAgICBpZiAoIU1BVFJJWF9BVChtYXRyaXgsIGksIGopLmlzVmlzaXRlZCkgewogICAgICAgICAgICAgICAgc2l6ZV90IGFkak5vZGVzID0gdmlzaXROb2RlKG1hdHJpeCwgaSwgaik7CiAgICAgICAgICAgICAgICBpZiAobWF4QWRqTm9kZXMgPCBhZGpOb2RlcykgewogICAgICAgICAgICAgICAgICAgIG1heEFkak5vZGVzID0gYWRqTm9kZXM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcHJpbnRmKCJNYXggYmxvY2sgc2l6ZTogJXpkXG50aW1lOiAlbGQiLCBtYXhBZGpOb2RlcywgKGNsb2NrKCkgLSBzdGFydCkgLyAoQ0xPQ0tTX1BFUl9TRUMgLyAxMDAwKSk7CiAgICBmcmVlKG1hdHJpeCk7CiAgICByZXR1cm4gMDsKfQo=