जाओ और इसे भूखा बनाओ


14

इस प्रतियोगिता में आपको एक प्रोग्राम लिखना होता है, जो एक ब्लैक एंड व्हाइट पिक्सेल इमेज को स्वीकार करता है, और इसे बदलने की कोशिश करता है, जैसे कि व्हाइट शेप में स्टार डोमेन बनता है , जहाँ तक संभव हो कुछ बदलाव होते हैं।

अनुमत परिवर्तन सफेद पिक्सेल को काले रंग में बदल रहे हैं और काले पिक्सेल को सफेद में बदल रहे हैं।

आउटपुट में फिर से समान छवि होनी चाहिए, लेकिन इस बार सभी परिवर्तनों के साथ और / केंद्र चिह्नित के साथ। जिन पिक्सलों को सफेद से काले में बदला गया था, उन्हें नीले रंग में प्रदर्शित किया जाना चाहिए, जिन्हें काले से सफेद में बदल दिया गया था, उन्हें पीले रंग में प्रदर्शित किया जाना चाहिए, और कम से कम एक केंद्र पिक्सेल को लाल रंग में प्रदर्शित किया जाना चाहिए। (सटीक रंग आपके ऊपर हैं।) कार्यक्रम में निर्दिष्ट छवि और साथ ही किए गए परिवर्तनों की कुल संख्या को अलग करना चाहिए।

परिभाषाएं

स्टार डोमेन

छवि के सफेद पिक्सेल का सेट एक स्टार डोमेन का प्रतिनिधित्व करता है यदि (और केवल अगर) तो एक केंद्र पिक्सेल है (कम से कम) । केंद्र पिक्सेल सफेद पिक्सल है कि एक से conneced किया जा सकता है में से एक है सीधी रेखा अन्य सफेद पिक्सल के सभी ऐसी है कि लाइन केवल सफेद पिक्सल को पार करता। ( केंद्र पिक्सेल इसलिए जरूरी नहीं है कि अनूठा हो।)

दो पिक्सेल के बीच सीधी रेखा

दो पिक्सेल (शुरू और अंत, नीचे दिए गए चित्रण में दोनों लाल) को देखते हुए, दो पिक्सेल के बीच की खिंचाव रेखा में सभी पिक्सेल शामिल होते हैं, जो पहले के केंद्र से निकलने वाली रेखा के नीचे (गणितीय, पीले रंग में चित्रण) को स्पर्श करते हैं अंतिम पिक्सेल के केंद्र में पिक्सेल। एक पिक्सेल लाइन को नहीं छू रहा है यदि यह केवल एक कोने से छूता है, तो पिक्सेल के लिए पिक्सेल लाइन (गणितीय, पीला) लाइन से संबंधित है और एक गैर-लंबाई के साथ प्रश्न में पिक्सेल को पार करना होगा। (यदि यह केवल कोने बिंदु को छूता है तो इसे लंबाई शून्य माना जाता है)। निम्नलिखित उदाहरणों पर विचार करें:

पिक्सल

उदाहरण

पहली छवि को एक उदाहरण टेस्टकेस 'इनपुट' का प्रतिनिधित्व करना चाहिए और दो अन्य चित्र दिए गए उदाहरण के लिए दो मान्य संभावित आउटपुट का प्रतिनिधित्व करते हैं:

उदाहरण परीक्षण पहला उदाहरण समाधान दूसरा उदाहरण समाधान

पीले क्षेत्र (पूर्व में काले) की गणना 'सफेद' डोमेन के रूप में अच्छी तरह से होती है, जबकि नीले क्षेत्र (पूर्व में सफेद) की गणना डोमेन के बाहर 'ब्लैक' भाग में होती है, और हर बार लाल डॉट एक संभव केंद्र पिक्सेल का प्रतिनिधित्व करता है।

परीक्षण के मामलों

Follwoing परीक्षण के मामले 256 x 256 पिक्सेल के प्रत्येक आकार के साथ png हैं।

परीक्षण मामला 1 परीक्षण का मामला २ परीक्षण मामला 3 परीक्षण मामला ४ टेस्ट केस 5 परीक्षण का मामला ६

स्कोरिंग

कृपया निम्नलिखित परीक्षण मामलों के साथ अपना कार्यक्रम चलाएं और अपने उत्तर में आउटपुट (छवि / परिवर्तनों की संख्या) को शामिल करें। मैं प्रत्येक परीक्षण मामले के लिए एक लीडरबोर्ड बनाऊंगा। आपका स्कोर लीडरबोर्ड में प्रत्येक रैंकिंग का योग होगा-स्कोर कम बेहतर होगा। मानक खामियां लागू होती हैं। यह कार्यक्रम को उन परीक्षण मामलों को पहचानने और उनके लिए एक विशेष मामला चलाने की अनुमति नहीं है। (यह उन सभी मामलों में से प्रत्येक के लिए इष्टतम केंद्र पिक्सेल को प्री-पंप और सहेजने की अनुमति नहीं है।) कार्यक्रम को किसी भी चित्र के लिए काम करना चाहिए।

लीडरबोर्ड

Name        | Score | 1     - rk | 2     - rk | 3     - rk | 4     - rk | 5     - rk | 5     - rk | Total Changes
------------+-------+------------+------------+------------+------------+------------+------------+--------------
Maltysen    |    11 | 28688 -  2 | 24208 -  2 | 24248 -  1 |  7103 -  2 | 11097 -  2 | 13019 -  2 | 108363
TheBestOne  |     7 | 0     -  1 | 13698 -  1 | 24269 -  2 |   103 -  1 |  5344 -  1 |  4456 -  1 |  47867  

2
यदि आप अंजीर की व्याख्या करना चाहते हैं तो यह मदद करेगा। आप उदाहरण के लिए, लाल पिक्स को क्यों जोड़ रहे हैं?
डेविड जेएन

4
मुझे वास्तव में यकीन नहीं है कि आपका क्या मतलब है। क्या आप अपने एक परीक्षण के पहले और बाद में दे सकते हैं?

पास होने के लिए एक लाइन को पिक्सेल के कोने के कितने करीब होना चाहिए?
TheNumberOne

मैंने कुछ उदाहरण जोड़े और पाठ को स्पष्ट करने की कोशिश की, मुझे उम्मीद है कि यह अब स्पष्ट है!
23

क्या कोई अन्य व्यक्ति इस चुनौती का प्रयास करने का इरादा रखता है? मैं कुछ उलझन में हूं, क्योंकि काफी लोगों ने इस चुनौती को बरकरार रखा है लेकिन हमें अब तक केवल एक (बहुत गंभीर नहीं) जवाब मिला है। कोई आलोचना?
22

जवाबों:


4

जावा 8, 47,867 कुल परिवर्तन।

केंद्र बिंदु के रूप में छवि के औसत का उपयोग करता है। यह केंद्र में सभी संभावित किरणों को खींचता है और इसे रंग के लिए सबसे अच्छा त्रिज्या देता है। यह तब सभी अमान्य बिंदुओं को रंग देता है।

import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class MakeItStarry {

    private static final int RGB_RED = Color.RED.getRGB();
    static int[][] originalImage;

    static final int WHITE = 0;
    static final int BLACK = 1;
    static final int RGB_WHITE = Color.WHITE.getRGB();
    static final int RGB_BLACK = Color.BLACK.getRGB();
    static final int RGB_BLUE = Color.BLUE.getRGB();
    static final int RGB_YELLOW = Color.YELLOW.getRGB();

    public static void main(String[] args) throws Exception{
        originalImage = convert(ImageIO.read(new File(args[0])));
        Point center = findCenter(originalImage);
        int[][] nextImage = starry(originalImage, center);
        BufferedImage result = difference(originalImage, nextImage);
        result.setRGB(center.x, center.y, RGB_RED);
        String fileType;
        String fileName;
        if (args[1].split("\\.").length > 1){
            fileType = args[1].split("\\.")[1];
            fileName = args[1];
        } else {
            fileType = "PNG";
            fileName = args[1] + ".PNG";
        }
        ImageIO.write(result, fileType, new File(fileName));
        System.out.println(cost);
    }

    static int cost;

    private static BufferedImage difference(int[][] image1, int[][] image2) {
        cost = 0;
        int height = image1[0].length;
        int width = image1.length;
        BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++){
            for (int y = 0; y < width; y++){
                if (image1[x][y] == image2[x][y]){
                    if (image1[x][y] == WHITE){
                        result.setRGB(x, y, RGB_WHITE);
                    } else {
                        result.setRGB(x, y, RGB_BLACK);
                    }
                } else {
                    cost++;
                    if (image1[x][y] == WHITE){
                        result.setRGB(x, y, RGB_BLUE);
                    } else {
                        result.setRGB(x, y, RGB_YELLOW);
                    }
                }
            }
        }
        return result;
    }

    private static int[][] starry(int[][] image, Point center) {
        int width = image.length;
        int height = image[0].length;
        int[][] result = new int[width][height];
        for (int x = 0; x < width; x++){
            for (int y = 0; y < height; y++){
                result[x][y] = BLACK;
            }
        }
        for (int x = 0; x < width; x++){
            for (int y = 0; y < height; y++) {
                Point endPoint = new Point(x, y, image);
                List<Point> line = Point.lineTo(center, endPoint, image);
                List<Point> newLine = starRay(line);
                newLine.stream().filter(point -> result[point.x][point.y] == BLACK).forEach(point -> {
                    result[point.x][point.y] = point.color;
                });
            }
        }
        int distance = 0;
        while (distance < height || distance < width){//This removes pixels that can't see the center.
            for (int x = Math.max(center.x - distance,0); x < center.x + distance && x < width; x++){
                for (int y = Math.max(center.y - distance, 0); y < center.y + distance && y < height; y++){
                    Point point = new Point(x, y, result);
                    if (Point.distance(center, point) != distance){
                        continue;
                    }
                    if (point.color == WHITE){
                        List<Point> line = Point.lineTo(center, point, result);
                        for (Point p : line){
                            if (p.color == BLACK){
                                point.color = BLACK;
                                break;
                            }
                        }
                        result[point.x][point.y] = point.color;
                    }
                }
            }//All white pixels can technically see the center but only if looking from the edge.
            distance++;
        }
        return result;
    }

    private static List<Point> starRay(List<Point> line) {
        int numOfWhites = 0;
        int farthestGoodPoint = 0;
        int blackCost = 0;
        int whiteCost = 0;
        for (int i = 0; i < line.size(); i++){
            if (line.get(i).color == WHITE){
                numOfWhites++;
                whiteCost++;
                if (numOfWhites + whiteCost > blackCost){
                    blackCost = 0;
                    whiteCost = 0;
                    farthestGoodPoint = i;
                }
            } else {
                blackCost++;
                numOfWhites = 0;
            }
        }
        List<Point> result = new ArrayList<>();
        for (int i = 0; i < line.size(); i++){
            Point p = line.get(i);
            if (i <= farthestGoodPoint){
                result.add(new Point(p.x, p.y, WHITE));
            } else {
                result.add(new Point(p.x, p.y, BLACK));
            }
        }
        return result;
    }

    private static Point findCenter(int[][] image) {
        double totalx = 0;
        double totaly = 0;
        int counter = 0;
        int width = image.length;
        int height = image[0].length;
        for (int x = 0; x < width; x++){
            for (int y = 0; y < height; y++){
                if (image[x][y] == WHITE){
                    totalx += x;
                    totaly += y;
                    counter++;
                }
            }
        }
        return new Point((int)(totalx/counter), (int)(totaly/counter), image);
    }

    private static int[][] convert(BufferedImage image) {
        int width = image.getWidth();
        int height  = image.getHeight();
        int[][] result = new int[width][height];
        for (int x = 0; x < width; x++){
            for (int y = 0; y < height; y++){
                if (image.getRGB(x, y) == RGB_WHITE){
                    result[x][y] = WHITE;
                } else {
                    result[x][y] = BLACK;
                }
            }
        }
        return result;
    }


    private static class Point {

        public int color;
        public int y;
        public int x;

        public Point(int x, int y, int[][] image) {
            this.x = x;
            this.y = y;
            this.color = image[x][y];
        }

        public Point(int x, int y, int color) {
            this.x = x;
            this.y = y;
            this.color = color;
        }

        public static List<Point> lineTo(Point point1, Point point2, int[][] image) {
            List<Point> result = new ArrayList<>();
            boolean reversed = false;
            if (point1.x > point2.x){
                Point buffer = point1;
                point1 = point2;
                point2 = buffer;
                reversed = !reversed;
            }
            int rise = point1.y - point2.y;
            int run = point1.x - point2.x;
            if (run == 0){
                if (point1.y > point2.y){
                    Point buffer = point1;
                    point1 = point2;
                    point2 = buffer;
                    reversed = !reversed;
                }
                int x = point1.x;
                for (int y = point1.y; y <= point2.y; y++){
                    result.add(new Point(x, y, image));
                }
                if (reversed){
                    return reversed(result);
                }
                return result;
            }
            if (rise == 0){
                if (point1.x > point2.x){
                    Point buffer = point1;
                    point1 = point2;
                    point2 = buffer;
                    reversed = !reversed;
                }
                int y = point1.y;
                for (int x = point1.x; x <= point2.x; x++){
                    result.add(new Point(x, y, image));
                }
                if (reversed){
                    return reversed(result);
                }
                return result;
            }
            int gcd = gcd(rise, run);
            rise /= gcd;
            run /= gcd;
            double slope = (rise + 0.0) / run;
            if (Math.abs(rise) >= Math.abs(run)){
                if (point1.y > point2.y){
                    Point buffer = point1;
                    point1 = point2;
                    point2 = buffer;
                    reversed = !reversed;
                }
                double x = point1.x;
                for (double y = point1.y + .5; y <= point2.y; y++){
                    int px = (int) Math.round(x);
                    if (Math.abs(Math.abs(px - x) - .5) < Math.abs(1.0 / (rise * 4))){
                        x += 1/slope;
                        continue;
                    }
                    result.add(new Point(px, (int) Math.round(y - .5), image));
                    result.add(new Point(px, (int) Math.round(y + .5), image));
                    x += 1/slope;
                }
                if (reversed){
                    return reversed(result);
                }
                return result;
            } else {
                if (point1.x > point2.x){
                    Point buffer = point1;
                    point1 = point2;
                    point2 = buffer;
                    reversed = !reversed;
                }
                double y = point1.y;
                for (double x = point1.x + .5; x <= point2.x; x++){
                    int py = (int) Math.round(y);
                    if (Math.abs(Math.abs(py - y) - .5) < Math.abs(1.0 / (run * 4))) {
                        y += slope;
                        continue;
                    }
                    result.add(new Point((int) Math.round(x - .5), py, image));
                    result.add(new Point((int) Math.round(x + .5), py, image));
                    y += slope;
                }
                if (reversed){
                    return reversed(result);
                }
                return result;
            }
        }

        private static List<Point> reversed(List<Point> points) {
            List<Point> result = new ArrayList<>();
            for (int i = points.size() - 1; i >= 0; i--){
                result.add(points.get(i));
            }
            return result;
        }

        private static int gcd(int num1, int num2) {
            if (num1 < 0 && num2 < 0){
                return -gcd(-num1, -num2);
            }
            if (num1 < 0){
                return gcd(-num1, num2);
            }
            if (num2 < 0){
                return gcd(num1, -num2);
            }
            if (num2 > num1){
                return gcd(num2, num1);
            }
            if (num2 == 0){
                return num1;
            }
            return gcd(num2, num1 % num2);
        }

        @Override
        public String toString(){
            return x + " " + y;
        }

        public static int distance(Point point1, Point point2) {
            return Math.abs(point1.x - point2.x) + Math.abs(point1.y - point2.y);
        }
    }
}

परिणाम

छवि 1 - 0 परिवर्तन, छवि 2 - 13,698 परिवर्तन

12

छवि 3 - 24,269 परिवर्तन, छवि 4 - 103 परिवर्तन

34

छवि 5 - 5,344 परिवर्तन, छवि 6 - 4,456 परिवर्तन

56

अमान्य पिक्सेल हटाए बिना, कुल 42,782 परिवर्तन

ग्रीन पिक्सल अमान्य पिक्सल की पहली परत है।

छवि 1 - 0 परिवर्तन, छवि 2- 9,889 परिवर्तन

12

छवि 3 - 24,268 परिवर्तन, छवि 4 - 103 परिवर्तन

34

छवि 5 - 4,471 परिवर्तन, छवि 6- 4,050 परिवर्तन

56

सभी चित्रों में सभी सफेद पिक्सेल केंद्र पिक्सेल से उनके लिए खींची गई एक पंक्ति हो सकती है यदि रेखा को केंद्रों पर उत्पन्न / समाप्त नहीं करना है, बल्कि पिक्सेल पर कहीं भी है।

args[0] इनपुट फ़ाइल नाम है।

args[1] जिसमें आउटपुट फ़ाइल नाम है।

stdoutपरिवर्तन की संख्या के लिए प्रिंट ।


अच्छा लग रहा है! क्या आप बता सकते हैं कि 'अमान्य पिक्सेल' से आपका क्या मतलब है? मुझे यह समझ में नहीं आया। नीचे दाईं ओर की छवि 2 में भी मैं इस बात का पालन नहीं कर सका कि आपका कार्यक्रम काली दीवार में क्यों खोदता है, लेकिन फिर भी सफेद डॉट्स को फिर से काले रंग में रंग देता है, लेकिन मुझे लगता है कि यह 'इनवैलिड पिक्सल' के साथ करना है?
दोष

कुछ अमान्य पिक्सेल एक कैस्केड प्रभाव का कारण बनते हैं जो कई और अधिक अमान्य बनाते हैं। मैं अमान्य पिक्सेल की पहली परत को हरा दिखाने के लिए पिछली कुछ छवियों को संशोधित करूंगा।
TheNumberOne

3

अजगर - पीआईएल - 216,228 108,363 कुल परिवर्तन

वू! इसे @AJMansfield को आधे धन्यवाद में काटें! यह एल्गोरिथ्म लाइनों और अनुकूलन की गणना और क्या नहीं के साथ सभी चिंता को छोड़ देता है। यह सिर्फ एक को छोड़कर सभी गोरों को काले रंग में बदल देता है। यदि कोई गोरे नहीं हैं, तो यह एक काले को सफेद बनाता है। यह जाँचता है कि क्या अधिक गोरे या काले हैं और हर एक को छोड़कर हर एक को बदल देता है। यदि कोई काला नहीं है तो यह केंद्र (0, 0) बनाता है।

import Image
from itertools import product

img = Image.open(raw_input())
img = img.convert("RGB")

pixdata = img.load()
changed=0

m=False
count=0
for x, y in product(xrange(img.size[1]), xrange(img.size[0])):
    if pixdata[x, y]==(0, 0, 0):
        count+=1

colors=[(0, 0, 0), (255, 255, 0)] if img.size[0]*img.size[1]-count>count else [(255, 255, 255), (0, 0, 255)]
m=False
for x, y in product(xrange(img.size[1]), xrange(img.size[0])):
    if pixdata[x, y] == colors[0]:
        if m:
            pixdata[x, y] = colors[1]
        else:
            pixdata[x, y] = (255, 0, 0)
            m=True
        changed+=1

if not m:
    pixdata[0, 0]==(255, 0, 0)
    changed+=1
if colors[0]==(255, 255, 255):
    changed-=1

print changed
img.save("out.png", "PNG")

परिणाम

छवि 1 - 28688 परिवर्तन, छवि 2 - 24208 परिवर्तन

छवि 3 - 24248 परिवर्तन, छवि 4 - 7103 परिवर्तन

छवि 5 - 11097 परिवर्तन, छवि 6 - 13019 परिवर्तन

Raw_input से फ़ाइल नाम लेता है और out.png और परिवर्तनों की संख्या प्रिंट करता है।


ध्यान दें कि आपके आउटपुट में काले से सफेद में परिवर्तित होने वाले पिक्सेल पीले होने चाहिए। थोस जिन्हें सफेद से काले में बदल दिया गया था, उन्हें नीला होना चाहिए, और केंद्र (आपके मामले में आपका एकमात्र 'सफेद' पिक्सेल आपके आउटपुट में होना चाहिए। इसके अलावा, भाग लेने के लिए धन्यवाद =) पुनश्च: यह हमेशा संभव होना चाहिए स्टार डोमेन बनाते हैं, यहां तक ​​कि जब आपके पास इनपुट के रूप में एक पूर्ण काली छवि होती है, तो आप एक पिक्सेल को सफेद (लाल) में बदल सकते हैं।
दोष

यह असंभव हो सकता है अगर कोई सफेद या काला पिक्सेल (पूर्ण रंग) नहीं है। किसी भी मामले में मैं अन्य बदलाव कर रहा हूं।
माल्टसेन

ओह। ब्लैक एंड व्हाइट छवि। मेरी गलती।
माल्टसेन

मुझे लगता है कि यह विपरीत रणनीति को करने के लिए अधिक कुशल हो सकता है, और सभी काले पिक्सेल को सफेद रंग में बदल सकते हैं। क्या आपने कोशिश की?
AJMansfield

@AJMansfield मुझे लगता है कि यह केवल दिए गए परीक्षण के मामले के लिए अधिक कुशल होगा, इसलिए शायद इसे पहले से ही दिए गए टेस्टकेस के लिए एल्गोरिदम के रूप में माना जा सकता है।
दोष
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.