Commit | Line | Data |
---|---|---|
3d51f952 MW |
1 | #! /usr/bin/python3 |
2 | ||
3 | import math as M | |
4 | import sys as SYS | |
5 | ||
6 | data = [] | |
7 | for line in SYS.stdin: data.append(float(line)) | |
8 | data.sort() | |
9 | data = [data] | |
10 | ||
11 | def cover(lo, hi): | |
12 | mid = (lo + hi)/2 | |
13 | return mid, 1.0 - lo/mid | |
14 | ||
15 | def metric(vv): | |
16 | print(";; measuring...") | |
17 | tot = 0 | |
18 | for v in vv: | |
19 | spread = M.pow(v[-1] - v[0], 0.5) | |
20 | print(";;\t%g .. %g -> %g" % (v[0], v[-1], spread)) | |
21 | tot += spread | |
22 | return tot | |
23 | ||
24 | def largest_gap(vv): | |
25 | #print(";; finding gap...") | |
26 | best, bestwd = None, None | |
27 | for i, v in enumerate(vv): | |
28 | lo = v[0] | |
29 | for j in range(1, len(v)): | |
30 | hi = v[j] | |
31 | _, spread = cover(lo, hi) | |
32 | #print(";;\t%d/%d: %g .. %g -> %g" % (i, j, lo, hi, spread)) | |
33 | if bestwd is None or spread > bestwd: | |
34 | best, bestwd = (i, j), spread | |
35 | lo = hi | |
36 | #if best is None: print(";; already atomized") | |
37 | #else: print(";; best gap %d/%d; %g" % (best[0], best[1], bestwd)) | |
38 | return best | |
39 | ||
40 | lastmetric = metric(data) | |
41 | while True: | |
42 | best = largest_gap(data) | |
43 | if best is None: break | |
44 | i, j = best | |
45 | newdata = data[:i] + [data[i][:j], data[i][j:]] + data[i + 1:] | |
46 | newmetric = metric(newdata) | |
47 | if newmetric > lastmetric: break | |
48 | lastmetric, data = newmetric, newdata | |
49 | ||
50 | def format_duration(t): | |
51 | f, t = M.modf(t) | |
52 | frac = ("%g" % f)[1:] | |
53 | if t >= 3600: return "%d:%02d:%02d%s" % (t//3600, (t//60)%60, t%60, frac) | |
54 | elif t >= 60: return "%d:%02d%s" % (t//60, t%60, frac) | |
55 | else: return "%d%s s" % (t, frac) | |
56 | ||
57 | for v in data: | |
58 | mid, spread = cover(v[0], v[-1]) | |
59 | print("%s ± %g%%" % (format_duration(mid), 100.0*spread)) |