Problem 151

completed January 1, 2013

Comments

This is the first time I’ve used two classes in a problem. I’m pretty proud of that. It made a lot of sense because there were literally two objects in the problem: cut sheets and envelopes.

My strategy was to simulate a week’s worth of work (all 16 batches completed) to see how many answers I got. I then ran this many, many, many times and averaged the answers.

The problem with this approach was that with every subsequent week, the answer would have less and less effect on the running average. This meant that the first 2 decimal places converged rather quickly. It took over 180 million runs though to get just 5 decimal places. From there, I have to admit, I just started guessing; not something I like to do, but after all that, I felt I deserved it.

I believe a better way to solve this would be to calculate every single possible outcome. There are a finite number of these. However, though I’m not sure, I believe this number is very high. From there, it would be easy to get the average.

Code

from random import *

class Envelope:

    def __init__(self):
        self.contents = ['A1']

    def grab(self):
        if len(self.contents) == 0:
            raise IndexError('contents empty')
        return self.contents.pop(randrange(len(self.contents)))

    def replace(self, items): # items must be list
        try:
            self.contents += items
        except:
            pass

    def size(self):
        return len(self.contents)



class Paper: # takes the size of paper and cuts it till it contains 2 size A5, returns list of the cut sizes

    def __init__(self, sheetSize):
        if sheetSize not in ['A1', 'A2', 'A3', 'A4', 'A5'] or sheetSize == None:
            raise ValueError('not correct size type or None type')
        else:
            self.sheetSize = sheetSize

    def cut(self):
        if self.sheetSize == 'A1':
            return ['A2', 'A3', 'A4', 'A5', 'A5']
        elif self.sheetSize == 'A2':
            return ['A3', 'A4', 'A5', 'A5']
        elif self.sheetSize == 'A3':
            return ['A4', 'A5', 'A5']
        elif self.sheetSize == 'A4':
            return ['A5', 'A5']
        elif self.sheetSize == 'A5':
            return ['A5']
        else:
            raise ValueError('not correct size type or None type')



totalWeeks = float(0)
totalOneSheets = float(0)
runningAverage = float(0)

while True:

totalWeeks += 1

thisWeek = Envelope()
oneSheet = 0
for i in xrange(16):
    if thisWeek.size() == 1:
        oneSheet += 1
    randomSheet = Paper(thisWeek.grab())
    cutSheet = randomSheet.cut()
    cutSheet.remove(cutSheet[-1])
    thisWeek.replace(cutSheet)

totalOneSheets += oneSheet
runningAverage = float( totalOneSheets / totalWeeks )

if totalWeeks % 10**4 == 0:
    print int(totalWeeks), int(totalOneSheets), runningAverage