C - 2982
Bu program geniş bir sonuç kümesi üzerinden bir arama gerçekleştirir. Bu aramayı pratik hale getirmenin önemli kısmı erken başarısız olmak ve / veya kötü yollardan aşağı inmemekti.
Bu, çözüm için dikkate alınması gereken bir dizi dikdörtgen oluşturur. Oluşturulan dikdörtgenler kümesi, yararlı olmayacak boyutlara sahip olanlardan kaçınır. Örneğin, program 8 dikdörtgene bölünmüş 128x128 kareye çözüm bulmaya çalışıyorsa, 128x16 boyutunda bir dikdörtgen oluşturur. Birinin 120x17 olduğunu üretmeyecektir, çünkü 120 sonunda boşluğu doldurmak için 8 genişlikte bir dikdörtgen oluşturma olasılığı yoktur.
Dikdörtgenleri yerleştirmek için ilk strateji, onları karenin çevresinin içine yerleştirmektir (buildedge işlevi). Bu şekilde, algoritma, seçilen dizide bir sorun olup olmadığı konusunda her köşede oldukça hızlı bir geri bildirim alır. Dikdörtgenleri yerleştirirken, mantık, herhangi bir dikdörtgen için çok dar olan boşluk boşluklarının gelişip gelişmediğini görmek için izlemeye devam eder. Çevre başarıyla doldurulduktan sonra, kalan alanı kalan dikdörtgenlerle eşleştirmeye çalışmak için strateji değişir (eşleme işlevi).
İlgilenebilecek başka bir şey, bunun dikdörtgen yığınları için geri alma işlemlerini gerçekleştirmesidir.
Bu program mümkün olan en iyi uyumu bulmaya çalışmaz. Bir bütçe (64) verilir ve ilk çözümü bulduğunda kapanır. Asla bir çözüm bulamazsa, bütçeyi (16'ya kadar) artırıp tekrar deneriz. Gereken süre (I7 işlemcili bir Dell dizüstü bilgisayarda) bir tarafta 150 için bir dakikadan 48 dakikaya kadar değişti (bir tarafta 149 2 dakikadan az sürdü). 51 çözümün hepsi 11 dikdörtgen kullandı. 51 çözümün skorları 41 ila 78 arasında değişiyordu. 11 dikdörtgen kullanmamın nedenleri, skorun daha az dikdörtgenle karşılaştırıldığında daha düşük olması ve 12 dikdörtgenin ayrılan saatten çok daha uzun sürmesi gibi görünüyordu.
Çözümler ve kod https://github.com/JaySpencerAnderson/mondrian adresinde bulunabilir . Bunlar iki my4 * dosyasıdır.
BTW, bunu "my4" olarak derlerseniz ve şu şekilde çalıştırırsanız: "./my4 -h", size kullanım sağlar. Eğer iş başında çalışırken görmek istiyorsanız, "./my4 -l 50 -n 8" gibi bir şey deneyin. Bir "#if 0" değerini "#if 1" olarak değiştirirseniz, ekranda kalan alan oluşturulur. Dikdörtgenleri oluşturmak için bunu değiştirmek isterseniz, kodun "grafik (boşluk, taraf)" yürüttüğü noktayı arayın ve bunun yerine "grafik (çağrı işareti, yan)" olarak değiştirin. Ayrıca, yaklaşık 50 genişliğindeki kareler için çözümlerle oynamak istiyorsanız, başlangıç bütçesini 64'den 32'ye değiştirmenizi öneririm. Daha küçük kareler için çözüm, daha küçük bir bütçeyle daha iyi bir puana sahip olacaktır.
Aşağıdaki program işlevseldir. Kodun tamamını (kullanım, yorumlar vb. İle) için github'a bakın.
#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;
}
}