# Prompts the user for the face values of banknotes
# and their associated quantities, as well as for an amount,
# and if possible, outputs the minimal number of banknotes
# needed to match that amount, as well as the detail of
# how many banknotes of each type value are used.
#
# Written by Eric Martin for COMP9021


def print_solution(solution):
    max_width = max([len(str(value)) for value in solution]) + 1
    for value in sorted(solution.keys()):
        print('{:>{:}}: {:}'.format('$' + str(value),
                                    max_width,
                                    solution[value]))

            
print("Input pairs of the form 'value : number'\n"
      "   to indicate that you have 'number' many banknotes "
      "of face value 'value'.")
print('Input these pairs one per line, with a blank line '
      'to indicate end of input.\n')
face_values = []
while True:
    line = input()
    if ':' not in line:
        break
    value, quantity = line.split(':')
    face_values.append((int(value), int(quantity)))
# Might make the computation more efficient.
face_values.sort(reverse = True)
nb_of_face_values = len(face_values)
amount = int(input('Input the desired amount: '))

# minimal_combinations[sub_amount] will be a pair whose first element
# is the minimal number of banknotes needed to yield sub_amount,
# and whose second element is the list of all possible solutions,
# each solution being a dictionary with face values as keys and
# number of banknotes used as values.
minimal_combinations = [[0, []]] + [[float('inf'), []] for i in range(amount)]
for sub_amount in range(1, amount + 1):
    for i in range(nb_of_face_values):
        value = face_values[i][0]
        if sub_amount < value:
            continue
        if value == sub_amount:
            minimal_combinations[sub_amount] = [1, [{value : 1}]]
            break
        # Using "value" to get "sub_amount" would require more banknotes
        # than the minimum number of banknotes so far found out to sum up
        # to "sub_amount".
        if minimal_combinations[sub_amount - value][0] >=\
                                          minimal_combinations[sub_amount][0]:
            continue
        for option in minimal_combinations[sub_amount - value][1]:
            # A banknote with face value "value" is available to complete
            # "option" and result in a sum of "sub_amount".
            if value not in option or option[value] < face_values[i][1]:
                # Moreover, it determines a new minimum to the number of
                # banknotes that can sum of to "sub_amount".
                if minimal_combinations[sub_amount - value][0] + 1 <\
                                          minimal_combinations[sub_amount][0]:
                    minimal_combinations[sub_amount][0] =\
                               minimal_combinations[sub_amount - value][0] + 1
                    minimal_combinations[sub_amount][1].clear()
                extended_option = dict(option)
                if value not in option:
                    extended_option[value] = 1
                else:
                    extended_option[value] += 1
                if extended_option not in minimal_combinations[sub_amount][1]:
                    minimal_combinations[sub_amount][1].append(extended_option)
minimal_nb_of_banknotes = minimal_combinations[amount][0]
if minimal_nb_of_banknotes == float('inf'):
    print('\nThere is no solution.')
else:
    solutions = minimal_combinations[amount][1]
    nb_of_solutions = len(solutions)
    if nb_of_solutions == 1:
        print('\nThere is a unique solution:')
        print_solution(solutions[0])
    else:
        print('\nThere are {:} solutions:'.format(nb_of_solutions))
        for i in range(nb_of_solutions - 1):
            print_solution(solutions[i])
            print()
        print_solution(solutions[nb_of_solutions - 1])
        

Resource created Monday 21 September 2015, 11:41:48 AM.

file: question_2.py


Back to top

COMP9021 15s2 (Principles of Programming) is powered by WebCMS3
CRICOS Provider No. 00098G