3 import sys, re, fractions
4 from fractions import Fraction
8 def got(n, m, minfrag, matrix):
9 # Search for a common denominator to re-express our entire matrix
10 # as rationals. We do this by rounding every matrix element
11 # (fragment length) to its nearest multiple of the candidate
12 # denominator, and seeing if the result still comes out as a legal
17 rmatrix = [[Fraction(int(round(d*x)), d)
18 for x in mrow] for mrow in matrix]
22 # Check that the dissection is still valid.
24 if sum(rmatrix[i]) != m:
30 if sum([rmatrix[i][j] for i in range(n)]) != n:
36 # Find the new minimum fragment length, and verify that it's
37 # about the same as the old one. (Protects against the
38 # possibility of a case where rounding every frag gives a
39 # legal but worse dissection.)
40 rminfrag = min([x for x in sum(rmatrix,[]) if x > 0])
41 if abs(rminfrag / minfrag - 1) < 1e-5:
44 # And store what we've now got, so we can later peruse our entire
45 # data set in a sensible order.
46 results[(n,m)] = (rminfrag, rmatrix)
49 return [x for x in a if x != 0]
52 for (n, m), (minfrag, matrix) in sorted(results.items()):
53 print "%d into %d: %s" % (n, m, str(minfrag))
54 # Reduce the matrix representation to just indicating how
55 # everything is cut up.
58 sorted_row = tuple(sorted(dezero(mrow), reverse=True))
59 rows.setdefault(sorted_row, 0)
61 rowout = sorted([(rows[r], r) for r in rows])
64 sorted_col = tuple(sorted(dezero([matrix[i][j]
67 cols.setdefault(sorted_col, 0)
69 colout = sorted([(cols[r], r) for r in cols])
70 print " Cut up %d sticks of length %d like this:" % (n, m)
71 for count, row in sorted(rowout, reverse=True):
72 print " %d x (%s)" % (count, " + ".join(map(str,row)))
73 print " Reassemble as %d sticks of length %d like this:" % (m, n)
74 for count, col in sorted(colout, reverse=True):
75 print " %d x (%s)" % (count, " + ".join(map(str,col)))
77 heading_re = re.compile(r'^(\d+) into (\d+): min fragment ([\d\.]+)')
83 match = heading_re.search(line)
85 n = int(match.group(1))
86 m = int(match.group(2))
87 minfrag = float(match.group(3))
89 # Now expect n lines of m matrix elements each.
95 mentry = mline[10*j:10*(j+1)]
96 if mentry == " " * 10:
99 mrow.append(float(mentry))
102 got(n, m, minfrag, matrix)
113 if __name__ == "__main__":