+dissect_re = re.compile(r'\s+(\d+)\s+x\s+\((([\d/]+ \+ )*[\d/]+)\)')
+
+dissections = {}
+
+def find_min_frag(dissection):
+ ret = None
+ for side in dissection:
+ for count, pieces in side:
+ for piece in pieces:
+ if piece > 0:
+ if ret is None or ret > piece:
+ ret = piece
+ assert ret is not None
+ return ret
+
+def verify(n, m, dissection):
+ collections = [{}, {}]
+ total = 0
+ for count, pieces in dissection[0]:
+ assert sum(pieces) == n
+ total += count
+ for piece in pieces:
+ collections[0].setdefault(piece, 0)
+ collections[0][piece] += count
+ assert total == m
+ total = 0
+ for count, pieces in dissection[1]:
+ assert sum(pieces) == m
+ total += count
+ for piece in pieces:
+ collections[1].setdefault(piece, 0)
+ collections[1][piece] += count
+ assert total == n
+ assert collections[0] == collections[1]
+
+def factor_dissector(n,m):
+ ret = []
+ gcd = fractions.gcd(n,m)
+ for i in range(1, gcd+1):
+ if gcd % i != 0: continue
+ prev = dissections[n/i, m/i]
+ ret.append(([[(i*count, [piece*i for piece in pieces])
+ for count, pieces in prev[0]],
+ [(i*count, [piece*i for piece in pieces])
+ for count, pieces in prev[1]]],
+ "multiply solution for (%d,%d) by %d" % (n/i, m/i, i)))
+
+def add_m_dissector(n,m):
+ if n <= 2*m:
+ return []
+ prev = dissections[(n-m, m)]
+ ret = [prev[0][:], prev[1][:]]
+ for i in range(len(ret[0])):
+ ret[0][i] = (ret[0][i][0], ret[0][i][1] + [m])
+ ret[1].append((m, (m,)))
+ return [(ret, "extend solution for (%d,%d) by %d" % (n-m, m, m))]
+
+def gcd_dissector(n,m):
+ gcd = fractions.gcd(n,m)
+ return [([[(m, (gcd,) * (n/gcd))],
+ [(n, (gcd,) * (m/gcd))]], "trivial gcd solution")]
+
+def invent_dissection(n,m):
+ # Try to come up with a dissection by assorted simple methods.
+ best = 0
+ for dissector in [gcd_dissector, add_m_dissector]:
+ for dissection, this_reason in dissector(n, m):
+ if dissection is None: continue
+ verify(n, m, dissection)
+ this_best = find_min_frag(dissection)
+ if best < this_best:
+ best, best_reason = this_best, this_reason
+ assert best > 0
+ return dissection, this_reason
+
+details = {} # maps (n,m) to a snippet of HTML
+
+def read_and_build_table_cell(n,m):
+ ret = ""