
Deprecated: Function set_magic_quotes_runtime() is deprecated in /DISK2/WWW/lokiware.info/mff/wakka.php on line 35
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

/*
 * Reseni (snad spravne) zapoctoveho testu z OOP v C++ 2008/1/14 10:00 
 *
 * Snazil jsem se to napsat behem tri hodin, takze neslo o to, aby byl kod hezky a plny komentaru. Snad je to i tak k necemu.
 * Mozna budete muset povolit deklarace uprostred kodu (implicitne Ok v gcc), nebo je presunout na zacatek bloku. Jinak je to celkem std C.
 *
 * Testovani chybnych vstupu neni uplne otestovane. Ale minimalne by program nemel na chybnem vstupu spadnout:).
 *
 * -- 
 * Adam Nohejl
 */



typedef struct Cell {
	char		fill;
	unsigned	z;
} Cell;


typedef struct LayerList{
	Cell**				layer;
	struct LayerList*	next;
} LayerList;


static Cell			makeEmptyCell(void);

static Cell**		makeLayer(unsigned w, unsigned h);
static void			freeLayer(Cell** layer);

static LayerList*	makeLayerList(Cell** layer, LayerList* next);
static void			freeLayerList(LayerList* layers);

static Cell**		readScene(char* cp, unsigned* wp, unsigned* hp);
static Cell**		readLayer(unsigned width, unsigned height);

static void			printScene(Cell** layer, char c, unsigned w, unsigned h);


static Cell**		layerUnion(LayerList* layers, unsigned w, unsigned h);
static Cell**		layerDifference(LayerList* layers, unsigned w, unsigned h);
static Cell**		layerIntersect(LayerList* layers, unsigned w, unsigned h);



typedef Cell**	(*layerOperation)(LayerList* layers, unsigned w, unsigned h);



int main (int argc, const char * argv[]) {

	char		c;
	unsigned	w;
	unsigned	h;
	
	Cell**	sceneLayer	= readScene(&c,&w,&h);
	
	if(!sceneLayer){
		fprintf(stderr, "Incorrect input.\n");
		exit(EXIT_FAILURE);
	}
	
	printScene(sceneLayer,c,w,h);
	
	freeLayer(sceneLayer);
	
	exit(EXIT_SUCCESS);
	
    return 0;
}



Cell**	makeLayer(unsigned w, unsigned h){
	
	Cell**	layer	= calloc( (w+1), sizeof(Cell*));	/* last pointer will be NULL for easy freeing */
	unsigned i;
	
	for( i = 0 ; i < w ; i++)
		layer[i]	= calloc( h, sizeof(Cell));
	
	return layer;
}



void	freeLayer(Cell** layer){
	unsigned i;
	
	assert(layer);
	
	for( i = 0 ; layer[i] ; i++)
		free(layer[i]);
	
	free(layer);
}



LayerList*	makeLayerList(Cell** layer, LayerList* next){
	LayerList* ll = calloc(1, sizeof(LayerList));
	ll->layer	= layer;
	ll->next	= next;
	return ll;
}



void		freeLayerList(LayerList* layers){
	
	while(layers){
		LayerList* next	= layers->next;
		freeLayer(layers->layer);
		free(layers);
		layers			= next;
	}
	
}



Cell**		readScene(char* cp, unsigned* wp, unsigned* hp){
	char c;
	unsigned w;
	unsigned h;
	
	if(scanf(" SCENE ( '%c' , %u , %u ) {", &c, &w, &h) != 3){
		fprintf(stderr, "Can't read SCENE()\n");
		return NULL;
	}
	
	if( ! (w && h) ){
		fprintf(stderr, "Zero scene size.\n");
		return NULL;
	}
	
	LayerList*	layers	= NULL;
	Cell**		layer;
	while( layer	= readLayer(w,h) )
		layers		= makeLayerList(layer, layers);
	
	layer			= layerUnion(layers, w, h);
	
	freeLayerList(layers);
	
	char close	= '0';
	if(scanf(" %c", &close) !=1 || close!='}'){
		free(layer);
		fprintf(stderr, "Unclosed SCENE()\n");
		return NULL;
	}
	
	assert(cp && wp && hp);
	
	*cp = c;
	*wp = w;
	*hp = h;
	
	return layer;
}



Cell**	readLayer(unsigned width, unsigned height){
	
	char			c;
	unsigned		w;
	unsigned		h;
	unsigned		x;
	unsigned		y;
	unsigned		z;
	char			ops[32];
	Cell**			layer	= NULL;
	
	
	if( scanf(" RECTANGLE ( '%c' , %u , %u , %u , %u , %u )", &c, &x, &y, &w, &h, &z) == 6 ){
		
		if( ! (x && y&& w && h && z ) ){
			fprintf(stderr, "Zero rectangle size/position.\n");
			return NULL;
		}
		
		x--;
		y--;
		
		if(x+w > width || y+h > height){
			fprintf(stderr, "Rectangle out of scene bounds.\n");
			return NULL;
		}
		
		layer	= makeLayer(width,height);
		
		unsigned i;
		unsigned j;
		
		Cell	cell	= {c, z};
		for(		i = x ; i < x+w ; i++ ){
			for(	j = y ; j < y+h ; j++ )
				layer[i][j]		= cell;
		}
		
	}else if( scanf(" %31[A-Z] {", ops ) == 1 ){
				
		layerOperation	op;
	
		if( ! strcmp(		"UNION", ops) )
			op	= layerUnion;
		else if( ! strcmp(	"INTERSECT", ops) )
			op	= layerIntersect;
		else if( ! strcmp(	"DIFFERENCE", ops) )
			op	= layerDifference;
		else
			return NULL;
		
		LayerList*	layers	= NULL;
		while( layer	= readLayer( width, height ) ){
			layers		= makeLayerList(layer, layers);
		}
		
		layer			= op(layers, width, height);
		
		freeLayerList(layers);
		
		char close = 0;
		if(scanf(" %c", &close) !=1 || close!='}'){
			free(layer);
			fprintf(stderr, "Unclosed %s\n", ops);
			return NULL;
		}
		
	}
	
	return layer;
	
}



static Cell**		layerUnion(LayerList* layers, unsigned w, unsigned h){
		
	Cell** result	= makeLayer(w,h);
	
	for( ; layers; layers = layers->next){
		Cell**	layer = layers->layer;

		unsigned i;
		unsigned j;
		for(		i = 0 ; i < w ; i++ ){
			for(	j = 0 ; j < h ; j++ ){
				if(layer[i][j].z > result[i][j].z)
					result[i][j]	= layer[i][j];
			}
		}		
		
	}

	return result;
}



static Cell**		layerIntersect(LayerList* layers, unsigned w, unsigned h){
	
	Cell** result	= makeLayer(w,h);
	
	if(layers){
		Cell**	layer	= layers->layer;
		layers			= layers->next;
	
		unsigned i;
		unsigned j;
		for(		i = 0 ; i < w ; i++ ){
			for(	j = 0 ; j < h ; j++ )
				result[i][j]	= layer[i][j];						/* 1st assignment */
		}
		
		for( ; layers; layers = layers->next){
			layer = layers->layer;
			
			for(		i = 0 ; i < w ; i++ ){
				for(	j = 0 ; j < h ; j++ ){
					if(!(result[i][j].fill && layer[i][j].fill))
						result[i][j]	= makeEmptyCell();					/* no intersect */
					else if(layer[i][j].z > result[i][j].z)
						result[i][j]	= layer[i][j];						/* intersect (z) */
				}
			}		
		}
		
	}

	return result;
}



static Cell**		layerDifference(LayerList* layers, unsigned w, unsigned h){
	Cell** result	= makeLayer(w,h);
	
	
	for( ; layers; layers = layers->next){
		Cell**	layer = layers->layer;
		
		unsigned i;
		unsigned j;
		for(		i = 0 ; i < w ; i++ ){
			for(	j = 0 ; j < h ; j++ ){
				if(!result[i][j].z)
					result[i][j]		= layer[i][j];						/* 1st assignment */
				else if((layer[i][j].fill && layer[i][j].fill)){
					result[i][j]		= makeEmptyCell();					/* 2nd assignment */
					result[i][j].z		= 1;								/* do not confuse with unassigned */
				}
			}
		}		
	}
	
	
	/* clean up */
		
	unsigned i;
	unsigned j;
	for(		i = 0 ; i < w ; i++ ){
		for(	j = 0 ; j < h ; j++ ){
			if(!result[i][j].fill)
				result[i][j].z		= 0;
		}
	}
			
	
	return result;
}



static void		printScene(Cell** layer, char c, unsigned w, unsigned h){

	/* Swap the coords (podle zadani ma byt prvni index sloupec, ne radek) */
	
	unsigned i;
	unsigned j;
	for(		i = 0 ; i < h ; i++ ){
		for(	j = 0 ; j < w ; j++ ){
			char lc = layer[j][i].fill;
			if(!lc)
				lc	= c;
			printf(" %c", lc);
		}
		putchar('\n');
	}

}



static Cell		makeEmptyCell(void){
	Cell	c	= {0, /* 0, ... */};
	return c;
}
