The concise 'how many beers' issue?

169 views Asked by At

Where I'm at

I'm trying to figure out how many beers I can buy with 10 RMB after recycling every bottle I get. It's obvious to me that I'm doing something wrong, procedurally, but it's not occurring to me what that is. I'm currently reading "How To Think Like a Computer Scientist: Think Python" on chapter 9. I feel like this should be an easy program for me, but I'm not sure how to loop in the recycling portion of the app. What would be the most concise way to rinse and repeat beer purchases?

The question

Basically, one beer costs 2 RMB. 2 bins gets 1 RMB. 4 caps gets 1 RMB. I'm starting out with 10 RMB. How many beers can I buy (recycling all the bins and caps)?

#5 bottles 5 caps 
#= 3 rmb + 1 caps 1 bottles
#6th bottle bought 
#= 2rmb + 2 caps
#7th bottle bought 
#= 0rmb + 3 caps 1 bottles.

import math

def countbeers(rmb):
    beers = 0;
    caps = 0;
    bins = 0;
    bcost = 2;

    for i in range (0,rmb):
        beers += 1/2

    for i in range (0,math.floor(beers)):
        caps += 1
        bins += 1
        rmb = rmb - bcost

    for i in range (0,caps):
        rmb += 1/4

    for i in range (0,bins):
        rmb += 1/2

    #  if rmb > 2  what goes here, trying to loop back through

    return beers

print(countbeers(10))

Second attempt

#5 bottles 5 caps 
#= 3 wallet + 1 caps 1 bottles
#6th bottle bought 
#= 2wallet + 2 caps
#7th bottle bought 
#= 0wallet + 3 caps 1 bottles.

import math

global beers
global caps
global bins
global bcost

beers = 0
caps = 0
bins = 0
bcost = 2

def buybeers(wallet):
    beers = 0
    for i in range (0,wallet):
        beers += 1/2
        wallet -= 2
    return beers

def drinkbeers(beers):
    for i in range (0,math.floor(beers)):
        caps += 1
        bins += 1
        wallet = wallet - bcost
    return wallet, caps, bins

def recycle(caps, bins):
    for i in range (0,caps):
        wallet += 1/4

    for i in range (0,bins):
        wallet += 1/2

    return wallet

def maxbeers(wallet):
    if wallet > 2:
        buybeers(wallet)

    if math.floor(beers) > 1:
        drinkbeers(beers)

    if caps > 4 | bins > 2:
        recycle(caps, bins)
        return wallet

wallet = int(input("How many wallet do you have?"))

maxbeers(wallet)
if wallet >= 2:
    maxbeers(wallet)
elif wallet < 2: 
    print(beers)
1

There are 1 answers

2
Filip Haglund On BEST ANSWER

Your main problem is that you are not looping. Every beer you bought from rmb gives you one more bottle, and one more cap. This new bottle and cap might be enough to earn you another rmb, which might be enough for another beer. Your implementation handles this to a limited extent, since you call maxbeers multiple times, but it will not give the correct answer if you give it a truckload of beers, i.e. 25656 bottles.

If you know the number of rmb you have, you can do the calculation by hand on paper and write this:

def maxbeers(rmb):
    return 7  # totally correct, I promise. Checked this by hand.

but that's no fun. What if rmb is 25656?

Assuming we can exchange:

2 bottles -> 1 rmb
4 caps -> 1 rmb
2 rmb -> 1 beer + 1 cap + 1 bottle

we calculate it like this, through simulation:

def q(rmb):
    beers = 0
    caps = 0
    bottles = 0
    while rmb > 0:
        # buy a beer with rmb
        rmb -= 2
        beers += 1
        caps += 1
        bottles += 1

        # exchange all caps for rmb
        while caps >= 4:
            rmb += 1
            caps -= 4

        # exchange all bottles for rmb
        while bottles >= 2:
            rmb += 1
            bottles -= 2

    return beers

for a in range(20):
    print("rmb:", a, "beers:", q(a))

Then we can buy 20525 beers.