I often have to write a function which may return an output of two kinds: "short" and "long". As an example, consider the subset sum problem: the input is a set of integers S and an integer C, and the output is the largest sum of a subset of S that is at most C. The short output is just the largest sum (an integer); the long output is the subset itself. I can implement both variants in two separate functions, e.g.:
>>> subset_sum_short([1,2,4,9], 8)
7
>>> subset_sum_long ([1,2,4,9], 8)
[1,2,4]
But this causes a lot of code duplication, since the implementation is very similar. Both functions use dynamic progamming to check all possible sums; the long version also keeps information for backtracking.
To avoid code-duplication, I can implement only the long version, since given the optimal subset, the user can easily compute its sum:
>>> subset_sum_long([1,2,4,9], 8)
7
But it is wasteful for users who only need the sum, since it requires keeping unneeded backtracking information. The backtracking information, in this case, can increase the run-time and the memory requirements of the function by a factor of 2 or even 3.
A third solution is to have a single function with a flag:
>>> subset_sum([1,2,4,9], 8, short=True)
7
>>> subset_sum([1,2,4,9], 8, short=False)
[1,2,4]
This avoids the duplication, but the code becomes cluttered with if
s. Moreover, in the future I would like to allow a third output format, for example, giving each item a name, and returning a list of names instead of their sizes:
>>> subset_sum({"a":1, "b":2, "c":4, "d":9}, 8)
["a","b","c"]
Again, the algorithm is the same, but implementing this in a single function will require even more if
s.
Is there a design pattern that allows to write clean, simple and efficient code, while still giving the user a simple way to choose the required output format?