diff --git a/Makefile b/Makefile index 3b3ec6b..1d29d69 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,18 @@ INC := -I include +STD := -std=c++11 main: compile link compile: - g++ $(INC) -c -o build/main.o src/main.cpp - g++ $(INC) -c -o build/sorts.o src/sorts.cpp + g++ $(INC) $(STD) -c -o build/main.o src/main.cpp + g++ $(INC) $(STD) -c -o build/sorts.o src/sorts.cpp link: g++ -o bin/main.out build/*.o +test: main + bin/main.out -a > test/SortTimes.txt + test/CheckSortedOutputs.sh + clean: rm build/*.o bin/*.out test/OUTPUT/*.txt diff --git a/README.md b/README.md index e69de29..1a3a027 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,42 @@ +# Sorting +A program written to test the time complexity of insertion, merge, and heap sort + +# Author +Gregory Crawford + +# Compiling +Run `make` to compile the project. +Output files get placed into test/SORTED + +# Running +Run `bin/main.out` with chosen arguments to run program + +# Commands +## bin/main.out [-a | -f filename | -d] +Ex: `bin/main.out -f test/PERM/perm15K.txt -s merge` + +# Arguments +## File selection +> -a OR --all +- Runs through all the original files (perm15K.txt - perm150K.txt) + - *EX: bin/main.out -a* +> -f path/to/file.txt OR --filename path/to/file.txt +- Runs a specific file to sort + - *EX: bin/main.out -f perm15K.txt* +> -d OR --default (**default**) +- Runs sort only on the default test file (perm15K.txt) + - *EX: bin/main.out -d* +## Sorting type selection +> -s | --sort-type + - Selects a sort type + - Options: + - insertion + - *EX: bin/main.out -s insertion* + - merge + - *EX: bin/main.out -s merge* + - heap + - *EX: bin/main.out -s heap* + - all (**default**) + - *EX: bin/main.out -s all* + +# Notes diff --git a/bin/main.out b/bin/main.out index 458b47c..576127a 100755 Binary files a/bin/main.out and b/bin/main.out differ diff --git a/build/main.o b/build/main.o index cdc982e..ee11072 100644 Binary files a/build/main.o and b/build/main.o differ diff --git a/include/sorts.h b/include/sorts.h index 74d531a..0120176 100644 --- a/include/sorts.h +++ b/include/sorts.h @@ -1,6 +1,7 @@ #ifndef SORTS_H #define SORTS_H +#include #include #include @@ -12,15 +13,20 @@ private: std::string filename; int lineCount; std::vector originalWordList; - std::vector newWordList; - SortType currentType; + std::chrono::duration sortTime; public: - Sorter(std::string newFilename); + Sorter(); + std::vector newWordList; + bool defaultOnly, fileGiven, allLists, sortGiven; + SortType currentType; std::string GetFilename(void); void SetFilename(std::string newName); void SetWordList(void); + void SortAll(void); void RunSorts(void); + void __RunSorts__(void); void OutputResult(void); + void PrintSortTime(std::string outputFilename); void PrintToFile(std::string outputFilename); void InsertionSort(void); void MergeSort(void); @@ -29,4 +35,6 @@ public: void HeapSort(void); }; +void CheckArguments(int argc, char* arguments[], Sorter* sortObj); + #endif diff --git a/src/main.cpp b/src/main.cpp index 12920af..d73fb73 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,9 @@ #include "sorts.h" -int main(int argc, char** argv) +int main(int argc, char* argv[]) { - Sorter newSort(argv[1]); + Sorter newSort; + CheckArguments(argc, argv, &newSort); newSort.RunSorts(); return 0; } diff --git a/src/sorts.cpp b/src/sorts.cpp index f4b524e..4ee20a9 100644 --- a/src/sorts.cpp +++ b/src/sorts.cpp @@ -1,34 +1,41 @@ #include "sorts.h" -#include +#include #include +#include #include #include -Sorter::Sorter(std::string newFilename) +// Initialization function for Sorter class +Sorter::Sorter() { lineCount = 0; currentType = INSERTION; - SetFilename(newFilename); - SetWordList(); + defaultOnly = 0; + fileGiven = 0; + allLists = 0; + sortGiven = 0; } +// Sets the current filename void Sorter::SetFilename(std::string newName) { this->filename = newName; } +// Returns the current filename std::string Sorter::GetFilename(void) { return this->filename; } +// Sets word list found in file into vector void Sorter::SetWordList(void) { std::string bufferStr; std::ifstream file(this->filename); if (!file.is_open()) { - std::cout << "Failed opening file\n"; + std::cout << "Failed opening file: " << this->filename << '\n'; exit(1); } while (getline(file, bufferStr)) @@ -39,32 +46,81 @@ void Sorter::SetWordList(void) return; } +// Main function for calling all sort categories void Sorter::RunSorts(void) { - newWordList = originalWordList; - InsertionSort(); - OutputResult(); - currentType = MERGE; - newWordList = originalWordList; - MergeSort(); - OutputResult(); - currentType = HEAP; - newWordList = originalWordList; - HeapSort(); - OutputResult(); + if (defaultOnly || fileGiven) + { + SetWordList(); + __RunSorts__(); + } + if (allLists) + SortAll(); + return; } +// Sorts all default files if allLists is set +void Sorter::SortAll(void) +{ + int fileCount = 10; + std::string newFilename; + for (int i = 1; i <= fileCount; i++) + { + lineCount = 0; + newFilename = "test/PERM/perm"; + newFilename += std::to_string(15*i); + newFilename += "K.txt"; + SetFilename(newFilename); + SetWordList(); + __RunSorts__(); + originalWordList.clear(); + } +} + +// Function for starting sort functions +void Sorter::__RunSorts__(void) +{ + if (!sortGiven) + currentType = INSERTION; + if (currentType == INSERTION) + { + newWordList = originalWordList; + InsertionSort(); + OutputResult(); + } + if (!sortGiven) + currentType = MERGE; + if (currentType == MERGE) + { + newWordList = originalWordList; + MergeSort(); + OutputResult(); + } + if (!sortGiven) + currentType = HEAP; + if (currentType == HEAP) + { + newWordList = originalWordList; + HeapSort(); + OutputResult(); + } +} + +// Main function for printing results void Sorter::OutputResult(void) { switch(currentType) { case INSERTION: + PrintSortTime("IS"); PrintToFile("IS"); break; case MERGE: + PrintSortTime("MS"); PrintToFile("MS"); break; case HEAP: + PrintSortTime("HS"); PrintToFile("HS"); break; default: @@ -72,12 +128,21 @@ void Sorter::OutputResult(void) } } +// Prints sort time to the screen +void Sorter::PrintSortTime(std::string outputFilename) +{ + std::string sortSizeString = std::to_string(lineCount / 1000); + std::cout << outputFilename << sortSizeString; + std::cout << " took " << sortTime.count() << " s" << std::endl; + return; +} + +// Prints result of sort operation to file void Sorter::PrintToFile(std::string outputFilename) { + std::string sortSizeString = std::to_string(lineCount / 1000); std::string outputPath = "test/OUTPUT/"; - outputPath += outputFilename; - outputPath += std::to_string(lineCount / 1000); - outputPath += "K.txt"; + outputPath += outputFilename + sortSizeString + "K.txt"; std::ofstream file(outputPath); if (!file.is_open()) { @@ -89,8 +154,10 @@ void Sorter::PrintToFile(std::string outputFilename) file.close(); } +// Main function for insertion sort void Sorter::InsertionSort(void) { + auto start = std::chrono::system_clock::now(); int i; std::string key; for (int j = 1; j < lineCount; j++) @@ -104,14 +171,21 @@ void Sorter::InsertionSort(void) } newWordList[i + 1] = key; } + auto end = std::chrono::system_clock::now(); + sortTime = end - start; } +// Main function for merge sort void Sorter::MergeSort(void) { + auto start = std::chrono::system_clock::now(); __MergeSort__(0, lineCount - 1); + auto end = std::chrono::system_clock::now(); + sortTime = end - start; return; } +// Merge sort function child void Sorter::__MergeSort__(int p, int r) { if (p < r) @@ -124,19 +198,21 @@ void Sorter::__MergeSort__(int p, int r) return; } +// Merge sort function child void Sorter::__Merge__(int p, int q, int r) { int n1 = q - p + 1; int n2 = r - q; - // L[i - 1] R[j - 1] - std::vector leftTmp; - std::vector rightTmp; + const int leftTmpSize = n1 + 1; + const int rightTmpSize = n2 + 1; + std::string leftTmp[leftTmpSize]; + std::string rightTmp[rightTmpSize]; for (int i = 0; i < n1; i++) - leftTmp.push_back(newWordList[p + i]); + leftTmp[i] = newWordList[p + i]; for (int i = 0; i < n2; i++) - rightTmp.push_back(newWordList[q + i + 1]); - leftTmp.push_back("ZZZZZ"); - rightTmp.push_back("ZZZZZ"); + rightTmp[i] = newWordList[q + i + 1]; + leftTmp[n1] = "ZZZZZ"; + rightTmp[n2] = "ZZZZZ"; int i = 0; int j = 0; for (int k = p; k <= r; k++) @@ -145,16 +221,63 @@ void Sorter::__Merge__(int p, int q, int r) { newWordList[k] = leftTmp[i]; i++; - } - else - { + } else { newWordList[k] = rightTmp[j]; j++; } } } +// Main function for heap sort void Sorter::HeapSort(void) { + auto start = std::chrono::system_clock::now(); ; + auto end = std::chrono::system_clock::now(); + sortTime = end - start; +} + +// Checks for command line arguments +void CheckArguments(int argc, char* arguments[], Sorter* sortObj) +{ + std::string tempStr; + for (int i = 0; i < argc; i++) + { + tempStr = arguments[i]; + if ((tempStr == "-a") || (tempStr == "--all")) + { + sortObj->allLists = 1; + return; + + } + if ((tempStr == "-f") || (tempStr == "--filename")) + { + sortObj->SetFilename(arguments[i + 1]); + sortObj->fileGiven = 1; + return; + } + if ((tempStr == "-d") || (tempStr == "--default")) + { + sortObj->SetFilename("test/PERM/perm15K.txt"); + sortObj->defaultOnly = 1; + return; + } + if ((tempStr == "-s") || (tempStr == "--sort-type")) + { + sortObj->sortGiven = 1; + tempStr = arguments[i + 1]; + std::cout << tempStr << '\n'; + if (tempStr == "insertion") + sortObj->currentType = INSERTION; + if (tempStr == "merge") + sortObj->currentType = MERGE; + if (tempStr == "heap") + sortObj->currentType = HEAP; + if (tempStr == "all") + sortObj->sortGiven = 0; + } + } + sortObj->SetFilename("test/PERM/perm15K.txt"); + sortObj->defaultOnly = 1; + return; } diff --git a/test/CheckSortedOutputs.sh b/test/CheckSortedOutputs.sh new file mode 100755 index 0000000..5d22feb --- /dev/null +++ b/test/CheckSortedOutputs.sh @@ -0,0 +1,22 @@ +#!/bin/bash +for ((i=1;i<=10;i++));do + diff -w test/OUTPUT/IS$((i*15))K.txt test/SORTED/sorted$((i*15))K.txt &>/dev/null + if [[ $? -eq 0 ]]; then + echo "IS$((i*15))K passed" + else + echo "IS$((i*15))K failed" + fi + diff -w test/OUTPUT/MS$((i*15))K.txt test/SORTED/sorted$((i*15))K.txt &>/dev/null + if [[ $? -eq 0 ]]; then + echo "MS$((i*15))K passed" + else + echo "MS$((i*15))K failed" + fi + diff -w test/OUTPUT/HS$((i*15))K.txt test/SORTED/sorted$((i*15))K.txt &>/dev/null + if [[ $? -eq 0 ]]; then + echo "HS$((i*15))K passed" + else + echo "HS$((i*15))K failed" + fi + echo "" +done \ No newline at end of file diff --git a/test/SortTimes.txt b/test/SortTimes.txt new file mode 100644 index 0000000..1453cc2 --- /dev/null +++ b/test/SortTimes.txt @@ -0,0 +1,30 @@ +IS15 took 2.06461 s +MS15 took 0.0154898 s +HS15 took 5.4e-08 s +IS30 took 8.38467 s +MS30 took 0.0324445 s +HS30 took 7.2e-08 s +IS45 took 18.9657 s +MS45 took 0.0506499 s +HS45 took 5.3e-08 s +IS60 took 34.2814 s +MS60 took 0.069865 s +HS60 took 4.7e-08 s +IS75 took 54.3642 s +MS75 took 0.0892599 s +HS75 took 6.4e-08 s +IS90 took 80.1745 s +MS90 took 0.110413 s +HS90 took 6e-08 s +IS105 took 111.424 s +MS105 took 0.130451 s +HS105 took 6.8e-08 s +IS120 took 149.645 s +MS120 took 0.15206 s +HS120 took 5.7e-08 s +IS135 took 196.821 s +MS135 took 0.169646 s +HS135 took 6.4e-08 s +IS150 took 250.343 s +MS150 took 0.194482 s +HS150 took 1.18e-07 s