Ваша проблема тесно связана с целочисленным разбиением в математике.
Представьте, что вы меняете сумму в долларах. Например, если вы вносите изменения за 0,87 долл. США, вы можете использовать 3 монеты по 25 plus каждая, плюс 1 монету по 10 ¢, плюс 2 монеты по 1 *.
import functools
import sys
import copy
class PossibilityMaker:
log_progress = lambda *args, sep=" ", end="\n", print=print, file=sys.stderr:\
print(*args, sep=sep, end=end, file=file)
log_progress = lambda *args, **kwargs: None
@classmethod
def get_possibilities(cls, total:int, denominations):
assert(isinstance(total, int))
denominations = set(denominations)
possibilities = list()
cls.get_possibilities_helper(total, denominations, possibilities, dict())
return possibilities
@classmethod
def get_possibilities_helper(cls, total:int, denominations:set, possibilities:list, partial):
assert(isinstance(total, int))
cls.log_progress("making change for", total, "cent(s) using coins", denominations)
if len(denominations) < 1:
partial = copy.copy(partial)
partial[1] = total
possibilities.append(partial)
cls.log_progress(partial)
del partial
else:
max_denom = max(denominations)
cls.log_progress("largest coin is", max_denom, "cent(s)")
max_coin_quantity = total//max_denom
for coin_quantity in range(max_coin_quantity + 1):
cls.log_progress("Using", coin_quantity, "of coin of size", max_denom)
next_partial = copy.deepcopy(partial)
next_partial[max_denom] = coin_quantity
next_total = total - coin_quantity * max_denom
next_denominations = copy.deepcopy(denominations)
next_denominations.remove(max_denom)
cls.get_possibilities_helper(next_total, next_denominations, possibilities, next_partial)
return
possibilities = PossibilityMaker.get_possibilities(18, [2, 5, 7, 10])
print(60*"#")
print(
"\n".join(
str(possibility) for possibility in possibilities
)
)
Вывод:
{10: 0, 7: 0, 5: 0, 2: 0, 1: 18}
{10: 0, 7: 0, 5: 0, 2: 1, 1: 16}
{10: 0, 7: 0, 5: 0, 2: 2, 1: 14}
{10: 0, 7: 0, 5: 0, 2: 3, 1: 12}
{10: 0, 7: 0, 5: 0, 2: 4, 1: 10}
{10: 0, 7: 0, 5: 0, 2: 5, 1: 8}
{10: 0, 7: 0, 5: 0, 2: 6, 1: 6}
{10: 0, 7: 0, 5: 0, 2: 7, 1: 4}
{10: 0, 7: 0, 5: 0, 2: 8, 1: 2}
{10: 0, 7: 0, 5: 0, 2: 9, 1: 0}
{10: 0, 7: 0, 5: 1, 2: 0, 1: 13}
{10: 0, 7: 0, 5: 1, 2: 1, 1: 11}
{10: 0, 7: 0, 5: 1, 2: 2, 1: 9}
{10: 0, 7: 0, 5: 1, 2: 3, 1: 7}
{10: 0, 7: 0, 5: 1, 2: 4, 1: 5}
{10: 0, 7: 0, 5: 1, 2: 5, 1: 3}
{10: 0, 7: 0, 5: 1, 2: 6, 1: 1}
{10: 0, 7: 0, 5: 2, 2: 0, 1: 8}
{10: 0, 7: 0, 5: 2, 2: 1, 1: 6}
{10: 0, 7: 0, 5: 2, 2: 2, 1: 4}
{10: 0, 7: 0, 5: 2, 2: 3, 1: 2}
{10: 0, 7: 0, 5: 2, 2: 4, 1: 0}
{10: 0, 7: 0, 5: 3, 2: 0, 1: 3}
{10: 0, 7: 0, 5: 3, 2: 1, 1: 1}
{10: 0, 7: 1, 5: 0, 2: 0, 1: 11}
{10: 0, 7: 1, 5: 0, 2: 1, 1: 9}
{10: 0, 7: 1, 5: 0, 2: 2, 1: 7}
{10: 0, 7: 1, 5: 0, 2: 3, 1: 5}
{10: 0, 7: 1, 5: 0, 2: 4, 1: 3}
{10: 0, 7: 1, 5: 0, 2: 5, 1: 1}
{10: 0, 7: 1, 5: 1, 2: 0, 1: 6}
{10: 0, 7: 1, 5: 1, 2: 1, 1: 4}
{10: 0, 7: 1, 5: 1, 2: 2, 1: 2}
{10: 0, 7: 1, 5: 1, 2: 3, 1: 0}
{10: 0, 7: 1, 5: 2, 2: 0, 1: 1}
{10: 0, 7: 2, 5: 0, 2: 0, 1: 4}
{10: 0, 7: 2, 5: 0, 2: 1, 1: 2}
{10: 0, 7: 2, 5: 0, 2: 2, 1: 0}
{10: 1, 7: 0, 5: 0, 2: 0, 1: 8}
{10: 1, 7: 0, 5: 0, 2: 1, 1: 6}
{10: 1, 7: 0, 5: 0, 2: 2, 1: 4}
{10: 1, 7: 0, 5: 0, 2: 3, 1: 2}
{10: 1, 7: 0, 5: 0, 2: 4, 1: 0}
{10: 1, 7: 0, 5: 1, 2: 0, 1: 3}
{10: 1, 7: 0, 5: 1, 2: 1, 1: 1}
{10: 1, 7: 1, 5: 0, 2: 0, 1: 1}
Вы можете рассматривать монеты в 1 цент как «остатки» или «потери». Я понимаю, что у вас на самом деле нет монет в 1 цент, но все всегда складывается с вашим limit = 18
, если вы представляете, что игрок купил предмет с нулевым расходом / потерей.