diff --git a/dotfiles/lib/python/plus_minus.py b/dotfiles/lib/python/plus_minus.py new file mode 100644 index 00000000..ecccdd09 --- /dev/null +++ b/dotfiles/lib/python/plus_minus.py @@ -0,0 +1,63 @@ +def groupings(numbers): + if len(numbers) == 0: + raise StopIteration() + if len(numbers) == 1: + yield ((numbers[0],),) + raise StopIteration() + this_number = numbers[0] + this_tuple = (this_number,) + next_groupings = groupings(numbers[1:]) + for grouping in next_groupings: + yield (this_tuple,) + grouping + yield (this_tuple + grouping[0],) + grouping[1:] + + +def plus_minus_n(numbers, n): + for grouping in groupings(numbers): + numbers = map(group_to_int, grouping) + pms = plus_minuses(len(numbers) - 1) + for pm in pms: + result = compute(numbers, pm) + string = generate_string(numbers, pm) + if result == n: + yield string + + +def generate_string(numbers, pms): + string = '' + for number in numbers: + string += '{0}'.format(number) + if pms: + string += '+' if pms[0] is PLUS else '-' + pms = pms[1:] + return string + + +def compute(numbers, plus_minus): + sum = numbers[0] + remaining = numbers[1:] + while remaining: + if plus_minus[0] == PLUS: + sum += remaining[0] + else: + sum -= remaining[0] + remaining = remaining[1:] + plus_minus = plus_minus[1:] + return sum + + +def group_to_int(group): + return int(''.join(map(str, group))) + + +PLUS = object() +MINUS = object() + + +def plus_minuses(n): + if n == 0: + yield () + raise StopIteration() + for pm in plus_minuses(n-1): + yield (PLUS,) + pm + yield (MINUS,) + pm