Notes on codes, projects and everything

Drink All You Can

Sometimes I really doubt about the advantage of recycling old stuff to fund for new units beyond goodwill. Sure you get to convince yourself that you are saving the environment by doing so, and it also saves money in the long run. However, I didn’t realize how much it generates it may be after trying to work out an answer for a fictional IQ question.

So the question goes like this, suppose one can purchase a bottle of beer with 2 bucks (or any unit of cash). Then this person can choose to recycle the bottle and caps for new bottles. For every 2 bottles, or 4 caps, a new bottle of new beer is given. With all these information in mind, how many bottles of beer can one consumes if this person has 20 bucks.

This is very much a optimization problem, but I was too lazy to dig out my notes just to answer this question. So I did some quick calculation to find the answer. My first attempt yielded 19


20/2=10, 10/2=5, 15\4=3, 4/4=1, hence 10+5+3+1=19

and found out something wasn’t right, and tried the second time


by cash: 20/2=10
by bottle: 10/2=5, 5/2=2;1
by cap: 17/4=4;1
by bottle(2nd time): (4+1)/2=2;1
by cap: (2+1)/4=0
total=10+5+2+4+2=23

Then I gave up and tried writing a simple program to solve the problem (the reason why I used logging instead of print).

import logging

logging.basicConfig(level=logging.INFO & logging.DEBUG)
logger = logging.getLogger()

COST_CASH = 2
COST_BOTTLE = 2
COST_CAPS = 4

def new_bottle_is_possible(cash, bottle, caps):
    return cash >= COST_CASH or bottle >= COST_BOTTLE or caps >= COST_CAPS

def bottle(cash, consumption = 0, bottle_current = 0, caps = 0, iteration = 1):
    logger.info('Iteration {}'.format(iteration))

    bottle_cash, _cash = divmod(cash, COST_CASH)
    logger.debug('PAID ${} for {} bottles, BALANCE ${}'.format(cash, bottle_cash, _cash))

    bottle_bottle, _bottles = divmod(bottle_current, COST_BOTTLE)
    logger.debug('TRADED {} empty bottles for {} new bottles, BALANCE {} empty bottles'.format(bottle_current, bottle_bottle, _bottles))

    bottle_caps, _caps = divmod(caps, COST_CAPS)
    logger.debug('TRADED {} caps for {} new bottles, BALANCE {} caps'.format(caps, bottle_caps, _caps))

    bottle_new = bottle_cash + bottle_bottle + bottle_caps
    caps_bal = _caps + bottle_new
    logger.info('GAIN {} new bottles, BALANCE {} bottles, {} caps'.format(bottle_new, _bottles + bottle_new, _caps + bottle_new))

    _consumption = consumption + bottle_new
    logger.info('Total consumption: {}'.format(_consumption))

    return bottle(_cash, _consumption, _bottles + bottle_new, caps_bal, iteration + 1) if new_bottle_is_possible(_cash, _bottles + bottle_new, caps_bal) else _consumption

print('Beer consumed: {}'.format(bottle(20)))

With the help from this snippet of code, the answer to the question is found to be 35.

$ python3 bottles.py
INFO:root:Iteration 1
DEBUG:root:PAID $20 for 10 bottles, BALANCE $0
DEBUG:root:TRADED 0 empty bottles for 0 new bottles, BALANCE 0 empty bottles
DEBUG:root:TRADED 0 caps for 0 new bottles, BALANCE 0 caps
INFO:root:GAIN 10 new bottles, BALANCE 10 bottles, 10 caps
INFO:root:Total consumption: 10
INFO:root:Iteration 2
DEBUG:root:PAID $0 for 0 bottles, BALANCE $0
DEBUG:root:TRADED 10 empty bottles for 5 new bottles, BALANCE 0 empty bottles
DEBUG:root:TRADED 10 caps for 2 new bottles, BALANCE 2 caps
INFO:root:GAIN 7 new bottles, BALANCE 7 bottles, 9 caps
INFO:root:Total consumption: 17
INFO:root:Iteration 3
DEBUG:root:PAID $0 for 0 bottles, BALANCE $0
DEBUG:root:TRADED 7 empty bottles for 3 new bottles, BALANCE 1 empty bottles
DEBUG:root:TRADED 9 caps for 2 new bottles, BALANCE 1 caps
INFO:root:GAIN 5 new bottles, BALANCE 6 bottles, 6 caps
INFO:root:Total consumption: 22
INFO:root:Iteration 4
DEBUG:root:PAID $0 for 0 bottles, BALANCE $0
DEBUG:root:TRADED 6 empty bottles for 3 new bottles, BALANCE 0 empty bottles
DEBUG:root:TRADED 6 caps for 1 new bottles, BALANCE 2 caps
INFO:root:GAIN 4 new bottles, BALANCE 4 bottles, 6 caps
INFO:root:Total consumption: 26
INFO:root:Iteration 5
DEBUG:root:PAID $0 for 0 bottles, BALANCE $0
DEBUG:root:TRADED 4 empty bottles for 2 new bottles, BALANCE 0 empty bottles
DEBUG:root:TRADED 6 caps for 1 new bottles, BALANCE 2 caps
INFO:root:GAIN 3 new bottles, BALANCE 3 bottles, 5 caps
INFO:root:Total consumption: 29
INFO:root:Iteration 6
DEBUG:root:PAID $0 for 0 bottles, BALANCE $0
DEBUG:root:TRADED 3 empty bottles for 1 new bottles, BALANCE 1 empty bottles
DEBUG:root:TRADED 5 caps for 1 new bottles, BALANCE 1 caps
INFO:root:GAIN 2 new bottles, BALANCE 3 bottles, 3 caps
INFO:root:Total consumption: 31
INFO:root:Iteration 7
DEBUG:root:PAID $0 for 0 bottles, BALANCE $0
DEBUG:root:TRADED 3 empty bottles for 1 new bottles, BALANCE 1 empty bottles
DEBUG:root:TRADED 3 caps for 0 new bottles, BALANCE 3 caps
INFO:root:GAIN 1 new bottles, BALANCE 2 bottles, 4 caps
INFO:root:Total consumption: 32
INFO:root:Iteration 8
DEBUG:root:PAID $0 for 0 bottles, BALANCE $0
DEBUG:root:TRADED 2 empty bottles for 1 new bottles, BALANCE 0 empty bottles
DEBUG:root:TRADED 4 caps for 1 new bottles, BALANCE 0 caps
INFO:root:GAIN 2 new bottles, BALANCE 2 bottles, 2 caps
INFO:root:Total consumption: 34
INFO:root:Iteration 9
DEBUG:root:PAID $0 for 0 bottles, BALANCE $0
DEBUG:root:TRADED 2 empty bottles for 1 new bottles, BALANCE 0 empty bottles
DEBUG:root:TRADED 2 caps for 0 new bottles, BALANCE 2 caps
INFO:root:GAIN 1 new bottles, BALANCE 1 bottles, 3 caps
INFO:root:Total consumption: 35
Beer consumed: 35

So the cost of each of them is slightly over 1 buck. Out of curiousity, I wrote this to figure out the relationship between available cash and number of bottles.

from pandas import DataFrame
stats = DataFrame(reduce(lambda result, incoming: result + [(incoming, bottle(incoming))],
                         range(0, 101, 2),
                         []),
                  columns=('cash', 'consumption'))
print(stats)

I didn’t make it a Panda Dataframe for no reason, it was mainly for this. I was quite surprised to find out the data looked quite linear (in fact it is 2x - 5) except for the first couple of points.

bottles
Looking quite linear

So, after all these done, the conclusion is, in this fictional world, as long as you have enough cash, you can enjoy beer at almost half the price (if you don’t mind the extra effort, that is).

leave your comment

name is required

email is required

have a blog?

This blog uses scripts to assist and automate comment moderation, and the author of this blog post does not hold responsibility in the content of posted comments. Please note that activities such as flaming, ungrounded accusations as well as spamming will not be entertained.

Click to change color scheme