//practical problem solutions as written by Dr. Ramsey
//it is most helpful if you write the solutions yourself,
//because you will have to to do so on the test.
//try writing the solutions out by hand.
//you should only refer to this if you get stuck
#include <iostream>
#include <cmath> //for sin/cos/log/etc
#include <ctime> //used for time
#include <cstdlib> //for rand/srand
#include <string>
using namespace std;

void getInteger(string, int&);
double f(double);
double distance(double, double, double);
int max(int, int, int);



int main() {
  cout << "*** Practical #2 *** " << endl;
  cout << "** Using Functions: **" << endl; 
  {
    /**** #1 *****/
    cout << " Input x:";
    double x;
    cin >> x;
    cout << "f(x) is " <<
      0.5*pow(sin(x), 2) + 0.5*pow(cos(x), 2) << endl;

    /**** #2 ****/
    srand(time(NULL)); // once per entire program
    int r = rand() % 11 + 13;
    cout << "Random # from 13-23 is: " << r << endl;

    /***** #3*****/
    cout << "Input x:";
    cin >> x; //already declared above
    while (cin.fail() || x <= 0) {
      cin.clear();
      cin.ignore(100, '\n');
      cout << "Input x:";
      cin >> x;
    }
    cout << "ln(x) is " << log(x) << endl;
  }
  cout << "** Writing Functions ** " << endl;
  {
    int a, b, c;
    cout << "Input 3 values: ";
    cin >> a >> b >> c;

    cout << "maximum of these 3 is: " << max(a, b, c) << endl;
    /*****2nd****/
    double x;
    cout << "Input x:";
    cin >> x;
    cout << "f(x) is " << f(x) << endl;
    /****3rd***/
    double v, accel, t;
    cout << "Input vel, acceleration and time: ";
    cin >> v >> accel >> t;
    cout << "Distance is " << distance(v, accel, t) << endl;

    /***4th***/
    int i = 3;
    getInteger("Input an integer:", i);
    cout << "Integer i / input is: " << i << endl;
  }

  cout << "** Static Arrays ** " << endl;
  {

    /******#1***********/
    const int NUM_PEEP = 5;
    string names[NUM_PEEP];
    int grades[NUM_PEEP];
    cout << "Input a name followed by a grade " << NUM_PEEP << " times! " << endl;
    int s = 0; // sum for average
    for (int i = 0; i < NUM_PEEP; i++) {
      cin >> names[i] >> grades[i];
      s = s + grades[i];
    }
    double average = (double)s / NUM_PEEP; //using a typecast to force double arithmetic
    double sum = 0;
    for (int i = 0; i < NUM_PEEP; i++) {
      sum = sum + pow( grades[i] - average, 2);
    }
    double stdev = sqrt( sum / NUM_PEEP );
    cout << "Average is " << average << " and Standard Deviation is " << stdev << endl;
    cout << "Students, Grades, and Standard Deviations Away from Average" << endl;
    for (int i = 0; i < NUM_PEEP; i++) {
      cout << names[i] << "\t" << grades[i] << "\t" << (grades[i] - average) / stdev << endl;
    }


    /****#2*****/
    const int NUM = 30;
    int revs[NUM] = { 1,2,3,5,7,8,9,4,6,0,1,2,3,5,7,8,9,4,6,0, 1,2,3,5,7,8,9,4,6,0 };
    cout << "Array orig has: ";
    for (int i = 0; i < NUM; i++) {
      cout << revs[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < NUM / 2; i++) { //last goes into first and so in towards the middle
      int t = revs[i]; // doing a swap, save this value
      revs[i] = revs[NUM - i - 1];
      revs[NUM - i - 1] = t;
    }
    cout << " Array now has: ";
    for (int i = 0; i < NUM; i++) {
      cout << revs[i] << " ";
    }
    cout << endl;

    /**** #3 *****/
    //decided to use the revs array - moving everything down one:
    int t = revs[0]; //store the first one for the end, because we're about to overwrite it
    for (int i = 0; i < NUM - 1; i++) { //changed loop condition - because dont' want to blow bounds
      revs[i] = revs[i + 1]; //i+1 requires NUM-1 in loop condition
    }
    revs[NUM - 1] = t; //the last one should be what was first
    cout << " Array now has: ";
    for (int i = 0; i < NUM; i++) {
      cout << revs[i] << " ";
    }
    cout << endl;
  }
  {
    cout << "*** Dynamic Arrays ****" << endl;
    int NUMGRADES;
    cout << "How many grades are there: ";
    cin >> NUMGRADES;
    int * grades = new int[NUMGRADES]; //array declaration for a dynamic array
    cout << "Input " << NUMGRADES << " integer grades: ";
    int s = 0; // sum for average
    for (int i = 0; i < NUMGRADES; i++) {
      cin >> grades[i];
      s = s + grades[i];
    }
    double average = (double)s / NUMGRADES; //using a typecast to force double arithmetic
    double sum = 0;
    for (int i = 0; i < NUMGRADES; i++) {
      sum = sum + pow(grades[i] - average, 2);
    }
    double stdev = sqrt(sum / NUMGRADES);
    cout << "Average is " << average << " and Standard Deviation is " << stdev << endl;
    cout << "Students, Grades, and Standard Deviations Away from Average" << endl;
    for (int i = 0; i < NUMGRADES; i++) {
      cout << grades[i] << "\t" << (grades[i] - average) / stdev << endl;
    }


    /******#2*******/
    cout << " How many birds? ";
    int NUMBIRDS;
    cin >> NUMBIRDS;
    string *birds = new string[NUMBIRDS];
    cout << "Input " << NUMBIRDS << " birds: ";
    for (int i = 0; i < NUMBIRDS; i++) {
      cin >> birds[i];
    }
    int firstrandbird = rand() % NUMBIRDS;
    int secondrandbird = rand() % NUMBIRDS;
    string newbird = birds[firstrandbird] + birds[secondrandbird];
    cout << "The new bird name is: " << newbird << endl;

  }



}


//use call by reference to read in an integer
//the 'in' integer must be declared in the 
//calling function - in this case, in main
// cannot call getInteger("hi",3);
// because 3 is not an integer that we can cin into!
void getInteger(string prompt, int&in) {
  cout << prompt;
  cin >> in;
  while (cin.fail()) {
    cin.clear();
    cin.ignore(100, '\n');
    cout << prompt;
    cin >> in;
  }
  //no return statement, this is a void function
}


//find the max of 3 integers!
int max(int a, int b, int c) {
  if (a >= b && a >= c) {
    return a;
  }
  if (b >= a && b >= c) {
    return b;
  }
  return c; //why does this need no if statement? hmmm...
}


//a 'silly' function that does a cool computation
double f(double x) {
  return 0.5*pow(sin(x), 2) + 0.5*pow(cos(x), 2);
}

//compute teh distance moved over
//a certain amount of time given a velocity and acceleration
// m/s, km / h , ft/s mph, all work here as long as all units
// agree
double distance(double vel, double acc, double tim) {
  return vel*tim + 0.5*acc*tim*tim;
}
