View difference between Paste ID: 5gkyim8x and RNbC6TtE
SHOW: | | - or go back to the newest paste.
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)
80+
        pool = multiprocessing.Pool(processes = 4)
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
largestPrime = None
116
117
def frange(x, y, jump):
118
    while x < y:
119
        yield x
120
        x += jump
121
122
def loadPrimes(N):
123
    global Primes
124
    global largestPrime
125-
        pfile = open("Primes.prep", "rb")
125+
126
        pfile = open("Primes" + str(N) + ".prep", "rb")
127
        Primes = cPickle.load(pfile)
128
        largestPrime = N
129-
    if B > 15485863:
129+
130
    except IOError:
131
        s = set(range(3, N + 1, 2))
132
        Primes = [2]
133
        for i in range(3, N + 1, 2):
134
            if i not in s:
135
                continue
136
    
137
            Primes.append(i)
138
            
139
            k = 2
140
            while k*i <= N:
141
                if k*i in s:
142
                    s.remove(k*i)
143
                k += 1
144
        pfile = open("Primes" + str(N) + ".prep", "wb")
145
        cPickle.dump(Primes, pfile, 2)
146
        largestPrime = N
147
    return
148
     
149
150
def getPrimes(A, B):
151
    global Primes
152
    global largestPrime
153
    """get primes between A and B inclusive"""
154
    if Primes == None:
155
        print "Prime numbers are not initialized"
156
        quit()
157
    
158
    if B > largestPrime:
159
        print "Sorry, no data on primes so large"
160
        quit()
161
    
162
    S = bisect.bisect_left(Primes, A)
163
    E = bisect.bisect_left(Primes, B + 1)
164
    return Primes[S:E]
165
166
167
def ncr(n, r):
168
    r = min(r, n-r)
169
    if r == 0: return 1
170
    if r < 0: return 0
171
    num = reduce(mul, xrange(n, n-r, -1))
172
    denom = reduce(mul, xrange(1, r+1))
173
    return num/denom
174
175
def memoize(f):
176
    cache= {}
177
    def memf(*x):
178
        if x not in cache:
179
            cache[x] = f(*x)
180
        return cache[x]
181
    return memf
182
183
def Transpose(M):
184
    X = len(M)
185
    Y = len(M[0])
186
    A = []
187
    for y in range(Y):
188
        B = [0] * X
189
        for x in range(X):
190
            B[x] = M[x][y]
191
        A.append(B)
192
    return A
193
194
def bin_search_max(function, search_from, search_to, *args):
195
    """
196
    function - function to test - must return True when result is OK.
197
    search_from - search from where (integer!)
198
    search_to - search to where (integer!)
199
    """
200
    
201
    while search_from <> search_to:
202
        guess = (search_from + search_to) / 2 + 1
203
        if function(guess, *args):
204
            search_from = guess 
205
        else:
206
            search_to = guess - 1
207
    
208
    return search_from
209
210
def bin_search_max_float(function, search_from, search_to, precision, *args):
211
    """
212
    function - function to test - must return True when result is OK.
213
    search_from - search from where (integer!)
214
    search_to - search to where (integer!)
215
    """
216
    
217
    while abs(search_from - search_to) > precision:
218
        guess = (search_from + search_to) / 2.0
219
        if function(guess, *args):
220
            search_from = guess 
221
        else:
222
            search_to = guess
223
    
224
    return search_from
225
226
def bin_search_min_float(function, search_from, search_to, precision, *args):
227
    """
228
    function - function to test - must return True when result is OK.
229
    search_from - search from where (integer!)
230
    search_to - search to where (integer!)
231
    """
232
    
233
    while abs(search_from - search_to) > precision:
234
        guess = (search_from + search_to) / 2.0
235
        if function(guess, *args):
236
            search_to = guess 
237
        else:
238
            search_from = guess
239
    
240
    return search_from
241
242
def bin_search_min(function, search_from, search_to, *args):
243
    """
244
    function - function to test - must return True when result is OK.
245
    search_from - search from where (integer!)
246
    search_to - search to where (integer!)
247
    """
248
    
249
    while search_from <> search_to:
250
        guess = (search_from + search_to) / 2
251
        if function(guess, *args):
252
            search_to = guess 
253
        else:
254
            search_from = guess + 1
255
    
256
    return search_from
257
258
259
def bin_search(function, search_result, search_from, search_to, precision, *args):
260
    """
261
    function - function to test
262
    search_result - what to look for (which number)
263
    search_from - search from where
264
    search_to - search to where
265
    precision - precision for comparison to test result
266
    """
267
    W = search_to - search_from
268
    step =  W / 4.0
269
    initial = W / 2.0 + search_from
270
    s = function(initial, *args)
271
    
272
    while abs(step) > precision:
273
        if s > search_result and step > 0:
274
            step = - step / 2
275
        if s < search_result and step < 0:
276
            step = - step / 2
277
        initial = initial + step
278
        s = function(initial, *args)
279
    return initial
280
281
def square_matrix_multiply(a, b):
282
    s = len(a)
283
    r = []
284
    
285
    for x in range(s):
286
        r.append([0] * s)
287
        for y in range(s):
288
            for t in range(s):
289
                r[x][y] += (a[x][t] * b[t][y])
290
                r[x][y] = r[x][y]
291
    
292
    return r 
293
294
def fastpower(m, x, p):
295
    """return a**b % q"""
296
    val = x
297
    mult = x
298
    p -= 1
299
    
300
    while p > 0:
301
        odd = p & 1 # bitwise and
302
        if odd == 1:
303
            val = m(val, mult)
304
            p -= 1
305
        if p == 0:
306
            break
307
        mult = m(mult, mult)
308
        p = p >> 1 # bitwise divide by 2
309
    return val
310
311
def feq(a, b):
312
    return fabs(a-b) < 1e-8
313
314
def next_permutation(L):
315
    B = len(L) - 1
316
    while L[B] <= L[B-1]:
317
        B = B - 1
318
        if (B == 0):
319
            return sorted(L)
320
    
321
    b = B
322
    for x in range(B, len(L)):
323
        if L[b] > L[x] and L[x] > L[B-1]:
324
            b = x
325
    
326
    (L[b], L[B - 1]) = (L[B - 1], L[b])
327
    L = L[:B] + sorted(L[B:])
328
    return L
329
330
def semi_circle_segment(x0, x1, R):
331
    def integral(x, R):
332
        h = R - x
333
        return (R**2*acos((R-h)/R) - (R-h)*sqrt(2*R*h-h**2))/2
334
    
335
    return - integral(x1, R) + integral(x0, R)
336
337
def isqrt(x):
338
    if x < 0:
339
        raise ValueError('square root not defined for negative numbers')
340
    n = int(x)
341
    if n == 0:
342
        return 0
343
    a, b = divmod(n.bit_length(), 2)
344
    x = 2**(a+b)
345
    while True:
346
        y = (x + n//x)//2
347
        if y >= x:
348
            return x
349
        x = y   
350
351
def ilog(x, b):
352
    if b == 1:
353
        raise "Log base 1 fail"
354
    a = -1
355
    bb = 1
356
    while bb <= x:
357
        bb *= b
358
        a += 1
359
    return a
360
361
class File:
362
    def __init__(self, filename, mode):
363
        self.handle = open(filename, mode)
364
        self.cursor = 0
365
        self.filename = filename
366
        self.mode = mode
367
        if mode == "r":
368
            self.lines = self.handle.readlines()
369
    
370
    def __del__(self):
371
        self.handle.close()
372
        
373
    def readint(self):
374
        a = int(self.lines[self.cursor])
375
        self.cursor += 1
376
        return a
377
    
378
    def readall(self):
379
        return self.lines
380
    
381
    def readbinary(self):
382
        self.handle.close()
383
        self.handle = open(self.filename, "rb")
384
        return self.handle.read()
385
386
    def readints(self):
387
        ints = self.lines[self.cursor]
388
        ints = strip(ints, "\n")
389
        ints = strip(ints, " ")
390
        while "  " in ints:
391
            ints = ints.replace("  ", " ")
392
        ints = ints.split(" ")
393
        for a in range(len(ints)):
394
            ints[a] = int(ints[a])
395
        self.cursor += 1
396
        return ints
397
398
    def readfloats(self):
399
        ints = self.lines[self.cursor]
400
        ints = strip(ints, "\n")
401
        ints = ints.split(" ")
402
        for a in range(len(ints)):
403
            ints[a] = float(ints[a])
404
        self.cursor += 1
405
        return ints
406
407
    def readstring(self):
408
        a = self.lines[self.cursor]
409
        a = strip(a, "\n")
410
        self.cursor += 1
411
        return a
412
    
413
    def readstrings(self):
414
        a = self.lines[self.cursor]
415
        a = strip(a, "\n")
416
        a = a.split(" ")
417
        self.cursor += 1
418
        return a
419
    
420
    def write(self, line):
421
        self.handle.write(line)
422
        return
423
424
    def writeint(self, number):
425
        self.handle.write(str(number))
426
        return
427
        
428
    def writefloat(self, fl, after):
429
        self.handle.write(("%." + str(after) + "f") % fl)
430
        return
431
        
432
    def nextline(self):
433
        self.handle.write("\n")
434
        return
435
        
436
        
437
    """Matrix = numpy.array(Matrix, dtype = numpy.int64)"""
438
    
439
    
440
class UnionFind:
441
    def __init__(self):
442
        '''\
443
Create an empty union find data structure.'''
444
        self.num_weights = {}
445
        self.parent_pointers = {}
446
        self.num_to_objects = {}
447
        self.objects_to_num = {}
448
        self.unique = 0
449
        
450
    def insert_objects(self, objects):
451
        '''\
452
Insert a sequence of objects into the structure.  All must be Python hashable.'''
453
        for object in objects:
454
            self.find(object);
455
            
456
    def find(self, object):
457
        '''\
458
Find the root of the set that an object is in.
459
If the object was not known, will make it known, and it becomes its own set.
460
Object must be Python hashable.'''
461
        if not object in self.objects_to_num:
462
            obj_num = len(self.objects_to_num)
463
            self.num_weights[obj_num] = 1
464
            self.objects_to_num[object] = obj_num
465
            self.num_to_objects[obj_num] = object
466
            self.parent_pointers[obj_num] = obj_num
467
            self.unique += 1
468
            return object
469
        stk = [self.objects_to_num[object]]
470
        par = self.parent_pointers[stk[-1]]
471
        while par != stk[-1]:
472
            stk.append(par)
473
            par = self.parent_pointers[par]
474
        for i in stk:
475
            self.parent_pointers[i] = par
476
        return self.num_to_objects[par]
477
    
478
    def union(self, object1, object2):
479
        '''\
480
Combine the sets that contain the two objects given.
481
Both objects must be Python hashable.
482
If either or both objects are unknown, will make them known, and combine them.'''
483
        o1p = self.find(object1)
484
        o2p = self.find(object2)
485
        if o1p != o2p:
486
            on1 = self.objects_to_num[o1p]
487
            on2 = self.objects_to_num[o2p]
488
            w1 = self.num_weights[on1]
489
            w2 = self.num_weights[on2]
490
            if w1 < w2:
491
                o1p, o2p, on1, on2, w1, w2 = o2p, o1p, on2, on1, w2, w1
492
            self.num_weights[on1] = w1+w2
493
            del self.num_weights[on2]
494
            self.parent_pointers[on2] = on1
495
            self.unique -= 1
496
    def getUnique(self):
497
        return self.unique
498
499
500
class mod_calc:
501
    def __init__(self, m):
502
        self.m = m
503
        self.fact_table = None
504
        
505
        self.pre_fact(m)
506
    
507
    def pre_fact(self, m):
508
        f = 1
509
        res = [1]
510
        for n in range(1, m):
511
            f = (f*n)%m
512
            res.append(f)
513
        return res
514
515
    def factorial(self, n):
516
        if self.fact_table == None:
517
            self.fact_table = self.pre_fact(self.m)
518
        if n==0:
519
            return 1
520
        r = n%self.m
521
        k = n//self.m
522
        kk = 1
523
        if k%2==1:
524
            kk = -1
525
        return (self.fact_table[r]*self.factorial(k)*kk)%self.m
526
527
    def fact_ord(self, n):
528
        r = n%self.m
529
        k = n//self.m
530
        if k==0:
531
            return 0
532
        return k+self.fact_ord(k)
533
534
    def gcd(self, a, b):
535
        if b==0:
536
            return [1,0]
537
        k = a//b
538
        r = a-b*k
539
        g = self.gcd(b, r)
540
        return [g[1], g[0]-g[1]*k]
541
542
    def inv(self, x):
543
        g = self.gcd(self.m, x)
544
        return g[1]%self.m
545
    
546
    def ncr(self, n, r):
547-
    return lower[:-1] + upper[:-1]
547+
548
            return 0
549
        return (self.factorial(n)*self.inv((self.factorial(r)*self.factorial(n-r))%self.m))%self.m    
550
551
def rotate_coordinates_clockwise(xr, yr, alpha):
552
    """point stays still, coordinate axis rotate clockwise by angle alpha"""
553
    y = yr * math.cos(alpha) + xr * math.sin(alpha)
554
    x = xr * math.cos(alpha) - yr * math.sin(alpha)
555
    return x, y
556
    
557
def point_left_line(a, b, c):
558
    """a and b are two points of line, showing direction. c is point to be determined"""
559
    r = (b[0] - a[0])*(c[1] - a[1]) - (b[1] - a[1])*(c[0] - a[0])
560
561
    if r > 1e-15:
562
        return True
563
    
564
    elif r < -1e-15:
565
        return False
566
    
567
    return None
568
    
569
def convex_hull(points):
570
    points = sorted(set(points))
571
    if len(points) <= 1:
572
        return points
573
    def cross(o, a, b):
574
        return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
575
    lower = []
576
    for p in points:
577
        while len(lower) >= 2 and cross(lower[-2], lower[-1], p) <= 0:
578
            lower.pop()
579
        lower.append(p)
580
    upper = []
581
    for p in reversed(points):
582
        while len(upper) >= 2 and cross(upper[-2], upper[-1], p) <= 0:
583
            upper.pop()
584
        upper.append(p)
585
    return lower[:-1] + upper[:-1]
586
 
587
def findSCCs(Graph, n = None):
588
    """Graph with vertices numbered from 1...n, represented as Dictionary""" 
589
        
590
    if n == None:
591
        n = len(Graph)
592
        
593
    po={}
594
    ll={}
595
    sf={}
596
    sq = []
597
    sl=[]
598
    i=0
599
    for s in xrange(1, n+1):
600
        if s not in sf:
601
            queue=[s]
602
            while queue:
603
                v=queue[-1]
604
                if v not in po:
605
                    i=i+1
606
                    po[v]=i
607
                done=1
608
                v_nbrs=Graph.get(v, [])
609
                for w in v_nbrs:
610
                    if w not in po:
611
                        queue.append(w)
612
                        done=0
613
                        break
614
                if done==1:
615
                    ll[v]=po[v]
616
                    for w in v_nbrs:
617
                        if w not in sf:
618
                            if po[w]>po[v]:
619
                                ll[v]=min([ll[v],ll[w]])
620
                            else:
621
                                ll[v]=min([ll[v],po[w]])
622
                    queue.pop()
623
                    if ll[v]==po[v]:
624
                        sf[v]=True
625
                        scc=[v]
626
                        while sq and po[sq[-1]]>po[v]:
627
                            k=sq.pop()
628
                            sf[k]=True
629
                            scc.append(k)
630
                        sl.append(scc)
631
                    else:
632
                        sq.append(v)
633
    return sl