C-2982
이 프로그램은 광범위한 결과 집합을 통해 검색을 구현합니다. 이 검색을 실용적으로 만드는 데있어 중요한 부분은 초기에 실패하거나 나쁜 길을 밟지 않는 것이 었습니다.
솔루션으로 고려할 사각형 세트가 생성됩니다. 생성 된 사각형 세트는 유용하지 않은 치수를 가진 사각형을 피합니다. 예를 들어, 프로그램이 8 개의 사각형으로 나눈 128x128 정사각형에 대한 솔루션을 찾으려고하면 128x16의 사각형이 생성됩니다. 120의 끝에서 간격을 채울 너비가 8 인 직사각형을 생성 할 가능성이 없기 때문에 120x17이라는 것을 생성하지 않습니다.
사각형을 배치하기위한 초기 전략은 사각형의 둘레 안쪽에 사각형을 배치하는 것입니다 (빌더 기능). 이런 식으로 알고리즘은 각 시퀀스에서 선택한 시퀀스에 문제가 있는지 여부에 대해 매우 빠른 피드백을받습니다. 직사각형을 배치하는 동안 논리는 공간에 틈이 생겨 직사각형에 비해 너무 좁은 지 계속 지켜보고 있습니다. 주변이 성공적으로 채워지면 남은 사각형으로 남은 공간을 일치 시키려고 전략이 변경됩니다 (일치 기능).
흥미로운 또 다른 사항은 사각형 스택에 대한 롤백으로 트랜잭션을 구현한다는 것입니다.
이 프로그램은 가장 적합한 것을 찾지 않습니다. 예산 (64)이 주어지고 첫 번째 솔루션을 찾으면 종료됩니다. 솔루션을 찾지 못하면 예산을 늘리고 (16) 다시 시도하십시오. 필요한 시간 (I7 프로세서가 장착 된 Dell 랩탑의 경우)은 1 분에서 48 분까지 150 분 동안 1 분에서 48 분 사이였습니다 (1 분에 149 분은 2 분 미만 소요). 모든 51 솔루션은 11 직사각형을 사용했습니다. 51 솔루션의 점수 범위는 41에서 78까지였습니다. 11 개의 사각형을 사용한 이유는 적은 사각형보다 점수가 낮았고 12 개의 사각형이 할당 된 시간보다 훨씬 많은 시간이 걸리는 것 같습니다.
솔루션과 코드는 https://github.com/JaySpencerAnderson/mondrian에 있습니다. . 두 my4 * 파일입니다.
BTW, 이것을 "my4"로 컴파일하고 "./my4 -h"와 같이 실행하면 사용법이 제공됩니다. 실제로 작동하지 않게하려면 "./my4 -l 50 -n 8"과 같은 것을 시도하십시오. "#if 0"을 "#if 1"로 변경하면 화면에 남은 공간이 렌더링됩니다. 사각형을 렌더링하기 위해 이것을 변경하려면 코드가 "graph (space, side)"를 실행하는 지점을 찾아서 대신 "graph (callstack, side)"로 변경하십시오. 또한 너비가 약 50 인 사각형에 대한 솔루션을 가지고 놀고 싶다면 초기 예산을 64에서 32로 변경하는 것이 좋습니다. 작은 사각형에 대한 솔루션은 적은 예산으로 더 나은 점수를 얻습니다.
아래 프로그램은 작동합니다. github에서 전체 코드 (사용법, 주석 등)를 확인하십시오.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct {
int y, x, height, width, created, deleted;
} rectangle;
#define NOTYET -1
#define TOPEDGE 1
#define RIGHTEDGE 2
#define BOTTOMEDGE 4
#define LEFTEDGE 8
#define CENTER 16
#define nextEdge(e) (e<<=1)
#define min(x,y) (((x)<(y))?(x):(y))
#define max(x,y) (((x)>(y))?(x):(y))
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define MAXFACTORS 1000
#define EOL printf("\n")
#define isCurrent(r) (r.created != NOTYET && r.deleted == NOTYET)
#define deleteTxn(r,t) (r.deleted=t)
int area(rectangle r){
return r.width*r.height;
}
void pop(rectangle *s){
unsigned int k=0;
while(s[k].width){
k++;
}
s[k-1].width=s[k-1].height=0;
}
void rpush(rectangle *s, rectangle x){
unsigned int k=0;
while(s[k].width){
k++;
}
x.deleted=NOTYET;
s[k++]=x;
s[k].width=s[k].height=0;
return;
}
void dumprectangle(rectangle r){
printf("%dX%d@[%d,%d] (%d,%d)\t",r.width, r.height, r.x, r.y, r.created, r.deleted);
}
void dumpstack(rectangle *s){
unsigned int k=0;
while(s[k].width){
dumprectangle(s[k]);
k++;
}
}
rectangle initrectangle(int width, int height){
rectangle r;
r.x=r.y=0;
r.width=width;
r.height=height;
r.created=0;
r.deleted=NOTYET;
return r;
}
void initstack(rectangle *s, int n){
int i;
for(i=0;i<n;i++){
s[i].y=s[i].x=s[i].height=s[i].width=0;
}
}
int bitcount(int x){
int count=0;
while(x){
if(x&1){
count++;
}
x>>=1;
}
return count;
}
int congruent(rectangle a, rectangle b){
return min(a.height,a.width) == min(b.height,b.width) && max(a.height,a.width) == max(b.height,b.width);
}
void report(rectangle *s, int side){
int i;
unsigned int smallest,biggest,area=0;
smallest=side*side;
biggest=0;
for(i=0;s[i].width;i++){
if(isCurrent(s[i])){
smallest=min(smallest,s[i].width*s[i].height);
biggest=max(biggest,s[i].width*s[i].height);
}
}
printf("{%d}\n",biggest-smallest);
printf("{\nDimensions\tLocation\n");
for(i=0;s[i].width;i++){
printf("%dx%d\t\t[%d,%d]\n",
s[i].width, s[i].height,
s[i].x, s[i].y);
}
printf("}\n");
}
unsigned int sumstack(rectangle *s){
unsigned int sum=0;
int i;
for(i=0;s[i].width;i++){
if(isCurrent(s[i])){
sum+=s[i].width*s[i].height;
s++;
}
}
return sum;
}
unsigned int minstack(rectangle *s){
unsigned int area=400000;
int i;
for(i=0;s[i].width;i++){
if(isCurrent(s[i])){
area=min(area,s[i].width*s[i].height);
}
}
return area;
}
void rollback(rectangle *r, int txn){
int i;
if(txn != NOTYET){
for(i=0;r[i].width;i++){
if(r[i].created == txn){
r[i].created=r[i].deleted=NOTYET;
r[i].x=r[i].width=r[i].y=r[i].height=0;
}
else if(r[i].deleted == txn){
r[i].deleted=NOTYET;
}
}
}
}
int overlap(rectangle a, rectangle b){
if((a.x < b.x+b.width && a.x+a.width > b.x) && (b.y < a.y+a.height && b.y+b.height > a.y)){
return TRUE;
}
return FALSE;
}
int stackoverlap(rectangle *callstack, rectangle next){
int i,j;
for(i=0;callstack[i].width;i++){
if(overlap(callstack[i], next)){
return TRUE;
}
}
return FALSE;
}
rectangle rotate(rectangle a){
int x=a.width;
a.width=a.height;
a.height=x;
return a;
}
int buildedge(rectangle *stack, rectangle *callstack,int side, rectangle *space){
int i,j,edge,goal,nextgoal,x,y,d,mindim,minarea,result=FALSE,spacetxn,stacktxn;
mindim=side;
minarea=side*side;
for(i=0;stack[i].width;i++){
mindim=min(mindim,min(stack[i].width,stack[i].height));
minarea=min(minarea,area(stack[i]));
}
x=y=0;
edge=TOPEDGE;
i=0;
while(edge == TOPEDGE && callstack[i].width != 0){
if(callstack[i].x == x && callstack[i].y == y){
x+=callstack[i].width;
if(x == side){
nextEdge(edge);
y=0;
}
i=0;
}
else {
i++;
}
}
while(edge == RIGHTEDGE && callstack[i].width != 0){
if(callstack[i].x+callstack[i].width == x && callstack[i].y == y){
y+=callstack[i].height;
if(y == side){
nextEdge(edge);
x=side;
}
i=0;
}
else {
i++;
}
}
while(edge == BOTTOMEDGE && callstack[i].width != 0){
if(callstack[i].x+callstack[i].width == x && callstack[i].y+callstack[i].height == y){
x-=callstack[i].width;
if(x == 0){
nextEdge(edge);
y=side;
}
i=0;
}
else {
i++;
}
}
while(edge == LEFTEDGE && callstack[i].width != 0){
if(callstack[i].x == x && callstack[i].y+callstack[i].height == y){
y-=callstack[i].height;
if(y == 0){
nextEdge(edge);
}
i=0;
}
else {
i++;
}
}
if(edge == CENTER){
/* rectangles are placed all along the perimeter of the square.
* Now match will use a different strategy to match the remaining space
* with what remains in stack */
if(match(stack,callstack,space)){
report(callstack,side);
return TRUE;
}
return FALSE;
}
switch(edge){
case TOPEDGE:
goal=side-x;
break;
case RIGHTEDGE:
goal=side-y;
break;
case BOTTOMEDGE:
goal=x;
break;
case LEFTEDGE:
/* Still a good assumption that callstack[0] is at 0,0 */
goal=y-callstack[0].height;
break;
default:
fprintf(stderr,"Error: buildedge has unexpected edge (b): %d\n",edge);
exit(0);
}
nextgoal=goal-mindim;
for(i=0;stack[i].width;i++){
if(isCurrent(stack[i])){
for(d=0;d<2;d++){
switch(edge){
case TOPEDGE:
if(stack[i].width == goal || stack[i].width <= nextgoal){
stack[i].x=x;
stack[i].y=y;
if(!stackoverlap(callstack, stack[i])){
spacetxn=nexttransaction(space);
stacktxn=nexttransaction(stack);
deleteTxn(stack[i],stacktxn);
removerectangle(space, stack[i], spacetxn);
if(narrow(space) >= mindim && smallest(space) >= minarea){
rpush(callstack, stack[i]);
if(buildedge(stack, callstack, side, space)){
return TRUE;
}
pop(callstack);
}
rollback(space, spacetxn);
rollback(stack, stacktxn);
stack[i].x=stack[i].y=0;
}
}
break;
case RIGHTEDGE:
if(stack[i].height == goal || stack[i].height <= nextgoal){
stack[i].x=x-stack[i].width;
stack[i].y=y;
if(!stackoverlap(callstack, stack[i])){
spacetxn=nexttransaction(space);
stacktxn=nexttransaction(stack);
deleteTxn(stack[i],stacktxn);
removerectangle(space, stack[i], spacetxn);
if(narrow(space) >= mindim && smallest(space) >= minarea){
rpush(callstack, stack[i]);
if(buildedge(stack, callstack, side, space)){
return TRUE;
}
pop(callstack);
}
rollback(space, spacetxn);
rollback(stack, stacktxn);
stack[i].x=stack[i].y=0;
}
}
break;
case BOTTOMEDGE:
if(stack[i].width == goal || stack[i].width <= nextgoal){
stack[i].x=x-stack[i].width;
stack[i].y=y-stack[i].height;
if(!stackoverlap(callstack, stack[i])){
spacetxn=nexttransaction(space);
stacktxn=nexttransaction(stack);
deleteTxn(stack[i],stacktxn);
removerectangle(space, stack[i], spacetxn);
if(narrow(space) >= mindim && smallest(space) >= minarea){
rpush(callstack, stack[i]);
if(buildedge(stack, callstack, side, space)){
return TRUE;
}
pop(callstack);
}
rollback(space, spacetxn);
rollback(stack, stacktxn);
stack[i].x=stack[i].y=0;
}
}
break;
case LEFTEDGE:
if(stack[i].height == goal || stack[i].height <= nextgoal){
stack[i].x=x;
stack[i].y=y-stack[i].height;
if(!stackoverlap(callstack, stack[i])){
spacetxn=nexttransaction(space);
stacktxn=nexttransaction(stack);
deleteTxn(stack[i],stacktxn);
removerectangle(space, stack[i], spacetxn);
if(narrow(space) >= mindim && smallest(space) >= minarea){
rpush(callstack, stack[i]);
if(buildedge(stack, callstack, side, space)){
return TRUE;
}
pop(callstack);
}
rollback(space, spacetxn);
rollback(stack, stacktxn);
stack[i].x=stack[i].y=0;
}
}
break;
default:
fprintf(stderr,"Error: buildedge has unexpected edge (c): %d\n",edge);
exit(0);
}
if(callstack[0].width != 0 && stack[i].width != stack[i].height){
stack[i]=rotate(stack[i]);
}
else {
break;
}
}
}
}
return FALSE;
}
int populatestack(rectangle *stack, int score, int side, int rectangles){
int offset,negative,area,mindim;
rectangle local;
int avg_area=(side*side)/rectangles;
if(avg_area < 4){
/* It's getting too small - really */
return FALSE;
}
local.x=0;
local.y=0;
local.created=0;
local.deleted=NOTYET;
initstack(stack,MAXFACTORS);
for(offset=1;offset<=score;offset++){
negative=offset&1;
area=avg_area + (negative?(0-(offset>>1)):(offset>>1));
mindim=area/side;
if(side*(area/side) == area){
local.width=side;
local.height=area/side;
rpush(stack,local);
}
if(area > 0){
for(local.width=side-mindim;local.width>=area/local.width;local.width--){
if(local.width*(area/local.width) == area){
local.height=area/local.width;
rpush(stack,local);
}
}
}
}
return TRUE;
}
int solve(int side,int rectangles,int score){
rectangle stack[MAXFACTORS],callstack[MAXFACTORS];
rectangle space[MAXFACTORS];
rectangle universe;
if(!populatestack(stack, score, side, rectangles)){
return FALSE;
}
if(sumstack(stack) >= side*side){
initstack(callstack,MAXFACTORS);
initstack(space,MAXFACTORS);
/* Initialize space (not occupied by a rectangle) to be side by side
* where side is the height/width of the square into which the rectangles fit. */
universe.width=universe.height=side;
universe.x=universe.y=0;
universe.created=0;
universe.deleted=NOTYET;
rpush(space, universe);
if(buildedge(stack,callstack,side,space)){
return TRUE;
}
}
return FALSE;
}
int containsPoint(rectangle a, int x, int y){
return a.x <= x && a.y <= y && a.x+a.width > x && a.y+a.height > y;
}
int containsRectangle(rectangle a, rectangle b){
return containsPoint(a, b.x, b.y) && containsPoint(a, b.x+b.width-1, b.y) && containsPoint(a, b.x, b.y+b.height-1) && containsPoint(a, b.x+b.width-1, b.y+b.height-1);
}
int areEqual(rectangle a, rectangle b){
return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height;
}
int nexttransaction(rectangle *r){
int i,n=NOTYET;
for(i=0;r[i].width;i++){
n=max(n,max(r[i].created,r[i].deleted));
}
return n+1;
}
void splitrectanglevertically(rectangle *space, int i, int x, int txn){
rectangle left, right;
left=right=space[i];
right.x=x;
left.width=right.x-left.x;
right.width-=left.width;
left.created=right.created=space[i].deleted=txn;
rpush(space,left);
rpush(space,right);
}
void splitrectanglehorizontally(rectangle *space, int i, int y, int txn){
rectangle top, bottom;
top=bottom=space[i];
bottom.y=y;
top.height=bottom.y-top.y;
bottom.height-=top.height;
top.created=bottom.created=space[i].deleted=txn;
rpush(space,top);
rpush(space,bottom);
}
int smallest(rectangle *space){
int i,j,smallest;
rectangle current;
smallest=0;
for(i=0;space[i].width;i++){
if(isCurrent(space[i])){
current=space[i];
for(j=0;space[j].width;j++){
if(isCurrent(space[j]) && i != j){
if(current.x+current.width == space[j].x
&& space[j].y <= current.y && space[j].y+space[j].height >= current.y+current.height){
current.width+=space[j].width;
}
else if(space[j].x+space[j].width == current.x
&& space[j].y <= current.y && space[j].y+space[j].height >= current.y+current.height){
current.x=space[j].x;
current.width+=space[j].width;
}
else if(current.y+current.height == space[j].y
&& space[j].x <= current.x && space[j].x+space[j].width >= current.x+current.width){
current.height+=space[j].height;
}
else if(space[j].y+space[j].height == current.y
&& space[j].x <= current.x && space[j].x+space[j].width >= current.x+current.width){
current.y=space[j].y;
current.height+=space[j].height;
}
}
}
if(smallest == 0){
smallest=current.width * current.height;
}
else if(smallest > current.width * current.height){
smallest=current.width * current.height;
}
}
}
return smallest;
}
int narrow(rectangle *space){
int i,j;
rectangle smallest,current;
smallest.width=0;
for(i=0;space[i].width;i++){
current=space[i];
if(isCurrent(current)){
for(j=0;space[j].width;j++){
if(isCurrent(space[j]) && i != j){
if(current.width <= current.height
&& current.x+current.width == space[j].x
&& space[j].y <= current.y && space[j].y+space[j].height >= current.y+current.height){
current.width+=space[j].width;
}
else if(current.width <= current.height
&& space[j].x+space[j].width == current.x
&& space[j].y <= current.y && space[j].y+space[j].height >= current.y+current.height){
current.x=space[j].x;
current.width+=space[j].width;
}
if(current.width >= current.height
&& current.y+current.height == space[j].y
&& space[j].x <= current.x && space[j].x+space[j].width >= current.x+current.width){
current.height+=space[j].height;
}
else if(current.width >= current.height
&& space[j].y+space[j].height == current.y
&& space[j].x <= current.x && space[j].x+space[j].width >= current.x+current.width){
current.y=space[j].y;
current.height+=space[j].height;
}
}
}
if(smallest.width == 0){
smallest=current;
}
else if(min(smallest.width,smallest.height) > min(current.width,current.height)){
smallest=current;
}
}
}
return min(smallest.width,smallest.height);
}
int notEmpty(rectangle *space){
int i,count;
for(i=0,count=0;space[i].width;i++){
if(isCurrent(space[i])){
count++;
}
}
return count;
}
int isAdjacent(rectangle r, rectangle s){
if(r.y == s.y+s.height && r.x < s.x+s.width && s.x < r.x+r.width){
return TOPEDGE;
}
if(s.x == r.x+r.width && r.y < s.y+s.height && s.y < r.y+r.height){
return RIGHTEDGE;
}
if(s.y == r.y+r.height && r.x < s.x+s.width && s.x < r.x+r.width){
return BOTTOMEDGE;
}
if(r.x == s.x+s.width && r.y < s.y+s.height && s.y < r.y+r.height){
return LEFTEDGE;
}
return NOTYET;
}
int adjacentrectangle(rectangle *space, int k, int k0){
int i,edge;
for(i=k0+1;space[i].width;i++){
if(i != k && isCurrent(space[i])){
if(isAdjacent(space[k],space[i]) != NOTYET){
return i;
}
}
}
return NOTYET;
}
int expanse(rectangle *space, int j, int d){ /* Returns how far space[j] can expand in the d direction */
int extent,k,giveUp,distance;
rectangle result=space[j];
extent=0;
giveUp=FALSE;
distance=0;
if(d == TOPEDGE || d == BOTTOMEDGE){
while(extent < space[j].width && !giveUp){
giveUp=TRUE;
for(k=0;space[k].width;k++){
if(k != j && isCurrent(space[k]) && isAdjacent(space[j],space[k]) == d){
if(space[j].x+extent == space[k].x){
extent+=space[k].width;
if(distance == 0){
distance=expanse(space,k,d);
}
else {
distance=min(distance,expanse(space,k,d));
}
giveUp=FALSE;
}
else if(space[j].x+extent > space[k].x && space[j].x+extent < space[k].x+space[k].width){
extent=space[k].x+space[k].width-space[j].x;
if(distance == 0){
distance=expanse(space,k,d);
}
else {
distance=min(distance,expanse(space,k,d));
}
giveUp=FALSE;
}
}
}
}
if(extent < space[j].width){
return 0;
}
return space[j].height+distance;
}
else if(d == LEFTEDGE || d == RIGHTEDGE){
while(extent < space[j].height && !giveUp){
giveUp=TRUE;
for(k=0;space[k].width;k++){
if(k != j && isCurrent(space[k]) && isAdjacent(space[j],space[k]) == d){
if(space[j].y+extent == space[k].y){
extent+=space[k].height;
if(distance == 0){
distance=expanse(space,k,d);
}
else {
distance=min(distance,expanse(space,k,d));
}
giveUp=FALSE;
}
else if(space[j].y+extent > space[k].y && space[j].y+extent < space[k].y+space[k].height){
extent=space[k].y+space[k].height-space[j].y;
if(distance == 0){
distance=expanse(space,k,d);
}
else {
distance=min(distance,expanse(space,k,d));
}
giveUp=FALSE;
}
}
}
}
if(extent < space[j].height){
return 0;
}
return space[j].width+distance;
}
return 0;
}
int match(rectangle *stack, rectangle *callstack, rectangle *space){
int i,j,k,d,goal,mn;
int height;
int spacetxn, stacktxn, calltxn;
int map;
rectangle r;
for(i=0,goal=0;space[i].width;i++){
if(isCurrent(space[i])){
goal+=space[i].width*space[i].height;
}
}
if(goal == 0){
return TRUE;
}
mn=minstack(stack);
if(goal < mn){
/* The goal (space available) is smaller than any rectangle left in the stack */
return FALSE;
}
spacetxn=nexttransaction(space);
stacktxn=nexttransaction(stack);
calltxn=nexttransaction(callstack);
for(j=0;space[j].width;j++){
for(i=0;stack[i].width;i++){
if(isCurrent(stack[i]) && isCurrent(space[j])){
if(congruent(space[j], stack[i]) && adjacentrectangle(space,j,NOTYET) == NOTYET){
r=space[j];
r.created=calltxn;
rpush(callstack, r);
deleteTxn(stack[i],stacktxn);
deleteTxn(space[j],spacetxn);
}
}
}
}
if(!notEmpty(space)){
return TRUE;
}
rectangle e;
for(j=0;space[j].width;j++){
if(isCurrent(space[j])){
e=space[j];
for(k=0,map=0;space[k].width;k++){
if(k != j && isCurrent(space[k])){
d=isAdjacent(space[j], space[k]);
if(d != NOTYET){
map|=d;
}
}
}
if(bitcount(map) == 1){ /* space[j] has adjacent space on only one side */
if(map == TOPEDGE || map == BOTTOMEDGE){
e.height=expanse(space,j,map);
}
else if(map == LEFTEDGE || map == RIGHTEDGE){
e.width=expanse(space,j,map);
}
for(i=0;stack[i].width;i++){
if(isCurrent(stack[i])){
if(congruent(e, stack[i])){
e.created=calltxn;
rpush(callstack, e);
deleteTxn(stack[i],stacktxn);
if(!removerectangle(space, e, spacetxn)){
printf("Logic error in match/expanse. Terminating\n");
exit(0);
}
if(match(stack,callstack,space)){
return TRUE;
}
else {
rollback(stack,stacktxn);
rollback(callstack,calltxn);
rollback(space,spacetxn);
return FALSE;
}
}
else if(congruent(space[j], stack[i])){
r=space[j];
r.created=calltxn;
rpush(callstack, r);
deleteTxn(stack[i],stacktxn);
if(!removerectangle(space, r, spacetxn)){
printf("Logic error in match/expanse. Terminating\n");
exit(0);
}
if(match(stack,callstack,space)){
return TRUE;
}
else {
rollback(stack,stacktxn);
rollback(callstack,calltxn);
rollback(space,spacetxn);
return FALSE;
}
}
}
}
}
}
}
if(notEmpty(space)){
rollback(stack,stacktxn);
rollback(callstack,calltxn);
rollback(space,spacetxn);
return FALSE;
}
return TRUE;
}
int removerectangle(rectangle *space, rectangle r, int ntxn){
int i,status=TRUE;
for(i=0;space[i].width;i++){
if(space[i].deleted == NOTYET){
if(areEqual(space[i], r)){
space[i].deleted=ntxn;
return TRUE;
}
else if(containsRectangle(space[i], r)){
if(r.x > space[i].x){
splitrectanglevertically(space, i, r.x, ntxn);
}
else if(r.y > space[i].y){
splitrectanglehorizontally(space, i, r.y, ntxn);
}
else if(r.x+r.width < space[i].x+space[i].width){
splitrectanglevertically(space, i, r.x+r.width, ntxn);
}
else if(r.y+r.height < space[i].y+space[i].height){
splitrectanglehorizontally(space, i, r.y+r.height, ntxn);
}
}
else if(overlap(space[i], r)){ /* we have to split both */
rectangle aux;
if(r.x < space[i].x){
aux=r;
aux.width=space[i].x-r.x;
r.x+=aux.width;
r.width-=aux.width;
if(!removerectangle(space,aux,ntxn)){
return FALSE;
}
}
if(r.x+r.width > space[i].x+space[i].width){
aux=r;
aux.x=space[i].x+space[i].width;
aux.width=r.x+r.width-aux.x;
r.width-=aux.width;
if(!removerectangle(space,aux,ntxn)){
return FALSE;
}
}
if(r.y < space[i].y){
aux=r;
aux.height=space[i].y-aux.y;
r.y+=aux.height;
r.height-=aux.height;
if(!removerectangle(space,aux,ntxn)){
return FALSE;
}
}
if(r.y+r.height > space[i].y+space[i].height){
aux=r;
aux.y=space[i].y+space[i].height;
aux.height=r.y+r.height-aux.y;
r.height-=aux.height;
if(!removerectangle(space,aux,ntxn)){
return FALSE;
}
}
if(areEqual(space[i], r)){
space[i].deleted=ntxn;
return TRUE;
}
else {
if(!removerectangle(space,r,ntxn)){
return FALSE;
}
return TRUE;
}
}
}
}
return TRUE;
}
int main(int argc, char *argv[]){
int side=15;
int n=5;
int budget=0;
int status;
while((status=getopt(argc,argv,"l:n:")) >= 0){
switch(status){
case 'l':
sscanf(optarg,"%d",&side);
break;
case 'n':
sscanf(optarg,"%d",&n);
break;
}
}
budget=64;
while(solve(side,n,budget) == FALSE){
budget+=16;
}
}