Rimuovi un rettangolo libero


20

Questa immagine è stata realizzata sovrapponendo 7 rettangoli di colori diversi uno sopra l'altro:

immagine principale

I rettangoli neri e marroni non sono ostruiti , ovvero nessun altro rettangolo è sopra di essi.

Scrivi un programma che contiene un'immagine come questa e rimuovi qualsiasi singolo rettangolo libero, producendo l'immagine risultante.

Esempio

Se hai eseguito il tuo programma sull'immagine sopra e hai continuato a eseguirlo nuovamente sull'output, potrebbe progredire in questo modo.

Esegui 1 - Nero rimosso (avrebbe potuto essere marrone):

eseguire 1

Run 2 - Maroon rimosso (unica scelta):

corri 2

Esegui 3 - Giallo rimosso (unica scelta):

corri 3

Esegui 4 - Blu rimosso (avrebbe potuto essere verde):

corri 4

Esegui 5 - Verde rimosso (unica scelta):

corri 5

Esegui 6 - Brown rimosso (unica scelta):

eseguire 6

Esegui 7 - Rosso rimosso (unica scelta):

corsa 7

Qualsiasi corsa aggiuntiva dovrebbe produrre la stessa immagine bianca.

Si spera che Stack Exchange non abbia compresso in modo perduto nessuna di queste immagini.

L'immagine avrà sempre uno sfondo bianco e ogni rettangolo avrà un colore RGB unico che non è bianco.

Si può presumere che l'immagine possa sempre essere interpretata come un insieme di rettangoli sovrapposti. In particolare, puoi supporre che, per un particolare colore, il pixel con quel colore più vicino alla parte superiore dell'immagine sia parte del bordo superiore del rettangolo di quel colore. Lo stesso vale per i bordi inferiore, sinistro e destro.

Quindi, ad esempio, in questa immagine, il bordo superiore del rettangolo rosso sarebbe appena sotto il bordo inferiore del rettangolo giallo, poiché il rettangolo arancione copriva il vecchio bordo superiore rosso:

Esempio 1

In questa immagine, il rettangolo rosso potrebbe essere rimosso per primo (insieme a nero / marrone / arancione / grigio):

esempio 2

Quando l'ordine dei rettangoli inferiori è ambiguo, puoi dare loro qualsiasi ordine.

Ad esempio, l'immagine a sinistra qui potrebbe diventare la metà o la destra:

esempio 3 esempio 4 esempio 5

L'output non dovrebbe avere sovrapposizioni paradossali (quindi dovrebbe essere possibile farlo con l' algoritmo del pittore ). Quindi in questa immagine ( grazie user23013 ), dovrebbe essere verde sotto il rettangolo arancione:

esempio 6

dettagli aggiuntivi

  • L'immagine e i rettangoli possono avere qualsiasi dimensione.
  • I rettangoli possono toccare il bordo dell'immagine.
  • Possono esserci fino a 256 3 - 1 rettangoli.
  • Se l'input è completamente bianco, anche l'output dovrebbe essere.
  • È possibile utilizzare librerie di immagini.
  • L'input deve essere il nome del file di immagine o i dati di immagine grezzi. Può provenire da stdin o dalla riga di comando.
  • L'output può essere scritto nello stesso o in un altro file di immagine, inviato in raw allo stdout o semplicemente visualizzato.
  • È consentito qualsiasi formato di file immagine truecolor senza perdita comune .

Vince l'invio con il minor numero di byte.



Tecnicamente non c'è nulla nei requisiti che dice che l'output potrebbe non avere sovrapposizioni paradossali. Dovrebbe essere aggiunto o entrambe le interpretazioni del test case sono OK?
John Dvorak,

Potete per favore chiarire "TrueColor"?
FUZxxl


@JanDvorak Avevo la speranza che fosse implicito ma, hai ragione, non è chiaro, quindi ho aggiunto una nota a riguardo.
Calvin's Hobbies,

Risposte:


10

CJam, 241 byte

(con le nuove righe rimosse.)

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

Utilizza il formato di file ppm. Esempio di utilizzo (utilizzando ImageMagick):

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

Bene, è troppo lungo e troppo lento ... Funziona circa un minuto per l'esempio.

Ho ridimensionato i casi di test (e ne ho aggiunti altri) per semplificare i test.

Sembra che le informazioni sullo spazio colore siano perse, quindi i colori sono leggermente diversi.


2

Python, 690 651 610 606 594 569 byte

Lo script legge il nome dell'immagine da stdin.

Rileva i bordi di ogni rettangolo, li ordina in base al numero di colori diversi che contengono (i rettangoli non ostruiti contengono solo 1 colore, quindi appaiono alla fine dell'elenco)

Questo elenco viene utilizzato per ridisegnare un'immagine. L'ordine di ridisegno viene deciso scegliendo la permutazione dell'elenco che genererebbe un'immagine di output con la minima differenza di pixel con l'input.

da PIL import Immagine come l, ImageDraw come D; da itertools import *; O, R, I, Z, k = [], range, l.open (raw_input ()), {}, lambda x: -x [1 ]; (W, H), Q = I.SIZE, I. Carico ()
per i, j nel prodotto (R (W), R (H)):
 c = Q [i, j]
 se c in Z: x, y, X, Y = Z [c]; Z [c] = [x, y, max (X, i), max (Y, j)]
 altro: Z [c] = [i, j, 0,0]
per n in permutazioni (ordinati ([(c, len ({Q [g] per g nel prodotto (R (x, X), R (y, Y))})) per c, (x, y, X, Y) in Z.items ()], chiave = k) [1: -1]): o = l.new (I.mode, I.size, 0xFFFFFF); [D.Draw (o) .rectangle (Z [c], fill = c) per c, _ in n]; O + = [(o, sum (abs (ab) per t, T in zip (I.getdata (), o.getdata ()) per a, b in zip (t, T)))]
max (O, key = k) [0] .Show ()

0

Java - 1483 byte

Non sono un grande golfista di codice, sia chiaro; quindi la verbosità non è interamente colpa di Java ;-) Tuttavia, questa sembrava una sfida davvero divertente. L'ho risolto in un modo che - penso - è un po 'noioso e dettagliato, ma ehi. Funziona, è (relativamente) veloce e, soprattutto, è stato divertente!

L'idea è la seguente: controlla ogni pixel partendo dall'angolo in alto a sinistra fino in fondo a destra. È un pixel bianco? Ignorare. È colorato? Bene, teniamoci traccia e proviamo a determinarne i confini (in alto a sinistra, in alto a destra, in basso a sinistra, in basso a destra).

Fatto ciò, controlla l'area di ogni rettangolo. Contiene un colore diverso rispetto al colore del rettangolo? Quindi scopri quale rettangolo appartiene a quel colore e aggiorna l'indice z di quel rettangolo sovrapposto di 1.

E infine, disegna tutti i rettangoli tenendo conto degli indici z. Funziona in realtà come un indice z che conosci da CSS e altre cose 3D. I rettangoli con l'indice z più basso vengono disegnati per primi, l'ultimo indice z più recente.

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"));}}}

Il codice completo che è un po '- e questo è un eufemismo ;-) - scritto più chiaramente, può essere trovato qui: http://pastebin.com/UjxUUXRp

Inoltre, ora che vedo l'invio di Dieter, avrei potuto semplificare alcune parti. Non è davvero necessario trovare il rettangolo il cui colore si sovrappone a un altro rettangolo. Potrei davvero contare solo il numero di colori "invasori".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.