// file DShelf018.cpp
// authors AOU
// date 2006.04.05
/*
-----------------------------------------------
2006.03.20 PROJECT #4 Assigned 3/29/2006, due 4/5/2006
CDShelf(char ch); //'s','S'=>sorted by id
constructor to create a bookshelf with books sorted by id
pick a random size between 1 and width
try to insert books until that size is reached
sort it by book id
void sortBubble(void);
Algorithm
test_constructorSorted
-----------------------------------------------
2006.03.15
void initialize(void);
CDShelf(char ch); //'d'=>dense
test_constructorDense
-----------------------------------------------
2006.03.13
int randomBook(void);
test_randomBook
-----------------------------------------------
2006.03.03
moveToRight(void); completed
test_moveToRight
-----------------------------------------------
2006.03.01
void moveToRight(void); algorithm started
-----------------------------------------------
2006.02.27
Search
test_search
-----------------------------------------------
2006.02.20
Algorithm for insertAtLeft
-----------------------------------------------
2006.02.17 New
insertAtLeft ..started
test_insertAtLeft
displaySimple
-----------------------------------------------
CDShelf(void); //constructorDefault
void test_constructorDefault(void);
void displayDetailed(void);
-----------------------------------------------
*/
/*
for a book of width 5 and id 1:
15 CBook books[MAX_SHELF_WIDTH]
11111 int a[MAX_SHELF_WIDTH]
function | int a[MAX_SHELF_WIDTH] vs CBook books[MAX_SHELF_WIDTH]
------------------------------------------------------------------------------
constructorDefault | |
isValid | |better
constructorRandom | |better
constructorWidth | |
constructorFragmented| |better
insertAtLeft | |better
displayDetailed | |
displaySimple |better |
displayBrief | |
isEmpty | |
randomBook | |better
randomBookPointer | |better
search | |better
remove_byID | |better
remove_byPointer | |better
reclaimSpace |better |
reclaimableSpace | |better
------------------------------------------------------------------------------
*/
///////////////////////////////////////////////////////////////////////////////
// includes
///////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <ctime>
using namespace std;
///////////////////////////////////////////////////////////////////////////////
// Constants
///////////////////////////////////////////////////////////////////////////////
// Constants
int const UNDEFINED = -9;
int const MIN_SHELF_WIDTH = 20;
int const MAX_SHELF_WIDTH = 80;//100;
int const MIN_BOOK_ID = 1;
int const MAX_BOOK_ID = 9;//100;
int const MIN_BOOK_WIDTH = 1;
int const MAX_BOOK_WIDTH = MAX_SHELF_WIDTH/10; //100;
int const TEST_COUNT = 10;
///////////////////////////////////////////////////////////////////////////////
// CBook
///////////////////////////////////////////////////////////////////////////////
class CBook
{
private:
int id; //id=0 => no book or empty space
int width;
public:
CBook(void);
friend class CDShelf;
};
///////////////////////////////////////////////////////////////////////////////
// CDShelf
///////////////////////////////////////////////////////////////////////////////
class CDShelf
{
private:
int width; // width of the bookshelf
int count; // number of books on shelf
int widthOccupied; // total width of book on shelf
// should it include empty holes?
// should not include empty holes
// instead use spaceAvailable
CBook books[MAX_SHELF_WIDTH];
void initialize(void);
public:
CDShelf(void); //constructorDefault
void displayDetailed(void);
bool insertAtLeft(int id, int width);
void displaySimple(void);
int search(int id);
void moveToRight(void);
int randomBook(void);
CDShelf(char ch);//'d'=>dense, 'f'=>fragmented, 's'=>sorted...
//'h'=>half full
// CDShelf myShelf('d')
void sortBubble(void);
bool isSorted(void);
/*
isValid
books with invalid id
books with invalid width
duplicate book
too many books
invalid shelf width
invalid count
invalid widthOccupied
constructorRandom
constructorWidth
constructorFragmented
displayBrief
isEmpty
randomBook
randomBookPointer
remove_byID
remove_byPointer
reclaimSpace
reclaimableSpace
*/
};
///////////////////////////////////////////////////////////////////////////////
// test functions prototypes
///////////////////////////////////////////////////////////////////////////////
void test_constructorDefault(void);
void test_insertAtLeft(void);
void test_search(void);
void test_moveToRight(void);
void test_randomBook(void);
void test_constructorDense(void);
void test_constructorHalf(void);
void test_constructorSorted(void);
void test_constructorFragmented(void);
// test_isValid
// test_constructorWidth
// test_insertAtLeft
// test_isEmpty
// test_randomBook
// test_randomBookPointer
// test_remove_byID
// test_remove_byPointer
// test_reclaimSpace
// test_reclaimableSpace
///////////////////////////////////////////////////////////////////////////////
// main
///////////////////////////////////////////////////////////////////////////////
void main(void)
{
srand(unsigned int(time(NULL)));
//srand(1);
//cout << "Hello\n";
//test_constructorDefault();
//test_insertAtLeft();
//test_search();
//test_moveToRight();
//test_randomBook();
//test_constructorDense();
//test_constructorHalf();
//test_constructorSorted();
test_constructorFragmented();
}
///////////////////////////////////////////////////////////////////////////////
// CDShelf::isSorted(void)
///////////////////////////////////////////////////////////////////////////////
bool CDShelf::isSorted(void)
{
for (int i=0; i<=this->count-2; i++)
if (this->books[i].id > this->books[i+1].id)
return false;
return true;
}
///////////////////////////////////////////////////////////////////////////////
// CDShelf::sortBubble(void)
///////////////////////////////////////////////////////////////////////////////
void CDShelf::sortBubble(void)
{
bool sorted;
do
{
sorted = true;
for (int i=0; i<=this->count-2; i++)
if (this->books[i].id > this->books[i+1].id)
{
CBook temp = this->books[i];
this->books[i] =this->books[i+1];
this->books[i+1] = temp;
sorted = false;
}
}
while (!sorted);
}
///////////////////////////////////////////////////////////////////////////////
// test_constructorFragmented
///////////////////////////////////////////////////////////////////////////////
void test_constructorFragmented(void)
{
cout << "-----------------------------------\n";
cout << "test_constructorFragmented\n";
cout << "-----------------------------------\n";
for (int t=1; t<=TEST_COUNT; t++)
{
CDShelf myShelf('F');
myShelf.displayDetailed();
myShelf.displaySimple();
if (myShelf.isSorted())
cout << "Shelf is sorted\n";
else
cout << "Shelf is NOT sorted\n";
cout << "---------------------------------\n";
}
}
///////////////////////////////////////////////////////////////////////////////
// test_constructorSorted
///////////////////////////////////////////////////////////////////////////////
void test_constructorSorted(void)
{
cout << "-----------------------------------\n";
cout << "test_constructorSorted\n";
cout << "-----------------------------------\n";
for (int t=1; t<=TEST_COUNT; t++)
{
CDShelf myShelf('s');
myShelf.displayDetailed();
myShelf.displaySimple();
if (myShelf.isSorted())
cout << "Shelf is sorted\n";
else
cout << "Shelf is NOT sorted\n";
cout << "---------------------------------\n";
}
}
///////////////////////////////////////////////////////////////////////////////
// test_constructorHalf
///////////////////////////////////////////////////////////////////////////////
void test_constructorHalf(void)
{
cout << "-----------------------------------\n";
cout << "test_constructorHalf\n";
cout << "-----------------------------------\n";
for (int t=1; t<=TEST_COUNT; t++)
{
CDShelf myShelf('h');
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "---------------------------------\n";
}
}
///////////////////////////////////////////////////////////////////////////////
// test_constructorDense
///////////////////////////////////////////////////////////////////////////////
void test_constructorDense(void)
{
cout << "-----------------------------------\n";
cout << "test_constructorDense\n";
cout << "-----------------------------------\n";
for (int t=1; t<=TEST_COUNT; t++)
{
CDShelf myShelf('d');
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "---------------------------------\n";
}
}
///////////////////////////////////////////////////////////////////////////////
// CDShelf::CDShelf
///////////////////////////////////////////////////////////////////////////////
/*
do
think of random bookID
think of random bookWidth
insert this book to the shelf
while widthOccupied < width
*/
CDShelf::CDShelf(char ch)
{
this->initialize();
if(('d'==ch) || ('D'==ch))
{
int bookID, bookWidth;
for (int i=0; i<MAX_SHELF_WIDTH; i++)
{
bookID = rand()%MAX_BOOK_ID + 1;
bookWidth = MIN_BOOK_WIDTH + rand()%(MAX_BOOK_WIDTH - MIN_BOOK_WIDTH);
if (bookWidth <= (this->width - this->widthOccupied))
this->insertAtLeft(bookID, bookWidth);
}
return;
}
if(('h'==ch) || ('H'==ch))
{
int bookID, bookWidth;
for (int i=0; i<MAX_SHELF_WIDTH; i++)
{
bookID = rand()%MAX_BOOK_ID + 1;
bookWidth = MIN_BOOK_WIDTH + rand()%(MAX_BOOK_WIDTH - MIN_BOOK_WIDTH);
if (bookWidth <= (this->width/2 - this->widthOccupied))
this->insertAtLeft(bookID, bookWidth);
}
return;
}
if(('s'==ch) || ('S'==ch))
{
int bookID, bookWidth;
for (int i=0; i<MAX_SHELF_WIDTH; i++)
{
bookID = rand()%MAX_BOOK_ID + 1;
bookWidth = MIN_BOOK_WIDTH + rand()%(MAX_BOOK_WIDTH - MIN_BOOK_WIDTH);
if (bookWidth <= (this->width - this->widthOccupied))
this->insertAtLeft(bookID, bookWidth);
}
this->sortBubble();
return;
}
if(('f'==ch) || ('F'==ch))
{
int bookID, bookWidth;
for (int i=0; i<MAX_SHELF_WIDTH; i++)
{
bookID = rand()%MAX_BOOK_ID + 1;
bookWidth = MIN_BOOK_WIDTH + rand()%(MAX_BOOK_WIDTH - MIN_BOOK_WIDTH);
if (bookWidth <= (this->width - this->widthOccupied))
this->insertAtLeft(bookID, bookWidth);
}
//set the booKid to 0 of some books
for (i=0; i<=this->count-1; i++)
{
if (rand()%100 < 30)
{
this->books[i].id = 0;
this->widthOccupied -=this->books[i].width;
}
}
return;
}
}
/*
CDShelf(char ch); //'s','S'=>sorted by id
constructor to create a bookshelf with books sorted by id
pick a random size between 1 and width
try to insert books until that size is reached
sort it by book id
void sortBubble(void);
Algorithm for sortBubble:
In: books[0..count-1]
Out:books[0..count-1] sorted by id
Version0:
do
set sorted=true
complete a pass
while not sorted
Version1:
do
set sorted=true
//complete a pass
for i=0 to count-2
if books[i].id > books[i+1].id then
swap books[i], books[i+1]
sorted=false
end if
end for
end do
while not sorted
//do while loop
do
{
i=i+1;
cout << i;
}
while (i<100);
//swap books[i], books[i+1]
CBook temp;
temp = books[i+1];
books[i+1] = books[i];
books[i] = temp;
//while not sorted
while (!sorted); //exclaimation
*/
///////////////////////////////////////////////////////////////////////////////
// CDShelf::initialize
///////////////////////////////////////////////////////////////////////////////
void CDShelf::initialize(void)
{
this->width = MIN_SHELF_WIDTH + rand()%(MAX_SHELF_WIDTH - MIN_SHELF_WIDTH + 1);
this->count = 0;
this->widthOccupied = 0;
for (int i=0; i<MAX_SHELF_WIDTH; i++)
{
books[i].id = 0;
books[i].width = 0;
}
}
///////////////////////////////////////////////////////////////////////////////
// test_randomBook
///////////////////////////////////////////////////////////////////////////////
void test_randomBook(void)
{
cout << "-----------------------------------\n";
cout << "test_randomBook\n";
cout << "-----------------------------------\n";
bool result;
CDShelf myShelf;
myShelf.displayDetailed();
myShelf.displaySimple();
int id;
for (int t=1; t<=TEST_COUNT; t++)
{
id = myShelf.randomBook();
cout << "Random book id = " << id << endl;
}
cout << "---------------------------------\n";
result = myShelf.insertAtLeft(3, 3);
myShelf.displayDetailed();
myShelf.displaySimple();
for (int t=1; t<=TEST_COUNT; t++)
{
id = myShelf.randomBook();
cout << "Random book id = " << id << endl;
}
cout << "---------------------------------\n";
result = myShelf.insertAtLeft(2, 2);
result = myShelf.insertAtLeft(1, 1);
result = myShelf.insertAtLeft(4, 4);
result = myShelf.insertAtLeft(5, 5);
result = myShelf.insertAtLeft(6, 6);
myShelf.displayDetailed();
myShelf.displaySimple();
for (int t=1; t<=TEST_COUNT*2; t++)
{
id = myShelf.randomBook();
cout << "Random book id = " << id << endl;
}
cout << "---------------------------------\n";
}
///////////////////////////////////////////////////////////////////////////////
// CDShelf::randomBook
///////////////////////////////////////////////////////////////////////////////
/*
returns the id of a book randomly selected
Possibilities
1. Empty shelf
2. Shelf is full
3. Shelf is not full
shelf is not fragmented
shelf is fragmented
Algorithm:
if shelf is Empty then
return UNDEFINED
do
{
select book random[0..count-1]
id = id of the selected book
}
while (id==0)
return id of the book
if count is 0 will this create a problem? no
if count is 1 will this create a problem? no
*/
int CDShelf::randomBook(void)
{
if (0 == this->count)
return UNDEFINED;
int bi;
do
bi = rand()%this->count; // 0..count-1
while (0==this->books[bi].id);
return books[bi].id;
}
///////////////////////////////////////////////////////////////////////////////
// test_moveToRight
///////////////////////////////////////////////////////////////////////////////
void test_moveToRight(void)
{
cout << "-----------------------------------\n";
cout << "test_moveToRight\n";
cout << "-----------------------------------\n";
bool result;
CDShelf myShelf;
myShelf.displayDetailed();
myShelf.displaySimple();
myShelf.moveToRight();
cout << "\nAfter myShelf.moveToRight();\n";
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "---------------------------------\n";
result = myShelf.insertAtLeft(3, 5);
cout << "\nAfter myShelf.insertAtLeft(3, 5);\n";
if (result)
cout << "myShelf.insertAtLeft was a success\n";
else
cout << "myShelf.insertAtLeft was NOT a success\n";
myShelf.displayDetailed();
myShelf.displaySimple();
myShelf.moveToRight();
cout << "\nAfter myShelf.moveToRight();\n";
myShelf.displayDetailed();
myShelf.displaySimple();
myShelf.moveToRight();
cout << "\nAfter myShelf.moveToRight();\n";
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "---------------------------------\n";
}
///////////////////////////////////////////////////////////////////////////////
// CDShelf::moveToRight
///////////////////////////////////////////////////////////////////////////////
/*
it is only making room for a book record/entry
we will have to make sure that the new book
depending on its width does not cause any
book(s) to be dropped (calling dropRightmost)
Possibilities
bookshelf is already full
drop the last book
move to right
bookshelf is not full
move to right
bookshelf is empty
do nothing
*/
void CDShelf::moveToRight(void)
{
//bookshelf is empty
// do nothing
if (this->count == 0)
return;
//bookshelf is already full
// drop the last book
// move to right
//bookshelf is not full
// move to right
// for i=count-1 to 0 step -1
// books[i+1] = books[i]
// books[0].id = 0
// count++
if (this->count < this->width)
{
for (int i=this->count-1; i>=0; i--)
this->books[i+1] = this->books[i]; //don't have to move id and width
this->books[0].id = 0;
this->count++;
return;
}
}
///////////////////////////////////////////////////////////////////////////////
// test_search
///////////////////////////////////////////////////////////////////////////////
void test_search(void)
{
cout << "-----------------------------------\n";
cout << "test_search\n";
cout << "-----------------------------------\n";
bool result;
CDShelf myShelf;
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "myShelf.search(2) = " << myShelf.search(2) << endl;
cout << "---------------------------------\n";
result = myShelf.insertAtLeft(3, 5);
cout << "After myShelf.insertAtLeft(3, 5);\n";
if (result)
cout << "myShelf.insertAtLeft was a success\n";
else
cout << "myShelf.insertAtLeft was NOT a success\n";
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "myShelf.search(2) = " << myShelf.search(2) << endl;
cout << "myShelf.search(3) = " << myShelf.search(3) << endl;
cout << "---------------------------------\n";
}
///////////////////////////////////////////////////////////////////////////////
// CDShelf::search
///////////////////////////////////////////////////////////////////////////////
/*
Search for a book with given id and return the
location 0 to count-1
for i=0 to count-1
if books[i].id is equal to id then return i
end for
return UNDEFINED
*/
int CDShelf::search(int id)
{
for (int i=0; i<this->count; i++)
if (books[i].id == id)
return i;
return UNDEFINED;
}
///////////////////////////////////////////////////////////////////////////////
// test_insertAtLeft
///////////////////////////////////////////////////////////////////////////////
/*
Algorithm0:
Possibilities:
(1) Empty shelf
(2) Invalid book
(3) Duplicate book
(4) Full shelf
We will have to drop one or more books
(5) Shelf is not full and not empty
We may have to move one or more books
We may have to drop one or more books
*/
void test_insertAtLeft(void)
{
cout << "-----------------------------------\n";
cout << "test_insertAtLeft\n";
cout << "-----------------------------------\n";
bool result;
CDShelf myShelf;
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "---------------------------------\n";
result = myShelf.insertAtLeft(3, 5);
cout << "After myShelf.insertAtLeft(3, 5);\n";
if (result)
cout << "myShelf.insertAtLeft was a success\n";
else
cout << "myShelf.insertAtLeft was NOT a success\n";
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "---------------------------------\n";
result = myShelf.insertAtLeft(-1, 5);
cout << "After myShelf.insertAtLeft(-1, 5);\n";
if (result)
cout << "myShelf.insertAtLeft was a success\n";
else
cout << "myShelf.insertAtLeft was NOT a success\n";
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "---------------------------------\n";
result = myShelf.insertAtLeft(2, -1);
cout << "After myShelf.insertAtLeft(2, -1);\n";
if (result)
cout << "myShelf.insertAtLeft was a success\n";
else
cout << "myShelf.insertAtLeft was NOT a success\n";
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "---------------------------------\n";
result = myShelf.insertAtLeft(3, 5);
cout << "After myShelf.insertAtLeft(3, 5);\n";
if (result)
cout << "myShelf.insertAtLeft was a success\n";
else
cout << "myShelf.insertAtLeft was NOT a success\n";
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "---------------------------------\n";
result = myShelf.insertAtLeft(4, 5);
cout << "After myShelf.insertAtLeft(4, 5);\n";
if (result)
cout << "myShelf.insertAtLeft was a success\n";
else
cout << "myShelf.insertAtLeft was NOT a success\n";
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "---------------------------------\n";
result = myShelf.insertAtLeft(5, 7);
cout << "After myShelf.insertAtLeft(5, 7);\n";
if (result)
cout << "myShelf.insertAtLeft was a success\n";
else
cout << "myShelf.insertAtLeft was NOT a success\n";
myShelf.displayDetailed();
myShelf.displaySimple();
cout << "---------------------------------\n";
}
///////////////////////////////////////////////////////////////////////////////
// CDShelf::insertAtLeft
///////////////////////////////////////////////////////////////////////////////
/*
Algorithm0:
Possibilities:
(1) Empty shelf
(2) Invalid book
(3) Duplicate book
(4) Full shelf
We will have to drop one or more books
(5) Shelf is not full and not empty
We may have to move one or more books
We may have to drop one or more books
*/
bool CDShelf::insertAtLeft(int id, int width)
{
//(1) Empty shelf
if (0 == this->count)
{
this->books[0].id=id;
this->books[0].width=width;
this->count++;
this->widthOccupied += width;
return true;
}
//(2) Invalid book
if (id < MIN_BOOK_ID || id > MAX_BOOK_ID)
return false;
if (width <= 0 || width > this->width)
return false;
//(3) Duplicate book
if(this->search(id) != UNDEFINED)
{
//cout << "Duplicate book\n";
return false;
}
//(4) Full shelf
// We will have to drop one or more books
// full <= widthOccupied .ge. shelf.width
//
//(5) Shelf is not full and not empty
// We may have to move one or more books
// We may have to drop one or more books
// not full <= widthOccupied .lt. shelf.width
if (this->widthOccupied < this->width)
{
this->moveToRight();
this->books[0].id=id;
this->books[0].width = width;
this->widthOccupied += width;
return true;
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
// CDShelf::displaySimple
///////////////////////////////////////////////////////////////////////////////
/*
void CDShelf::displaySimple(void)
Algorithm0:
for each book b do the following
display id width times
Algorithm1:
for each book b do the following
do the following b.width times
display b.id
Algorithm2:
for i=0 to count-1 do the following
for j=0 to b[i].width-1 do the following
display b[i].id
*/
void CDShelf::displaySimple(void)
{
cout << "Simple view:\n";
cout << "width = " << width << endl;
cout << "count = " << count << endl;
cout << "widthOccupied = " << widthOccupied << endl;
for (int i=0; i<this->count; i++)
for (int j=0; j<books[i].width; j++)
cout << books[i].id;
cout << endl;
}
///////////////////////////////////////////////////////////////////////////////
// CDShelf::displayDetailed
///////////////////////////////////////////////////////////////////////////////
void CDShelf::displayDetailed(void)
{
cout << "Detailed view:\n";
cout << "width = " << width << endl;
cout << "count = " << count << endl;
cout << "widthOccupied = " << widthOccupied << endl;
for (int i=0; i<MAX_SHELF_WIDTH; i++)
{
cout << books[i].id ;
cout << books[i].width << ' ';
}
cout << endl;
}
///////////////////////////////////////////////////////////////////////////////
// test_constructorDefault
///////////////////////////////////////////////////////////////////////////////
void test_constructorDefault(void)
{
CDShelf myShelf;
myShelf.displayDetailed();
myShelf.displaySimple();
}
///////////////////////////////////////////////////////////////////////////////
// CDShelf::CDShelf
///////////////////////////////////////////////////////////////////////////////
CDShelf::CDShelf(void)
{
this->initialize();
}
///////////////////////////////////////////////////////////////////////////////
// CBook::CBook
///////////////////////////////////////////////////////////////////////////////
CBook::CBook(void)
{
id = 0;
width = 0;
};
|