/*
FILE: matrix.h
Name: Luke O'Callaghan
*/
#ifndef _matrix_H_
#define _matrix_H_
#include <iostream>
using namespace std;
const int MAX_ROW = 5;
const int MAX_COLUMN = 5;
//********************************************
// Matrix class definition.
template <class T>
class matrix;
template <class T>
ostream& operator<<(ostream &, const matrix<T> &);
template <class T>
istream& operator>>(istream &, matrix<T> &);
template <class T>
class matrix {
friend ostream& operator<< <T>(ostream &, const matrix<T> &);
friend istream& operator>> <T>(istream &, matrix<T> &);
private:
int column;
int row;
T data[MAX_ROW][MAX_COLUMN];
public:
matrix();
matrix(const int &, const int &);
matrix<T> operator+(const matrix<T> &);
matrix<T> operator-(const matrix<T> &);
matrix<T> operator*(const matrix<T> &);
};
//********************************************
// Complex matrix class definition
class complexn;
ostream& operator<<(ostream &, const complexn &);
istream& operator>>(istream &, complexn &);
class complexn {
friend ostream& operator<<(ostream &, const complexn &);
friend istream& operator>>(istream &, complexn &);
private:
float real;
float img;
float g;
public:
complexn();
complexn(const float &, const float &);
complexn operator+(const complexn &);
complexn operator-(const complexn &);
complexn operator*(const complexn &);
void operator=(const int &); // Used to initialise the complexn type matrix
};
#endif
/*
FILE: matrix.cpp
Name: Luke O'Callaghan
*/
#include <iostream>
#include <iomanip>
#include <cmath>
#include <typeinfo>
#include "matrix.h"
using namespace std;
//************************************
// Global manipulator flags
bool info_flag = false;
bool cplx_flag = true; // default value
bool real_flag = false;
bool img_flag = false;
bool magnitude_flag = false;
//************************************
// matrix manipulators
ostream& info(ostream &out)
{
info_flag = true;
return out;
}
ostream& noinfo(ostream &out) {
info_flag = false;
return out;
};
//************************************
// matrix function implementations
template <class T>
ostream& operator<<(ostream &out, const matrix<T> &m)
{
if(info_flag == true)
cout << m.row << "x" << m.column << " matrix" << endl;
for(int i = 0; i < m.row; ++i) {
for(int j = 0; j < m.column; ++j) {
out << '\t' << fixed << setprecision(1) << m.data[i][j];
}
out << endl;
}
return out;
}
template <class T>
istream& operator>>(istream &in, matrix<T> &m)
{
for(int i = 0; i < m.row; ++i) {
for(int j = 0; j < m.column; ++j) {
in >> m.data[i][j];
}
}
return in;
}
template <class T>
matrix<T>::matrix()
{
row = 0;
column = 0;
}
template <class T>
matrix<T>::matrix(const int &new_row, const int &new_column)
{
row = new_row;
column = new_column;
for(int i = 0; i < row; ++i){
for(int j = 0; j < column; ++j){
data[i][j] = 0;
}
}
}
template <class T>
matrix<T> matrix<T>::operator+(const matrix<T> &b)
{
if(row != b.row || column != b.column)
throw(string("Matrices are not the same size."));
if(typeid(*this).name() != typeid(b).name())// NOTE: not able to compile if types are different.
throw(string("Matrix types are not the same."));
matrix<T> c(row, column);
for(int i = 0; i < row; ++i){
for(int j = 0; j < column; ++j){
c.data[i][j] = data[i][j] + b.data[i][j];
}
}
return c;
}
template <class T>
matrix<T> matrix<T>::operator-(const matrix<T> &b)
{
if(row != b.row || column != b.column)
throw(string("Matrices are not the same size."));
if(typeid(*this).name() != typeid(b).name())// NOTE: not able to compile if types are different.
throw(string("Matrix types are not the same."));
matrix<T> c(row, column);
for(int i = 0; i < row; ++i){
for(int j = 0; j < column; ++j){
c.data[i][j] = data[i][j] - b.data[i][j];
}
}
return c;
}
template <class T>
matrix<T> matrix<T>::operator*(const matrix<T> &b)
{
if(row != b.column && b.row != column)
throw(string("Matrices are not the same size."));
if(typeid(*this).name() != typeid(b).name()) // NOTE: not able to compile if types are different.
throw(string("Matrix types are not the same."));
matrix<T> c(row, b.column);
for(int i = 0; i < row; ++i){
for(int j = 0; j < b.column; ++j){
c.data[i][j] = 0;
for(int k = 0; k < column; ++k){
c.data[i][j] = c.data[i][j] + data[i][k] * b.data[k][j];
}
}
}
return c;
}
//***********************************************
// complexn manipulators
// flags defined at the begining of file matrix.cpp
ostream& cplx(ostream& out)
{
cplx_flag = true;
real_flag = false;
img_flag = false;
magnitude_flag = false;
return out;
}
ostream& real(ostream& out)
{
cplx_flag = false;
real_flag = true;
img_flag = false;
magnitude_flag = false;
return out;
}
ostream& img(ostream& out)
{
cplx_flag = false;
real_flag = false;
img_flag = true;
magnitude_flag = false;
return out;
}
ostream& magnitude(ostream& out)
{
cplx_flag = false;
real_flag = false;
img_flag = false;
magnitude_flag = true;
return out;
}
//***********************************************
// complexn function implementations
ostream& operator<<(ostream &out, const complexn &complex)
{
if(cplx_flag == true){
out << fixed << setprecision(1) << complex.real;
switch ((int)complex.img){
case 0: cout << showpos << complex.img << "i" << noshowpos;
break;
case 1: cout << "+i";
break;
default: cout << showpos << complex.img << "i" << noshowpos;
}
}
if(real_flag == true){
out << fixed << setprecision(1) << complex.real;
}
if(img_flag == true){
switch ((int)complex.img){
case 0: cout << showpos << complex.img << "i" << noshowpos;
break;
case 1: cout << "i";
break;
default: cout << complex.img << "i";
}
}
if(magnitude_flag == true){
cout << complex.g;
}
return out;
}
istream& operator>>(istream &in, complexn &complex)
{
in >> complex.real >> complex.img;
return in;
}
complexn::complexn()
{
real = 0;
img = 0;
g = 0;// g means magnitude
}
complexn::complexn(const float &new_real, const float &new_img)
{
real = new_real;
img = new_img;
g = sqrt((real * real) + (img * img));
}
complexn complexn::operator+(const complexn &b)
{
float new_real = 0;
float new_img = 0;
new_real = real + b.real;
new_img = img + b.img;
complexn c(new_real, new_img);// call the constructor to make the new object and calculate the magnitude
return c;
}
complexn complexn::operator-(const complexn &b)
{
float new_real = 0;
float new_img = 0;
new_real = real - b.real;
new_img = img - b.img;
complexn c(new_real, new_img);// call the constructor to make the new object and calculate the magnitude
return c;
}
complexn complexn::operator*(const complexn &b)
{
float new_real = 0;
float new_img = 0;
new_real = (real * b.real) - (img * b.img);
new_img = (img * b.real) + (real * b.img);
complexn c(new_real, new_img); // call the constructor to make the new object and calculate the magnitude
return c;
}
// NOTE: must be included so that matrix constructor can intialise the memory to zero.
void complexn::operator=(const int &a)
{
real = (float)a;
img = (float)0;
}
Test data:
3 3
1.3 2.5 3.8 4.2 5.4 6.8 7.7 8.5 9.1
3 3
4.6 5.4 6.3 7.8 8.5 9.1 1.9 2.6 3.4
3 3
1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0
3 3
5 6 6 7 7 8 9 4 7 4 1 2 2 3 3 4 4 5
/*
FILE: DocRetrieval.cpp
Name: Luke O'Callaghan
Description: Search files listed in the file "listofdocs.txt". Returns a list of the documents
with relevance in descending order.
Requirements: Must be a text file.
Usage: ./search [keywords]
*/
#include <iostream>
#include <iomanip>
#include <cmath>
#include <fstream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
// Additional functions for the main program
void load_keywords(vector<string> &, char**, int);
void load_word_list(vector<string> &, vector<string> &, ifstream &);
int count_similar(vector<string> , vector<string> );
void print_file(ifstream &);
int main(int argc, char **argv)
{
ifstream docs("listofdocs.txt"); // load the list of documents into the program.
ifstream fin;
vector<string> keywords;
vector<string> word_list;
vector<string> original_text;
multimap<double, string, greater<double> > results; // sort the relevance in descending order.
string filename;
int intersections = 0;
double relevance = 0;
if(!docs.good()) {
cerr << "Error: listofdocs.txt does not exist!" << endl;
return -1;
}
load_keywords(keywords, argv, argc);
while(docs.good()) {
docs >> filename;
if(docs.eof()) // check if eof was triggered by the input function
continue;
// load the words into the word list.
fin.open(filename.c_str());
if(!fin.good()) { // If the file can't be read, print error and continue the loop.
cerr << "Error: cannot read " << filename << endl;
continue;
}
load_word_list(word_list, original_text, fin); // save the original text for the calculation of the relevance later.
// calculate the relevance of the keywords to the current document.
intersections = count_similar(keywords, word_list);
relevance = intersections / (sqrt(keywords.size()) * sqrt(original_text.size()));
results.insert(pair<double, string>(relevance, filename));
// Clear the word list, original text, close the file and loop again.
word_list.clear();
original_text.clear();
fin.close();
}
docs.close();
// print the files in descending order. note: Map automatically sorts itself.
multimap<double, string>::iterator it = results.begin();
for(int i = 0; i < results.size(); ++i) {
cout << "(" << it->second << " - " << fixed << setprecision(2) << it->first * 100 << "%) ";
fin.open(it->second.c_str());
print_file(fin);
fin.close();
++it;
}
return 0;
}
void load_keywords(vector<string> &keywords, char **inputs, int size)
{
string text, text_nopunct;
for(int i = 1; i < size; ++i) {
text = inputs[i];
// Remove punctuation and convert string to lowercase
remove_copy_if(text.begin(), text.end(), back_inserter(text_nopunct), ptr_fun<int, int>(&ispunct));
transform(text_nopunct.begin(), text_nopunct.end(), text_nopunct.begin(), ::tolower);
if(count(keywords.begin(), keywords.end(), text_nopunct) == 0) // If the word isn't in the vector, add it. otherwise ignore it.
keywords.push_back(text_nopunct);
text_nopunct = ""; // reset the string for next loop.
}
}
void load_word_list(vector<string> &word_list, vector<string> &original_text, ifstream &fin)
{
string text, text_nopunct;
while(fin.good()) {
fin >> text;
if(fin.eof()) // if there are no more words to read, exit the loop.
continue;
// Remove punctuation and convert string to lowercase
remove_copy_if(text.begin(), text.end(), back_inserter(text_nopunct), ptr_fun<int, int>(&ispunct));
transform(text_nopunct.begin(), text_nopunct.end(), text_nopunct.begin(), ::tolower);
if(count(word_list.begin(), word_list.end(), text_nopunct) == 0) // If the word isn't in the vector, add it. otherwise ignore it.
word_list.push_back(text_nopunct);
original_text.push_back(text);
text_nopunct = ""; // reset the string for next loop.
}
}
int count_similar(vector<string> keywords, vector<string> word_list)
{
vector<string>::iterator it = keywords.begin();
int intersect = 0; // count how many similar words contained in BOTH vectors.
while(it != keywords.end()) {
if(count(word_list.begin(), word_list.end(), *it)) // value > 0 is true, so if it does have the word then it will be true.
++intersect;
++it;
}
return intersect;
}
void print_file(ifstream &fin)
{
string text;
int i = 0;
for(i = 0; i < 10; ++i) {
fin >> text;
if(fin.eof()) // while reading, if the file gets to the end, exit the loop
break;
cout << text << ' ';
}
if(i == 10) // If it printed out 10 words, output "..."
cout << "..." << endl;
}
Test data:
(listofdocs.txt)
Kyle01.txt
(Kyle01.txt)
The Ten Network has dumped embattled host Kyle Sandilands as a judge on Australian Idol. Ten confirmed the news this afternoon, after its senior executives spent the weekend deliberating Sandilands' future.
/*
FILE: Movies.cpp
Name: Luke O'Callaghan
Description: Collects movie reviews and calculates the average of them.
Requirements: File must have the format:
number of reviews
movie title
score
.
.
.
Usage: ./movies [files]
*/
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
int main(int argc, char **argv)
{
map<string, float> movie_rating;
map<string, float> movie_amount;
map<string, float>::iterator mr;
map<string, float>::iterator ma;
ifstream fin;
string movie = "";
float rating = 0;
int record_numbers = 0;
for(int i = 1; i < argc; ++i) {
fin.open(argv[i]);
if(!fin.good()) { // If the file can't be read, print error and continue the loop.
cerr << "Error: cannot read " << argv[i] << endl;
continue;
}
fin >> record_numbers;
fin.ignore(2, '\n'); // ignore newline character and carriage return if it exists. (DOS format only)
for(int j = 0; j < record_numbers; ++j) {
getline(fin, movie, '\n');
// Remove the carriage return from the input if it exists. (DOS format only)
string::const_iterator s_it = movie.end() - 1;
if(*s_it == '\r') {
movie = movie.substr(0, movie.length() - 1);
}
fin >> rating;
fin.ignore(2, '\n'); // ignore newline character and carriage return if it exists. (DOS format only)
mr = movie_rating.find(movie);
ma = movie_amount.find(movie);
if(mr != movie_rating.end()) { // Increment the rating and the number of appearances.
mr->second += rating;
ma->second += 1;
}
else { // If it doesn't exist, add it to the map.
movie_rating.insert(pair<string, float>(movie, rating));
movie_amount.insert(pair<string, float>(movie, 1));
}
}
fin.close();
}
// Print out the movie ratings and their average rating.
mr = movie_rating.begin();
ma = movie_amount.begin();
for(int i = 0; i < movie_rating.size(); ++i) {
cout << mr->first << ": " << ma->second;
if(ma->second > 1) // use plural if more than one review, else use singluar.
cout << " reviews, average of ";
else
cout << " review, average of ";
cout << setprecision(2) << mr->second / ma->second << "/5"<< endl;
++mr;
++ma;
}
return 0;
}
Test data:
(ratings.txt)
7
Harry Potter and the Order of the Phoenix
4
Harry Potter and the Order of the Phoenix
5
The Bourne Ultimatum
3
Harry Potter and the Order of the Phoenix
4
The Bourne Ultimatum
4
Wall-E
4
Glitter
1