13. #define CD_H
#include "Song.h"
#include "Text.h"
using CSC2110::String;
#include "ListArray.h"
using CSC2110::ListArray;
namespace CSC2110
{
class CD
{
private:
String* artist;
String* title;
int year;
int rating;
14. int num_tracks;
ListArray<Song>* songs;
public:
CD(String* artist, String* title, int year, int rating, int
num_tracks);
virtual ~CD();
String* getKey();
void addSong(String* title, String* length);
void displayCD();
static ListArray<CD>* readCDs(const char* file_name);
static int compare_items(CD* one, CD* two);
static int compare_keys(String* sk, CD* cd);
static char getRadixChar(CD* cd, int index); //1-based
};
24. Keyboard* Keyboard::getKeyboard()
{
static Keyboard keyboard; //initialized when method is called
the first time
return &keyboard; //won't go out of scope as keyboard is
static
}
int Keyboard::readInt(string prompt)
{
cout << prompt;
int val = 0;
cin >> val;
return val;
}
int Keyboard::getValidatedInt(string prompt, int min, int max)
{
28. {
class Keyboard
{
private:
Keyboard();
public:
virtual ~Keyboard();
static Keyboard* getKeyboard();
//pre: the string (character literal) that will prompt the user for
input
//post: the input read from the keyboard interpreted as an int is
returned
int readInt(string prompt);
int getValidatedInt(string prompt, int min, int max);
//pre: the string that will prompt the user for input
//post: the input read from the keyboard interpreted as a double
29. is returned
double readDouble(string prompt);
double getValidatedDouble(string prompt, double min, double
max);
//pre: the string that will prompt the user for input
// the string to store the user input and the length of the input
storage string
//post: the text read from the keyboard is copied into the storage
string
String* readString(string prompt);
};
}
#endif
ListArray.h
#if !defined (LISTARRAY_H)
#define LISTARRAY_H
32. sz = 0;
}
template < class T >
ListArray<T>::~ListArray()
{
delete[] items; //the items themselves are not deleted
}
template < class T >
bool ListArray<T>::isEmpty()
{
return (sz == 0);
}
template < class T >
int ListArray<T>::size()
{
33. return sz;
}
template < class T > //1-based
T* ListArray<T>::get(int index)
{
T* item = NULL;
if (index >= 1 && index <= sz)
{
item = items[index - 1];
}
return item;
}
template < class T >
void ListArray<T>::add(T* item)
34. {
add(sz + 1, item); //add the item to the end of the array list
}
template < class T >
void ListArray<T>::add(int index, T* item)
{
if (index < 1 || index > sz + 1)
{
return;
}
//need more room in the array list
if (sz == max_size)
{
arrayResize(2*max_size);
}
35. for (int i = sz; i >= index; i--)
{
items[i] = items[i - 1];
}
items[index - 1] = item;
sz++;
}
template < class T >
void ListArray<T>::remove(int index)
{
if (index < 1 || index > sz)
{
return;
}
for (int i = index; i < sz; i++)
36. {
items[i - 1] = items[i];
}
items[sz - 1] = NULL;
sz--;
/*
if (sz < max_size/2 - 1) //halve the size of the array, smallest
size of max_size should be 2
{
arrayResize(max_size/2);
}
*/
}
template < class T >
ListArrayIterator<T>* ListArray<T>::iterator()
{
37. ListArrayIterator<T>* iter = new ListArrayIterator<T>(items,
sz);
return iter;
}
template < class T >
void ListArray<T>::set(int index, T* item)
{
//could use other methods already written, but this is more
efficient
if (index >= 1 && index <= sz)
{
items[index - 1] = item; //overwrite contents at that
location
}
}
template < class T >
void ListArray<T>::arrayResize(int new_max_size)
38. {
max_size = new_max_size;
T** temp = new T*[max_size];
for (int i = 0; i < sz; i++)
{
temp[i] = items[i];
}
delete[] items;
items = temp;
}
template < class T >
void ListArray<T>::removeAll()
{
delete[] items;
39. max_size = 10;
items = new T*[max_size];
sz = 0;
}
template < class T >
T** ListArray<T>::toArray()
{
int num_items = size();
T** to_array = new T*[num_items];
for (int i = 0; i < num_items; i++)
{
to_array[i] = items[i];
}
return to_array;
}
}
40. #endif
ListArrayIterator.h
#if !defined (NULL)
#define NULL 0
#endif
#if !defined (LISTARRAYITERATOR_H)
#define LISTARRAYITERATOR_H
namespace CSC2110
{
template < class T >
class ListArrayIterator
{
private:
int index;
int sz;
T** items;
41. public:
ListArrayIterator(T** items, int size);
~ListArrayIterator();
bool hasNext();
T* next();
};
template < class T >
ListArrayIterator<T>::ListArrayIterator(T** itms, int size)
{
items = new T*[size];
for (int i = 0; i < size; i++)
{
items[i] = itms[i]; //snapshot of the data
}
index = 1;
42. sz = size;
}
template < class T >
ListArrayIterator<T>::~ListArrayIterator()
{
delete[] items;
}
template < class T >
bool ListArrayIterator<T>::hasNext()
{
return (index <= sz);
}
template < class T >
T* ListArrayIterator<T>::next()
{
44. #include <fstream>
#include <iostream>
using namespace std;
int Matrix::getNumRows()
{
return rows;
}
int Matrix::getNumCols()
{
return cols;
}
//the indices are 1-based!!
Matrix::Matrix(int r, int c)
{
rows = r;
45. cols = c;
if (r < 1)
{
rows = 1;
}
if (c < 1)
{
cols = 1;
}
int num_elements = rows*cols;
mat = new double[rows*cols];
//initialize the matrix to contain all zeroes (might not be
square in general)
int count = 0;
for (int i = 1; i <= rows; i++)
46. {
for (int j = 1; j <= cols; j++)
{
mat[count] = 0.0;
count++;
}
}
}
Matrix::~Matrix()
{
delete[] mat;
}
void Matrix::setElement(int row, int col, double val)
{
int index = (row - 1) * cols + col - 1;
mat[index] = val;
47. }
double Matrix::getElement(int row, int col)
{
int index = (row - 1) * cols + col - 1;
return mat[index];
}
void Matrix::displayMatrix()
{
for (int i = 1; i <= rows; i++)
{
for (int j = 1; j <= cols; j++)
{
cout << this->getElement(i, j) << " ";
}
cout << endl;
}
48. cout << endl;
}
Matrix* Matrix::add(Matrix* other)
{
int rows1 = rows;
int cols1 = cols;
int rows2 = other->rows; //getNumRows()
int cols2 = other->cols; //getNumCols()
if (cols1 != rows1 || cols2 != rows2)
{
cout << "Cannot add matrices." << endl;
return NULL;
}
Matrix* result = new Matrix(rows1, cols1);
49. int rows = rows1;
int cols = cols1;
//loop over all elements of resulting matrix
for (int i = 1; i <= rows; i++)
{
for (int j = 1; j <= cols; j++)
{
double x = this->getElement(i, j) + other->getElement(i,
j);
result->setElement(i, j, x);
}
}
return result;
}
50. Matrix* Matrix::multiply(Matrix* other)
{
int rows1 = rows;
int cols1 = cols;
int rows2 = other->rows;
int cols2 = other->cols;
if (cols1 != rows2)
{
cout << "Cannot multiply matrices." << endl;
return NULL;
}
Matrix* result = new Matrix(rows1, cols2);
int rows = rows1;
int cols = cols2;
51. double x;
//loop over all elements of resulting matrix
for (int i = 1; i <= rows; i++)
{
for (int j = 1; j <= cols; j++)
{
x = 0;
//sum up multiplying matrices to obtain value placed in
new matrix
for (int k = 1; k <= cols1; k++)
{
x = x + this->getElement(i, k) * other->getElement(k,
j);
}
result->setElement(i, j, x);
}
}
52. return result;
}
//assumes a specific format for the file
Matrix* Matrix::readMatrix(const char* file_name)
{
ifstream matrix_file;
matrix_file.open(file_name);
int rows = 1;
int cols = 1;
matrix_file >> rows >> cols;
if (rows < 1)
{
rows = 1;
53. }
if (cols < 1)
{
cols = 1;
}
Matrix* matrix = new Matrix(rows, cols);
for (int i = 1; i <= rows; i++)
{
for (int j = 1; j <= cols; j++)
{
double val = 0.0;
matrix_file >> val;
matrix->setElement(i, j, val);
}
}
54. matrix_file.close();
return matrix;
}
//assumes a specific format for the file
void Matrix::writeMatrix(const char* file_name)
{
ofstream matrix_file;
matrix_file.open(file_name);
matrix_file << rows << " " << cols << endl;
for (int i = 1; i <= rows; i++)
{
for (int j = 1; j <= cols; j++)
{
55. matrix_file << this->getElement(i, j) << " ";
}
matrix_file << endl;
}
matrix_file.close();
}
Matrix.h
#if !defined MATRIX_H
#define MATRIX_H
//the indices are 1-based!!
namespace CSC2110
{
class Matrix
{
private:
int rows;
56. int cols;
double* mat;
public:
Matrix(int rows, int cols); //constructor
~Matrix(); //destructor
void displayMatrix();
int getNumRows();
int getNumCols();
double getElement(int row, int col);
void setElement(int row, int col, double val);
Matrix* add(Matrix* other);
Matrix* multiply(Matrix* other);
57. static Matrix* readMatrix(const char* file_name); //discuss
static
void writeMatrix(const char* file_name);
};
}
#endif
Permutation.cpp
#include "Permutation.h"
using CSC2110::Permutation;
#include "ListArrayIterator.h"
using CSC2110::ListArrayIterator;
Permutation::Permutation(int q, int n)
{
random = Random::getRandom();
r = q;
58. numbers = new ListArray<Integer>();
for (int i = 1; i <= n; i++)
{
Integer* num = new Integer(i);
numbers->add(num);
}
}
Permutation::~Permutation()
{
ListArrayIterator<Integer>* iter = numbers->iterator();
while(iter->hasNext())
{
Integer* i = iter->next();
delete i;
}
delete iter;
delete numbers;
59. }
int Permutation::next()
{
if (r == 0) return -1;
int rand = random->getRandomInt(1, numbers->size());
Integer* num = numbers->get(rand);
int value = num->getValue();
numbers->remove(rand);
delete num;
r--;
return value;
}
Permutation.h
#if !defined (PERMUTATION_H)
60. #define PERMUTATION_H
#include "ListArray.h"
using CSC2110::ListArray;
#include "Integer.h"
using CSC2110::Integer;
#include "Random.h"
using CSC2110::Random;
namespace CSC2110
{
class Permutation
{
private:
int r;
ListArray<Integer>* numbers;
Random* random;
64. return coeffs[power];
}
void Poly::setCoeff(int power, double cf)
{
if (power > max_power || power < 0) return;
coeffs[power] = cf;
if (power >= degree)
{
degree = power;
}
}
double Poly::evaluate(double x)
{
double result = getCoeff(degree);
65. for (int i = degree - 1; i >= 0; i--)
{
result = result * x;
result = result + getCoeff(i);
}
return result;
}
Poly* Poly::multiply(Poly* other)
{
double TOL = .00001;
int n = getDegree();
int m = other->getDegree();
Poly* temp = new Poly(n + m);
66. for (int i = 0; i <= n; i++) //loop over coeffs
{
for (int j = 0; j <= m; j++) //loop over second coeffs
{
double coeff_i = getCoeff(i);
double coeff_j = other->getCoeff(j);
if (fabs(coeff_i) > TOL && fabs(coeff_j) > TOL)
{
int power = i + j;
double coeff = temp->getCoeff(power);
temp->setCoeff(power, coeff + (coeff_i * coeff_j));
}
}
}
return temp;
}
67. void Poly::displayPoly()
{
double TOL = .00001;
int degree = getDegree();
cout << getCoeff(degree) << "x^" << degree;
for (int i = degree - 1; i >= 0; i--)
{
double coeff = getCoeff(i);
if (fabs(coeff) > TOL)
{
cout << " + " << coeff << "x^" << i << " ";
}
}
cout << endl;
}
68. //assumes a specific format for the file
//why is this method static in the header file?
Poly* Poly::readPoly(const char* file_name)
{
ReadFile* rf = new ReadFile(file_name); //for reading
String* degree_str = rf->readLine();
int degree = degree_str->a_to_i();
delete degree_str;
Poly* poly = new Poly(degree);
for (int i = 0; i <= degree; i++)
{
String* coeff_str = rf->readLine();
float coeff = coeff_str->a_to_f();
delete coeff_str;
poly->setCoeff(i, (double) coeff);
69. }
delete rf;
return poly;
}
//assumes a specific format for the file
void Poly::writePoly(const char* file_name)
{
WriteFile wf(file_name); //for writing
String* degree_str = String::f_to_a(degree);
wf.writeLine(degree_str);
delete degree_str;
for (int i = 0; i <= degree; i++)
{
float coeff = (float) getCoeff(i);
70. String* coeff_str = String::f_to_a(coeff);
wf.writeLine(coeff_str);
delete coeff_str;
}
}
Poly.h
#if !defined (POLY)
#define POLY
namespace CSC2110
{
class Poly
{
private:
int max_power;
int degree;
73. }
Random* Random::getRandom()
{
static Random random; //initialized when method is called
the first time
return &random;
}
void Random::randomInit()
{
srand (time(NULL));
//try to get a more random starting number
rand();
rand();
rand();
rand();
74. }
int Random::getRandomInt(int lower, int upper)
{
int diff = upper - lower + 1;
int random_num = rand()%diff;
random_num = random_num + lower; //gives a number
between lower and upper, inclusive
return random_num;
}
float Random::getRandomFloat(float lower, float upper)
{
float r_float_1 = (float) rand();
float r_float_2 = (float) RAND_MAX;
float random_normalized = r_float_1/r_float_2; //between 0.0
and 1.0
float random_float = lower + random_normalized*(upper -
lower);
82. #include "Text.h"
using CSC2110::String;
namespace CSC2110
{
class Song
{
private:
String* title;
String* length;
public:
Song(String* title, String* length);
virtual ~Song();
void displaySong();
};
}
83. #endif
String.cpp
#include "Text.h"
using CSC2110::String;
#include <stdlib.h> //needed for atoi and atof
#include <cstring> //needed for strlen and strcmp
#include <sstream>
#include <iostream>
using namespace std;
String::String(const char* char_array)
{
sz = strlen(char_array);
char* text = new char[sz+1];
for (int i = 0; i < sz; i++)
{
text[i] = char_array[i];
86. int String::find(char delimiter, int start)
{
if (start >= sz || start < 0) return -1;
int loc = sz;
for (int i = start; i < sz; i++)
{
if (text[i] == delimiter)
{
loc = i;
break;
}
}
return loc; //delimiter not found
}
87. //the substring will use the characters from start to end inclusive
String* String::substr(int start, int end)
{
if (start > end || start < 0) return NULL;
if (start > sz || end > sz) return NULL;
int sub_len = end - start + 1;
char* sub_text = new char[sub_len + 1];
int count = 0;
for (int i = start; i <= end; i++)
{
sub_text[count] = text[i];
count++;
}
sub_text[count] = 0;
String* sub = new String((const char*) sub_text);
88. return sub;
}
int String::a_to_i()
{
return atoi(text);
}
float String::a_to_f()
{
return atof(text);
}
String* String::i_to_a(int number)
{
stringstream out;
out << number;
const char* text = out.str().c_str();
89. return new String(text);
}
String* String::f_to_a(float number)
{
stringstream out;
out << number;
const char* text = out.str().c_str();
return new String(text);
}
Text.h
#if !defined STRING_H
#define STRING_H
namespace CSC2110
{
90. class String
{
private:
const char* text;
int sz; //length of string not including null terminator
public:
String(const char* char_array);
virtual ~String();
void displayString();
int length();
const char* getText();
//add this member function
char charAt(int index);
int a_to_i();
float a_to_f();
91. static String* i_to_a(int number);
static String* f_to_a(float number);
//find the location of a particular character in a String and
return the index if found
//preconditions:
// str is the String being examined for the character delimiter
(str must point to a valid String)
// delimiter is the character being searched for
// start is the index to start the search at (the first index of
the String is 0, start cannot exceed the length of the String)
//postconditions:
// if the preconditions are met, the index of the first delimiter
encountered at or after the start index is returned
// if the delimiter is not present in the String at index start or
later, -1 is returned
// if the preconditions are not met, no guarantees on output
are made
int find(char delimiter, int start);
//creates a new String that is extracted from an existing String
with characters specified by the start and end indices
92. //preconditions:
// str is the String from which the substring will be extracted
(str must point to a valid String)
// start and end are the indices used to create the substring
// start must be less than or equal to end, start must be >= 0,
end must be >= 0, end < the length of the String
//postconditions:
// if the preconditions are met, the String extracted from the
parameter String
// that starts at index start and ends at index end is created
and returned
// the original string is unaffected
String* substr(int start, int end);
//need to document that this compare only has three possible
return values (-1, 0, 1)
int compare(String* other);
};
}
94. tokens = new String*[max_tokens];
for (int i = 0; i < max_tokens; i++)
{
tokens[i] = NULL;
}
int str_len = str->length();
int current_loc = 0;
int count = 0;
while(current_loc < str_len)
{
int next_loc = str->find(delimiter, current_loc);
if (next_loc > 0) //a delimiter as the first character is a
problem
{
String* token = str->substr(current_loc, next_loc - 1);
99. {
class Tokens
{
private:
String** tokens;
int max_tokens;
int sz;
void addToken(String* str); //requires a resizing check
void resize();
public:
Tokens(String* str, char delimiter);
~Tokens(); //Tokens is not responsible for deleting each
token
void displayTokens();
String* getToken(int index); //returns a specifically
requested token
int getNumTokens();
104. int Password::bestGuess()
{
int best_guess_index = -1;
int best_num_eliminated = -1;
int num_viable_passwords = getNumberOfPasswordsLeft();
//loop over ALL words, even if they have been eliminated as
the password
int count = 1;
ListArrayIterator<String>* all_iter = all_words->iterator();
while(all_iter->hasNext())
105. {
String* original_word = all_iter->next();
//loop over only those words that could still be the password
//count up the number of matches between a possible
password and a word in the original list
int* count_num_matches = new int[len + 1];
for (int i = 0; i < len; i++)
{
count_num_matches[i] = 0;
}
ListArrayIterator<String>* viable_iter = viable_words-
>iterator();
while(viable_iter->hasNext())
{
String* viable_word = viable_iter->next();
int num_matches = getNumMatches(viable_word,
106. original_word);
count_num_matches[num_matches]++;
}
delete viable_iter;
//find the largest number in the count_num_matches array
//the largest number indicates the guess that will generate
the most eliminations
int most_num_matches = 0;
for (int j = 0; j < len; j++)
{
int curr_num_matches = count_num_matches[j];
if (curr_num_matches > most_num_matches)
{
most_num_matches = curr_num_matches;
}
}
//compute the fewest that can possibly be eliminated by
107. guessing the current word (original list)
int num_eliminated = num_viable_passwords -
most_num_matches;
//select the word to guess that maximizes the minimum
number of eliminations (minimax)
if (num_eliminated > best_num_eliminated)
{
best_num_eliminated = num_eliminated;
best_guess_index = count;
}
count++;
delete[] count_num_matches;
}
delete all_iter;
return best_guess_index; //return a 1-based index into the
all_words list of words (careful)
}
108. lab03/Password.h
#if !defined PASSWORD_H
#define PASSWORD_H
//complete the includes
class Password
{
private:
ListArray<String>* viable_words; //the list of words that
can still be the password
ListArray<String>* all_words; //the original list of words
int len; //the length of the first word entered is stored to
check that all subsequent words have the same length
//a private helper method to report the number of character
matches between two Strings
int getNumMatches(String* curr_word, String*
word_guess);
110. containing the possible passwords: ");
ReadFile* rf = new ReadFile(file_str->getText());
delete file_str;
String* num_words_str = rf->readLine();
int num_words = num_words_str->a_to_i();
delete num_words_str;
for (int i = 0; i < num_words; i++)
{
String* word = rf->readLine();
fh->addWord(word);
}
delete rf;
fh->displayViableWords();
}
111. void guessWords(Password* fh)
{
Keyboard* kb = Keyboard::getKeyboard();
int numLeft = fh->getNumberOfPasswordsLeft();
while (numLeft > 1) //terminate if the password has been
identified, or there is no valid password (user entry error)
{
int best_guess_index = fh->bestGuess();
String* best_guess_word = fh-
>getOriginalWord(best_guess_index);
cout << "You should guess "";
best_guess_word->displayString();
cout << "" at index " << best_guess_index;
cout << endl << endl;
String* guess_str = kb->readString("Index of word in the
original word list to guess (1-based): ");
int guess = guess_str->a_to_i();
delete guess_str;
112. String* match_str = kb->readString("Number of character
matches: ");
int match = match_str->a_to_i();
delete match_str;
cout << endl;
fh->guess(guess, match); //1-based index of the guessed
word and the number of character matches
fh->displayViableWords();
numLeft = fh->getNumberOfPasswordsLeft();
}
}
int main()
{
Password* fallout = new Password();
addWords(fallout);