1 import unittest
   2 """
   3 Seminar:FourBoxes problem in [yong27/2003-01-10]
   4 
   5 Wrong approach --> [yong27/2003-01-12] correct. performance improvement
   6 """
   7 import unittest
   8 
   9 def intersect(*args):
  10     result=[]
  11     for x in args[0]:
  12         for other in args[1:]:
  13             if x not in other: break
  14         else:
  15             result.append(x)
  16     return result
  17 
  18 def combo(aList, size=2): 
  19     if size==0 or not aList: 
  20         return [aList[:0]] 
  21     else: 
  22         result = [] 
  23         for i in range(0, (len(aList)-size)+1): 
  24             pick = aList[i:i+1] 
  25             rest = aList[i+1:] 
  26             for x in combo(rest, size-1): 
  27                 result.append(pick+x) 
  28         return result 
  29 
  30 class Rect:
  31     def __init__(self, x1,y1, x2, y2):
  32         self.x1=x1; self.y1=y1
  33         self.x2=x2; self.y2=y2
  34         self.xr=range(x1,x2)
  35         self.yr=range(y1,y2)
  36     def area(self):
  37         return (self.x2-self.x1) * (self.y2-self.y1)
  38     def getPileArea(self, *aRect):
  39         xrList=[self.xr]; yrList=[self.yr]
  40         for rect in aRect:
  41             xrList.append(rect.xr)
  42             yrList.append(rect.yr)
  43         xIts = intersect(*xrList)
  44         yIts = intersect(*yrList)
  45         if xIts and yIts:
  46             return len(xIts) * len(yIts)
  47         else:
  48             return 0
  49 
  50 def main(a,b,c,d):
  51     totalArea = a.area()+b.area()+c.area()+d.area()
  52     for pair in combo([a,b,c,d]):
  53         totalArea -= pair[0].getPileArea(pair[1])
  54     for three in combo([a,b,c,d],3):
  55         totalArea += three[0].getPileArea(three[1],three[2])
  56     totalArea -= a.getPileArea(b,c,d)
  57     return totalArea
  58 
  59 def myProblem():
  60     a=Rect(1,2,4,4)
  61     b=Rect(2,3,5,7)
  62     c=Rect(3,1,6,5)
  63     d=Rect(7,3,8,6)
  64     return main(a,b,c,d)
  65 
  66 class RectTest(unittest.TestCase):
  67     def testIntersect(self):
  68         a = [1,2,3,4]
  69         b = [3,4,5,6]
  70         self.assertEquals([3,4], intersect(a,b))
  71     def testIntersectMultiArgu(self):
  72         a = [[1,2],[0]]
  73         self.assertEquals([], intersect(*a))
  74     def testIntersectThree(self):
  75         a = [1,2,3,4]
  76         b = [3,4,5,6]
  77         c = [4,5,6,7]
  78         self.assertEquals([4], intersect(a,b,c))
  79     def testCombination(self):
  80         self.assertEquals([[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]],
  81                           combo([1,2,3,4]))
  82         self.assertEquals([[1,2],[1,3],[2,3]],combo([1,2,3]))
  83 
  84     def testOneArea(self):
  85         a = Rect(1,2,4,4)
  86         self.assertEquals(6, a.area())
  87     def testIsPile1(self):
  88         a = Rect(0,0,1,1)
  89         b = Rect(1,0,2,1)
  90         self.assertEquals(0, a.getPileArea(b))
  91     def testIsPile2(self):
  92         a = Rect(0,0,2,2)
  93         b = Rect(1,1,3,3)
  94         self.assertEquals(1, a.getPileArea(b))
  95     def testIsPileThree(self):
  96         a = Rect(0,0,2,1)
  97         b = Rect(1,0,3,2)
  98         c = Rect(1,0,2,3)
  99         self.assertEquals(1, a.getPileArea(b,c))
 100     def testMain(self):
 101         self.assertEquals(26, myProblem())
 102 
 103 def specialProblem():
 104     a=Rect(1,2,800,600)
 105     b=Rect(2,3,700,900)
 106     c=Rect(3,1,666,666)
 107     d=Rect(7,3,1000,888)
 108     return main(a,b,c,d)
 109 
 110 if __name__=='__main__':
 111     #unittest.main(argv=('','-v'))
 112     print specialProblem()
web biohackers.net