LMU ☀️ CMSI 3801
LANGUAGES AND AUTOMATA I
HOMEWORK #5 PARTIAL ANSWERS
exercises.cpp
#include "exercises.h"
#include <map>
#include <algorithm>
#include <stdexcept>

using namespace std;

double dot(valarray<double> a, valarray<double> b) {
  return (a * b).sum();
}

vector<int> stretched_nonzeros(vector<int> v) {
  vector<int> stretched;
  int repeat = 0;
  for (int item: v) {
    if (item != 0) {
      for (int j = 0; j <= repeat; j++) {
        stretched.push_back(item);
      }
      repeat++;
    }
  }
  return stretched;
}

void powers(int base, int limit, function<void(int)> consume) {
  int power = 1;
  while (power <= limit) {
    consume(power);
    power *= base;
  }
}

int IntStack::size() {
  int count = 0;
  for (shared_ptr<Node> node = top; node; node = node->next) {
    count++;
  }
  return count;
}

void IntStack::push(int item) {
  top = shared_ptr<Node>(new Node { item, top });
}

int IntStack::pop() {
  if (!top) {
    throw logic_error("Cannot pop from empty stack");
  }
  int value_to_pop = top->value;
  top = top->next;
  return value_to_pop;
}

string Sayer::operator()() { return words; }
  
Sayer Sayer::operator()(string word) {
  // Must return a *new* Say object here. Don't be stateful!
  // Also, take care of the special case of the first word.
  return { words + (words == "" ? "" : " ") + word };
}

Sayer say;

vector<pair<string, int>> sorted_word_counts(list<string> words) {
  map<string, int> counts;
  for (string word : words) {
    counts[word]++;
  }
  auto value_descending = [](auto x, auto y) { return y.second < x.second; };
  vector<pair<string, int>> pairs(counts.begin(), counts.end());
  sort(pairs.begin(), pairs.end(), value_descending);
  return pairs;
}

Quaternion::Quaternion(double a, double b, double c, double d): a(a), b(b), c(c), d(d) {
}

array<double, 4> Quaternion::coefficients() {
  return { a, b, c, d };
}

Quaternion Quaternion::operator+(const Quaternion& other) {
  return { a + other.a, b + other.b, c + other.c, d + other.d };
}

Quaternion Quaternion::operator-(const Quaternion& other) {
  return { a - other.a, b - other.b, c - other.c, d - other.d };
}

Quaternion Quaternion::operator*(const Quaternion& other) {
  return {
    other.a * a - other.b * b - other.c * c - other.d * d,
    other.a * b + other.b * a - other.c * d + other.d * c,
    other.a * c + other.b * d + other.c * a - other.d * b,
    other.a * d - other.b * c + other.c * b + other.d * a
  };
}

bool Quaternion::operator==(const Quaternion& other) const {
  return a == other.a && b == other.b && c == other.c && d == other.d;
}

Quaternion Quaternion::ZERO = {0, 0, 0, 0};
Quaternion Quaternion::I = {0, 1, 0, 0};
Quaternion Quaternion::J = {0, 0, 1, 0};
Quaternion Quaternion::K = {0, 0, 0, 1};

ostream& operator<<(ostream& o, Quaternion q) {
  o << q.a;
  o << (q.b >= 0 ? "+" : "") << q.b << "i";
  o << (q.c >= 0 ? "+" : "") << q.c << "j";
  o << (q.d >= 0 ? "+" : "") << q.d << "k";
  return o;
}