Couvrir une région avec des rectangles

22

Contribution

Votre contribution à ce défi est une liste de paires entières. Ils représentent les coins sud-ouest des carrés d'unité dans l'avion, et la liste représente leur union en tant que sous-ensemble de l'avion. Par exemple, la liste

[(0,0),(1,0),(0,1),(1,1),(2,1),(1,2),(2,2)]

représente l'ensemble de couleur rouge dans cette image:

Un domaine

Sortie

Votre sortie est une liste de quadruples entiers, représentant des sous-ensembles rectangulaires du plan. Plus explicitement, un quadruple (x,y,w,h)représente un rectangle de largeurw > 0 et de hauteur h > 0dont l'angle sud-ouest est à (x,y). Les rectangles doivent former une couverture exacte de la région d'entrée, dans le sens où chacun des carrés unitaires est un sous-ensemble d'un rectangle, chaque rectangle est un sous-ensemble de la région et deux rectangles peuvent se chevaucher uniquement à leurs frontières. Pour interdire les solutions triviales, le revêtement ne doit pas contenir deux rectangles qui pourraient être fusionnés en un rectangle plus grand.

Par exemple, la liste

[(0,0,2,1),(0,1,3,1),(1,2,2,1)]

représente la couverture juridique

Une couverture juridique

de la région susmentionnée, alors que la couverture

[(0,0,2,2),(2,1,1,1),(1,2,1,1),(2,2,1,1)]

est illégal, car les carrés 1 par 1 voisins pourraient être fusionnés:

Une couverture illégale

Règles

Vous pouvez donner un programme complet ou une fonction. Le formatage précis de l'entrée et de la sortie n'est pas important, dans des limites raisonnables. Le nombre d'octets le plus court l'emporte et les failles standard sont interdites. Nous vous encourageons à fournir une explication de votre algorithme et quelques exemples de résultats.

Cas de test

Une région en U:

[(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(1,0),(1,1),(1,2),(1,3),(1,4),(1,5),(2,0),(2,1),(3,0),(3,1),(4,0),(4,1),(4,2),(4,3),(4,4),(4,5),(5,0),(5,1),(5,2),(5,3),(5,4),(5,5)]

En forme de U

Un grand triangle:

[(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),(0,8),(0,9),(1,0),(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(2,0),(2,1),(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),(3,0),(3,1),(3,2),(3,3),(3,4),(3,5),(3,6),(4,0),(4,1),(4,2),(4,3),(4,4),(4,5),(5,0),(5,1),(5,2),(5,3),(5,4),(6,0),(6,1),(6,2),(6,3),(7,0),(7,1),(7,2),(8,0),(8,1),(9,0)]

Triangle

Un carré avec des trous:

[(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),(0,8),(1,0),(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8),(1,9),(2,0),(2,1),(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),(2,8),(2,9),(3,0),(3,1),(3,2),(3,4),(3,5),(3,6),(3,7),(3,8),(3,9),(4,0),(4,1),(4,2),(4,3),(4,4),(4,5),(4,6),(4,7),(4,8),(4,9),(5,0),(5,1),(5,2),(5,3),(5,4),(5,5),(5,7),(5,8),(5,9),(6,1),(6,2),(6,3),(6,5),(6,6),(6,7),(6,8),(6,9),(7,0),(7,1),(7,2),(7,3),(7,4),(7,5),(7,6),(7,7),(7,8),(7,9),(8,0),(8,1),(8,2),(8,3),(8,4),(8,5),(8,6),(8,7),(8,8),(8,9),(9,0),(9,1),(9,2),(9,3),(9,4),(9,5),(9,6),(9,7),(9,8),(9,9)]

Carré troué

Régions déconnectées:

[(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),(0,8),(1,0),(1,1),(1,2),(1,3),(1,4),(1,6),(1,7),(1,8),(1,9),(2,1),(2,2),(2,3),(2,4),(2,5),(2,6),(2,7),(2,8),(2,9),(4,0),(4,1),(4,2),(4,4),(4,5),(4,6),(4,7),(4,8),(4,9),(5,0),(5,1),(5,2),(5,3),(5,4),(5,5),(5,6),(5,7),(5,8),(5,9),(6,0),(6,1),(6,2),(6,4),(6,5),(6,6),(6,7),(6,8),(6,9),(8,0),(8,1),(8,2),(8,3),(8,4),(8,5),(8,6),(8,7),(8,8),(8,9),(9,0),(9,1),(9,2),(9,3),(9,7),(9,8),(9,9),(10,0),(10,1),(10,2),(10,3),(10,4),(10,5),(10,6),(10,7),(10,8),(10,9)]

Débranché

Vérifieur

Utilisez ce programme Python 2 pour vérifier votre solution. Il prend de STDIN une liste de tuples (l'entrée) et une liste de quadruples (votre sortie), séparés par une virgule.

J'ai également écrit ce programme Python 2 pour générer les images, et vous pouvez également l'utiliser. Il prend de STDIN une liste de tuples ou de quadruples et produit un fichier nommé out.png. Il nécessite la bibliothèque PIL. Si vous le souhaitez, vous pouvez également modifier la taille des cellules de la grille et la largeur des lignes de ceinture.

Zgarb
la source

Réponses:

12

Python: 196 193 182 caractères

def g(r):
 for p in r:
  for q in r:
   for h in 0,1:
    if p[h::2]==q[h::2]and p[1-h]+p[~h]==q[1-h]:p[~h]+=q[~h];r.remove(q);return g(r)
 return r
f=lambda P:g([x+[1,1]for x in P])

Ma première solution a utilisé exactement le même algorithme que KSFT, j'ai donc expérimenté d'autres méthodes.

Je fais d'abord du prétraitement, je convertis tous les points en petits rectangles 1x1 {x+(1,1)for x in P}. Avec ces rectangles, j'appelle la fonction g. gitère sur chaque combinaison de rectangles. S'il trouve 2 rectangles, qui peuvent être fusionnés en un plus grand, il supprime les deux et ajoute le nouveau. Ensuite, il se fait appeler avec le nouvel ensemble de rectangles.

Usage

f([[0,0],[1,0],[0,1],[1,1],[2,1],[1,2],[2,2]])

Résultats

Voici la visualisation des résultats. Notez qu'ils peuvent être un peu différents dans la version actuelle. L'idée est cependant qu'il n'y a aucun type de schéma perceptible.

Une région en U:

Un grand triangle

Un carré avec des trous:

Régions déconnectées:

Juste pour le plaisir: Pyth: 73 69 caractères

D!HFGHFZHV2I&q%2>GN%2>ZNqs%2>G-1N@Z-1N X-3NG@Z-3NR!-H]Z)))RH!m+d*2]1Q

Fonctionne uniquement dans la version hors ligne. Le bug dans la version en ligne est maintenant corrigé. Essayez-le ici: Pyth Compiler / Executor . Attend une liste de listes, pas une liste de tuples.

edit: J'ai utilisé une idée de @ edc65: Au lieu de supprimer les deux rectangles et d'en créer un nouveau, j'en manipule un et je n'en supprime qu'un. Dans la solution Python, je pouvais me débarrasser des ensembles et des moulages de tuple-list-tuple. -11 caractères en Python / -4 caractères en Pyth

Jakube
la source
2
Python3: les visages souriants sont maintenant du code valide.
flawr
Je me trompe peut-être, mais je pense que vous pouvez changer 3-hpour ~h?
Sp3000
Accepté pour la version Pyth.
Zgarb
14

Python - 272 261 258 251 224

Je pense que je peux jouer au golf plus. Je suis presque sûr que cela fonctionne, mais je n'ai pas encore fini de le tester sur tous les cas de test. J'ai fini de le tester. Cela fonctionne pour tous les cas de test.

a=sorted(input())
b=[]
r=range
for i in a:
 c=set(a)-set(b);w=h=1;x,y=i
 if i in b:continue
 while not{(x,y+h)}-c:h+=1
 while all((x+w,y+j)in c for j in r(h)):w+=1
 for j in r(w):
  for k in r(h):b+=(j+x,k+y),
 print x,y,w,h

Je travaille sur l'ajout d'images des résultats. Edit: Voici les résultats de l'exemple et des cas de test:

Exemple de sortie Cas de test 1 sortie Cas de test 2 sorties Cas de test 3 sorties Cas de test 4 sorties

J'essaie d'écrire ceci en Perl, mais je ne peux pas comprendre comment obtenir des tableaux multidimensionnels à partir de stdin sans un grand nombre de caractères. Est-ce que quelqu'un a des suggestions?

KSFT
la source
Deux choses: (i[0]+w,i[1]+j)not in cpour {(i[0]+w,i[1]+j)}-cet vous pouvez passer w=h=1à la c=set(a)-set(b)ligne
Sp3000
Quelques autres: b+=[(j+i[0],k+i[1])]to b+=(j+i[0],k+i[1]),et vous utilisez rangetrois fois donc il est plus court à attribuerr=range
Sp3000
De plus, je ne suis pas sûr, mais est-il possible de faire x,y=iensuite en utilisant xet yau lieu de i[0]et i[1]? Cela économiserait beaucoup d'octets.
Sp3000
Je n'ai pas testé cela, mais je pense que cela fonctionne: Au lieu de l' while not[j for j in r(h)if(x+w,y+j)not in c]:w+=1utiliser while all((x+w,y+j)in c for j in r(h)):w+=1.
Jakube
@ Sp3000 / Jakube J'ai utilisé toutes vos suggestions.
KSFT
8

Python 2, 139

Le programme accepte des listes de paires ordonnées entourées d'accolades sur une entrée standard. Par exemple,{(0,0),(1,0),(0,1),(1,1),(2,1),(1,2),(2,2)}

s=input()
while s:x,y=min(s);w=h=0;exec"while(x+w,y)in s:w+=1\nwhile%s<=s:s-=%s;h+=1"%(("{(X,y+h)for X in range(x,x+w)}",)*2);print x,y,w,h

Il est souvent irritant (pas seulement dans le golf) que Python n'autorise pas une affectation à l'intérieur d'un test de boucle. Pour contourner ce problème, j'ai utilisé des opérations de formatage de chaînes.

feersum
la source
C'est impressionnant. Le même algorithme que KSFT, «seulement» 85 (!!!) caractères plus courts.
Jakube
5

Mathematica - 315 285 267 octets

f=(r={};For[m=MemberQ;t=Table;s=Sort@#,s!={},For[{x,y,w,h}=#~Join~{1,1}&@@s;i=j=0,i<1||j<1,If[s~m~{x+w,y+a-1}~t~{a,h}==True~t~{h},w++,i++];If[s~m~{x+a-1,y+h}~t~{a,w}==True~t~{w},h++,j++]];s=s~Cases~_?(!m[Join@@t[{x+a,y+b}-1,{a,w},{b,h}],#]&);r~AppendTo~{x,y,w,h}];r)&

Avec l'aide de @ MartinBüttner.

Non golfé:

f = (
    rectangles = {};
    For[squares = Sort[#], squares != {},
        For[{x, y, w, h} = Join[squares[[1]], {1, 1}]; i = j = 0, i < 1 || j < 1,
            If[Table[MemberQ[squares, {x + w, y + a - 1}], {a, h}] == Table[True, {h}], w++, i++];
            If[Table[MemberQ[squares, {x + a - 1, y + h}], {a, w}] == Table[True, {w}], h++, j++];
        ];
        squares = Cases[squares, _ ? (!MemberQ[Join@@Table[{x + a - 1, y + b - 1}, {a, w}, {b, h}], #] &)];
        AppendTo[rectangles, {x, y, w, h}]
    ];
    rectangles
)&

Usage:

In: f @ {{0,0},{1,0},{0,1},{1,1},{2,1},{1,2},{2,2}}
Out: {{0, 0, 2, 2}, {1, 2, 2, 1}, {2, 1, 1, 1}}

entrez la description de l'image ici

Cas de test

Une région en U

entrez la description de l'image ici

{{0, 0, 6, 2}, {0, 2, 2, 4}, {4, 2, 2, 4}}

Un grand triangle

entrez la description de l'image ici

{{0, 0, 6, 5}, {0, 5, 3, 3}, {0, 8, 2, 1}, {0, 9, 1, 1}, {3, 5, 2, 1}, {3, 6, 1, 1}, {6, 0, 3, 2}, {6, 2, 2, 1}, {6, 3, 1, 1}, {9, 0, 1, 1}}

Un carré avec des trous

entrez la description de l'image ici

{{0, 0, 6, 3}, {0, 3, 3, 6}, {1, 9, 9, 1}, {3, 4, 3, 2}, {3, 6, 2, 3}, {4, 3, 6, 1}, {5, 7, 5, 2}, {6, 1, 4, 2}, {6, 5, 4, 2}, {7, 0, 3, 1}, {7, 4, 3, 1}}

Régions déconnectées

entrez la description de l'image ici

{{0, 0, 2, 5}, {0, 5, 1, 4}, {1, 6, 2, 4}, {2, 1, 1, 5}, {4, 0, 3, 3}, {4, 4, 3, 6}, {5, 3, 1, 1}, {8, 0, 3, 4}, {8, 4, 1, 6}, {9, 7, 2, 3}, {10, 4, 1, 3}}
kukac67
la source
4

Haskell, 158

f[]=[]
f s@((x,y):_)=(x,y,w-x,h-y):f[r|r@(a,b)<-s,a<x||a>=w||b<y||b>=h]where w=[i|i<-[x..],notElem(i,y)s]!!0;h=[i|i<-[y..],not$all(\x->elem(x,i)s)[x..w-1]]!!0

des cas de test et des images seront bientôt disponibles.

Algorithme: prenez le premier carré. Atteignez l'extrême droite sans rencontrer un carré qui n'est pas dans l'entrée. Atteignez ensuite le plus haut possible sans avoir de carré non en entrée. Nous avons maintenant un rectangle sans carré manquant. Ajoutez-le à la sortie, supprimez tous ses carrés de l'entrée et appelez récursivement.

fier haskeller
la source
Vous pouvez enregistrer 1 octet en le remplaçant not$all(\x->elem(x,i)s)par any(\x->notElem(x,i)s).
nimi
4

JavaScript (ES6) 148 155 199

Edit2 Un peu plus de réglage
Modifier Some golfing + rewrite using recursion. Je ne m'attendais pas à une telle réduction. Maintenant, c'est un peu difficile à suivre, mais l'algorithme est le même.

L'algorithme est similaire à la réponse @jakube.

  1. Chaque point devient un carré 1x1 (prétraitement)
  2. Pour chaque élément, vérifiez s'il peut être fusionné avec un autre
    Oui? Le premier élément grandit, le deuxième élément est effacé, recommencez à l'étape 2
    Sinon, passez à l'élément suivant
F=l=>
  (l.map(x=>x.push(1,1)),R=f=>
    l.some(u=>
      (l=l.filter(t=>
        [0,1].every(p=>u[p]-t[p]|u[p^=2]-t[p]|u[p^=3]-t[p]+u[p^=2]||!(f=u[p]+=t[p]))
      ),f)
    )?R():l
  )()

Tester dans l'extrait

F=l=>(l.map(x=>x.push(1,1)),R=f=>l.some(u=>(l=l.filter(t=>[0,1].every(p=>u[p]-t[p]|u[p^=2]-t[p]|u[p^=3]-t[p]+u[p^=2]||!(f=u[p]+=t[p]))),f))?R():l)()

// Test
MyCanvas.width= 600;
MyCanvas.height = 220;
var ctx = MyCanvas.getContext("2d");
ctx.fillStyle="#f23";

Draw=(x,y,f,l)=>l.forEach(p=>ctx.fillRect(x+p[0]*f,y+p[1]*f,p[2]*f-1||f-1,p[3]*f-1||f-1));

test=[
[[0,0],[1,0],[0,1],[1,1],[2,1],[1,2],[2,2]],
[[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[1,0],[1,1],[1,2],[1,3],[1,4],[1,5],[2,0],[2,1],[3,0],[3,1],[4,0],[4,1],[4,2],[4,3],[4,4],[4,5],[5,0],[5,1],[5,2],[5,3],[5,4],[5,5]],
[[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7],[0,8],[0,9],[1,0],[1,1],[1,2],[1,3],[1,4],[1,5],[1,6],[1,7],[1,8],[2,0],[2,1],[2,2],[2,3],[2,4],[2,5],[2,6],[2,7],[3,0],[3,1],[3,2],[3,3],[3,4],[3,5],[3,6],[4,0],[4,1],[4,2],[4,3],[4,4],[4,5],[5,0],[5,1],[5,2],[5,3],[5,4],[6,0],[6,1],[6,2],[6,3],[7,0],[7,1],[7,2],[8,0],[8,1],[9,0]],
[[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7],[0,8],[1,0],[1,1],[1,2],[1,3],[1,4],[1,5],[1,6],[1,7],[1,8],[1,9],[2,0],[2,1],[2,2],[2,3],[2,4],[2,5],[2,6],[2,7],[2,8],[2,9],[3,0],[3,1],[3,2],[3,4],[3,5],[3,6],[3,7],[3,8],[3,9],[4,0],[4,1],[4,2],[4,3],[4,4],[4,5],[4,6],[4,7],[4,8],[4,9],[5,0],[5,1],[5,2],[5,3],[5,4],[5,5],[5,7],[5,8],[5,9],[6,1],[6,2],[6,3],[6,5],[6,6],[6,7],[6,8],[6,9],[7,0],[7,1],[7,2],[7,3],[7,4],[7,5],[7,6],[7,7],[7,8],[7,9],[8,0],[8,1],[8,2],[8,3],[8,4],[8,5],[8,6],[8,7],[8,8],[8,9],[9,0],[9,1],[9,2],[9,3],[9,4],[9,5],[9,6],[9,7],[9,8],[9,9]],
[[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7],[0,8],[1,0],[1,1],[1,2],[1,3],[1,4],[1,6],[1,7],[1,8],[1,9],[2,1],[2,2],[2,3],[2,4],[2,5],[2,6],[2,7],[2,8],[2,9],[4,0],[4,1],[4,2],[4,4],[4,5],[4,6],[4,7],[4,8],[4,9],[5,0],[5,1],[5,2],[5,3],[5,4],[5,5],[5,6],[5,7],[5,8],[5,9],[6,0],[6,1],[6,2],[6,4],[6,5],[6,6],[6,7],[6,8],[6,9],[8,0],[8,1],[8,2],[8,3],[8,4],[8,5],[8,6],[8,7],[8,8],[8,9],[9,0],[9,1],[9,2],[9,3],[9,7],[9,8],[9,9],[10,0],[10,1],[10,2],[10,3],[10,4],[10,5],[10,6],[10,7],[10,8],[10,9]]
]

Draw(0,0,10,test[0]),Draw(0,110,10,F(test[0]))
Draw(50,0,10,test[1]),Draw(50,110,10,F(test[1]))
Draw(130,0,10,test[2]),Draw(130,110,10,F(test[2]))
Draw(250,0,10,test[3]),Draw(250,110,10,F(test[3]))
Draw(370,0,10,test[4]),Draw(370,110,10,F(test[4]))
<canvas id=MyCanvas></canvas>

edc65
la source
3

Mathematica, 153 151 144 136 133 133

Sort[{##,1,1}&@@@Input[]]//.{a___,r:{x_,y_,__},b___,{X_,Y_,W_,H_},c___}/;r=={x,Y,X-x,H}||r=={X,y,W,Y-y}:>{a,r+Sign@{0,0,X-x,Y-y},b,c}

Exemple:

Contribution:

{{0, 0}, {1, 0}, {0, 1}, {1, 1}, {2, 1}, {1, 2}, {2, 2}}

Sortie:

{{0, 0, 2, 2}, {1, 2, 2, 1}, {2, 1, 1, 1}}

entrez la description de l'image ici

Contribution:

{{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}, {1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}, {1, 9}, {2, 0}, {2, 1}, {2, 2}, {2, 3}, {2, 4}, {2, 5}, {2, 6}, {2, 7}, {2, 8}, {2, 9}, {3, 0}, {3, 1}, {3, 2}, {3, 4}, {3, 5}, {3, 6}, {3, 7}, {3, 8}, {3, 9}, {4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 4}, {4, 5}, {4, 6}, {4, 7}, {4, 8}, {4, 9}, {5, 0}, {5, 1}, {5, 2}, {5, 3}, {5, 4}, {5, 5}, {5, 7}, {5, 8}, {5, 9}, {6, 1}, {6, 2}, {6, 3}, {6, 5}, {6, 6}, {6, 7}, {6, 8}, {6, 9}, {7, 0}, {7, 1}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7, 6}, {7, 7}, {7, 8}, {7, 9}, {8, 0}, {8, 1}, {8, 2}, {8, 3}, {8, 4}, {8, 5}, {8, 6}, {8, 7}, {8, 8}, {8, 9}, {9, 0}, {9, 1}, {9, 2}, {9, 3}, {9, 4}, {9, 5}, {9, 6}, {9, 7}, {9, 8}, {9, 9}}

Sortie:

{{0, 0, 3, 9}, {1, 9, 9, 1}, {3, 0, 3, 3}, {3, 4, 1, 5}, {4, 3, 1, 6}, {5, 3, 1, 3}, {5, 7, 1, 2}, {6, 1, 1, 3}, {6, 5, 1, 4}, {7, 0, 3, 9}}

entrez la description de l'image ici

Algorithme:

Couvrez la région avec des carrés d'unité, puis fusionnez-les.

entrez la description de l'image ici

alephalpha
la source