Удалить свободный прямоугольник


20

Это изображение было сделано путем наложения 7 разноцветных прямоугольников друг на друга:

основное изображение

Черный и бордовый прямоугольники свободны , то есть над ними нет никаких других прямоугольников.

Напишите программу, которая принимает изображение, подобное этому, и удаляет любой свободный прямоугольник, выводя полученное изображение.

пример

Если вы запустили свою программу на изображении выше и продолжали повторно запускать ее на выходе, она может развиваться следующим образом.

Прогон 1 - черные удалены (мог быть бордовым):

запустить 1

Прогон 2 - Maroon удален (только выбор):

запустить 2

Прогон 3 - Желтый удален (только выбор):

запустить 3

Прогон 4 - Синий удален (мог быть зеленым):

запустить 4

Прогон 5 - Зеленый удален (только выбор):

запустить 5

Прогон 6 - Браун удален (только выбор):

пробег 6

Прогон 7 - красный удален (только выбор):

запустить 7

Любые дополнительные прогоны должны давать одинаковое белое изображение.

Надеемся, что Stack Exchange не сжал без потерь ни одно из этих изображений.

Изображение всегда будет иметь белый фон, и каждый прямоугольник будет иметь уникальный цвет RGB, который не является белым.

Вы можете предположить, что изображение всегда можно интерпретировать как набор перекрывающихся прямоугольников. В частности, вы можете предположить, что для определенного цвета пиксель с этим цветом, ближайшим к верхней части изображения, является частью верхнего края прямоугольника этого цвета. То же самое относится к нижнему, левому и правому краям.

Так, например, на этом изображении верхний край красного прямоугольника будет чуть ниже нижнего края желтого прямоугольника, так как оранжевый прямоугольник покрывает старый красный верхний край:

пример 1

На этом изображении красный прямоугольник может быть удален первым (наряду с черным / бордовым / оранжевым / серым):

пример 2

Когда порядок нижних прямоугольников неоднозначен, вы можете дать им любой порядок.

Например, левое изображение здесь может стать средним или правым:

пример 3 пример 4 пример 5

Вывод не должен иметь парадоксальных совпадений (поэтому возможно сделать это с помощью алгоритма художника ). Так что на этом изображении ( спасибо user23013 ), он должен быть зеленым под оранжевым прямоугольником:

пример 6

дополнительные детали

  • Изображение и прямоугольники могут иметь любые размеры.
  • Прямоугольники могут касаться границы изображения.
  • Может быть до 256 3 - 1 прямоугольника.
  • Если вход полностью белый, то выход должен быть также.
  • Вы можете использовать библиотеки изображений.
  • Входными данными должны быть имя файла изображения или необработанные данные изображения. Это может быть из стандартного ввода или командной строки.
  • Вывод может быть записан в тот же или другой файл изображения, выгружен сырым в стандартный вывод или просто отображен.
  • Разрешен любой распространенный формат изображения без потерь цвета .

Представление с наименьшим количеством байтов выигрывает.



Технически в требованиях нет ничего, что говорит о том, что выходные данные могут не иметь парадоксальных совпадений. Должен ли он быть добавлен, или обе интерпретации тестового примера в порядке?
Джон Дворжак

Можете ли вы уточнить «truecolor»?
FUZxxl


@JanDvorak У меня была надежда, что это подразумевалось, но, вы правы, это неясно, поэтому я добавил примечание об этом.
Увлечения Кэлвина

Ответы:


10

CJam, 241 байт

(с удаленными символами новой строки.)

rri:Hri:Vri:Q[q~]3/_Qa3*a+_|$W%:Pf{\a#}:AH/:B0ff*
P,,[AHAW%HBz:+_W%V\V]2/
ff{~@@f=/::|1#}0Ua4*t:R;
P0f<
V{H{BI=J=_2$=
0R{"I>! I+V<J>! J+H<"4/+4/z{~~}%:&1$*\)}%);2$-|t
}fJ}fI
[P,{_La#\1$0t1$f-}*;;]
{:TR=2/~\~V\-,>\f{\_3$=@~H\-,>{Tt}/t}~}/
:~Pf=:~
~]S*N

Он использует формат файла ppm. Пример использования (с использованием ImageMagick):

convert IVYvE.png -compress none ppm:-| (time /path/to/cjam-0.6.4.jar 1.cjam) |display

Ну, это слишком долго и слишком медленно ... Примерно за минуту.

Я изменил размеры тестовых случаев (и добавил некоторые другие), чтобы упростить тестирование.

Кажется, информация о цветовом пространстве теряется, поэтому цвета немного отличаются.


2

Python, 690 651 610 606 594 569 байт

Скрипт читает имя изображения из стандартного ввода.

Он обнаруживает края каждого прямоугольника, сортирует их по количеству различных цветов, которые они содержат (свободные прямоугольники содержат только 1 цвет, а затем появляются в конце списка)

Этот список используется для перерисовки изображения. Порядок перерисовки определяется путем выбора перестановки списка, которая будет генерировать выходное изображение, которое имеет наименьшую разницу в пикселях по сравнению с входными данными.

из PIL импортировать Image как l, ImageDraw как D; из itertools import *; O, R, I, Z, k = [], range, l.open (raw_input ()), {}, lambda x: -x [1 ]; (W, H), Q = I.size, I.load ()
для i, j в произведении (R (W), R (H)):
 с = Q [I, J]
 если c в Z: x, y, X, Y = Z [c]; Z [c] = [x, y, max (X, i), max (Y, j)]
 остальное: Z [с] = [I, J 0,0]
для n в перестановках (отсортировано ([(c, len ({Q [g] для g в произведении (R (x, X), R (y, Y))))))) для c, (x, y, X, Y) в Z.items ()], key = k) [1: -1]): o = l.new (I.mode, I.size, 0xFFFFFF); [D.Draw (o) .rectangle (Z) [c], заполните = c) для c, _ в n]; O + = [(o, сумма (abs (ab) для t, T в zip (I.getdata (), o.getdata ()) для a, б в почтовый индекс (т, т)))]
макс (О, ключ = к) [0] .show ()

0

Java - 1483 байта

Я не большой гольфист кода, пусть это будет ясно; так что многословие не является полностью ошибкой Java ;-) Тем не менее, это казалось действительно забавным испытанием. Я решил это таким образом, что - я думаю - немного скучно и многословно, но эй. Это работает, это (относительно) быстро и, особенно, было весело!

Идея заключается в следующем: проверьте каждый пиксель, начиная с верхнего левого угла до самого нижнего правого. Это белый пиксель? Отбой. Это цветной? Круто, давайте отследим это и попробуем определить его границы (вверху слева, вверху справа, внизу слева, внизу справа).

Как только это будет сделано, проверьте область каждого прямоугольника. Содержит ли он цвет, отличный от цвета прямоугольника? Затем выясните, какой прямоугольник принадлежит этому цвету, и обновите z-индекс этого перекрывающегося прямоугольника на 1.

И, наконец, нарисуйте все прямоугольники, принимая во внимание z-индексы. На самом деле он работает как z-index, который вы знаете по CSS и другим 3D вещам. Прямоугольники с самым низким z-индексом рисуются первыми, а самый высокий z-индекс - последним.

import java.awt.*;import java.awt.image.*;import java.io.File;import java.util.*;import java.util.List;import javax.imageio.*;class A{class R{public Color k=new Color(-1);public int z;public Point a;public Point b;public Point c;public Point d;}public static void main(String[]w)throws Exception{BufferedImage i=ImageIO.read(new File(w[0]));List<R>r=new Vector<R>();for(int y=0;y<i.getHeight();y++){for(int x=0;x<i.getWidth();x++){Color c=new Color(i.getRGB(x,y));if(c.getRGB()==-1){continue;}R t=null;for(R s:r){if(s.k.equals(c)){t=s;}}if(t==null){t=new A().new R();r.add(t);}if(t.a==null){t.a=new Point(x, y);t.b=new Point(x, y);t.c=new Point(x, y);t.d=new Point(x, y);t.k=new Color(c.getRGB());}if(x<t.a.x){t.a.x=x;t.c.x=x;}if(x>t.b.x){t.b.x=x;t.d.x=x;}t.c.y=y;t.d.y=y;}}for(R s:r){List<Color>b=new Vector<Color>();for(int y=s.a.y;y<=s.c.y;y++){for(int x = s.a.x;x<=s.b.x;x++){if(i.getRGB(x, y)!=s.k.getRGB()){Color a=new Color(i.getRGB(x,y));boolean q=false;for(Color l:b){if(l.equals(a)){q=true;}}if(!q){b.add(a);} else {continue;}R f=null;for(R k:r){if(k.k.equals(a)){f=k;}}f.z=s.z+1;}}}}Collections.sort(r,new Comparator<R>(){public int compare(R a, R b){return a.z>b.z?1:(a.z==b.z?0:-1);}});for(int ii=r.size();ii>0;ii--){BufferedImage d=new BufferedImage(i.getWidth(),i.getHeight(),2);Graphics2D g=(Graphics2D)d.getGraphics();for(R s : r.subList(0, ii)){g.setColor(s.k);g.fillRect(s.a.x,s.a.y,s.b.x-s.a.x,s.c.y-s.a.y);}ImageIO.write(d,"png",new File(r.size()-ii+".png"));}}}

Полный код, который немного - и это преуменьшение ;-) - написан более четко, можно найти здесь: http://pastebin.com/UjxUUXRp

Кроме того, теперь, когда я вижу подчинение Дитера, я мог бы упростить некоторые детали. Нет необходимости искать прямоугольник, цвет которого перекрывает другой прямоугольник. Я мог бы просто посчитать количество «вторгающихся» цветов.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.