zholnin

Google Code Jam Helper file

Apr 11th, 2014
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.98 KB | None | 0 0
  1. import multiprocessing
  2. import cPickle
  3. import time
  4. import bisect
  5. import math
  6. from files import *
  7.  
  8. """
  9. Things yet to do:
  10.  
  11. """
  12.  
  13. BABY = 0
  14. SMALL = 1
  15. LARGE = 2
  16. PSMALL = 3
  17. PLARGE = 4
  18.  
  19. def doit(preprocess, readinput, solve, MultiCore = True, Verify = False, Input  = None, Filename = None, Problem = "A", Attempt = 0, SingleCase = False):
  20.     start_time = time.time()
  21.  
  22.     if Input == None:
  23.         if Filename == None:
  24.             print "Input Filename Not specified."
  25.             return
  26.         INPUTNAME = Filename
  27.     else:
  28.         INPUTNAME = Problem + "_baby.in"
  29.         if Input == SMALL: INPUTNAME = Problem + "-small-attempt" + str(Attempt) + ".in"
  30.         if Input == LARGE: INPUTNAME = Problem + "-large.in"
  31.         if Input == PSMALL: INPUTNAME = Problem + "-small-practice.in"
  32.         if Input == PLARGE: INPUTNAME = Problem + "-large-practice.in"
  33.            
  34.        
  35.    
  36.     OUTPUTNAME = INPUTNAME[:INPUTNAME.find(".")] + ".out"
  37.    
  38.     Input = File(INPUTNAME, "r")
  39.     Correct = None
  40.    
  41.     if Verify == True:
  42.         try:
  43.             Output = File(OUTPUTNAME, "r")
  44.             Correct = Output.readall()
  45.         except IOError:
  46.             print "Verification not possible - output file does not exist. Fall back to normal mode."
  47.             Verify = False
  48.             Output = File(OUTPUTNAME, "w")
  49.     else:
  50.         Output = File(OUTPUTNAME, "wb")
  51.    
  52.     PREPNAME = Problem + ".prep"
  53.     try:
  54.         pfile = open(PREPNAME, "rb")
  55.         Prep = cPickle.load(pfile)
  56.         pfile.close()
  57.         print "Loaded preprocessed information from file"
  58.     except IOError:
  59.         Prep = preprocess()
  60.         if Prep <> None:
  61.             pfile = open(PREPNAME, "wb")
  62.             cPickle.dump(Prep, pfile, 2)
  63.             pfile.close()
  64.             print "Saved preprocessed information to file"            
  65.    
  66.     if SingleCase == True:
  67.         n_cases = 1
  68.     else:
  69.         n_cases = Input.readint()
  70.    
  71.     Problems = []
  72.    
  73.     # Just reading input
  74.     for _ in range(n_cases):
  75.         Problems.append(readinput(Input))
  76.        
  77.     AllCorrect = True
  78.    
  79.     if MultiCore:
  80.         pool = multiprocessing.Pool(processes = 6)
  81.         Result = [pool.apply_async(solve, [p, Prep]) for p in Problems]
  82.    
  83.     for n in range(n_cases):
  84.         if MultiCore:
  85.             Solution = Result[n].get()
  86.         else:
  87.             Solution = solve(Problems[n], Prep)
  88.            
  89.         sline = "Case #" + str(n+1) + ": " + str(Solution)
  90.        
  91.         print sline
  92.  
  93.         if not Verify:
  94.             Output.write(sline + "\n")
  95.         else:
  96.             for line in split(sline, "\n"):
  97.                 if len(Correct) == 0 or line.rstrip("\n") <> Correct[0].rstrip("\n"):
  98.                     print "MISMATCH: ", line,
  99.                     AllCorrect = False
  100.                     if len(Correct) > 0: print Correct[0]
  101.                     else: print ""
  102.                 if len(Correct) > 0: Correct.pop(0)
  103.    
  104.         TOT = (time.time() - start_time) / (n + 1) * n_cases
  105.         if TOT > 120:
  106.             print "Running over two minutes by:", int (TOT - 120), "seconds"
  107.    
  108.     print time.time() - start_time, "seconds"
  109.     if Verify and AllCorrect == False:
  110.         print "VERIFICATION FAILED - ERRORS WERE FOUND IN SOLUTION"
  111.    
  112.     return
  113.  
  114. Primes = None
  115.  
  116. def frange(x, y, jump):
  117.     while x < y:
  118.         yield x
  119.         x += jump
  120.  
  121. def getPrimes(A, B):
  122.     global Primes
  123.     """get primes between A and B inclusive"""
  124.     if Primes == None:
  125.         pfile = open("Primes.prep", "rb")
  126.         Primes = cPickle.load(pfile)
  127.         pfile.close()
  128.    
  129.     if B > 15485863:
  130.         print "Sorry, no data on primes so large"
  131.         quit()
  132.    
  133.     S = bisect.bisect_left(Primes, A)
  134.     E = bisect.bisect_left(Primes, B + 1)
  135.     return Primes[S:E]
  136.  
  137.  
  138. def ncr(n, r):
  139.     r = min(r, n-r)
  140.     if r == 0: return 1
  141.     if r < 0: return 0
  142.     num = reduce(mul, xrange(n, n-r, -1))
  143.     denom = reduce(mul, xrange(1, r+1))
  144.     return num/denom
  145.  
  146. def memoize(f):
  147.     cache= {}
  148.     def memf(*x):
  149.         if x not in cache:
  150.             cache[x] = f(*x)
  151.         return cache[x]
  152.     return memf
  153.  
  154. def Transpose(M):
  155.     X = len(M)
  156.     Y = len(M[0])
  157.     A = []
  158.     for y in range(Y):
  159.         B = [0] * X
  160.         for x in range(X):
  161.             B[x] = M[x][y]
  162.         A.append(B)
  163.     return A
  164.  
  165. def bin_search_max(function, search_from, search_to, *args):
  166.     """
  167.    function - function to test - must return True when result is OK.
  168.    search_from - search from where (integer!)
  169.    search_to - search to where (integer!)
  170.    """
  171.    
  172.     while search_from <> search_to:
  173.         guess = (search_from + search_to) / 2 + 1
  174.         if function(guess, *args):
  175.             search_from = guess
  176.         else:
  177.             search_to = guess - 1
  178.    
  179.     return search_from
  180.  
  181. def bin_search_max_float(function, search_from, search_to, precision, *args):
  182.     """
  183.    function - function to test - must return True when result is OK.
  184.    search_from - search from where (integer!)
  185.    search_to - search to where (integer!)
  186.    """
  187.    
  188.     while abs(search_from - search_to) > precision:
  189.         guess = (search_from + search_to) / 2.0
  190.         if function(guess, *args):
  191.             search_from = guess
  192.         else:
  193.             search_to = guess
  194.    
  195.     return search_from
  196.  
  197. def bin_search_min_float(function, search_from, search_to, precision, *args):
  198.     """
  199.    function - function to test - must return True when result is OK.
  200.    search_from - search from where (integer!)
  201.    search_to - search to where (integer!)
  202.    """
  203.    
  204.     while abs(search_from - search_to) > precision:
  205.         guess = (search_from + search_to) / 2.0
  206.         if function(guess, *args):
  207.             search_to = guess
  208.         else:
  209.             search_from = guess
  210.    
  211.     return search_from
  212.  
  213. def bin_search_min(function, search_from, search_to, *args):
  214.     """
  215.    function - function to test - must return True when result is OK.
  216.    search_from - search from where (integer!)
  217.    search_to - search to where (integer!)
  218.    """
  219.    
  220.     while search_from <> search_to:
  221.         guess = (search_from + search_to) / 2
  222.         if function(guess, *args):
  223.             search_to = guess
  224.         else:
  225.             search_from = guess + 1
  226.    
  227.     return search_from
  228.  
  229.  
  230. def bin_search(function, search_result, search_from, search_to, precision, *args):
  231.     """
  232.    function - function to test
  233.    search_result - what to look for (which number)
  234.    search_from - search from where
  235.    search_to - search to where
  236.    precision - precision for comparison to test result
  237.    """
  238.     W = search_to - search_from
  239.     step =  W / 4.0
  240.     initial = W / 2.0 + search_from
  241.     s = function(initial, *args)
  242.    
  243.     while abs(step) > precision:
  244.         if s > search_result and step > 0:
  245.             step = - step / 2
  246.         if s < search_result and step < 0:
  247.             step = - step / 2
  248.         initial = initial + step
  249.         s = function(initial, *args)
  250.     return initial
  251.  
  252. def square_matrix_multiply(a, b):
  253.     s = len(a)
  254.     r = []
  255.    
  256.     for x in range(s):
  257.         r.append([0] * s)
  258.         for y in range(s):
  259.             for t in range(s):
  260.                 r[x][y] += (a[x][t] * b[t][y])
  261.                 r[x][y] = r[x][y]
  262.    
  263.     return r
  264.  
  265. def fastpower(m, x, p):
  266.     """return a**b % q"""
  267.     val = x
  268.     mult = x
  269.     p -= 1
  270.    
  271.     while p > 0:
  272.         odd = p & 1 # bitwise and
  273.         if odd == 1:
  274.             val = m(val, mult)
  275.             p -= 1
  276.         if p == 0:
  277.             break
  278.         mult = m(mult, mult)
  279.         p = p >> 1 # bitwise divide by 2
  280.     return val
  281.  
  282. def feq(a, b):
  283.     return fabs(a-b) < 1e-8
  284.  
  285. def next_permutation(L):
  286.     B = len(L) - 1
  287.     while L[B] <= L[B-1]:
  288.         B = B - 1
  289.         if (B == 0):
  290.             return sorted(L)
  291.    
  292.     b = B
  293.     for x in range(B, len(L)):
  294.         if L[b] > L[x] and L[x] > L[B-1]:
  295.             b = x
  296.    
  297.     (L[b], L[B - 1]) = (L[B - 1], L[b])
  298.     L = L[:B] + sorted(L[B:])
  299.     return L
  300.  
  301. def semi_circle_segment(x0, x1, R):
  302.     def integral(x, R):
  303.         h = R - x
  304.         return (R**2*acos((R-h)/R) - (R-h)*sqrt(2*R*h-h**2))/2
  305.    
  306.     return - integral(x1, R) + integral(x0, R)
  307.  
  308. def isqrt(x):
  309.     if x < 0:
  310.         raise ValueError('square root not defined for negative numbers')
  311.     n = int(x)
  312.     if n == 0:
  313.         return 0
  314.     a, b = divmod(n.bit_length(), 2)
  315.     x = 2**(a+b)
  316.     while True:
  317.         y = (x + n//x)//2
  318.         if y >= x:
  319.             return x
  320.         x = y  
  321.  
  322.  
  323. class File:
  324.     def __init__(self, filename, mode):
  325.         self.handle = open(filename, mode)
  326.         self.cursor = 0
  327.         self.filename = filename
  328.         self.mode = mode
  329.         if mode == "r":
  330.             self.lines = self.handle.readlines()
  331.    
  332.     def __del__(self):
  333.         self.handle.close()
  334.        
  335.     def readint(self):
  336.         a = int(self.lines[self.cursor])
  337.         self.cursor += 1
  338.         return a
  339.    
  340.     def readall(self):
  341.         return self.lines
  342.    
  343.     def readbinary(self):
  344.         self.handle.close()
  345.         self.handle = open(self.filename, "rb")
  346.         return self.handle.read()
  347.  
  348.     def readints(self):
  349.         ints = self.lines[self.cursor]
  350.         ints = strip(ints, "\n")
  351.         ints = strip(ints, " ")
  352.         while "  " in ints:
  353.             ints = ints.replace("  ", " ")
  354.         ints = ints.split(" ")
  355.         for a in range(len(ints)):
  356.             ints[a] = int(ints[a])
  357.         self.cursor += 1
  358.         return ints
  359.  
  360.     def readfloats(self):
  361.         ints = self.lines[self.cursor]
  362.         ints = strip(ints, "\n")
  363.         ints = ints.split(" ")
  364.         for a in range(len(ints)):
  365.             ints[a] = float(ints[a])
  366.         self.cursor += 1
  367.         return ints
  368.  
  369.     def readstring(self):
  370.         a = self.lines[self.cursor]
  371.         a = strip(a, "\n")
  372.         self.cursor += 1
  373.         return a
  374.    
  375.     def readstrings(self):
  376.         a = self.lines[self.cursor]
  377.         a = strip(a, "\n")
  378.         a = a.split(" ")
  379.         self.cursor += 1
  380.         return a
  381.    
  382.     def write(self, line):
  383.         self.handle.write(line)
  384.         return
  385.  
  386.     def writeint(self, number):
  387.         self.handle.write(str(number))
  388.         return
  389.        
  390.     def writefloat(self, fl, after):
  391.         self.handle.write(("%." + str(after) + "f") % fl)
  392.         return
  393.        
  394.     def nextline(self):
  395.         self.handle.write("\n")
  396.         return
  397.        
  398.        
  399.     """Matrix = numpy.array(Matrix, dtype = numpy.int64)"""
  400.    
  401.    
  402. class UnionFind:
  403.     def __init__(self):
  404.         '''\
  405. Create an empty union find data structure.'''
  406.         self.num_weights = {}
  407.         self.parent_pointers = {}
  408.         self.num_to_objects = {}
  409.         self.objects_to_num = {}
  410.         self.unique = 0
  411.        
  412.     def insert_objects(self, objects):
  413.         '''\
  414. Insert a sequence of objects into the structure.  All must be Python hashable.'''
  415.         for object in objects:
  416.             self.find(object);
  417.            
  418.     def find(self, object):
  419.         '''\
  420. Find the root of the set that an object is in.
  421. If the object was not known, will make it known, and it becomes its own set.
  422. Object must be Python hashable.'''
  423.         if not object in self.objects_to_num:
  424.             obj_num = len(self.objects_to_num)
  425.             self.num_weights[obj_num] = 1
  426.             self.objects_to_num[object] = obj_num
  427.             self.num_to_objects[obj_num] = object
  428.             self.parent_pointers[obj_num] = obj_num
  429.             self.unique += 1
  430.             return object
  431.         stk = [self.objects_to_num[object]]
  432.         par = self.parent_pointers[stk[-1]]
  433.         while par != stk[-1]:
  434.             stk.append(par)
  435.             par = self.parent_pointers[par]
  436.         for i in stk:
  437.             self.parent_pointers[i] = par
  438.         return self.num_to_objects[par]
  439.    
  440.     def union(self, object1, object2):
  441.         '''\
  442. Combine the sets that contain the two objects given.
  443. Both objects must be Python hashable.
  444. If either or both objects are unknown, will make them known, and combine them.'''
  445.         o1p = self.find(object1)
  446.         o2p = self.find(object2)
  447.         if o1p != o2p:
  448.             on1 = self.objects_to_num[o1p]
  449.             on2 = self.objects_to_num[o2p]
  450.             w1 = self.num_weights[on1]
  451.             w2 = self.num_weights[on2]
  452.             if w1 < w2:
  453.                 o1p, o2p, on1, on2, w1, w2 = o2p, o1p, on2, on1, w2, w1
  454.             self.num_weights[on1] = w1+w2
  455.             del self.num_weights[on2]
  456.             self.parent_pointers[on2] = on1
  457.             self.unique -= 1
  458.     def getUnique(self):
  459.         return self.unique
  460.  
  461.  
  462. class mod_calc:
  463.     def __init__(self, m):
  464.         self.m = m
  465.         self.fact_table = None
  466.        
  467.         self.pre_fact(m)
  468.    
  469.     def pre_fact(self, m):
  470.         f = 1
  471.         res = [1]
  472.         for n in range(1, m):
  473.             f = (f*n)%m
  474.             res.append(f)
  475.         return res
  476.  
  477.     def factorial(self, n):
  478.         if self.fact_table == None:
  479.             self.fact_table = self.pre_fact(self.m)
  480.         if n==0:
  481.             return 1
  482.         r = n%self.m
  483.         k = n//self.m
  484.         kk = 1
  485.         if k%2==1:
  486.             kk = -1
  487.         return (self.fact_table[r]*self.factorial(k)*kk)%self.m
  488.  
  489.     def fact_ord(self, n):
  490.         r = n%self.m
  491.         k = n//self.m
  492.         if k==0:
  493.             return 0
  494.         return k+self.fact_ord(k)
  495.  
  496.     def gcd(self, a, b):
  497.         if b==0:
  498.             return [1,0]
  499.         k = a//b
  500.         r = a-b*k
  501.         g = self.gcd(b, r)
  502.         return [g[1], g[0]-g[1]*k]
  503.  
  504.     def inv(self, x):
  505.         g = self.gcd(self.m, x)
  506.         return g[1]%self.m
  507.    
  508.     def ncr(self, n, r):
  509.         if self.fact_ord(n)>self.fact_ord(r)+self.fact_ord(n-r):
  510.             return 0
  511.         return (self.factorial(n)*self.inv((self.factorial(r)*self.factorial(n-r))%self.m))%self.m    
  512.  
  513. def rotate_coordinates_clockwise(xr, yr, alpha):
  514.     """point stays still, coordinate axis rotate clockwise by angle alpha"""
  515.     y = yr * math.cos(alpha) + xr * math.sin(alpha)
  516.     x = xr * math.cos(alpha) - yr * math.sin(alpha)
  517.     return x, y
  518.    
  519. def point_left_line(a, b, c):
  520.     """a and b are two points of line, showing direction. c is point to be determined"""
  521.     r = (b[0] - a[0])*(c[1] - a[1]) - (b[1] - a[1])*(c[0] - a[0])
  522.  
  523.     if r > 1e-15:
  524.         return True
  525.    
  526.     elif r < -1e-15:
  527.         return False
  528.    
  529.     return None
  530.    
  531. def convex_hull(points):
  532.     points = sorted(set(points))
  533.     if len(points) <= 1:
  534.         return points
  535.     def cross(o, a, b):
  536.         return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
  537.     lower = []
  538.     for p in points:
  539.         while len(lower) >= 2 and cross(lower[-2], lower[-1], p) <= 0:
  540.             lower.pop()
  541.         lower.append(p)
  542.     upper = []
  543.     for p in reversed(points):
  544.         while len(upper) >= 2 and cross(upper[-2], upper[-1], p) <= 0:
  545.             upper.pop()
  546.         upper.append(p)
  547.     return lower[:-1] + upper[:-1]
Add Comment
Please, Sign In to add comment