// Example solution to programming assignment 1.
// CS 509, Spring 2002.


#include <iostream>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cctype>


// Both the portfolio and the current share prices can be represented by the
// same data structure.


   struct triple {
     double x, y, z;
     triple() : x(0), y(0), z(0) { }
     triple(double x, double y, double z) : x(x), y(y), z(z) { }
     };


// One problem with using double values (floating-point values in general) is
// they are inexact, and it is frequently difficult to determine both when and
// how the values are inexact.  One pratical consiquence of these difficulties
// is that direct comparisons between double values usually don't work as
// expected.  The following comparison routines get around this problem by
// assuming that two double values that are within a penny of each other are
// close enough.


   static bool equal(double a, double b) {
     const double d = a - b;
     return (-0.01 < d) && (d < 0.01);
     }

   static bool greater(double a, double b) {
     return 0.01 < (a - b);
     }

   static double min(double a, double b) {
     return greater(a, b) ? b : a;
     }


// Return the value of a portfolio given a set of share prices.

   static double portfolio_value(const triple & portfolio, const triple & prices) {
     return portfolio.x*prices.x + portfolio.y*prices.y + portfolio.z*prices.z;
     }


// Given a portfolio and a set of share prices, return a new portfilio
// containing the old portfolio plus the monthly amount worth of shares bought
// according to strategy s.


   static triple strategy_s(
     double monthly_amount,
     const triple & percentages,
     const triple & prices, 
     const triple & portfolio) {

     triple p;

     p.x = portfolio.x + (monthly_amount*percentages.x)/prices.x;
     p.y = portfolio.y + (monthly_amount*percentages.y)/prices.y;
     p.z = portfolio.z + (monthly_amount*percentages.z)/prices.z;

     return p;
     }


// Strategy c repeatedly reduces the largest difference in actual-ideal value
// percentages until there are either no more differences or no more money.
//
// The code implementing stragegy c follows the description: loop until there's
// no more money.  In each loop, find the largest percentage difference, spend
// as much money as possible to eliminate it, and add the shares to the
// portfolio.  If there are no differences - that is, the actual value
// percentages are ideal - use stragegy s to spend the rest of the money (which
// must be there, otherwise the loop wouldn't be iterating).  When the loop
// terminates, return the new portfolio.
//
// The trick is in the differences - not computing them, but using them.  The
// percentage difference for X, for example, can be computed as
//
//   Dx = Ix - Vx/Vp
//
// where Dx is the percentage difference for x,
//       Ix is the ideal percentage for x,
//       Vx is the dollar value of X in the current portfolio, and
//       Px is the dollar value of the total current portfolio.
//
// Unfortunatley, you can't use Dx*Vp to determine the dollar amount of X
// shares to buy because Dx is a percentage relative to the current portfolio
// value and we need a percentage relative to the expected portfolio value
// after the shares have been bought.
//
// To understand why Dx doesn't work, consider a simple example where Vx = $0
// and Vp = $100.00.  Dx is 0.5 - 0/100.00 = 0.5, which means buy $100.00*0.5 =
// $50.00 worth of X.  But if we add $50 shares of X to the portfolio, the new
// value for Dx is 0.5 - 50.00/150.00 = 0.5 - 0.33 = 0.23, not quite what we
// wanted.
//
// What we need to know is not the percentage of the total portfolio value
// before we buy the stocks, but the percentage of the total portfolio value
// after we buy the stocks; that is, find Bx in
//
//   (Vx + Bx)/(Vp + Bx) = Ix
//
// where Bx is the dollar value of X shares to buy.  This can be rearranged to
//
//   Bx = (Ix*Vp - Vx)/(1 - Ix)


   static triple strategy_c2(
     double monthly_amount,
     const triple & percentages,
     const triple & prices, 
     triple portfolio) {

     while (!equal(monthly_amount, 0)) {

       const double total = portfolio_value(portfolio, prices);

       double max_difference = (0.5*total - portfolio.x*prices.x)/(1.0 - 0.5);
       char max = 'x';

       double d = (0.3*total - portfolio.y*prices.y)/(1.0 - 0.3);
       if (greater(d, max_difference)) {
	 max_difference = d;
	 max = 'y';
	 }

       d = (0.2*total - portfolio.z*prices.z)/(1.0 - 0.2);
       if (greater(d, max_difference)) {
	 max_difference = d;
	 max = 'z';
	 }

       if (equal(max_difference, 0))
	 return strategy_s(monthly_amount, percentages, prices, portfolio);
       else {
	 const double amt = min(monthly_amount, max_difference);
	 monthly_amount -= amt;

	 if (max == 'x')
	   portfolio.x += amt/prices.x;
	 else if (max == 'y')
	   portfolio.y += amt/prices.y;
	 else 
	   portfolio.z += amt/prices.z;
	 }
       }

     return portfolio;
     }


// That was pretty ugly: lots of iterations, calculations, and testing - all in
// all, it's complex.  You should learn to complexity as an indicator that
// something's wrong: either you don't understand the problem, or the design is
// lacking, or the implementation is using the wrong tools.
//
// In this case, code complexity means the design is lacking.  There are two
// problems with basing a solution on calculating Bi.  First, Bi doesn't get us
// where we want to be; rather than completely eliminating the difference
// between the two actual and ideal value percentages, it reduces it.  Second,
// Bi is based on the current portfolio value; every time that changes, the Bi
// values need to be recalculated.  Not surprisingly, code based on using Bi is
// going to require a lot of calculations and a lot of iterations.
//
// Is there a better way?  One way to look a solution based on Bi is that it
// starts at the beginning and stops at the end; that is, c2() starts with the
// current portfolio value and stops when the current monthly amount has been
// added to the portfolio.  One obvious alternative is to go in the other
// direction: start with the current portfolio value that includes the monthly
// amount.
//
// One immediate advantage provided by the alternative is a constant portfolio
// value: portfolio value is going to increase by the monthly amount no matter
// how the stocks are bought, which should cut down on a lot of recalculation
// caused by changing protfolio values.
//
// How many shares of each stock to buy?  Again, starting at where we'd like to
// end up, the value of X shares should be
//
//   Vx = Ix(Vp + M)
//
// where Vx is the final value of X shares in the protfolio, Vp is the current
// portfilio value, and M is the monthly amount.  To make that be true we need
// to buy shares of X equal to
//
//   Vx - Sx*Px
//
// where Sx is the number of shares of X in the current portfolio and Px is the
// current X share price.


   static triple strategy_c(
     double monthly_amount,
     const triple & percentages,
     const triple & prices, 
     const triple & portfolio) {

     triple p = portfolio;
     const double total = portfolio_value(p, prices) + monthly_amount;

     while (!equal(monthly_amount, 0)) {

       double max_difference = total*percentages.x - p.x*prices.x;
       char max = 'x';

       double d = total*percentages.y - p.y*prices.y;
       if (greater(d, max_difference)) {
	 max_difference = d;
	 max = 'y';
	 }

       d = total*percentages.z - p.z*prices.z;
       if (greater(d, max_difference)) {
	 max_difference = d;
	 max = 'z';
	 }

       if (equal(max_difference, 0)) {
	 p = strategy_s(monthly_amount, percentages, prices, p);
	 break;
	 }
       else {
	 const double amt = min(monthly_amount, max_difference);
	 monthly_amount -= amt;

	 if (max == 'x')
	   p.x += amt/prices.x;
	 else if (max == 'y')
	   p.y += amt/prices.y;
	 else 
	   p.z += amt/prices.z;
	 }
       }

     return p;
     }


// Input, as usual, is a pain not because it's difficult, but becuase there's a
// lot of little details to keep straight.  However, the pain of writing a
// correct input routine can be minimized by dividing the routine into smaller,
// well-defined pieces that follow the structure of the input problem.
//
// Assume for the moment we have available for use a procedure
//
   static bool read_price(std::istream &, double &);
//
// that reads a double from an input stream and a procedure
//
   static bool skip_space(std::istream &);
//
// that eats space characters from an input stream.  Using these procedures
// makes reading a triple of prices on a line in an input stream is relatively
// striaghtforward:


   static bool read_prices(std::istream & is, triple & prices) {

     if (!read_price(is, prices.x)) {
       if (is.eof()) return false;
       std::cerr << "Input error while reading X price.\n";
       exit(EXIT_FAILURE);
       }

     if (!read_price(is, prices.y)) {
       std::cerr << "Input error while reading Y price.\n";
       exit(EXIT_FAILURE);
       }

     if (!read_price(is, prices.z)) {
       std::cerr << "Input error while reading Z price.\n";
       exit(EXIT_FAILURE);
       }

     if (!skip_space(is) && !is.eof()) {
       std::cerr << "Junk at end of input line.\n";
       exit(EXIT_FAILURE);
       }

     return true;
     }


// If a price is missing, the input is incorrect - except when the first price
// is missing due to eof, which is fine because input must end sometime.  In
// all other cases, a missing price - even due to eof - is an error.
//
// In addition, there should no non-space characters between the third price
// and the end of the line; if there is, it's another input error.
// 
// The way these routines deal with input errors is not very good - programs
// that give up and die on the first error are not considered reliable or
// pleasant to use.  However, correctly recovering from errors is not easy to
// do and it adds much complexity to the code.  Because there's only a finite
// amount of time avaialble to work on these assignments, it is better to make
// sure errors get caught, and then spend the time making sure the program
// works correctly when the input is correct.

// Read into price the next double value from the text line in the input stream
// ins.  Return true if a double was read, false otherwise.


   static bool read_price(std::istream & is, double & price) {

     if (skip_space(is) || is.eof())
       return false;

     is >> price;
     if (!is.good()) {
       std::cerr << "Input error while reading a price.\n";
       exit(EXIT_FAILURE);
       }

     return true;
     }


// And finaly, read and eat space characters from the text line in the input
// stream ins until either a newline is read and eaten, the next character from
// ins would be a non-space character, or ins has no more characters.  Return
// true if a newline was eaten, false otherwise.


   static bool skip_space(std::istream & ins) {

     while (true) {
       const char ch = ins.peek();
       if (ins.eof() || !isspace(ch)) return false;
       (void) ins.get();
       if (ch == '\n') return true;
       }
     }


// More complexity, this time in the number of procedures necessary.  What's
// wrong now?  The input needed is simple, so it's unlikely we don't understand
// that.  The design doesn't have any obvious (to me) flaws:  there's a lot of
// parts involved, but each part is simple, as is the relation among the parts.
// That leaves the implementation tools.
//
// The standard C++ libraries include <sstream>, a facility to do stream io to
// and from strings.  Using <sstream> eliminates the auxiliary routines needed
// above, but only reduces the complexity of the remaining routine.
//
// For the record, here's the <sstream> implementation of price input:

#  include <sstream>
#  include <string>

   static bool read_prices2(std::istream & ins, triple & prices) {

     std::string s;
     if (!std::getline(ins, s)) return false;

     std::istringstream sin(s);

     if (!(sin >> prices.x)) {
       std::cerr << "Input error while reading X price.\n";
       exit(EXIT_FAILURE);
       }

     if (!(sin >> prices.y)) {
       std::cerr << "Input error while reading Y price.\n";
       exit(EXIT_FAILURE);
       }

     if (!(sin >> prices.z)) {
       std::cerr << "Input error while reading Z price.\n";
       exit(EXIT_FAILURE);
       }

     char c;
     if (sin >> c) {
       std::cerr << "Junk at end of input line.\n";
       exit(EXIT_FAILURE);
       }

     return true;
     }


// The last test takes advantage of the space-eating behavior of i-o stream
// input.


// Output is straightforward, except for two potential problems when computing
// precentages.  First, if the portfolio is empty, there's no percentages to
// compute; this can be dealt with by a test for zero portfolio value.  Second,
// the percentages have to sum to 100, which means the code has to keep track
// of the round-off error to make sure it doesn't accumulate.  Fortunately,
// this is not as complicated to do as it sounds because each integer
// percentage already contains the round-off error (the round-off error is what
// makes it an integer).  Not only does this handle the round-off error
// properly (subtracting the overages and adding the underages) but it makes it
// clear that the three percentages sum to 100.
// 
// A third problem, with which this code doesn't deal, is formatting the output
// nicely.  Doing so would involve the ridiculusly complicated i-o stream
// manipulators, and it just isn't worth the effort.  However, to avoid
// excessive precision, the portfolio value is rounded to the nearest penny.


   static int pct(double n, double d) {
     return equal(d, 0) ? 0 : static_cast<int>((n/d + 0.005)*100);
     }

   static void print_portfolio(
     std::ostream & os,
     const char type[],
     const triple & portfolio,
     const triple & prices) {

     const double total = portfolio_value(portfolio, prices);

     const int xpct = pct(portfolio.x*prices.x, total);
     const int ypct = pct(portfolio.y*prices.y, total);

     os << type 
	<< " " << xpct 
	<< " " << ypct
	<< " " << (equal(total, 0) ? 0 : 100 - (xpct + ypct))
	<< " " << static_cast<double>(static_cast<int>((total*100) + 0.5))/100 
	<< "\n";
     }


// And that's it.


   int main() {

     const triple percentages(0.5, 0.3, 0.2);
     const double monthly_amount = 2500.00;

     triple prices,
	    portfolio_s,
	    portfolio_c;

     while (read_prices2(std::cin, prices)) {
       portfolio_s = strategy_s(monthly_amount, percentages, prices, portfolio_s);
       portfolio_c = strategy_c(monthly_amount, percentages, prices, portfolio_c);
       }

     print_portfolio(std::cout, "c", portfolio_c, prices);
     print_portfolio(std::cout, "s", portfolio_s, prices);
     }


syntax highlighted by Code2HTML, v. 0.9