from math import prod # bounds N = 99999 C = 16 # precondition k <= n def all_partitions_(n, k): if n == 0: return [[]] acc = [] for j in range(1, k + 1): ps = all_partitions_(n - j, min(n - j, j)) acc.extend([[j] + p for p in ps]) return acc def all_partitions(n): return all_partitions_(n, n) def highest_product(n): ps = all_partitions(n) highest_prod = {} for p in ps: if len(p) > C: continue v = prod(p) if len(p) not in highest_prod: highest_prod[len(p)] = v else: if v > highest_prod[len(p)]: highest_prod[len(p)] = v return highest_prod def tabulate(upper): highest_n_per_c = {} table = {} for s in range(1, upper + 1): res = highest_product(s) for c, n in res.items(): for n2 in range(highest_n_per_c.get(c, 0) + 1, min(n, N) + 1): table[(n2, c)] = s highest_n_per_c[c] = n return {(n, c): s for (n, c), s in table.items() if s <= n} def trim_tab(tab): best_s = {} best_c = {} for (n, c), s in tab.items(): if n not in best_s: best_s[n] = s best_c[n] = c if s < best_s[n]: best_s[n] = s best_c[n] = c return {(n, c): s for (n, c), s in tab.items() if c <= best_c[n] or s <= best_s[n]} def print_table(tab0): tab = trim_tab(tab0) col_width = {0: 1} | {c: len(str(c)) for (_, c) in tab.keys()} for (n, c), s in tab.items(): col_width[0] = max(col_width[0], len(str(n))) col_width[c] = max(col_width[c], len(str(s))) N = max([n for (n, _) in tab.keys()]) C = max([c for (_, c) in tab.keys()]) prev_row = '' for n in range(1, N + 1): best = None row = '' for c in range(1, C + 1): if (n, c) in tab: row += ' ' + str(tab[(n, c)]).rjust(col_width[c]) if not best or tab[(n, c)] < best[0]: best = (tab[(n, c)], c) else: row += ' ' + ''.rjust(col_width[c]) if row != prev_row: print(str(n).rjust(col_width[0]) + ' |' + row + ' | ' + str(best)) prev_row = row