Skip to content

Instantly share code, notes, and snippets.

@fesoliveira014
Last active August 18, 2017 20:24
Show Gist options
  • Save fesoliveira014/6bcf914fda658f469d488349069a4e70 to your computer and use it in GitHub Desktop.
Save fesoliveira014/6bcf914fda658f469d488349069a4e70 to your computer and use it in GitHub Desktop.
Substance problem
#include <stdio.h>
#include <malloc.h>
#define MAX_SIZE 500
#define MIN_SIZE 10
#define MAX_SUBS 300
struct list_t
{
int nodes[MAX_SUBS];
int size;
};
void list_push(int i, struct list_t* list)
{
if (list->size < MAX_SUBS) {
list->nodes[list->size] = i;
list->size++;
}
}
int list_has_element(int value, struct list_t* list)
{
for (int i = 0; i < list->size; ++i) {
if (list->nodes[i] == value) return 1;
}
return 0;
}
void clear_list(struct list_t* list)
{
for (int i = 0; i < MAX_SUBS; ++i) {
list->nodes[i] = 0;
}
list->size = 0;
}
int abs(int a)
{
return a > 0 ? a : -a;
}
struct substance_t
{
int type;
int x0, y0;
int x1, y1;
};
int board[MAX_SIZE][MAX_SIZE];
int processing_order[MAX_SUBS]; // processing order of a given substance
struct list_t dependency_list[MAX_SUBS];
struct substance_t geometries[MAX_SUBS]; // substance position
int board_size, max_substance;
int target;
void find_substance_geometry(struct substance_t* substance)
{
int c0_x, c0_y; // upper left
int c1_x, c1_y; // upper right
int c2_x, c2_y; // lower left
int c3_x, c3_y; // lower right
c0_x = substance->x0;
c0_y = substance->y0;
c1_x = c0_x;
c1_y = c0_y; // same y-coordinate
c2_x = c0_x; // same x-coordinate
c2_y = c0_y;
c3_x = c0_x;
c3_y = c0_y;
for (int i = c0_x; i < MAX_SIZE; ++i) {
if (board[c1_y][i] == 0) break;
if (board[c1_y][i] == substance->type) c1_x = i;
}
for (int i = c0_y; i < MAX_SIZE; ++i) {
if (board[i][c2_x] == 0) break;
if (board[i][c2_x] == substance->type) c2_y = i;
}
if (c1_x != c0_x && c2_y != c0_y) { // there is a 4th corner
c3_x = c1_x;
c3_y = c2_y;
}
else if (c1_x != c0_x) { // horizontal strip or bottom left not found
c3_x = c1_x;
c3_y = c1_y;
for (int i = c1_y; i < MAX_SIZE; ++i) {
if (board[i][c3_x] == 0) break;
if (board[i][c3_x] == substance->type) c3_y = i;
}
}
else if (c2_y != c0_y) { // vertical strip or top right not found
c3_x = c2_x;
c3_y = c2_y;
for (int i = c2_x; i < MAX_SIZE; ++i) {
if (board[c3_y][i] == 0) break;
if (board[c3_y][i] == substance->type) c3_x = i;
}
}
substance->x1 = c3_x;
substance->y1 = c3_y;
}
int depends(struct substance_t* a, struct substance_t* b)
{
if (a->x0 < b->x0 &&
a->y0 < b->y0 &&
a->x1 > b->x1 &&
a->y1 > b->y1) {
return 1; // b inside a
}
else if (abs(a->x0 - b->x0) * 2 < ((a->x1 - a->x0) + (b->x1 - b->x0)) &&
abs(a->y0 - b->y0) * 2 < ((a->y1 - a->y0) + (b->y1 - b->y0))) {
// boxes are intersecting, need to walk on border to infer dependency
// if while we are walking on the border of 'a' we find a patch with type 'b'
// we can garantee that 'b' depends on 'a'
for (int i = a->x0; i <= a->x1; ++i) { // top border walk
if (board[a->y0][i] == b->type) return 1;
}
for (int i = a->y0; i <= a->y1; ++i) { // left border walk
if (board[i][a->x0] == b->type) return 1;
}
for (int i = a->x0; i <= a->x1; ++i) { // bottom border walk
if (board[a->y1][i] == b->type) return 1;
}
for (int i = a->y0; i <= a->y1; ++i) { // right border walk
if (board[i][a->x1] == b->type) return 1;
}
}
return 0;
}
int solve()
{
for (int i = 0; i < MAX_SIZE; ++i) {
for (int j = 0; j < MAX_SIZE; ++j) {
if (board[i][j] != 0 && geometries[board[i][j]].type == 0) {
geometries[board[i][j]].type == board[i][j];
geometries[board[i][j]].x0 = j;
geometries[board[i][j]].y0 = i;
find_substance_geometry(&geometries[board[i][j]]);
}
}
}
for (int i = 0; i < MAX_SUBS; ++i) {
if (geometries[i].type == 0) continue;
for (int j = 0; j < MAX_SUBS; ++j) {
if (i == j || geometries[j].type == 0) continue;
else if (depends(&geometries[i], &geometries[j]) && !list_has_element(i, &dependency_list[j])) {
list_push(i, &dependency_list[j]);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment