গ্যাপগুলি ব্রিজ করুন


14

একটি সাদা ব্যাকগ্রাউন্ড এবং কালো বিন্দুর একটি সেট সহ একটি কালো এবং সাদা চিত্র দেওয়া, সাদা পিক্সেল লাল সেট সেট করুন, যেমন কালো পিক্সেল প্রতিটি জোড়া মধ্যে একটি পথ আছে যে।

বিস্তারিত

  • একটি পাথ সংযুক্ত পিক্সেলের একটি সেট (8-পার্শ্ববর্তী সংযোগ)। কালো পিক্সেলগুলি পাথের অংশ হিসাবে ব্যবহার করা যেতে পারে। লক্ষ্যটি উপরের অবস্থার অধীনে লাল পিক্সেলের সেটটি ছোট করার এবং একটি সম্পর্কিত চিত্র আউটপুট করার চেষ্টা করছে।

  • আপনি না আছে সন্তোষজনক সমাধান খুঁজে।

  • একটি তুচ্ছ এবং একই সময়ে সবচেয়ে খারাপ সমাধানটি কেবল সমস্ত সাদা পিক্সেলকে লাল রঙ করে।

  • উদাহরণ (পিক্সেল দৃশ্যমানতার জন্য বড় করা হয়েছে):

বিস্তারিত

  • একটি পিক্সেল চিত্র দেওয়া (কোনও উপযুক্ত বিন্যাসে) উপরে উল্লিখিত হিসাবে সংযুক্ত বিন্দাগুলি সহ আরও একটি চিত্র ফেরত দেয়, পাশাপাশি কতগুলি লাল পিক্সেল ব্যবহৃত হয়েছিল তা ইঙ্গিত করে একটি পূর্ণসংখ্যা।
  • স্কোরটি 14 টি টেস্টকেসের প্রতিটিটির জন্য (লাল পিক্সেলের সংখ্যা 1) এর পণ্য।
  • গোলটি হচ্ছে সর্বনিম্ন স্কোর।

Testcases

14 টি টেস্টকেসগুলি নীচে দেখানো হয়েছে। আউটপুটগুলির সংযোগতা যাচাই করার জন্য একটি অজগর প্রোগ্রামটি এখানে পাওয়া যাবে।

মেটা

বিভিন্ন পরামর্শের জন্য @ ভেস্কাহ, @ ফ্যাটালাইজ, @ উইজউইজ্জেড ৪ এবং @ ট্রিকোপল্যাক্সকে ধন্যবাদ।


1
ভাল চ্যালেঞ্জ; আমি বিভিন্ন এবং সৃজনশীল স্কোরিং স্কিমগুলি পছন্দ করি। আমি ধরে নিই যে প্রোগ্রামটি কেবল একটি 14 টি সুনির্দিষ্ট উদাহরণ নয়, একটি স্বেচ্ছাসেবী চিত্রটিতে কাজ করা দরকার? যদি তা হয়, তবে আমরা কী মোনা লিসা চিত্র প্রতি 512x512, বা 1024x1024 এর মতো যুক্তিসঙ্গত সর্বোচ্চ আকার ধরে নিতে পারি?
ব্র্যাডসি

সাহায্য করার জন্য ধন্যবাদ! হ্যাঁ আপনি সর্বাধিক আকার ধরে নিতে পারেন (প্রয়োজনে একটি ন্যূনতম আকারও), যতক্ষণ না সমস্ত 14 টি উদাহরণ প্রক্রিয়া করা যায়।
flawr

আমি কীভাবে পিএনজিকে আসকি বা জসন বা পার্স করার সহজ কিছুতে রূপান্তর করব?
এনজিএন

আপনার নিজের স্কোর গণনা করতে সক্ষম হতে হবে? এমন একটি প্রোগ্রাম যা সাদা রঙিন রঙিন করার জন্য সাদা পিক্সেলের প্রতিটি সম্ভাব্য সংমিশ্রণের চেষ্টা করে এবং সমস্ত কালো পিক্সেলের সাথে সংযোগ করার সময় কোন সাবসেটটিতে সবচেয়ে কম লাল পিক্সেল রয়েছে তা দেখা যায় তবে এটি এত আস্তে আস্তে সময় নেয় যে এটি আজীবন বেশি সময় নেয় মহাবিশ্বের আসলে যে স্কোর গণনা করা।
লিও টেনেনবুম

1
@ জিএনপি জিএমপিতে খুলুন, নেটপবিএম ফর্ম্যাট হিসাবে সংরক্ষণ করুন।
wizzwizz4

উত্তর:


7

সি, স্কোর 2.397x10 ^ 38

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

এখনও! এটি প্রতিটি পরীক্ষার ক্ষেত্রে অন্য প্রবেশকে মারধর করে এবং সর্বোত্তম হতে পারে এমনকি বেশিরভাগ সময় কাছাকাছি বা হুবহু সর্বোত্তম সমাধান পেতে পারে।

যাইহোক, কোড এখানে:

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#define WHITE 'W'
#define BLACK 'B'
#define RED   'R'


typedef struct image {
    int w, h;
    char* buf;
} image;

typedef struct point {
    int x, y;
    struct point *next;
    struct point *parent;
} point;

typedef struct shape {
    point* first_point;
    point* last_point;

    struct shape* next_shape;
} shape;


typedef struct storage {
    point* points;
    size_t points_size;
    size_t points_index;

    shape* shapes;
    size_t shapes_size;
    size_t shapes_index;
} storage;

char getpx(image* img, int x, int y) {
    if (0>x || x>=img->w || 0>y || y>=img->h) {
        return WHITE;
    } else {
        return img->buf[y*img->w+x];
    }
}

storage* create_storage(int w, int h) {
    storage* ps = (storage*)malloc(sizeof(storage));

    ps->points_size = 8*w*h;
    ps->points = (point*)calloc(ps->points_size, sizeof(point));
    ps->points_index = 0;

    ps->shapes_size = 2*w*h;
    ps->shapes = (shape*)calloc(ps->shapes_size, sizeof(shape));
    ps->shapes_index = 0;

    return ps;
}

void free_storage(storage* ps) {
    if (ps != NULL) {
        if (ps->points != NULL) {
            free(ps->points);
            ps->points = NULL;
        }
        if (ps->shapes != NULL) {
            free(ps->shapes);
            ps->shapes = NULL;
        }
        free(ps);
    }
}


point* alloc_point(storage* ps) {
    if (ps->points_index == ps->points_size) {
        printf("WHOAH THERE BUDDY SLOW DOWN\n");
        /*// double the size of the buffer
        point* new_buffer = (point*)malloc(ps->points_size*2*sizeof(point));
        // need to change all existing pointers to point to new buffer
        long long int pointer_offset = (long long int)new_buffer - (long long int)ps->points;
        for (size_t i=0; i<ps->points_index; i++) {
            new_buffer[i] = ps->points[i];
            if (new_buffer[i].next != NULL) {
                new_buffer[i].next += pointer_offset;
            }
            if (new_buffer[i].parent != NULL) {
                new_buffer[i].parent += pointer_offset;
            }
        }

        for(size_t i=0; i<ps->shapes_index; i++) {
            if (ps->shapes[i].first_point != NULL) {
                ps->shapes[i].first_point += pointer_offset;
            }
            if (ps->shapes[i].last_point != NULL) {
                ps->shapes[i].last_point += pointer_offset;
            }
        }

        free(ps->points);
        ps->points = new_buffer;
        ps->points_size = ps->points_size * 2;*/
    }
    point* out = &(ps->points[ps->points_index]);
    ps->points_index += 1;
    return out;
}

shape* alloc_shape(storage* ps) {
    /*if (ps->shapes_index == ps->shapes_size) {
        // double the size of the buffer
        shape* new_buffer = (shape*)malloc(ps->shapes_size*2*sizeof(shape));
        long long int pointer_offset = (long long int)new_buffer - (long long int)ps->shapes;
        for (size_t i=0; i<ps->shapes_index; i++) {
            new_buffer[i] = ps->shapes[i];
            if (new_buffer[i].next_shape != NULL) {
                new_buffer[i].next_shape += pointer_offset;
            }
        }
        free(ps->shapes);
        ps->shapes = new_buffer;
        ps->shapes_size = ps->shapes_size * 2;
    }*/
    shape* out = &(ps->shapes[ps->shapes_index]);
    ps->shapes_index += 1;
    return out;
}

shape floodfill_shape(image* img, storage* ps, int x, int y, char* buf) {
    // not using point allocator for exploration stack b/c that will overflow it

    point* stack = (point*)malloc(sizeof(point));
    stack->x = x;
    stack->y = y;
    stack->next = NULL;
    stack->parent = NULL;

    point* explored = NULL;
    point* first_explored;
    point* next_explored;

    while (stack != NULL) {
        int sx = stack->x;
        int sy = stack->y;
        point* prev_head = stack;
        stack = stack->next;
        free(prev_head);

        buf[sx+sy*img->w] = 1; // mark as explored

        // add point to shape
        next_explored = alloc_point(ps);
        next_explored->x = sx;
        next_explored->y = sy;
        next_explored->next = NULL;
        next_explored->parent = NULL;

        if (explored != NULL) {
            explored->next = next_explored;
        } else {
            first_explored = next_explored;
        }
        explored = next_explored;

        for (int dy=-1; dy<2; dy++) {
        for (int dx=-1; dx<2; dx++) {
            if (dy != 0 || dx != 0) {
                int nx = sx+dx;
                int ny = sy+dy;
                if (getpx(img, nx, ny) == WHITE || buf[nx+ny*img->w]) {
                    // skip adding point to fringe
                } else {
                    // push point to top of stack
                    point* new_point = (point*)malloc(sizeof(point));
                    new_point->x = nx;
                    new_point->y = ny;
                    new_point->next = stack;
                    new_point->parent = NULL;

                    stack = new_point;
                } 
            }
        }
        }
    }

    /*if (getpx(img, x, y) == WHITE || buf[x+y*img->w]) {
        return (shape){NULL, NULL, NULL};
    } else {
        buf[x+y*img->w] = 1;

        shape e  = floodfill_shape(img, ps, x+1, y,   buf);
        shape ne = floodfill_shape(img, ps, x+1, y+1, buf);
        shape n  = floodfill_shape(img, ps, x,   y+1, buf);
        shape nw = floodfill_shape(img, ps, x-1, y+1, buf);
        shape w  = floodfill_shape(img, ps, x-1, y,   buf);
        shape sw = floodfill_shape(img, ps, x-1, y-1, buf);
        shape s  = floodfill_shape(img, ps, x,   y-1, buf);
        shape se = floodfill_shape(img, ps, x+1, y-1, buf);

        point *p = alloc_point(ps);
        p->x = x;
        p->y = y;
        p->next = NULL;
        p->parent = NULL;

        shape o = (shape){p, p, NULL};
        if (e.first_point != NULL) {
            o.last_point->next = e.first_point;
            o.last_point = e.last_point;
        }
        if (ne.first_point != NULL) {
            o.last_point->next = ne.first_point;
            o.last_point = ne.last_point;
        }
        if (n.first_point != NULL) {
            o.last_point->next = n.first_point;
            o.last_point = n.last_point;
        }
        if (nw.first_point != NULL) {
            o.last_point->next = nw.first_point;
            o.last_point = nw.last_point;
        }
        if (w.first_point != NULL) {
            o.last_point->next = w.first_point;
            o.last_point = w.last_point;
        }
        if (sw.first_point != NULL) {
            o.last_point->next = sw.first_point;
            o.last_point = sw.last_point;
        }
        if (s.first_point != NULL) {
            o.last_point->next = s.first_point;
            o.last_point = s.last_point;
        }
        if (se.first_point != NULL) {
            o.last_point->next = se.first_point;
            o.last_point = se.last_point;
        }

        return o;
    }*/

    shape out = {first_explored, explored, NULL};

    return out;
}

shape* create_shapes(image* img, storage* ps) {
    char* added_buffer = (char*)calloc(img->w*img->h, sizeof(char));
    shape* first_shape = NULL;
    shape* last_shape = NULL;
    int num_shapes = 0;
    for (int y=0; y<img->h; y++) {
        for (int x=0; x<img->w; x++) {
            if (getpx(img, x, y) != WHITE && !(added_buffer[x+y*img->w])) {
                shape* alloced_shape = alloc_shape(ps);
                *alloced_shape = floodfill_shape(img, ps, x, y, added_buffer);

                if (first_shape == NULL) {
                    first_shape = alloced_shape;
                    last_shape = alloced_shape;
                } else if (last_shape != NULL) {
                    last_shape->next_shape = alloced_shape;
                    last_shape = alloced_shape;
                }

                num_shapes++;
            }
        }
    }

    free(added_buffer);

    return first_shape;
}

void populate_buf(image* img, shape* s, char* buf) {
    point* p = s->first_point;

    while (p != NULL) {
        buf[p->x+p->y*img->w] = 1;
        p = p->next;
    }
}

bool expand_frontier(image* img, storage* ps, shape* prev_frontier, shape* next_frontier, char* buf) {
    point* p = prev_frontier->first_point;
    point* n = NULL;

    bool found = false;

    size_t starting_points_index = ps->points_index;

    while (p != NULL) {
        for (int dy=-1; dy<2; dy++) {
        for (int dx=-1; dx<2; dx++) {
            if (dy != 0 || dx != 0) {
                int nx = p->x+dx;
                int ny = p->y+dy;
                if ((0<=nx && nx<img->w && 0<=ny && ny<img->h) // in bounds
                        && !buf[nx+ny*img->w]) {               // not searched yet
                    buf[nx+ny*img->w] = 1;
                    if (getpx(img, nx, ny) != WHITE) {
                        // found a new shape!
                        ps->points_index = starting_points_index;
                        n = alloc_point(ps);
                        n->x = nx;
                        n->y = ny;
                        n->next = NULL;
                        n->parent = p;
                        found = true;
                        goto __expand_frontier_fullbreak;
                    } else {
                        // need to search more
                        point* f = alloc_point(ps);
                        f->x = nx;
                        f->y = ny;
                        f->next = n;
                        f->parent = p;
                        n = f;
                    }
                }
            }
        }}

        p = p->next;
    }
__expand_frontier_fullbreak:
    p = NULL;
    point* last_n = n;
    while (last_n->next != NULL) {
        last_n = last_n->next;
    }

    next_frontier->first_point = n;
    next_frontier->last_point = last_n;

    return found;
}

void color_from_frontier(image* img, point* frontier_point) {
    point* p = frontier_point->parent;

    while (p->parent != NULL) { // if everything else is right,
                                // a frontier point should come in a chain of at least 3
                                // (f point (B) -> point to color (W) -> point in shape (B) -> NULL)
        img->buf[p->x+p->y*img->w] = RED;
        p = p->parent;
    }
}

int main(int argc, char** argv) {
    if (argc < 3) {
        printf("Error: first argument must be filename to load, second argument filename to save to.\n");
        return 1;
    }

    char* fname = argv[1];
    FILE* fp = fopen(fname, "r");

    if (fp == NULL) {
        printf("Error opening file \"%s\"\n", fname);
        return 1;
    }

    int w, h;
    w = 0;
    h = 0;
    fscanf(fp, "%d %d\n", &w, &h);

    if (w==0 || h==0) {
        printf("Error: invalid width/height specified\n");
        return 1;
    }

    char* buf = (char*)malloc(sizeof(char)*w*h+1);
    fgets(buf, w*h+1, fp);
    fclose(fp);

    image img = (image){w, h, buf};

    int nshapes = 0;
    storage* ps = create_storage(w, h);

    while (nshapes != 1) {
        // main loop, do processing step until one shape left
        ps->points_index = 0;
        ps->shapes_index = 0;

        shape* head = create_shapes(&img, ps);
        nshapes = 0;
        shape* pt = head;
        while (pt != NULL) {
            pt = pt->next_shape;
            nshapes++;
        }
        if (nshapes % 1024 == 0) {
            printf("shapes left: %d\n", nshapes);
        }
        if (nshapes == 1) {
            goto __main_task_complete;
        }


        shape* frontier = alloc_shape(ps);
        // making a copy so we can safely free later
        point* p = head->first_point;
        point* ffp = NULL;
        point* flp = NULL;
        while (p != NULL) {
            if (ffp == NULL) {
                ffp = alloc_point(ps);
                ffp->x = p->x;
                ffp->y = p->y;
                ffp->next = NULL;
                ffp->parent = NULL;
                flp = ffp;
            } else {
                point* fnp = alloc_point(ps);
                fnp->x = p->x;
                fnp->y = p->y;
                fnp->next = NULL;
                fnp->parent = NULL;

                flp->next = fnp;
                flp = fnp;
            }

            p = p->next;
        }
        frontier->first_point = ffp;
        frontier->last_point = flp;
        frontier->next_shape = NULL;

        char* visited_buf = (char*)calloc(img.w*img.h+1, sizeof(char));
        populate_buf(&img, frontier, visited_buf);

        shape* new_frontier = alloc_shape(ps);
        new_frontier->first_point = NULL;
        new_frontier->last_point = NULL;
        new_frontier->next_shape = NULL;

        while (!expand_frontier(&img, ps, frontier, new_frontier, visited_buf)) {
            frontier->first_point = new_frontier->first_point;
            frontier->last_point = new_frontier->last_point;
            new_frontier->next_shape = frontier;
        }

        free(visited_buf);
        color_from_frontier(&img, new_frontier->first_point);
__main_task_complete:
        img = img;
    }

    free_storage(ps);

    char* outfname = argv[2];
    fp = fopen(outfname, "w");

    if (fp == NULL) {
        printf("Error opening file \"%s\"\n", outfname);
        return 1;
    }

    fprintf(fp, "%d %d\n", img.w, img.h);
    fprintf(fp, "%s", img.buf);

    free(img.buf);

    fclose(fp);

    return 0;
}

পরীক্ষিত: আর্চ লিনাক্স, জিসিসি 9.1.0, -O3

এই কোডটি একটি কাস্টম ফাইলের ইনপুট / আউটপুট নেয় যা আমি "সিপিপিএম" বলি (কারণ এটি ক্লাসিক পিপিএম ফর্ম্যাটের সংশ্লেষিত সংস্করণের মতো)। এটি থেকে / এ রূপান্তর করার জন্য একটি অজগর স্ক্রিপ্ট নীচে রয়েছে:

from PIL import Image

BLACK='B'
WHITE='W'
RED  ='R'


def image_to_cppm(infname, outfname):
    outfile = open(outfname, 'w')
    im = Image.open(infname)

    w, h = im.width, im.height
    outfile.write(f"{w} {h}\n")
    for y in range(h):
        for x in range(w):
            r, g, b, *_ = im.getpixel((x, y))
            if r==0 and g==0 and b==0:
                outfile.write(BLACK)
            elif g==0 and b==0:
                outfile.write(RED)
            else:
                outfile.write(WHITE)
    outfile.write("\n")
    outfile.close()
    im.close()

def cppm_to_image(infname, outfname):
    infile = open(infname, 'r')

    w, h = infile.readline().split(" ")
    w, h = int(w), int(h)

    im = Image.new('RGB', (w, h), color=(255, 255, 255))

    for y in range(h):
        for x in range(w):
            c = infile.read(1)
            if c==BLACK:
                im.putpixel((x,y), (0, 0, 0))
            elif c==RED:
                im.putpixel((x,y), (255, 0, 0))

    infile.close()
    im.save(outfname)
    im.close()


if __name__ == "__main__":
    import sys
    if len(sys.argv) < 3:
        print("Error: must provide 2 files to convert, first is from, second is to")

    infname = sys.argv[1]
    outfname = sys.argv[2]

    if not infname.endswith("cppm") and outfname.endswith("cppm"):
        image_to_cppm(infname, outfname)
    elif infname.endswith("cppm") and not outfname.endswith("cppm"):
        cppm_to_image(infname, outfname)
    else:
        print("didn't do anything, exactly one file must end with .cppm")

অ্যালগরিদম ব্যাখ্যা

এই অ্যালগরিদম কীভাবে কাজ করে তা হ'ল এটি লাল পিক্সেল সহ চিত্রের সমস্ত সংযুক্ত আকার খুঁজে বের করে শুরু হয়। এটি পরে প্রথমটি নেয় এবং এটি অন্য আকারের মুখোমুখি না হওয়া অবধি একবারে এর সীমান্ত এক পিক্সেল প্রসারিত করে। এরপরে স্পর্শ করা থেকে মূল আকারের সমস্ত পিক্সেলকে রঙ করে (ট্র্যাক রাখার পথে এটি তৈরি লিঙ্কলিস্টটি ব্যবহার করে)। অবশেষে, এটি প্রক্রিয়াটি পুনরাবৃত্তি করে, তৈরি হওয়া সমস্ত নতুন আকার খুঁজে বের করে, যতক্ষণ না কেবলমাত্র একটি আকার থাকে।

ছবির গ্যালারি

টেস্টকেস 1, 183 পিক্সেল

টেস্টকেস ঘ

টেস্টকেস 2, 140 পিক্সেল

টেস্টকেস 2

টেস্টকেস 3, 244 পিক্সেল

টেস্টকেস 3

টেস্টকেস 4, 42 পিক্সেল

টেস্টকেস 4

টেস্টকেস 5, 622 পিক্সেল

টেস্টকেস 5

টেস্টকেস 6, 1 পিক্সেল

টেস্টকেস 6

টেস্টকেস 7, 104 পিক্সেল

টেস্টকেস 7

টেস্টকেস 8, 2286 পিক্সেল

টেস্টকেস 8

টেস্টকেস 9, 22 পিক্সেল

টেস্টকেস 9

টেস্টকেস 10, 31581 পিক্সেল

টেস্টকেস 10

টেস্টকেস 11, 21421 পিক্সেল

টেস্টকেস 11

টেস্টকেস 12, 5465 পিক্সেল

টেস্টকেস 12

টেস্টকেস 13, 4679 পিক্সেল

টেস্টকেস 13

টেস্টকেস 14, 7362 পিক্সেল

টেস্টকেস 14


2
চমৎকার কাজ! খুব দক্ষ বলে মনে হচ্ছে, যদিও আমি কিছুটা আরও অনুকূল সমাধান সহ কয়েকটি আকারের কল্পনা করতে পারি: টেস্টকেস 3 (একটি বর্গক্ষেত্রে 4 টি বিন্দু), উদাহরণস্বরূপ, আমি (ম্যানুয়ালি) 175 (একটি রেড এক্স) এর চেয়ে কম পেয়েছি, কীভাবে নিশ্চিত তা নয় আমি এটিকে অ্যালগরিদমের মাধ্যমে জোর করে দেব।
ব্র্যাডিসি

6

পাইথন, 2.62 * 10 ^ 40

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

আউটপুট

এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন

import numpy as np
from scipy import ndimage
import imageio
from collections import deque

# path to your image
for k in range(1, 15):
    fname=str(k).zfill(2) +'.png'
    print("processing ", fname)

    # load image
    img = imageio.imread("./images/"+fname, pilmode="RGB")
    print(img.shape)

    # determine non_white part
    white = np.logical_and(np.logical_and(img[:,:,0] == 255, img[:,:,1] == 255), img[:,:,2] == 255)
    non_white = np.logical_not(white)

    # find connected components of non-white part
    neighbourhood = np.ones((3,3))
    labeled, nr_objects = ndimage.label(non_white, neighbourhood)

    # print result
    print("number of separate objects is {}".format(nr_objects))

    # start flood filling algorithm
    ind = np.nonzero(labeled)
    front = deque(zip(ind[0],ind[1]))

    membership = np.copy(labeled)
    is_merge_point = np.zeros_like(labeled) > 0
    parent = np.zeros((2,) + labeled.shape) #find ancestor of each pixel
    is_seed = labeled > 0
    size_i, size_j = labeled.shape
    # flood from every seed
    while front: #while we have unexplored pixels
        point = front.popleft()
        # check neighbours:
        for (di,dj) in [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]:
            current = membership[point[0], point[1]]
            new_i, new_j = point[0]+di, point[1]+dj
            if 0 <= new_i < size_i and 0 <= new_j < size_j:
                value = membership[new_i, new_j]
                if value == 0:
                    membership[new_i, new_j] = current
                    front.append((new_i, new_j))
                    parent[:, new_i, new_j] = point
                elif value != current: #MERGE!
                    is_merge_point[point[0], point[1]] = True
                    is_merge_point[new_i, new_j] = True
                    membership[np.logical_or(membership == value, membership == current)] = min(value, current)

    # trace back from every merger
    ind = np.nonzero(is_merge_point)
    merge_points = deque(zip(ind[0].astype(np.int),ind[1].astype(np.int)))
    for point in merge_points:
        next_p = point
        while not is_seed[next_p[0], next_p[1]]:
            is_merge_point[next_p[0], next_p[1]] = True
            next_p = parent[:, next_p[0], next_p[1]].astype(np.int)

    # add red points:
    img_backup = np.copy(img)
    img[:,:,0][is_merge_point] = 255 * img_backup[:,:,0]
    img[:,:,1][is_merge_point] = 0   * img_backup[:,:,1]
    img[:,:,2][is_merge_point] = 0   * img_backup[:,:,2]

    #compute number of new points
    n_red_points = (img[:,:,0] != img[:,:,1]).sum()
    print("#red points:", n_red_points)

    # plot: each component should have separate color
    imageio.imwrite("./out_images/"+fname, np.array(img))

স্কোর

(1+183)*(1+142)*(1+244)*(1+42)*(1+1382)*(1+2)*(1+104)*(1+7936)*(1+26)*(1+38562)*(1+42956)*(1+6939)*(1+8882)*(1+9916)
= 26208700066468930789809050445560539404000
= 2.62 * 10^40

- এটি, আমি বিশ্বাস করি, এটি সর্বোত্তম। ভাল হয়েছে ---- ঠিক আছে, এটি অনুকূল নয় । বুঝতে পারছি না কেন।
wizzwizz4

@ wizzwizz4 একটি বর্গক্ষেত্রের চারটি কোণার সহজ কেসটি দেখুন: সর্বোত্তম সমাধানটি এক্স হবে While যদিও তত্ত্বের ক্ষেত্রে আমার অ্যালগরিদম এই সমাধানটি খুঁজে পেতে পারে, এটি খুব কমই সম্ভব। এটি অনেক বেশি সম্ভবত যে এটি দুটি পয়েন্টের সাথে সংযোগকারী তিনটি পথের সাথে একটি সমাধান খুঁজে পেয়েছে।
flawr

@ wizzwizz4 হ্যাঁ, উইকিপিডিয়া পাঠ্যের উদাহরণটিতে জুম করুন এবং আপনি এমন অনেকগুলি ছোট্ট জায়গা দেখতে পাবেন যেখানে ভিন্ন সংযোগের পথটি একটি লাল পিক্সেল বা দুটি সংরক্ষণ করতে পারে; তারা যোগ হবে
ব্র্যাডিসি

কিন্তু এই খুটা উপর সাবান-বুদবুদ, যা করার জন্য একটি বৈধ সমাধান মত মনে হয় স্টেনার গাছ সমস্যা
wizzwizz4

1
@ wizzwizz4 পার্থক্যটি হ'ল অবশ্যই আমরা পয়েন্টগুলি সংযোগ করছি না , আমরা সংযুক্ত করছি পয়েন্টের সেটগুলি , সুতরাং আমাদের অবশ্যই সিদ্ধান্ত নিতে হবে না যে প্রতিটি সেটে কোন পয়েন্টগুলি সর্বোত্তম উপায়ে সংযুক্ত করা যায়। আবার টেক্সট উদাহরণ মধ্যে জুম, উন্নতি আপনি বেশিরভাগ দেখতে পারেন সঙ্গে কি আছে যা প্রতিটি আকৃতি অংশগুলি সংযুক্ত।
ব্র্যাডিসি 8:12 '

5

পাইথন 3: 1.7x10 ^ 42 1.5x10 ^ 41

ব্যবহার Pillow, numpyএবং scipy

চিত্রগুলি imagesস্ক্রিপ্টের মতো একই ডিরেক্টরিতে অবস্থিত একটি ফোল্ডারে রয়েছে বলে ধরে নেওয়া হয় ।

দাবি অস্বীকার : সমস্ত চিত্র প্রক্রিয়া করতে এটি অনেক সময় নেয়।

কোড

import sys
import os

from PIL import Image
import numpy as np
import scipy.ndimage


def obtain_groups(image, threshold, structuring_el):
    """
    Obtain isles of unconnected pixels via a threshold on the R channel
    """
    image_logical = (image[:, :, 1] < threshold).astype(np.int)
    return scipy.ndimage.measurements.label(image_logical, structure=structuring_el)


def swap_colors(image, original_color, new_color):
    """
    Swap all the pixels of a specific color by another color 
    """
    r1, g1, b1 = original_color  # RGB value to be replaced
    r2, g2, b2 = new_color  # New RGB value
    red, green, blue = image[:, :, 0], image[:, :, 1], image[:, :, 2]
    mask = (red == r1) & (green == g1) & (blue == b1)
    image[:, :, :3][mask] = [r2, g2, b2]
    return image


def main(image_path=None):
    images = os.listdir("images")
    f = open("results.txt", "w")

    if image_path is not None:
        images = [image_path]

    for image_name in images:
        im = Image.open("images/"+image_name).convert("RGBA")
        image = np.array(im)

        image = swap_colors(image, (255, 255, 255), (255, 0, 0))

        # create structuring element to determine unconnected groups of pixels in image
        s = scipy.ndimage.morphology.generate_binary_structure(2, 2)

        for i in np.ndindex(image.shape[:2]):
            # skip black pixels
            if sum(image[i[0], i[1]]) == 255:
                continue
            image[i[0], i[1]] = [255, 255, 255, 255]
            # label the different groups, considering diagonal connections as valid
            groups, num_groups = obtain_groups(image, 255, s)
            if num_groups != 1:
                image[i[0], i[1]] = [255, 0, 0, 255]
            # Show percentage
            print((i[1] + i[0]*im.size[0])/(im.size[0]*im.size[1]))

        # Number of red pixels
        red_p = 0
        for i in np.ndindex(image.shape[:2]):
            j = (im.size[1] - i[0] - 1, im.size[0] - i[1] - 1)
            # skip black and white pixels
            if sum(image[j[0], j[1]]) == 255 or sum(image[j[0], j[1]]) == 255*4:
                continue
            image[j[0], j[1]] = [255, 255, 255, 255]
            # label the different groups, considering diagonal connections as valid
            groups, num_groups = obtain_groups(image, 255, s)
            if num_groups != 1:
                image[j[0], j[1]] = [255, 0, 0, 255]
            # Show percentage
            print((j[1] + j[0]*im.size[0])/(im.size[0]*im.size[1]))
            red_p += (sum(image[j[0], j[1]]) == 255*2)

        print(red_p)
        f.write("r_"+image_name+": "+str(red_p)+"\n")

        im = Image.fromarray(image)
        im.show()
        im.save("r_"+image_name)
    f.close()


if __name__ == "__main__":
    if len(sys.argv) == 2:
        main(sys.argv[1])
    else:
        main()

ব্যাখ্যা

মামুলি সমাধান. আমরা একটি চিত্রের সমস্ত সাদা পিক্সেলের রঙ লাল করে শুরু করি। এটি করার মাধ্যমে, গ্যারান্টিযুক্ত যে সমস্ত উপাদান (কালো পিক্সেলের কোনও আইল) সংযুক্ত রয়েছে।

তারপরে, আমরা চিত্রের সমস্ত পিক্সেল ধরে উপরে বাম কোণ থেকে শুরু করে ডান এবং নীচে চলি rate প্রতিটি লাল পিক্সেলের জন্য আমরা দেখতে পাই যে আমরা এর রঙ সাদা করে রাখি। যদি রঙের এই পরিবর্তনের পরে এখনও কেবলমাত্র একটি উপাদান থাকে (একটি উপাদান এখন কালো এবং লাল পিক্সেলের কোনও দ্বীপ), আমরা পিক্সেলটিকে সাদা ছেড়ে পরবর্তী পিক্সেলের দিকে এগিয়ে যাই। তবে, যদি লাল থেকে সাদা রঙে বর্ণ পরিবর্তনের পরে উপাদানের সংখ্যা একের বেশি হয় তবে আমরা পিক্সেলটিকে লাল ছেড়ে পরবর্তী পিক্সেলটিতে চলে যাই।

হালনাগাদ

যেমন এটি দেখা যায় (এবং প্রত্যাশিত) কেবলমাত্র এই পদ্ধতিটি ব্যবহার করে প্রাপ্ত সংযোগগুলি একটি নিয়মিত প্যাটার্ন দেখায় এবং কিছু ক্ষেত্রে যেমন 6th ষ্ঠ এবং একাদশ চিত্রগুলিতে অপ্রয়োজনীয় লাল পিক্সেল রয়েছে।

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

ফলাফল

দ্বিতীয় পাসের পরে সংশোধিত চিত্রগুলি পার্থক্য দেখানোর জন্য দু'বার তালিকাভুক্ত করা হয়েছে।

18825

লাল পিক্সেলের সংখ্যা: 18825

334

লাল পিক্সেলের সংখ্যা: 334

1352

লাল পিক্সেলের সংখ্যা: 1352

20214

লাল পিক্সেলের সংখ্যা: 20214

এখানে চিত্র বর্ণনা লিখুন

লাল পিক্সেলের সংখ্যা: 47268

63 এখানে চিত্র বর্ণনা লিখুন

লাল পিক্সেলের সংখ্যা: 63 27

17889

লাল পিক্সেলের সংখ্যা: 17889

259

লাল পিক্সেলের সংখ্যা: 259

6746

লাল পিক্সেলের সংখ্যা: 6746

586

লাল পিক্সেলের সংখ্যা: 586

9 এখানে চিত্র বর্ণনা লিখুন

লাল পিক্সেলের সংখ্যা: 9 1

126

লাল পিক্সেলের সংখ্যা: 126

212

লাল পিক্সেলের সংখ্যা: 212

683

লাল পিক্সেলের সংখ্যা: 683

স্কোর গণনা:

(1 + 6746) * (1 + 126) * (1 + 259) * (1 + 17889) * (1 + 334) * (1 + 586) * (1 + 18825) * (1 + 9) * (1 +683) * (1 + 1352) * (1 + 20214) * (1 + 212) * (1 + 63) * (1 + 47268) = 1778700054505858720992088713763655500800000 ~ 1.7x10 ^ 42

দ্বিতীয় পাস যোগ করার পরে স্কোর গণনা আপডেট করা:

(1+ 18825) * (1+ 1352) * (1+ 20214) * (1+ 47268) * (1+ 27) * (1+ 17889) * (1+ 6746) * (1+ 586) * (1 + 1) * (1+ 126) * (1+ 212) * (1+ 334) * (1 + 259) * (1 + 683) = 155636254769262638086807762454319856320000 ~ 1.5x10 ^ 41


চমৎকার কাজ. দেখে মনে হচ্ছে বৈজ্ঞানিক স্বরলিপিতে আমাদের এটির একটি স্কোর করার প্রয়োজন হতে পারে: 1.7x10 ^ 42
ব্র্যাডিসি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.