C - 2982
โปรแกรมนี้ใช้การค้นหาผ่านชุดผลลัพธ์แบบกว้าง ส่วนที่สำคัญในการทำให้การค้นหาในทางปฏิบัตินี้เกิดขึ้นได้ก็คือการล้มเหลว แต่เนิ่นๆและ / หรือไม่ลงเส้นทางที่ไม่ดี
สิ่งนี้จะสร้างชุดของรูปสี่เหลี่ยมผืนผ้าที่จะพิจารณาสำหรับการแก้ปัญหา ชุดของรูปสี่เหลี่ยมผืนผ้าที่สร้างขึ้นจะหลีกเลี่ยงสิ่งที่มีขนาดซึ่งจะไม่มีประโยชน์ ตัวอย่างเช่นหากโปรแกรมพยายามค้นหาวิธีแก้ปัญหาเป็นสี่เหลี่ยมจัตุรัส 128x128 แบ่งออกเป็น 8 สี่เหลี่ยมมันจะสร้างสี่เหลี่ยมที่มีขนาด 128x16 มันจะไม่สร้างอันนั้นคือ 120x17 เนื่องจากไม่มีโอกาสของสี่เหลี่ยมสร้างที่มีความกว้าง 8 เพื่อเติมเต็มช่องว่างในตอนท้ายของ 120
กลยุทธ์เริ่มต้นสำหรับการวางรูปสี่เหลี่ยมคือการวางไว้ที่ด้านในของเส้นรอบวงของตาราง (ฟังก์ชัน buildedge) ด้วยวิธีนี้อัลกอริทึมจะได้รับการตอบรับอย่างรวดเร็วในแต่ละมุมว่ามีปัญหากับลำดับที่เลือกหรือไม่ ในขณะที่วางรูปสี่เหลี่ยมตรรกะจะคอยดูว่าช่องว่างใด ๆ ของการพัฒนาที่แคบเกินไปสำหรับสี่เหลี่ยมใด ๆ หลังจากการเติมขอบเขตให้สำเร็จกลยุทธ์จะเปลี่ยนเป็นพยายามจับคู่พื้นที่ที่เหลือกับสี่เหลี่ยมที่เหลือ (ฟังก์ชันจับคู่)
อีกสิ่งหนึ่งที่อาจเป็นที่น่าสนใจก็คือการทำธุรกรรมนี้มีการย้อนกลับสำหรับกองสี่เหลี่ยม
โปรแกรมนี้ไม่ได้พยายามที่จะหาแบบที่ดีที่สุด จะได้รับงบประมาณ (64) และออกเมื่อพบโซลูชั่นแรก หากไม่พบวิธีแก้ปัญหาเราชนงบประมาณ (เพิ่มขึ้น 16) และลองอีกครั้ง เวลาที่ต้องการ (บนแล็ปท็อป Dell ที่มีโปรเซสเซอร์ I7) อยู่ในช่วงเวลาไม่เกิน 48 นาทีเป็น 150 นาทีสำหรับด้านข้าง (ด้านข้าง 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" จะเป็นการแสดงพื้นที่ที่เหลือบนหน้าจอ หากคุณต้องการเปลี่ยนสิ่งนี้เพื่อแสดงผลเป็นรูปสี่เหลี่ยมผืนผ้าให้มองหาจุดเดียวที่รหัสเรียกใช้ "กราฟ (ช่องว่างด้านข้าง)" และเปลี่ยนเป็น "กราฟ (โทรกลับด้านข้าง)" แทน ฉันขอแนะนำให้เปลี่ยนงบประมาณเริ่มต้นจาก 64 เป็น 32 หากคุณต้องการแก้ไขด้วยวิธีแก้ปัญหาสำหรับช่องสี่เหลี่ยมที่มีความกว้างประมาณ 50 วิธีแก้ปัญหาของกำลังสองที่น้อยกว่าจะได้คะแนนที่ดีกว่าด้วยงบประมาณที่น้อยลง
โปรแกรมด้านล่างใช้งานได้ ตรวจสอบ 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;
}
}