# Euler Problem 31¶

Back to overview.

In England the currency is made up of pound, £, and pence, p, and there are eight coins in general circulation:

1p, 2p, 5p, 10p, 20p, 50p, £1 (100p) and £2 (200p).

It is possible to make £2 in the following way:

1×£1 + 1×50p + 2×20p + 1×5p + 1×2p + 3×1p

How many different ways can £2 be made using any number of coins?

Let's do it non-recursive. Tricky part is to use ceil, otherwise we get wrong ranges for example for $\frac{50}{20}$.

In [1]:

    from math import ceil

    print(list(range(50 // 20)))
    print(list(range(ceil(50 / 20))))

    [0, 1]
    [0, 1, 2]

In [8]:

    from math import ceil

    def calculate():
        r = 200
        c = 0

        if r % 200 == 0:
            c += 1
        for p200 in range(ceil(r / 200)):
            r200 = r - p200 * 200
            if r200 % 100 == 0:
                c += 1
            for p100 in range(ceil(r200 / 100)):
                r100 = r200 - p100 * 100
                if r100 % 50 == 0:
                    c += 1
                for p50 in range(ceil(r100 / 50)):
                    r50 = r100 - p50 * 50
                    if r50 % 20 == 0:
                        c += 1
                    for p20 in range(ceil(r50 / 20)):
                        r20 = r50 - p20 * 20
                        if r20 <= 0:
                            break
                        if r20 % 10 == 0:
                            c += 1
                        for p10 in range(ceil(r20 / 10)):
                            r10 = r20 - p10 * 10
                            if r10 % 5 == 0:
                                c += 1
                            for p5 in range(ceil(r10 / 5)):
                                r5 = r10 - p5 * 5
                                if r5 % 2 == 0:
                                    c += 1
                                for p2 in range(ceil(r5 / 2)):
                                    r2 = r5 - p2 * 2
                                    if r2 % 1 == 0:
                                        c += 1

        return c

    s = calculate()

In [9]:

    print(s)
    assert(s == 73682)

    73682

I came up with a more concise solution that can be implemented in Scheme. I would like to compare the performance of the solutions.

In [34]:

    def count_change(change, coins):
        if not coins:
            return 0
        count = 0
        coin, coins = coins[0], coins[1:]
        for i in range(change // coin + 1):
            if change - i * coin == 0:
                count += 1
                continue
            if change - i * coin < 0:
                break
            count += count_change(change - i * coin, coins)
        return count

    def calculate_iterative():
        return count_change(200, [200, 100, 50, 20, 10, 5, 2, 1])

    s = calculate_iterative()
    print(s)

    73682

In [35]:

    import timeit
    print(timeit.timeit(calculate, number=10))
    print(timeit.timeit(calculate_iterative, number=10))

    0.16300111500095227
    11.429953110000497

Turns out I was way smarter than I thought when I have developped calculate. It checks the remainder and by doing that saves a ton of iterations.

In [36]:

    def count_change(change, coins):
        count = 0
        coin, coins = coins[0], coins[1:]

        if change % coin == 0:
            count += 1

        if not coins:
            return count

        for i in range(ceil(change / coin)):
            count += count_change(change - i * coin, coins)
        return count

    def calculate_iterative():
        return count_change(200, [200, 100, 50, 20, 10, 5, 2, 1])

    s = calculate_iterative()
    print(s)
    print(timeit.timeit(calculate_iterative, number=10))

    73682
    0.34602016500139143

In [ ]: