Eine Woche Programmierwettbewerb: Rechtecke
-
Der alte Thread ist leider kaputt gegangen (letzte Seite geht nicht):
http://www.c-plusplus.net/forum/viewtopic-var-t-is-181382.html@Ponto:
Könntest du bitte deinen letzten Beitrag nochmal schreiben? Ich hoffe mal, dass die Auswertung diesmal geklappt hat
-
Kann mal jemand den alten Beitrag ficksen?
-
phpBB ist schon eine tolle Software.
Als Markus das Forum aufgesetzt hat, hat er wohl nie mit mehr als 10 Postings/Tag gerechnet...
-
Wir kümmern uns drum. Ich hab versucht einige Beiträge zu entfernen. Aber das hat bisher nicht geholfen. Macht so lange bitte hier weiter.
-
TomasRiker schrieb:
Der alte Thread ist leider kaputt gegangen (letzte Seite geht nicht):
http://www.c-plusplus.net/forum/viewtopic-var-t-is-181382.html@Ponto:
Könntest du bitte deinen letzten Beitrag nochmal schreiben? Ich hoffe mal, dass die Auswertung diesmal geklappt hatMit http://www.c-plusplus.net/forum/viewtopic-var-t-is-181382-and-start-is-139.html kommst du an die Auswertung.
-
Ich kenne ein Forum, das mal mit dem gleichen Problem zu kämpfen hatte.
Laut Admin hat die Wiederinstandsetzung ziemliche Mühe gekostet.
Also viel Glück.
-
Cool
Hier ist mein Algorithmus:
http://rafb.net/p/fso6kK79.htmlDie Kommentare sollten keine Fragen offen lassen.
-
Hier kommt nochmal meine Auswertung:
Es gab vier Einsendungen: otze, Jens, camper und TomasRiker
Jens hatte zwei Algorithmen abgegeben, die ich beide getestet habe, weil noch genug Kapazität da war.
Da aber jeder nur einen Algorithmus in den Contest schicken kann, gilt nur der, der hier als Jens-1 bezeichnet ist. Der andere läuft außer Konkurrenz.Ebenso wird mein Algorithmus nicht berücksichtigt, der hier als Ponto bezeichnet wird. Zusätzlich taucht in den Tabellen noch der Algorithmus "TomasRiker Mod" auf. Diesen habe ich aufgenommen, weil TomasRiker in seiner Originallösung die Generatoren stark berücksichtigt.
Insgesamt tauchen hier also 7 Algorithmen auf.
Ich habe die Generatoren mit verschiedenen Parametern gefüttert und die Laufzeiten der Algorithmen aufsummiert. Damit denke ich den Algorithmus zu erhalten, der über einen breiten Anwendungsbereich am besten arbeitet.
Die Tests liefen auf einer Maschine mit 8 Prozessoren von AMD: "AMD Opteron(tm) Processor 852". Die Taktrate ist 2.6GHz. Die Testmaschine hat 64GB Hauptspeicher, welcher von keinem Programm ausgenutzt wurde.
Für jeden Test habe ich den Programmen 120 Sekunden CPU-Zeit gegeben. Testläufe, die länger benötigten wurden mit 130 Sekunden bewertet. Für die anderne Läufe gelten die tatsächlichen Sekunden.Hier die Laufzeiten in Sekunden:
User: camper Jens-1 Jens-2 otze TomasRiker TomasRiker Ponto Mod Dot: 86 783 2194 2507 38 42 61 Wiring: 1104 2392 1965 2686 114 924 757 Placement 1708 3566 5711 6906 255 516 986 Random: 2248 5107 884 5331 28 1472 771 ----- ----- ----- ----- ----- ----- ----- Gesamt: 5146 11848 10754 17430 435 2954 2574
Damit ergibt sich die folgende Reihenfolge:
4. otze
3. Jens
2. camper
1. TomasRikerMan sieht, dass TomasRiker auch ohne seine Optimierung auf die Generatoren hin gewonnen hätte.
Herzlichen Glückwunsch an den Gewinner.
Alle Testläufe sind in der folgenden Tabelle eingetragen: http://www.pontohonk.de/wpc/Contest.ods
Die Rohdaten sind in http://www.pontohonk.de/wpc/Contest.txt zu finden. Die Laufzeitspalten sind sortiert nach camper, Jens-1, Jens-2, otze, TomasRiker Mod, Ponto, TomasRiker, Ponto (mit TomasRiker optimierungen)
-
Hier ist mein eigener Code:
Grob gesagt, wird hier ein Quadtree aufgebaut, der an jedem Knoten abspeichert, ob dieser und die gesamte
Fläche darunter schon belegt sind.Der erste Knoten (layer0[0]) repräsentiert die gesamte Ebene. In jedem weiteren Layer werden die darüberliegenden Flächen in vier gleich große Quadrate aufgeteilt.
Der Algorithmus läuft dann rekursiv. Es wird das Rechteck in das kleinste Quadrat gelegt, in das das Rechteck passt. Dann wird Anhand der Viertelung aufgeschnitten und die nächste Ebene aufgerufen. Ist eine Ebene schon belegt, kann abgebrochen werden.
#include <cmath> #include <vector> #include "rectangle.hpp" char layerC[4096*4096/8]; char layerB[2048*2048/8]; char layerA[1024*1024/8]; char layer9[512*512/8]; char layer8[256*256/8]; char layer7[128*128/8]; char layer6[64*64/8]; char layer5[32*32/8]; char layer4[16*16/8]; char layer3[8*8/8]; char layer2[4*4/8]; char layer1[1]; char layer0[1]; char * layer[] = { layer0, layer1, layer2, layer3, layer4, layer5, layer6, layer7, layer8, layer9, layerA, layerB, layerC }; inline bool get(int l, int x, int y) { unsigned int pos = (x * (1 << l) + y); unsigned int byte = pos / 8; unsigned int bit = pos % 8; return (layer[l][byte]) & (1 << bit); } inline void set(int l, int x, int y) { unsigned int pos = (x * (1 << l) + y); unsigned int byte = pos / 8; unsigned int bit = pos % 8; layer[l][byte] |= (1 << bit); } static int pixel = 0; static std::vector<std::vector<std::size_t> > * res; inline unsigned int floor_log2_p1(unsigned int v) { if (v <= 2) return v; unsigned int b = 17U; if (v < 1U<<16U) b = 1U; if (v >= (1U<< 7U) << b) b += 8U; if (v >= (1U<< 3U) << b) b += 4U; if (v >= (1U<< 1U) << b) b += 2U; return(b + (v >= (1U<<0U) << b)); } inline void draw(int l, int x, int y, int minx, int maxx, int miny, int maxy, std::size_t idx) { if (minx >= maxx or miny >= maxy) return; if (get(l, x, y)) return; int size = (4096U >> l); if (size == 1) { ++pixel; set(l, x, y); (*res)[x][y] = idx; return; } int half = size/2; int startx = x * size; int midx = startx + half; int starty = y * size; int midy = starty + half; draw(l+1, 2*x, 2*y, minx, std::min(maxx, midx), miny, std::min(maxy, midy), idx); draw(l+1, 2*x+1, 2*y, std::max(minx, midx), maxx, miny, std::min(maxy, midy), idx); draw(l+1, 2*x, 2*y+1, minx, std::min(maxx, midx), std::max(miny, midy), maxy, idx); draw(l+1, 2*x+1, 2*y+1, std::max(minx, midx), maxx, std::max(miny, midy), maxy, idx); if (get(l+1, 2*x, 2*y) and get(l+1, 2*x+1, 2*y) and get(l+1, 2*x, 2*y+1) and get(l+1, 2*x+1, 2*y+1)) { set(l, x, y); return; } } void algorithm(Rectangle plane, std::vector<Rectangle> const & rectangles, std::vector<std::vector<std::size_t> > & result) { res = &result; Coordinate width = plane.maxx - plane.minx; Coordinate height = plane.maxy - plane.miny; for (std::size_t i = rectangles.size(); i > 0; --i) { Rectangle rect = {rectangles[i-1].minx - plane.minx, rectangles[i-1].maxx - plane.minx, rectangles[i-1].miny - plane.miny, rectangles[i-1].maxy - plane.miny }; rect.minx = std::max(Coordinate(0), rect.minx); rect.miny = std::max(Coordinate(0), rect.miny); rect.maxx = std::min(width, rect.maxx); rect.maxy = std::min(height, rect.maxy); if (rect.minx >= rect.maxx or rect.miny >= rect.maxy) continue; int layer = floor_log2_p1(std::max(((rect.maxy-1) ^ rect.miny), ((rect.maxx-1) ^ rect.minx))); draw(12 - layer, (rect.minx >> layer) , (rect.miny >> layer), rect.minx, rect.maxx, rect.miny, rect.maxy, i-1); if (pixel == width * height) break; } }
-
Otze hat mich gebeten seinen Code auch zu veröffentlichen.
Jens und Camper können dies bei Bedarf selbst tun.#include <list> #include <utility> #include <cmath> #include <boost/optional.hpp> #include <boost/foreach.hpp> #define foreach BOOST_FOREACH #define BOOST_NO_MT #include <boost/pool/pool_alloc.hpp> #include <iostream> struct Cross { int middleX; int middleY; }; enum Quadrant { rightTop=0, leftTop=1, rightDown=2, leftDown=3, several }; struct TreeRectangle { Rectangle rect; std::size_t number; Quadrant quadrant; }; typedef std::list<TreeRectangle,boost::fast_pool_allocator<TreeRectangle> > Container; //typedef std::list<TreeRectangle> Container; typedef Container::iterator iterator; /////////////////////////////////////////////////////////////////////////////// //RECTANGLE /////////////////////////////////////////////////////////////////////////////// Rectangle makeRectangle(int minx,int maxx,int miny,int maxy) { Rectangle rect; rect.minx=minx; rect.maxx=maxx; rect.miny=miny; rect.maxy=maxy; return rect; } std::pair<Rectangle,boost::optional<Rectangle> > cutHorizontal(const Rectangle& rectangle,int lineY) { std::pair<Rectangle,boost::optional<Rectangle> > result; //no conversion needed,simply copy if((rectangle.maxy<=lineY)||(rectangle.miny>=lineY)) { result.first=rectangle; } else { result.first=makeRectangle(rectangle.minx,rectangle.maxx,rectangle.miny,lineY); result.second=boost::optional<Rectangle>(makeRectangle(rectangle.minx,rectangle.maxx,lineY,rectangle.maxy)); } return result; } std::pair<Rectangle,boost::optional<Rectangle> > cutVertical(const Rectangle& rectangle,int lineX) { std::pair<Rectangle,boost::optional<Rectangle> > result; //no conversion needed,simply copy if((rectangle.maxx<=lineX)||(rectangle.minx>=lineX)) { result.first=rectangle; } else { result.first=makeRectangle(rectangle.minx,lineX,rectangle.miny,rectangle.maxy); result.second=boost::optional<Rectangle>(makeRectangle(lineX,rectangle.maxx,rectangle.miny,rectangle.maxy)); } return result; } std::list<Rectangle> cutRectangle(const Rectangle& rectangle,const Cross& cross) { std::list<Rectangle> result; std::pair<Rectangle,boost::optional<Rectangle> > hCut=cutHorizontal(rectangle,cross.middleY); std::pair<Rectangle,boost::optional<Rectangle> > vCut=cutVertical(hCut.first,cross.middleX); result.push_back(vCut.first); if(vCut.second) { result.push_back(vCut.second.get()); } if(hCut.second) { std::pair<Rectangle,boost::optional<Rectangle> > vCut=cutVertical(hCut.second.get(),cross.middleX); result.push_back(vCut.first); if(vCut.second) { result.push_back(vCut.second.get()); } } return result; } //////////////////////////////////////////////////////////////////////////////// //QUADRANT //////////////////////////////////////////////////////////////////////////////// Quadrant getQuadrant(const Rectangle& rectangle,const Cross& cross) { if( (rectangle.maxx<=cross.middleX) && (rectangle.maxy<=cross.middleY) ) { return leftDown; } if( (rectangle.maxx<=cross.middleX) && (rectangle.miny>=cross.middleY) ) { return leftTop; } if( (rectangle.minx>=cross.middleX) && (rectangle.maxy<=cross.middleY) ) { return rightDown; } if( (rectangle.minx>=cross.middleX) && (rectangle.miny>=cross.middleY) ) { return rightTop; } return several; } Rectangle getQuadrantOfRectangle(const Rectangle& plane,Quadrant quadrant) { int middleX=(plane.maxx-plane.minx)/2+plane.minx; int middleY=(plane.maxy-plane.miny)/2+plane.miny; switch(quadrant) { case rightTop: return makeRectangle(middleX,plane.maxx,middleY,plane.maxy); break; case leftTop: return makeRectangle(plane.minx,middleX,middleY,plane.maxy); break; case rightDown: return makeRectangle(middleX,plane.maxx,plane.miny,middleY); break; case leftDown: return makeRectangle(plane.minx,middleX,plane.miny,middleY); break; default: return Rectangle();//just making the compiler happy } } //////////////////////////////////////////////////////////////////////////////// //TREE RECTANGLE //////////////////////////////////////////////////////////////////////////////// TreeRectangle transformRectangle(const Rectangle& plane,const Rectangle& rectangle,std::size_t number) { TreeRectangle rect; rect.rect.minx=std::max(rectangle.minx,plane.minx); rect.rect.miny=std::max(rectangle.miny,plane.miny); rect.rect.maxx=std::min(rectangle.maxx,plane.maxx); rect.rect.maxy=std::min(rectangle.maxy,plane.maxy); rect.number=number; return rect; } TreeRectangle transformRectangleSimple(const Rectangle& rectangle,std::size_t number) { TreeRectangle rect; rect.rect=rectangle; rect.number=number; return rect; } bool operator<(const TreeRectangle& o1,const TreeRectangle& o2) { return o1.number>o2.number; } void classifyRectangle(TreeRectangle& rectangle,const Cross cross) { rectangle.quadrant=getQuadrant(rectangle.rect,cross); } //////////////////////////////////////////////////////////////////////////////// //ALGORITHM //////////////////////////////////////////////////////////////////////////////// bool isInvisible(const TreeRectangle& lower,const TreeRectangle& upper) { return (lower.rect.minx>=upper.rect.minx) && (lower.rect.maxx<=upper.rect.maxx) && (lower.rect.miny>=upper.rect.miny) && (lower.rect.maxy<=upper.rect.maxy); } //ok, i really hate myself for this function... void cullInvisibleRectangles(Container& rectList) { for(iterator i=rectList.begin();i!=rectList.end();++i) { iterator j=i; j++; while(j!=rectList.end()) { if(isInvisible(*j,*i)) { j=rectList.erase(j); } else { j++; } } } } void createVisibilityList(Rectangle plane,Container& rectangles) { if(rectangles.empty()||rectangles.size()==1) { return; } //the cross splits the ground Plane in 4 parts Cross cross; cross.middleX=(plane.maxx-plane.minx)/2+plane.minx; cross.middleY=(plane.maxy-plane.miny)/2+plane.miny; Container quadrants[4]; for(iterator rect=rectangles.begin();rect!=rectangles.end();) { classifyRectangle(*rect,cross); if(rect->quadrant==several) { std::list<Rectangle> newRectangles=cutRectangle(rect->rect,cross); foreach(Rectangle& newRect,newRectangles) { TreeRectangle newTransformedRect=transformRectangle(plane,newRect,rect->number); classifyRectangle(newTransformedRect,cross); quadrants[newTransformedRect.quadrant].push_back(newTransformedRect); } rect=rectangles.erase(rect); } else { iterator copy=rect; ++copy; //quadrants[rect->quadrant].push_back(*rect); quadrants[rect->quadrant].splice(quadrants[rect->quadrant].end(),rectangles,rect); rect=copy; } } for(std::size_t i=0;i!=4;++i) { Rectangle newPlane=getQuadrantOfRectangle(plane,Quadrant(i)); cullInvisibleRectangles(quadrants[i]); createVisibilityList(newPlane,quadrants[i]); rectangles.splice(rectangles.begin(),quadrants[i],quadrants[i].begin(),quadrants[i].end()); } } void algorithm(Rectangle plane, std::vector<Rectangle> const & rectangles, std::vector<std::vector<std::size_t> > & result) { //transform the rects into a better format Container transformedRectangles; std::size_t i=0; std::vector<Rectangle>::const_reverse_iterator end=rectangles.rend(); for(std::vector<Rectangle>::const_reverse_iterator rect=rectangles.rbegin();rect!=end;++rect) { if((rect->maxx>plane.minx) && (rect->minx<plane.maxx) && (rect->maxy>plane.miny) && (rect->miny<plane.maxy) ) { transformedRectangles.push_back(transformRectangle(plane,*rect,rectangles.size()-1-i)); } ++i; } //the algorithm createVisibilityList(plane,transformedRectangles); //map the rectangles on result foreach(TreeRectangle& rectangle, transformedRectangles) { for(int x=rectangle.rect.minx;x<rectangle.rect.maxx;++x) { for(int y=rectangle.rect.miny; y<rectangle.rect.maxy; ++y) { result[x-plane.minx][y-plane.miny]=rectangle.number; } } } }
-
1. Juhu, ich hab wieder internet
2. hab mir fast gedacht, dass mein algo der langsamste im test ist, ich hab aber nicht genau ahnung, woran es nun hängt.mein algorithmus funktioniert folgendermaßen: ich baue einen baum auf,indem ich alle rechteck dahingehend einteile, in welchem quadrant des rechtecks sie sich befinden. wenn ein rechteck in verschiedenen quadranten ist, dann wird es an den quadrantgrenzen zerschnitten, sodass dann jedes teil genau in einen quadranten passt. Danach geh ich alle rechtecke durch und überprüfe jedes einzelne, ob es ein anderes rechteck verdeckt. wenn ja, dann wird das verdeckte rechteck entfernt. Das ganze ruf ich dann rekursiv für die einzelnen quadranten wieder auf.
Am Ende füg ich die übrig gebliebenen rechtecke wieder in einer liste zusammen. jedes rechteck in der liste ist dann vollständig sichtbar und kann dann so gezeichnet werden.
-
TomasRiker schrieb:
Cool
Hier ist mein Algorithmus:
http://rafb.net/p/fso6kK79.htmlDie Kommentare sollten keine Fragen offen lassen.
Den Link gibts leider nicht mehr, könntest du deinen Algorithmus noch einmal hochladen?
Danke.