পিট (মন্ড্রিয়ান) এর ধাঁধা


20

আরও তথ্যের জন্য, এই ভিডিওটি দেখুন এবং সম্পর্কিত ক্রমের জন্য A276523 এ যান ।

মন্ড্রিয়ান ধাঁধা (একটি পূর্ণসংখ্যার জন্য n) নিম্নলিখিত:

একটি n*nবর্গ গ্রিডে অ-সংগৃহীত আয়তক্ষেত্রগুলি ফিট করুন । বৃহত্তম এবং ক্ষুদ্রতম আয়তক্ষেত্রের মধ্যে ক্ষুদ্রতম পার্থক্য কী?

জন্য 6, জন্য অনুকূল পার্থক্য M(6)হল 5, এবং তাই মত প্রদর্শিত করা যেতে পারে:

 ___________
| |S|_______|
| | |   L   |
| |_|_______|
| |     |   |
| |_____|___|
|_|_________| (fig. I)

বৃহত্তম আয়তক্ষেত্রের (এল) এর ক্ষেত্রফল রয়েছে 2 * 4 = 8এবং সবচেয়ে ছোট আয়তক্ষেত্রের (এস) এর ক্ষেত্রফল রয়েছে 1 * 3 = 3। সুতরাং, পার্থক্য হয় 8 - 3 = 5

মনে রাখবেন যে বর্তমানে, এর জন্য কোনও অনুকূল সমাধান n > 44খুঁজে পাওয়া যায় নি।

আপনার কাজটি এমন একটি প্রোগ্রাম তৈরি করা যা একটি পূর্ণসংখ্যার ভিত্তিতে একটি মন্ড্রিয়ান গ্রিড তৈরি করে যা একটি (অপ-অনুকূল) সমাধানযুক্ত n

100 থেকে 150 পর্যন্ত সংখ্যায় আপনাকে পরীক্ষা করা হবে test প্রতিটি পরীক্ষার জন্য আপনার স্কোর বৃহত্তম এবং ক্ষুদ্রতম আয়তক্ষেত্রের মধ্যে পার্থক্য হবে। আপনার মোট স্কোরটি 100 থেকে 150 পর্যন্ত সমস্ত পরীক্ষার জন্য আপনার স্কোরগুলির যোগফল।

আপনার অবশ্যই আপনার আউটপুট উপস্থাপন করতে হবে:

{number}
{grid}

numberস্কোর কোথায় (বৃহত্তম এবং ক্ষুদ্রতম মধ্যে পার্থক্য), এবং gridহয় হয়:

  • একটি বহু-রেখাযুক্ত স্ট্রিং, বা
  • একটি দ্বিমাত্রিক তালিকা।

গ্রিডটি অবশ্যই স্পষ্টভাবে দেখাবে যেখানে একটি আয়তক্ষেত্র শুরু হয় এবং শেষ হয়।

নিয়মাবলী:

  • আপনার প্রোগ্রামটি অবশ্যই আপনার উত্তরের সাথে মাপসই করা উচিত।
  • আপনার প্রোগ্রামকে একটি আধুনিক ল্যাপটপে 1 ঘন্টার মধ্যে 100 এবং 150 এর মধ্যে যে কোনও সংখ্যার জন্য একটি মান আউটপুট করতে হবে।
  • আপনার প্রোগ্রামটি nপ্রতিবার প্রোগ্রামটি চালানোর সময় পূর্ণসংখ্যার জন্য একই সমাধান তৈরি করতে হবে ।
  • আপনাকে অবশ্যই সমস্ত 51 টি সমাধানের আউটপুটগুলিতে একটি লিঙ্ক সরবরাহ করতে হবে (পাস্তবিন, গিথুব গিস্ট ... সত্যিই কিছু ব্যবহার করে)।
  • আপনার সমাধানের জন্য স্কোয়ার গ্রিডে আপনার কমপক্ষে দুটি আয়তক্ষেত্র থাকতে হবে।

1
OEIS A276523 । মনে রাখবেন যে ওপেনের সীমাটি এখানে তালিকাবদ্ধ করা উন্নত করা খুব সহজ।
পিটার টেলর

হা। আমি এক সপ্তাহ আগে একই ভিডিওটি দেখেছি এবং আমার প্রথম চিন্তা এটি সমাধান করার জন্য একটি প্রোগ্রাম করার চেষ্টা করছে। আমি যদিও এটি সম্পর্কে সম্পূর্ণ ভুলে গেছি।
কারসিজেনিকেট

4
কেবল এটি বাইরে রাখার জন্য, আমাদের একটি পিট উত্তর দরকার । সম্ভবত এটির জন্য একটি অনুগ্রহ ...
NoOneIsHere

উত্তর:


11

পিট, 9625

(এটি শেষ পর্যন্ত কাজ করে!)

লোকেরা এটি দাবি করেছিল, তাই এটি এখানে। এটি একটি অত্যন্ত নিষ্পাপ সমাধান (মূলত ওইআইএস পৃষ্ঠায় আলগা উপরের সীমানার সমান): এটি প্রতিটি বর্গকে মাত্র দুটি আয়তক্ষেত্রে বিভক্ত করে into

এই সংক্ষেপে দুটি ফাইলে বিশদ রয়েছে :

  • সমস্ত প্রয়োজনীয় ইনপুটগুলির জন্য প্রোগ্রামটির আউটপুট (এনপিট ভি 1.3 ব্যবহার করে)। মনে রাখবেন যে আমি কেবল স্টডআউটকে ক্যাপচার করেছি, সুতরাং তা ?হ'ল ইনপুট প্রম্পট, সাথে সাথে আউটপুট স্কোর, তারপরে গ্রিড।
  • "সিউডো-অ্যাসেম্বলি" উত্সটি আমি প্রোগ্রামটি তৈরির পরিকল্পনা করতাম।

পিট সমাধান, কোডেলের আকার 10 10

ব্যাখ্যা

এই প্রোগ্রামটি Nইনপুট হিসাবে একক সংখ্যা নেয় । সংখ্যাটি বিজোড় হলে স্কোরটি সংখ্যাটি; এমনকি যদি, স্কোর সংখ্যা দ্বিগুণ হয়।

স্কোর আউটপুট দেওয়ার পরে, প্রোগ্রামের বাম-হাতের বাকি অংশগুলি নীচের পাঁচটি তথ্যের সাথে স্ট্যাকটি পূরণ করতে ব্যয় করা হয়:

  • গ্রিডের প্রস্থ (যা N)
  • মুদ্রণের জন্য বেশ কয়েকটি লাইন
  • গ্রিড জুড়ে মুদ্রণের জন্য একটি অক্ষর (হয় _বা স্থান)
  • গ্রিডের প্রতিটি প্রান্তে মুদ্রণের জন্য একটি অক্ষর (স্থান বা হয় |)

প্রোগ্রামের ডান হাতের চারটি মানের প্রতিটি সেট নেয় এবং গ্রিডের সেই অংশটি মুদ্রণ করে।


আপনি যাইহোক একটি অনুগ্রহ পেতে!
NoOneIs এখানে

সমাধান পোস্ট করতে বৈধ হতে হবে।
mbomb007

@ mbomb007 ঠিক আছে, আমি বুঝতে পারি নি। আমি আশা করি এটি 7 দিনের মধ্যে শেষ হয়ে গেছে।
NoOneIs এখানে

6

সি 6108

এটি ন্যূনতম সমাধানের একটি পুনরাবৃত্ত (সত্যই পুনরাবৃত্ত) সংস্করণ ব্যবহার করে। বর্গক্ষেত্রকে দুটি আয়তক্ষেত্রে ভাগ করার পরিবর্তে যেখানে অর্ধেক অঞ্চলের চেয়ে কিছুটা বড়, এটি এটিকে আয়তক্ষেত্রগুলিতে ভাগ করে দেয়। সুতরাং প্রথম আয়তক্ষেত্রটি 1/Nমোট ক্ষেত্রের চেয়ে কিছুটা বড় । তারপরে বাকী অংশটি গ্রহণের পরে, প্রোগ্রামটি একটি আয়তক্ষেত্রটি বিভাজিত হয়ে 1/(N-1)যায়, যতক্ষণ না বাকি অংশটিকে শেষ আয়তক্ষেত্র হিসাবে গ্রহণ করে until একটি আয়তক্ষেত্রগুলি ঘড়ির কাঁটার সর্পিল বাকী অংশ থেকে কেটে দেওয়া হয়, সুতরাং প্রথমে উপরে, তারপরে ডানদিকে, ইত্যাদি

যেহেতু এটি একটি বিস্তৃত স্থান অনুসন্ধানের পরিবর্তে খুব প্রত্যক্ষ পদ্ধতি, এটি দ্রুত চলে - প্রদত্ত সমস্যার সমাধানের জন্য প্রতিটি 74 টি সমাধান দেখার জন্য প্রায় 25 সেকেন্ড (একটি রাস্পবেরি পাইতে) লাগবে।

আমার উদ্দেশ্যটি আরও পরিশীলিত পদ্ধতির জন্য অনুসন্ধানের অ্যালগরিদমকে আরও ভালভাবে জানাতে এই ফলাফলগুলি ব্যবহার করা।

আউটপুটটি স্কোর এবং উভয়কে (ascii) অঙ্কন দেয় এবং আয়তক্ষেত্রের শীর্ষকোষের জন্য স্থানাঙ্ক করে। উল্লম্বগুলি প্রশ্নযুক্ত আয়তক্ষেত্রের উপরের বাম দিকের কোণ থেকে শুরু করে ঘড়ির কাঁটার দিকে থাকে।

জিসিসি 4.9.2-10 ব্যবহার করে বিকাশ হয়েছে।

Https://github.com/JaySpencerAnderson/mondrian এ ফলাফল

কোড:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct {
    int y, x, height, width;
} rectangle;
#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 MAXCOUNT 75

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 valid(rectangle *s,int n){
    int i,j;
    for(i=0;i<n-1;i++){
        for(j=i+1;j<n;j++){
            if(min(s[i].height,s[i].width) == min(s[j].height,s[j].width) && max(s[i].height,s[i].width) == max(s[j].height,s[j].width)){

                initstack(s, n);
                return FALSE;
            }
        }
    }
    return TRUE;
}
int horizontal(rectangle s, int y, int x){
    if(s.y == y && x >= s.x && x < s.x+s.width){
        return TRUE;
    }
    else if(s.y+s.height == y && x >= s.x && x < s.x+s.width){
        return TRUE;
    }
    return FALSE;
}
int vertical(rectangle s, int y, int x){
    if(s.x == x && y > s.y && y <= s.y+s.height){
        return TRUE;
    }
    else if(s.x+s.width == x && y > s.y && y <= s.y+s.height){
        return TRUE;
    }
    return FALSE;
}
void graph(rectangle *s, int n, int side){
    unsigned int row,col,i;
    unsigned int line;
    printf("{\n");
/* vertical lines take precedence since "1" cell is 1 char high and 2 char wide */
    for(row=0;row<=side;row++){
        for(col=0;col<=side;col++){
            line=0;
/* Possible values are "  " (0), "__" (1), "| " (2) or "|_" (3). */
            for(i=0;i<n;i++){
                if(horizontal(s[i],row,col)){
                    line|=1;
                }
                if(vertical(s[i],row,col)){
                    line|=2;
                }
            }

            switch(line){
            case 0: printf("  ");   break;
            case 1: printf("__");   break;
            case 2: printf("| ");   break;
            case 3: printf("|_");   break;
            default: printf("##");  break;
            }
        }
        printf("\n");
    }
    printf("}\n");
}
unsigned int score(rectangle *s, int n){
    int i;
    unsigned int smallest,biggest;

    smallest=biggest=s[0].width*s[0].height;

    for(i=0;i<n;i++){
        smallest=min(smallest,s[i].width*s[i].height);
        biggest=max(biggest,s[i].width*s[i].height);
    }
    return biggest-smallest;
}
void report(rectangle *s, int n, int side){
    int i;

    printf("{%d}\n",score(s,n));
    graph(s, n, side);
    printf("{\n");
    for(i=0;i<n;i++){
        printf("[%d,%d] ",s[i].x,s[i].y);
        printf("[%d,%d] ",s[i].x+s[i].width,s[i].y);
        printf("[%d,%d] ",s[i].x+s[i].width,s[i].y+s[i].height);
        printf("[%d,%d]\n",s[i].x,s[i].y+s[i].height);
    }
    printf("\n}\n");
}
void locateandrotate(rectangle *stack, int n){
    unsigned int scratch,i;
    for(i=1;i<n;i++){
        /* Odd rectangles are on their side */
        if(i&1){
            scratch=stack[i].width;
            stack[i].width=stack[i].height;
            stack[i].height=scratch;
        }
        switch(i%4){
        case 0:
            stack[i].x=stack[i-1].x+stack[i-1].width;
            stack[i].y=stack[i-1].y;
            break;
        case 1:
            stack[i].x=stack[i-1].x+stack[i-1].width-stack[i].width;
            stack[i].y=stack[i-1].y+stack[i-1].height;
            break;
        case 2:
            stack[i].x=stack[i-1].x-stack[i].width;
            stack[i].y=stack[i-1].y+stack[i-1].height-stack[i].height;
            break;
        case 3:
            stack[i].x=stack[i-1].x;
            stack[i].y=stack[i-1].y-stack[i].height;
            break;
        default:
            printf("Woops!\n");
        }
    }
}
/* These are the height and width of the remaining area to be filled. */
void door(rectangle *stack, unsigned int height, unsigned int width, unsigned int n, unsigned int totaln){
    unsigned int thisheight, thiswidth;
    int i;

    for(i=0;i<totaln;i++){
/* Not yet used */
        if(stack[i].width == 0){
            stack[i].width=width;
            if(i+1 == totaln){
                stack[i].height=height;
            }
            else {
/* Sometimes yields congruent rectangles, as with 16x16, 8 rectangles */
                if(totaln&1 || height%n){
                    int j;
                    stack[i].height=height-(((n-1)*height)/n);
                }
                else {
                    stack[i].height=height-((((n-1)*height)-1)/n);
                }
                /* Exchange height and width to rotate */
                door(stack,width,height-stack[i].height,n-1,totaln);
            }
            return;
        }
    }
}
void usage(char *argv[],int side){
    printf("Usage: %s -s <side-length>\n",argv[0]);
    printf("Purpose: Calculate N non-congruent rectangles arranged to exactly fill a square with the specified side length.\n");
    printf("Defaults: %s -s %d\n",argv[0],side);
    exit(0);

}
int main(int argc, char *argv[]){
    int side=16;
    int n,bestscore,bestn=2;
    int status;

    while((status=getopt(argc,argv,"s:h")) >= 0){
        switch(status){
        case 's':
            sscanf(optarg,"%d",&side);
            break;
        case 'h':
        default:
            usage(argv,side);
        }
    }

    bestscore=side+side;

    rectangle stack[MAXCOUNT],best[MAXCOUNT];
    for(n=2;n<=MAXCOUNT;n++){
        initstack(stack,MAXCOUNT);
        door(stack, side, side, n, n);
        locateandrotate(stack, n);
        if(valid(stack,n)){
            if(score(stack,n) < bestscore){
                bestn=n;
                initstack(best,MAXCOUNT);
                door(best, side, side, n, n);
                locateandrotate(best, n);

                bestscore=score(best,n);
            }
        }
    }
    report(best,bestn,side);
}

1
উম্মম ... আপনি কি হেডারে চূড়ান্ত স্কোর দিতে পারবেন? ধন্যবাদ। দুর্দান্ত সমাধান, যদিও - কোনও সমাধানের প্রত্যাশা করছিল না ('কারণ কিছু দিন কারও উত্তর দেওয়া হয়নি)।
ক্লিশমিক

1

সি - 2982

এই প্রোগ্রামটি একটি বিস্তৃত ফলাফল সেটের মাধ্যমে একটি অনুসন্ধান কার্যকর করে। এই অনুসন্ধানকে ব্যবহারিক করে তোলার গুরুত্বপূর্ণ অংশটি তাড়াতাড়ি ব্যর্থ হওয়া এবং / বা খারাপ পথে নামা ছিল না।

এটি সমাধানের জন্য বিবেচনার জন্য একটি আয়তক্ষেত্রের সেট তৈরি করে। উত্পন্ন আয়তক্ষেত্রের সেটগুলি কার্যকর নয় এমন মাত্রাগুলির সাথে এড়িয়ে চলে। উদাহরণস্বরূপ, যদি প্রোগ্রামটি 128x128 বর্গক্ষেত্রের 8 টি আয়তক্ষেত্রগুলিতে বিভক্ত সমাধানের সন্ধানের চেষ্টা করে তবে এটি 128x16 এর একটি আয়তক্ষেত্র তৈরি করবে। এটি একটিকে 120x17 উত্পন্ন করবে না কারণ 120 এর শেষে ফাঁক পূরণ করতে 8 প্রস্থের উত্পন্ন আয়তক্ষেত্রের কোনও সম্ভাবনা নেই।

আয়তক্ষেত্র স্থাপনের প্রাথমিক কৌশলটি তাদের বর্গক্ষেত্রের ঘেরের ভিতরে স্থাপন করা (বিল্ডজ ফাংশন)। এইভাবে, অ্যালগরিদম প্রতিটি কোণায় চমত্কার দ্রুত প্রতিক্রিয়া পেয়েছে যে ক্রমটি বেছে নেওয়া হয়েছে তা বেছে নিয়েছে কিনা to আয়তক্ষেত্র স্থাপন করার সময়, যুক্তি নজর রাখে যে কোনও স্থানের ফাঁকগুলি কোনও আয়তক্ষেত্রের জন্য খুব সংকীর্ণ বিকাশ করে কিনা তা দেখার জন্য। পরিধিটি সফলভাবে পপুলেটেড হওয়ার পরে, কৌশলটি অবশিষ্ট আয়তক্ষেত্রগুলির সাথে ম্যাচের ফাংশনটি (ম্যাচ ফাংশন) এর সাথে ম্যাচের চেষ্টা করার পরিবর্তে কৌশল পরিবর্তন করে।

আর একটি বিষয় যা আগ্রহী হতে পারে তা হ'ল এটি আয়তক্ষেত্রের স্ট্যাকের জন্য রোলব্যাকের সাথে লেনদেন প্রয়োগ করে।

এই প্রোগ্রামটি সেরা সম্ভাব্য ফিট খুঁজে পাওয়ার চেষ্টা করে না। এটি একটি বাজেট দেওয়া হয় (64) এবং যখন প্রথম সমাধানটি খুঁজে পায় তখন ত্যাগ করে। যদি এটির কোনও সমাধান কখনই খুঁজে পাওয়া যায় না, আমরা বাজেটটি (16 দ্বারা) ছড়িয়ে দেব এবং আবার চেষ্টা করব। প্রয়োজনীয় সময় (আই আই প্রসেসর সহ ডেল ল্যাপটপে) ভালভাবে একদিকে থেকে একপাশে 150 এর জন্য 48 মিনিট অবধি (একদিকে 149 কম 2 মিনিটের বেশি সময় নেয়)। সমস্ত 51 সমাধান 11 টি আয়তক্ষেত্র ব্যবহার করেছে। ৫১ টি সমাধানের স্কোর ৪১ থেকে 78 78 পর্যন্ত। আমি ১১ টি আয়তক্ষেত্র ব্যবহার করার কারণগুলি হ'ল স্কোর কম আয়তক্ষেত্রের চেয়ে কম ছিল এবং দেখে মনে হয়েছিল যে 12 টি আয়তক্ষেত্র বরাদ্দ হওয়া সময়ের চেয়ে অনেক বেশি সময় নেয়।

সমাধান এবং কোড https://github.com/JaySpencerAnderson/mondrian এ পাওয়া যেতে পারে । এগুলি দুটি মাই 4 * ফাইল।

বিটিডাব্লু, আপনি যদি এটি "মাই 4" তে সংকলন করেন এবং নীচে এটি কার্যকর করেন: "./my4 -h", এটি আপনাকে ব্যবহার দেবে। আপনি যদি এটিকে কর্মক্ষেত্রে দূরে কাজ করে দেখতে চান তবে "./my4 -l 50 -n 8" এর মতো কিছু চেষ্টা করুন। যদি আপনি একটি "#if 0" কে "#if 1" তে পরিবর্তন করেন তবে এটি স্ক্রিনের অবশিষ্ট স্থানটি রেন্ডার করবে। আপনি যদি আয়তক্ষেত্রগুলি রেন্ডার করতে এটি পরিবর্তন করতে চান, কোডটি একটি "গ্রাফ (স্থান, পাশ)" চালায় এমন এক জায়গার সন্ধান করুন এবং পরিবর্তে "গ্রাফ (কলস্ট্যাক, পাশ)" এ পরিবর্তন করুন। আপনি প্রায় 50 বিস্তৃত বর্গক্ষেত্রের সমাধানগুলি নিয়ে খেলতে চান তবে আমি প্রাথমিক বাজেটটি 64 থেকে 32 থেকে পরিবর্তন করার পরামর্শ দেব। আরও ছোট স্কোয়ারগুলির সমাধানের জন্য আরও কম স্কোর থাকবে একটি ছোট বাজেট।

নীচের প্রোগ্রামটি কার্যকরী। সম্পূর্ণ কোডের জন্য গিথুবটি পরীক্ষা করুন (ব্যবহার, মন্তব্য ইত্যাদি)

#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;
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.