using System;using System.Collections.Generic;using System.Linq;namespace Solution
{publicstaticclassKata{publicstaticlongCalculate(IEnumerable<int[]> rectangles){if(!rectangles.Any())return0;
rectangles = rectangles.OrderBy(r => r[0]).ToList();var xs = rectangles.Select(r=>r[0]).Concat(rectangles.Select(r=>r[2])).Distinct().OrderBy(x=>x).ToList();var scan =newList<int[]>();// long recIndex = 0;long area =0;long scanLeft = xs[0];
xs.RemoveAt(0);using(var recsEnum = rectangles.GetEnumerator()){bool hasMoreRec = recsEnum.MoveNext();
xs.ForEach(scanRight =>{// add rectangles to scan that align on scan left...for(;hasMoreRec && recsEnum.Current[0]== scanLeft; hasMoreRec = recsEnum.MoveNext()){
scan.Add(recsEnum.Current);}
scan.Sort((a,b)=> a[1]- b[1]);// order by toplong height =0;long lastY =long.MinValue;// last y accounted for in height
scan.ForEach(s =>{long top = s[1];long bottom = s[3];if(lastY < bottom)// overlaps, add height of overlapping portion{
height += bottom - Math.Max(lastY, top);
lastY = bottom;}});// area of rectangles that overlap scan: height * width
area += height *(scanRight - scanLeft);// proceding left-to-right, so remove the scan rectangles whose right-side is to the left of current scan
scan.RemoveAll(r=>r[2]<= scanRight);
scanLeft = scanRight;});}return area;}}}
using System;using System.Collections.Generic;using System.Linq;namespace Solution
{publicstaticclassKata{//full_list is a list of top-tier rectangles. As we add more rectangles,// if there are overlaps, we will create "super rectangles" that are// larger rectangles containing rectangles within it's area.// This will keep the algorythm efficient by not having to// compare the current rectangle to every rectangle previously// encountered.//We will eventually end up with a hyerarchy of super rectangles.publicstatic List<Rect> full_list;publicstaticlong full_size;publicstaticbool debug;publicstaticlongCalculate(IEnumerable<int[]> rectangles){
full_list =newList<Rect>();
full_size =0;
debug =false;foreach(int[] i in rectangles){Rect r =newRect(i[0],i[1],i[2],i[3],true);AddNewRect(r);}return full_size;}//We have a new Rectangle and we want to add it to our list// and gather the new amount it addspublicstaticvoidAddNewRect(Rect r){
List<Rect> intersect_list;long size =0;
intersect_list =GetAllTopIntersects(r);//If it doesn't intersect with anything, just add itif(intersect_list.Count ==0){
full_list.Add(r);
size = r.Size();
full_size += size;return;}//If it intersects with only 1, we only need a larger rectangle if they are// both base rectanglesif(intersect_list.Count ==1){Rect intersecting = intersect_list[0];if(intersecting.isbase && intersecting.Contains(r))return;//this rectangle contains nothing newif(!intersecting.isbase){
intersecting.SmashThis(r);
size = r.Size();if(size ==0)return;
full_size += size;
intersecting.Add(r);return;}}//If we get here, either there are multiple intersects or an intersect with a base rectangle//either way, a new super rectangle is needed unless we junk this rectangleforeach(Rect intersecting in intersect_list)
intersecting.SmashThis(r);
size = r.Size();if(size ==0)return;
full_size += size;Rect super =newRect(r);foreach(Rect intersecting in intersect_list){
full_list.Remove(intersecting);
super.Add(intersecting);}
full_list.Add(super);}//We have a new Rectangle and we want a list of all current// rectangles it intersects with;publicstatic List<Rect>GetAllTopIntersects(Rect r){
List<Rect> result =newList<Rect>();foreach(Rect top in full_list){if(top.Intersects(r))
result.Add(top);}return result;}}//end of Kata classpublicclassRect{publicint _x0, _x1, _y0, _y1;private List<Rect> subrecs;publicbool isbase;publicRect(int x0,int y0,int x1,int y1,bool is_base =false){
_x0 = x0; _y0 = y0; _x1 = x1; _y1 = y1;
isbase = is_base;}//Creating a super list with the given base rectangle as the first entrypublicRect(Rect r){
_x0 = r._x0; _y0 = r._y0; _x1 = r._x1; _y1 = r._y1;
isbase =false;
subrecs =newList<Rect>();
subrecs.Add(r);//we bypass Rect.Add because we don't need to adjust size}//This will never be called on a base rect and is used to add new// subrecspublicvoidAdjustSize(int x0,int y0,int x1,int y1){if(x0 < _x0) _x0 = x0;if(y0 < _y0) _y0 = y0;if(x1 > _x1) _x1 = x1;if(y1 > _y1) _y1 = y1;}publicvoidAdd(Rect r){AdjustSize(r._x0,r._y0,r._x1,r._y1);
subrecs.Add(r);}publicboolIntersects(Rect r){return r._x0 < _x1 && r._y0 < _y1 && r._x1 > _x0 && r._y1 > _y0;}publicboolContains(Rect r){return r._x0 >= _x0 && r._y0 >= _y0 && r._x1 <= _x1 && r._y1 <= _y1;}publicboolContainedIn(Rect r){return r.Contains(this);}publiclongSize(){//We only ever get size after smashing and we don't need pieces anymorelong size =0;if(subrecs ==null)
size =(long)(_x1-_x0)*(long)(_y1-_y0);else{foreach(Rect r in subrecs)
size += r.Size();
subrecs.Clear();
subrecs =null;}return size;}//Pass in a list of rectangles (or super) that need to be compared// to the current rectangle. Break up the current rectangle into sub-// rectangles to determine the area that has not yet been "covered".publicvoidSmashThis(Rect smashee){//We only call SmashMe with a base rectangle, otherwise we recurseif(isbase)
smashee.SmashMe(this);elseforeach(Rect r in subrecs)if(r.Intersects(smashee))
r.SmashThis(smashee);}//Returns a list of smaller rectangles created by removing overlapping// area for a different rectangle. Original rectangle should not be// modified.public List<Rect>GetSmashList(Rect tosmash){int newx0 = _x0;int newx1 = _x1;
List<Rect> smashlist;
smashlist =newList<Rect>();//get piece on the leftif(tosmash._x0 > _x0){
smashlist.Add(newRect(_x0,_y0,tosmash._x0,_y1));
newx0 = tosmash._x0;}//get piece on the rightif(tosmash._x1 < _x1){
smashlist.Add(newRect(tosmash._x1,_y0,_x1,_y1));
newx1 = tosmash._x1;}//get bottom pieceif(tosmash._y0 > _y0)
smashlist.Add(newRect(newx0,_y0,newx1,tosmash._y0));//get top pieceif(tosmash._y1 < _y1)
smashlist.Add(newRect(newx0,tosmash._y1,newx1,_y1));return smashlist;}//We have a rectangle that overlaps this one and we want to break this one//up, removing any overlapping area//Note: parameter should probably be "smasher" to distinguish from "smashee"// but I don't feel like changing all references.publicvoidSmashMe(Rect tosmash){
List<Rect> tocheck;if(subrecs ==null){
subrecs =GetSmashList(tosmash);return;}//We have already broken into subrecs
tocheck =newList<Rect>();//we need to create a copy list since we will be removing things from the original list as we goforeach(Rect r in subrecs)
tocheck.Add(r);//Now we process each of the sub rectanglesforeach(Rect r in tocheck){if(tosmash.Intersects(r)){
subrecs.Remove(r);if(!tosmash.Contains(r)){//need to get left overs
List<Rect> pieces = r.GetSmashList(tosmash);foreach(Rect piece in pieces)
subrecs.Add(piece);}}}}//The following are display routines that made things a bit easier to debug.publicoverridestringToString(){returnstring.Format("({0},{1}) to ({2},{3})",newobject[]{_x0,_y0,_x1,_y1});}publicvoidDisplay(bool withpieces =false){if(isbase){
Console.WriteLine(string.Format("Base ({0},{1}) to ({2},{3})",newobject[]{_x0,_y0,_x1,_y1}));if(withpieces &&(subrecs !=null)){foreach(Rect r in subrecs)
r.Display();
Console.WriteLine(string.Format("Base Done ({0},{1}) to ({2},{3})",newobject[]{_x0,_y0,_x1,_y1}));}}else{
Console.WriteLine(string.Format("-Sub ({0},{1}) to ({2},{3})",newobject[]{_x0,_y0,_x1,_y1}));if(subrecs !=null){foreach(Rect r in subrecs)
r.Display();
Console.WriteLine(string.Format("-Done ({0},{1}) to ({2},{3})",newobject[]{_x0,_y0,_x1,_y1}));}}}}}
答案10:
using System;using System.Collections.Generic;using System.Linq;namespace Solution
{publicstaticclassKata{//list is sortedpublicstatic List<int[]> activeList =newList<int[]>(100);publicstatic List<int[]> events =newList<int[]>(100);publicstaticlongRecalculateTopBottom(){int activeCount = activeList.Count();long size =0;long current =0;for(int i =0; i < activeCount; i++){//get are current bottom
current = current > activeList[i][1]? current : activeList[i][1];//should we add to our size?
size +=(activeList[i][3]-current)>0?(activeList[i][3]-current):0;//see if top should be our current bottom
current = current > activeList[i][3]? current : activeList[i][3];}// Console.WriteLine("size {0}",size);return size;}publicstaticlongSweepMethod(IEnumerable<int[]> rectangles){int iCount = rectangles.Count();if(iCount==0)return0;long total =0;
List<int[]> rects = rectangles.OrderBy(x => x[0]).ToList();
events.Clear();for(int h =0; h < iCount; h++){
events.Add(newint[]{0, rects[h][0], h});
events.Add(newint[]{1, rects[h][2], h});}
events = events.OrderBy(x => x[1]).ToList();//events order when sweping from leftlong iSize =0;
activeList.Clear();int eventCount = events.Count()-1;//minus one because we don't need to do last eventlong lastX = rects[0][0];
Console.WriteLine(eventCount);for(int i =0; i < eventCount && i <1000; i++){//enters rect eventif(events[i][0]==0){//events 2 is its index in the rects array// Console.WriteLine("add {0} {1}", i, events[i][2]);
activeList.Add(rects[events[i][2]]);
activeList = activeList.OrderBy(x => x[1]).ToList();
iSize =RecalculateTopBottom();}else//remove rect event{// Console.WriteLine("remove {0} {1}", i, events[i][2]);bool bAnyChange =false;for(int j =0; j < activeList.Count(); j++){//events 2 is its index in the rects arrayif(rects[events[i][2]]== activeList[j]){//Console.WriteLine("remove event {0}",exitList[j][2]);
activeList.RemoveAt(j);
j--;
bAnyChange =true;}}if(bAnyChange)
iSize =RecalculateTopBottom();}
total +=(iSize*(events[i+1][1]- lastX));//Console.WriteLine("total {0} {1} {2}",total, events[i+1][1], lastX);
lastX = events[i+1][1];//Console.WriteLine();}return total;}publicstaticlongRemoveOverlapMethod(IEnumerable<int[]> rectangles){long total =0;int Count = rectangles.Count();
List<int[]> rects = rectangles.ToList();
List<long[]> removed =newList<long[]>(100);long[] overlap =newlong[4];long[] overlapExtra =newlong[4];
Console.WriteLine("count {0}", rectangles.Count());for(int j =0;(j < Count); j++){
total +=(long)(rects[j][2]-rects[j][0])*(long)(rects[j][3]-rects[j][1]);// Console.WriteLine("rec1 {0} {1} {2} {3}", rects[j][0],rects[j][1],rects[j][2],rects[j][3]);// Console.WriteLine("give areas {0}", (long)(rects[j][2]-rects[j][0])*(long)(rects[j][3]-rects[j][1]));//Console.WriteLine("current {0}", total);
removed.Clear();for(int i =(j+1);(i < Count); i++){if(rects[j][2]<= rects[i][0]|| rects[j][0]>= rects[i][2]|| rects[j][1]>= rects[i][3]|| rects[j][3]<= rects[i][1])continue;
overlap[0]=(rects[j][0]> rects[i][0])? rects[j][0]: rects[i][0];
overlap[1]=(rects[j][1]> rects[i][1])? rects[j][1]: rects[i][1];
overlap[2]=(rects[j][2]< rects[i][2])? rects[j][2]: rects[i][2];
overlap[3]=(rects[j][3]< rects[i][3])? rects[j][3]: rects[i][3];long extraOverlap =0;//*for(int k =0; k < removed.Count(); k++){//Console.WriteLine("O {0} {1} {2} {3}", overlap[0], overlap[1],overlap[2],overlap[3]);//Console.WriteLine("R {0} {1} {2} {3}", removed[k][0], removed[k][1],removed[k][2],removed[k][3]);if(overlap[2]> removed[k][0]&& overlap[0]< removed[k][2]&& overlap[1]< removed[k][3]&& overlap[3]> removed[k][1]){
overlapExtra[0]=(overlap[0]> removed[k][0])? overlap[0]: removed[k][0];
overlapExtra[1]=(overlap[1]> removed[k][1])? overlap[1]: removed[k][1];
overlapExtra[2]=(overlap[2]< removed[k][2])? overlap[2]: removed[k][2];
overlapExtra[3]=(overlap[3]< removed[k][3])? overlap[3]: removed[k][3];
extraOverlap +=(overlapExtra[2]-overlapExtra[0])*(overlapExtra[3]-overlapExtra[1]);//Console.WriteLine("G {0} {1} {2} {3}", overlapExtra[0], overlapExtra[1],overlapExtra[2],overlapExtra[3]);//Console.WriteLine("extraOverlap {0}", (overlapExtra[2]-overlapExtra[0])*(overlapExtra[3]-overlapExtra[1]));}}//*/long removeArea =(overlap[2]-overlap[0])*(overlap[3]-overlap[1]);if(extraOverlap > removeArea)
extraOverlap = removeArea;
total -= removeArea - extraOverlap;//Console.WriteLine("add O {0} {1} {2} {3}", overlap[0], overlap[1],overlap[2],overlap[3]);long[] saveOverlap =newlong[4];
saveOverlap[0]= overlap[0];
saveOverlap[1]= overlap[1];
saveOverlap[2]= overlap[2];
saveOverlap[3]= overlap[3];
removed.Add(saveOverlap);// Console.WriteLine("remove -{0} +{1}", removeArea, extraOverlap);}//Console.WriteLine("after remove {0}", total);// Console.WriteLine();}
Console.WriteLine("ret {0}", total);return total;}publicstaticlongCalculate(IEnumerable<int[]> rectangles){int iCount = rectangles.Count();if(iCount==0)return0;if(iCount <=1000)returnSweepMethod(rectangles);returnRemoveOverlapMethod(rectangles);}}}