view optim.py @ 4:14c8b6dad88a draft

final_capital: new function This is the objective function that we must maximise with a buying plan
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Tue, 10 Mar 2015 21:21:03 -0400
parents c683f80bc858
children cd24a8027d5f
line wrap: on
line source

#!/usr/bin/env python

from collections import namedtuple

Machine = namedtuple("Machine", ["day", "buy", "sell", "profit", "maxprofit"])
Case = namedtuple("Case", ["machines", "days", "capital"])

def parseinput(fname):
    """
    Parse the input file, forget about input validation
    """
    cases = []
    with open(fname) as f:
        while True:
            header = [int(x) for x in f.readline().split()]
            if header == [0, 0, 0]:
                return cases
            N = header[0]
            case = Case([], header[1], header[2])
            for i in range(0, N):
                machine = Machine(*[int(x) for x in f.readline().split()],
                                  maxprofit = None)
                # Maximum profit possible from each machine
                maxprofit = ((case.days - machine.day)*machine.profit
                             - machine.buy + machine.sell)
                machine = machine._replace(maxprofit = maxprofit)
                case.machines.append(machine)

            cases.append(case)

class InvalidPlan(Exception):
    pass

def final_capital(case, machines, plan):
    """Given a case, some machines, and an action plan about whether to
    buy a machine or not, compute the final capital given by this
    plan. Raises InvalidPlan if it's impossible to buy a machine at
    any step.

    This is our objective function to maximise over all possible
    plans.

    """
    capital = case.capital

    # The "slot" that holds a machine. Initially, there's nothing
    # there.
    slot = None

    for (action, machine) in sorted(zip(plan, machines),
                                    key = lambda x: x[1].day):
        if action:
            # We attempt to buy a new machine
            if capital < machine.buy:
                raise InvalidPlan("Not enough capital at day %d: "
                                  "machine cost is %d, and capital is %d"
                                  % (machine.day, machine.buy, capital))

            capital -= machine.buy
            if slot:
                # Subtract 1, because the machine in the slot cannot
                # be used the day it's sold.
                days_used = machine.day - slot.day - 1
                capital += days_used*slot.profit
                capital += slot.sell

            slot = machine

    # We account for the final machine, if we have it.
    if slot:
        # We can sell the day after the restructuring period, so no
        # subtracting 1 here.
        days_used = case.days - slot.day
        capital += days_used*slot.profit
        capital += slot.sell

    return capital
def main():
    cases = parseinput("input.txt")
    for case in cases:
        print "Next case:", case["header"]
        for machine in case["machines"]:
            print machine

if __name__ == "__main__":
    main()