diff options
Diffstat (limited to 'cs162')
74 files changed, 2684 insertions, 0 deletions
diff --git a/cs162/BUILD b/cs162/BUILD new file mode 100644 index 0000000..10ccc2e --- /dev/null +++ b/cs162/BUILD @@ -0,0 +1,14 @@ +filegroup( + name = "build_all", + srcs = [ + "//cs162/wk1:build_all", + "//cs162/wk2:build_all", + "//cs162/wk3:build_all", + "//cs162/wk4:build_all", + "//cs162/wk5:build_all", + "//cs162/wk6:build_all", + "//cs162/wk7:build_all", + "//cs162/wk8:build_all", + "//cs162/wk9:build_all", + ], +) diff --git a/cs162/CMakeLists.txt b/cs162/CMakeLists.txt new file mode 100644 index 0000000..e5cdfca --- /dev/null +++ b/cs162/CMakeLists.txt @@ -0,0 +1,10 @@ +add_subdirectory(wk1) +add_subdirectory(wk2) +add_subdirectory(wk3) +add_subdirectory(wk4) +add_subdirectory(wk5) +add_subdirectory(wk6) +add_subdirectory(wk7) +add_subdirectory(wk8) +add_subdirectory(wk9) +add_subdirectory(wk10) diff --git a/cs162/wk1/BUILD b/cs162/wk1/BUILD new file mode 100644 index 0000000..0e5dde9 --- /dev/null +++ b/cs162/wk1/BUILD @@ -0,0 +1,33 @@ +cc_binary( + name = "quickstop", + srcs = glob([ + "quickstop/**/*.cc", + "quickstop/**/*.hh", + ]), +) + +cc_binary( + name = "random2dArrays", + srcs = glob([ + "random2dArrays/**/*.cc", + "random2dArrays/**/*.hh", + ]), +) + +cc_binary( + name = "randoms", + srcs = glob([ + "randoms/**/*.cc", + "randoms/**/*.hh", + ]), +) + +filegroup( + name = "build_all", + srcs = [ + "quickstop", + "random2dArrays", + "randoms", + ], + visibility = ["//visibility:public"], +) diff --git a/cs162/wk1/CMakeLists.txt b/cs162/wk1/CMakeLists.txt new file mode 100644 index 0000000..b253e2d --- /dev/null +++ b/cs162/wk1/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(randoms) +add_subdirectory(quickstop) +add_subdirectory(random2dArrays) diff --git a/cs162/wk1/quickstop/CMakeLists.txt b/cs162/wk1/quickstop/CMakeLists.txt new file mode 100644 index 0000000..59d03bd --- /dev/null +++ b/cs162/wk1/quickstop/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk1_quickstop) + +add_executable(wk1_quickstop quickstop.cc) diff --git a/cs162/wk1/quickstop/quickstop.cc b/cs162/wk1/quickstop/quickstop.cc new file mode 100644 index 0000000..208ac5c --- /dev/null +++ b/cs162/wk1/quickstop/quickstop.cc @@ -0,0 +1,57 @@ +#include <iostream> + +// Print instructions +void instructions(); +// Get and assign the input +void getInput(double &, int &); +// Calculate the adjusted price +double price(double, int); +// Output the adjusted price +void giveOutput(double, int, double); + +int main() { + // Declare variables + double wholesalePrice; + int shelfDays; + double adjustedPrice; + + instructions(); + getInput(wholesalePrice, shelfDays); + adjustedPrice = price(wholesalePrice, shelfDays); + giveOutput(wholesalePrice, shelfDays, adjustedPrice); + + return 0; +} + +void instructions() { + // Output instructions + std::cout << "Enter the wholesale price and the number of days the item is" + "expected to be on shelf, get adjusted price.\n" + << std::endl; +} + +void getInput(double &cost, int &turnover) { + // Get and assign input + std::cout << "Wholesale price: "; + std::cin >> cost; + std::cout << "Number of days item is expected to be on a shelf: "; + std::cin >> turnover; +} + +double price(double cost, int turnover) { + // Compare `turnover` to get adjusted price + if (turnover <= 7) { + return cost + (5.0f / cost); + } else if (turnover > 7) { + return cost + (10.0f / cost); + } + + return 0.0f; +} + +void giveOutput(double cost, int turnover, double price) { + // Output adjusted price + std::cout << "\nIf an item costing $" << cost + << " is expected to be on a shelf for " << turnover + << " days, the item will cost $" << price << std::endl; +} diff --git a/cs162/wk1/random2dArrays/CMakeLists.txt b/cs162/wk1/random2dArrays/CMakeLists.txt new file mode 100644 index 0000000..8bf860a --- /dev/null +++ b/cs162/wk1/random2dArrays/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk1_random2dArrays) + +add_executable(wk1_random2dArrays random2dArrays.cc) diff --git a/cs162/wk1/random2dArrays/random2dArrays.cc b/cs162/wk1/random2dArrays/random2dArrays.cc new file mode 100644 index 0000000..db2a8c9 --- /dev/null +++ b/cs162/wk1/random2dArrays/random2dArrays.cc @@ -0,0 +1,205 @@ +#include <iomanip> +#include <iostream> +#include <random> + +// Declare a helper macro for obtaining random numbers +#define realRand() distribution(mersenneTwister) + +// Prints an array +void printArrayOfSize(int[], int); +// Prints a two-dimensional array (uses `printArrayOfSize` internally) +void printTwoDimensionalArray(int[4][5]); +// Adds two, two-dimensional arrays +void addTwoDimensionalArrayCells(int[4][5], int[4][5], int[4][5]); +// Adds two, two-dimensional arrays' rows +void addTwoDimensionalArrayRows(int[4][5], int[4]); +// Adds two, two-dimensional arrays' columns +void addTwoDimensionalArrayColumns(int[4][5], int[5]); +int addTwoDimensionalArrays(int[4][5], int[4][5]); + +int main() { + // Declare variables + int arrayOne[4][5]; + int arrayTwo[4][5]; + int userChoice; + // Decided to use C++11 random for sound non-predictable random numbers + std::random_device randomDevice; + std::mt19937_64 mersenneTwister(randomDevice()); + std::uniform_real_distribution<double> distribution(10.0, 99.0); + + // Iterate over `arrayOne` and `arrayTwo` + for (int i = 0; i < 4; ++i) { + // Iterate over `arrayOne` and `arrayTwo`'s rows + for (int j = 0; j < 5; ++j) { + // Generate and assign a random `int` + arrayOne[i][j] = + static_cast<int>(realRand()); // arrayOne[i][j] = realRand(); + arrayTwo[i][j] = + static_cast<int>(realRand()); // arrayTwo[i][j] = realRand(); + } + } + + // Output information + std::cout << "Choose what to do with two randomly generated 2D arrays\n" + "1. Display both 2D arrays\n" + "2. Add both 2D arrays\n" + "3. Add rows of both 2D arrays\n" + "4. Add columns of both 2D arrays\n" + "5. Add all values of both arrays\n" + << std::endl + << "Your choice: "; + // Get user's choice + std::cin >> userChoice; + + // Run correct branch per user's choice + switch (userChoice) { + // Output arrays + case 1: { + std::cout << "\nArray one:\n"; + printTwoDimensionalArray(arrayOne); + + std::cout << "Array two:\n"; + printTwoDimensionalArray(arrayTwo); + } break; + + // Add and output arrays + case 2: { + int addArray[4][5]; + + addTwoDimensionalArrayCells(arrayOne, arrayTwo, addArray); + + std::cout << "\nArray one:\n"; + printTwoDimensionalArray(arrayOne); + + std::cout << "Array two:\n"; + printTwoDimensionalArray(arrayTwo); + + std::cout << '\n'; + + std::cout << "Added arrays:\n"; + printTwoDimensionalArray(addArray); + } break; + + // Add and output arrays' rows + case 3: { + int arrayOneRowsSums[4] = {0}; + int arrayTwoRowsSums[4] = {0}; + + std::cout << "\nArray one:\n"; + printTwoDimensionalArray(arrayOne); + + std::cout << "Array two:\n"; + printTwoDimensionalArray(arrayTwo); + + std::cout << '\n'; + + addTwoDimensionalArrayRows(arrayOne, arrayOneRowsSums); + addTwoDimensionalArrayRows(arrayTwo, arrayTwoRowsSums); + + std::cout << "Array one row sums:\n"; + printArrayOfSize(arrayOneRowsSums, 4); + + std::cout << '\n'; + + std::cout << "Array two row sums:\n"; + printArrayOfSize(arrayTwoRowsSums, 4); + } break; + + // Add and output arrays' columns + case 4: { + int arrayOneColumnsSums[5] = {0}; + int arrayTwoColumnsSums[5] = {0}; + + std::cout << "\nArray one:\n"; + printTwoDimensionalArray(arrayOne); + + std::cout << "Array two:\n"; + printTwoDimensionalArray(arrayTwo); + + std::cout << '\n'; + + addTwoDimensionalArrayColumns(arrayOne, arrayOneColumnsSums); + addTwoDimensionalArrayColumns(arrayTwo, arrayTwoColumnsSums); + + std::cout << "Array one row columns:\n"; + printArrayOfSize(arrayOneColumnsSums, 5); + + std::cout << '\n'; + + std::cout << "Array two row columns:\n"; + printArrayOfSize(arrayTwoColumnsSums, 5); + } break; + + case 5: { + std::cout << "\nAll cells of array one plus array two: " + << addTwoDimensionalArrays(arrayOne, arrayTwo) << '\n'; + } break; + + default: { + std::cout << "That is not a valid choice.\n"; + } break; + } + + return 0; +} + +void printArrayOfSize(int array[4], int size) { + // Iterate over `array` + for (int i = 0; i < size; ++i) { + std::cout << std::right << std::setw(3) << " " << array[i]; + } +} + +void printTwoDimensionalArray(int array[4][5]) { + // Iterate over `array` + for (int i = 0; i < 4; ++i) { + printArrayOfSize(array[i], 5); + + std::cout << '\n'; + } +} + +void addTwoDimensionalArrayCells(int arrayOne[4][5], int arrayTwo[4][5], + int addArray[4][5]) { + // Iterate over arrays + for (int i = 0; i < 4; ++i) { + // Iterate over arrays' rows + for (int j = 0; j < 5; ++j) { + addArray[i][j] = arrayOne[i][j] + arrayTwo[i][j]; + } + } +} + +void addTwoDimensionalArrayRows(int array[4][5], int sum[4]) { + // Iterate over arrays + for (int i = 0; i < 4; ++i) { + // Iterate over arrays' rows + for (int j = 0; j < 5; ++j) { + sum[i] += array[i][j]; + } + } +} + +void addTwoDimensionalArrayColumns(int array[4][5], int sum[5]) { + // Iterate over arrays + for (int i = 0; i < 4; ++i) { + // Iterate over arrays' rows + for (int j = 0; j < 5; ++j) { + sum[j] = array[0][j] + array[1][j] + array[2][j] + array[3][j]; + } + } +} + +int addTwoDimensionalArrays(int arrayOne[4][5], int arrayTwo[4][5]) { + int sum = 0; + + // Iterate over arrays + for (int i = 0; i < 4; ++i) { + // Iterate over arrays' rows + for (int j = 0; j < 5; ++j) { + sum += arrayOne[i][j] + arrayTwo[i][j]; + } + } + + return sum; +} diff --git a/cs162/wk1/randoms/CMakeLists.txt b/cs162/wk1/randoms/CMakeLists.txt new file mode 100644 index 0000000..85226b3 --- /dev/null +++ b/cs162/wk1/randoms/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk1_randoms) + +add_executable(wk1_randoms randoms.cc) diff --git a/cs162/wk1/randoms/randoms.cc b/cs162/wk1/randoms/randoms.cc new file mode 100644 index 0000000..ec7d11c --- /dev/null +++ b/cs162/wk1/randoms/randoms.cc @@ -0,0 +1,71 @@ +#include <iostream> + +// Check if there are any duplicates within the array given the array, number +// to check against, and a reference to a variable which will be used to keep +// track if the duplicates within the array. +void checkArrayForDupes(const int[20], int, int &); +// Print the entire array +void printArray(const int[20]); +// Given a variable which may or may not be zero, a reference to a variable +// which will be assigned to, and the value to assign to the reference; check +// if the value is zero and assign if the value is zero. +bool assignIfZero(int &, int &, int); + +int main() { + int randomNumbers[20]; + + // Seed `rand` + srand(static_cast<unsigned int>(time(nullptr))); // srand(time(nullptr)); + + // Iterate over `random_numbers` + for (int &randomNumber : randomNumbers) { + // Iterate endlessly until a unique number is found + for (;;) { + // Generate a random `int` + int randomInt = rand() % (20 + 1 - 1) + 1; + // Keep track of how many times the random number occurs within the + // array + int duplicates = 0; + + // Check if the random number already has occurred within the array + checkArrayForDupes(randomNumbers, randomInt, duplicates); + + // If the random number has not occurred yet, assign it and break out + // of the loop + if (assignIfZero(duplicates, randomNumber, randomInt)) { + break; + } + } + } + + // Print out array values + printArray(randomNumbers); + + return 0; +} + +void checkArrayForDupes(const int numbers[20], int number, int &duplicates) { + for (int i = 0; i < 20; ++i) { + if (numbers[i] == number) { + duplicates += 1; + } + } +} + +void printArray(const int numbers[20]) { + for (int i = 0; i < 20; ++i) { + std::cout << numbers[i] << std::endl; + } +} + +bool assignIfZero(int &compare, int &assign, int value) { + if (compare == 0) { + // Assign is a part of the array, so this function makes changes to a + // value in the array. + assign = value; + + return true; + } + + return false; +} diff --git a/cs162/wk10/BUILD b/cs162/wk10/BUILD new file mode 100644 index 0000000..f15d0eb --- /dev/null +++ b/cs162/wk10/BUILD @@ -0,0 +1,25 @@ +cc_binary( + name = "pointersOnly", + srcs = glob([ + "pointersOnly/**/*.cc", + "pointersOnly/**/*.hh", + ]), +) + +cc_binary( + name = "dynamicArray", + srcs = glob([ + "dynamicArray/**/*.cc", + "dynamicArray/**/*.hh", + ]), + data = ["//data:dataFile.txt"], +) + +filegroup( + name = "build_all", + srcs = [ + "pointersOnly", + "dynamicArray", + ], + visibility = ["//visibility:public"], +) diff --git a/cs162/wk10/CMakeLists.txt b/cs162/wk10/CMakeLists.txt new file mode 100644 index 0000000..6ba4ef3 --- /dev/null +++ b/cs162/wk10/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(pointersOnly) +add_subdirectory(dynamicArray) diff --git a/cs162/wk10/dynamicArray/CMakeLists.txt b/cs162/wk10/dynamicArray/CMakeLists.txt new file mode 100644 index 0000000..d4c4a57 --- /dev/null +++ b/cs162/wk10/dynamicArray/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.21) +project(wk10_dynamicArray) + +add_executable( + wk10_dynamicArray + dynamicArray.cc +)
\ No newline at end of file diff --git a/cs162/wk10/dynamicArray/dynamicArray.cc b/cs162/wk10/dynamicArray/dynamicArray.cc new file mode 100644 index 0000000..5fcba9a --- /dev/null +++ b/cs162/wk10/dynamicArray/dynamicArray.cc @@ -0,0 +1,65 @@ +#include <algorithm> +#include <fstream> +#include <iostream> +#include <string> + +int main() { + std::size_t data_file_size = 0; + std::ifstream data_file("data/dataFile.txt"); + std::string data_item; + int lowest = std::numeric_limits<int>::max(); + int highest = std::numeric_limits<int>::lowest(); + + // Make sure the file is open + if (!data_file.is_open()) { + std::cout << "data file is not open" << std::endl; + + return 0; + } + + // Count how many numbers there are in the data file + while (data_file >> data_item) { + data_file_size += 1; + } + + // Seek back the beginning the of the file + data_file.clear(); + data_file.seekg(0, std::ios::beg); + + // auto data = std::make_unique<int[]>(data_file_size); + // Set up a dynamic array to hold the exact number of numbers in the data file + int *data = new int[data_file_size]; + + // Read the values from the data file into the array + for (std::size_t i = 0; i < data_file_size; ++i) { + data_file >> data[i]; + } + + // Sort the array using bubble sort + for (std::size_t i = 0; i < data_file_size - 1; ++i) { + for (std::size_t j = 0; j < data_file_size - 1; ++j) { + if (data[j] > data[j + 1]) { + std::swap(data[j], data[j + 1]); + } + } + } + + // Find the lowest and highest numbers in the array + for (std::size_t i = 0; i < data_file_size; ++i) { + if (data[i] < lowest) { + lowest = data[i]; + } + + if (data[i] > highest) { + highest = data[i]; + } + } + + // Output the lowest and highest numbers in the array + std::cout << "lowest: " << lowest << "\nhighest: " << highest << std::endl; + + // Free the array + delete[] data; + + return 0; +} diff --git a/cs162/wk10/pointersOnly/CMakeLists.txt b/cs162/wk10/pointersOnly/CMakeLists.txt new file mode 100644 index 0000000..7aaa73e --- /dev/null +++ b/cs162/wk10/pointersOnly/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.21) +project(wk10_pointersOnly) + +add_executable( + wk10_pointersOnly + pointersOnly.cc +)
\ No newline at end of file diff --git a/cs162/wk10/pointersOnly/pointersOnly.cc b/cs162/wk10/pointersOnly/pointersOnly.cc new file mode 100644 index 0000000..31b6f35 --- /dev/null +++ b/cs162/wk10/pointersOnly/pointersOnly.cc @@ -0,0 +1,40 @@ +#include <iostream> + +void inputFeetAndInches(double *, double *); +void feetAndInchesToMeters(const double *, const double *, double *); +void outputFeetInchesAndMeters(const double *, const double *, const double *); + +int main() { + auto *feet = new double; + auto *inches = new double; + auto *meters = new double; + + inputFeetAndInches(feet, inches); + feetAndInchesToMeters(feet, inches, meters); + outputFeetInchesAndMeters(feet, inches, meters); + + delete feet; + delete inches; + delete meters; + + return 0; +} + +void inputFeetAndInches(double *feet, double *inches) { + std::cout << "feet: "; + std::cin >> *feet; + std::cout << "inches: "; + std::cin >> *inches; +} + +void feetAndInchesToMeters(const double *feet, const double *inches, + double *meters) { + *meters = ((*feet * 12) + *inches) * 0.0254; +} + +void outputFeetInchesAndMeters(const double *feet, const double *inches, + const double *meters) { + std::cout << "feet: " << *feet << '\n' + << "inches: " << *inches << '\n' + << "meters: " << *meters << std::endl; +} diff --git a/cs162/wk2/BUILD b/cs162/wk2/BUILD new file mode 100644 index 0000000..cde7d85 --- /dev/null +++ b/cs162/wk2/BUILD @@ -0,0 +1,26 @@ +cc_binary( + name = "dictionaryRead", + srcs = glob([ + "dictionaryRead/**/*.cc", + "dictionaryRead/**/*.hh", + ]), + data = ["//data:words.txt"], +) + +cc_binary( + name = "friendsFile", + srcs = glob([ + "friendsFile/**/*.cc", + "friendsFile/**/*.hh", + ]), + data = ["//data:nums.txt"], +) + +filegroup( + name = "build_all", + srcs = [ + "dictionaryRead", + "friendsFile", + ], + visibility = ["//visibility:public"], +) diff --git a/cs162/wk2/CMakeLists.txt b/cs162/wk2/CMakeLists.txt new file mode 100644 index 0000000..da2cb80 --- /dev/null +++ b/cs162/wk2/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(friendsFile) +add_subdirectory(dictionaryRead) diff --git a/cs162/wk2/dictionaryRead/CMakeLists.txt b/cs162/wk2/dictionaryRead/CMakeLists.txt new file mode 100644 index 0000000..827784a --- /dev/null +++ b/cs162/wk2/dictionaryRead/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk2_dictionaryRead) + +add_executable(wk2_dictionaryRead dictionaryRead.cc) diff --git a/cs162/wk2/dictionaryRead/dictionaryRead.cc b/cs162/wk2/dictionaryRead/dictionaryRead.cc new file mode 100644 index 0000000..e911543 --- /dev/null +++ b/cs162/wk2/dictionaryRead/dictionaryRead.cc @@ -0,0 +1,31 @@ +#include <fstream> +#include <iostream> + +int main() { + // Declare variables + std::string userWord; + std::ifstream wordsFile("data/words.txt", std::ifstream::in); + std::string currentWord; + + // Get user's word + std::cout << "Enter a word: "; + std::cin >> userWord; + + // Check lines for word + while (!wordsFile.eof()) { + wordsFile >> currentWord; + + // Check if line is word + if (currentWord == userWord) { + std::cout << "That word is spelled correctly." << std::endl; + + wordsFile.close(); + return 0; + } + } + + std::cout << "That word is not spelled correctly." << std::endl; + + wordsFile.close(); + return 0; +} diff --git a/cs162/wk2/friendsFile/CMakeLists.txt b/cs162/wk2/friendsFile/CMakeLists.txt new file mode 100644 index 0000000..4140119 --- /dev/null +++ b/cs162/wk2/friendsFile/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk2_friendsFile) + +add_executable(wk2_friendsFile friendsFile.cc) diff --git a/cs162/wk2/friendsFile/friendsFile.cc b/cs162/wk2/friendsFile/friendsFile.cc new file mode 100644 index 0000000..c132165 --- /dev/null +++ b/cs162/wk2/friendsFile/friendsFile.cc @@ -0,0 +1,57 @@ +#include <fstream> +#include <iostream> +#include <string> + +int main() { + // Declare variables + std::ofstream outputFile("data/nums.txt", std::ofstream::out); + std::string userFirstLastName; + std::string userAddress; + std::string userPhoneNumber; + std::string currentFirstLastName; + std::string currentAddress; + std::string currentPhoneNumber; + + // Output information + std::cout << "Enter the names (first and last), phone numbers, and addresses " + "of three friends.\n" + << std::endl; + + for (int i = 1; i < 4; ++i) { + // Get friends' information + std::cout << '#' << i << " First and last name: "; + std::getline(std::cin, userFirstLastName); + std::cout << '#' << i << " Address: "; + std::getline(std::cin, userAddress); + std::cout << '#' << i << " Phone number: "; + std::getline(std::cin, userPhoneNumber); + + // Write friends' data + outputFile << userFirstLastName << '\n' + << userAddress << '\n' + << userPhoneNumber; + + if (i < 3) { + outputFile << '\n'; + } + } + + outputFile.close(); + + std::ifstream inputFile("data/nums.txt", std::ifstream::in); + + std::cout << "\nRecords: " << std::endl; + + // Read and output user's friends + while (!inputFile.eof()) { + std::getline(inputFile, currentFirstLastName); + std::getline(inputFile, currentAddress); + std::getline(inputFile, currentPhoneNumber); + + std::cout << currentFirstLastName << ", " << currentAddress << ", " + << currentPhoneNumber << std::endl; + } + + inputFile.close(); + return 0; +} diff --git a/cs162/wk3/BUILD b/cs162/wk3/BUILD new file mode 100644 index 0000000..dfe23a9 --- /dev/null +++ b/cs162/wk3/BUILD @@ -0,0 +1,15 @@ +cc_binary( + name = "musicStruct", + srcs = glob([ + "musicStruct/**/*.cc", + "musicStruct/**/*.hh", + ]), +) + +filegroup( + name = "build_all", + srcs = [ + "musicStruct", + ], + visibility = ["//visibility:public"], +) diff --git a/cs162/wk3/CMakeLists.txt b/cs162/wk3/CMakeLists.txt new file mode 100644 index 0000000..9804ee6 --- /dev/null +++ b/cs162/wk3/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(musicStruct) diff --git a/cs162/wk3/musicStruct/CMakeLists.txt b/cs162/wk3/musicStruct/CMakeLists.txt new file mode 100644 index 0000000..80b2d2e --- /dev/null +++ b/cs162/wk3/musicStruct/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk3_musicStruct) + +add_executable(wk3_musicStruct musicStruct.cc) diff --git a/cs162/wk3/musicStruct/musicStruct.cc b/cs162/wk3/musicStruct/musicStruct.cc new file mode 100644 index 0000000..5c17839 --- /dev/null +++ b/cs162/wk3/musicStruct/musicStruct.cc @@ -0,0 +1,168 @@ +#include <iostream> +#include <ranges> +#include <string> +#include <vector> + +// A structure to hold information about a CD +struct CD { + std::string title; + std::vector<std::string> performers; + size_t tracks; + size_t playtime; + char genre; +}; + +// Fill a `CD` with information +void fillCd(CD &); +// Query a set of CDs based on certain criteria +std::vector<CD> search(const std::vector<CD> &, int, const std::string &); +// Display a set of CDs +void displayCds(const std::vector<CD> &); + +int main() { + // Declare and initialise variables + size_t cdCount = 0; + std::vector<CD> cds = {{}, {}, {}, {}}; + int searchType; + std::string searchQuery; + + // Get CD amount + do { + std::cout << "How many CDs do you have? (Minimum of three) "; + std::cin >> cdCount; + } while (cdCount < 3); + std::cin.ignore(1024, '\n'); + std::cout << std::endl; + + // Fill CDs + for (int i = 0; i < cdCount; ++i) { + std::cout << "CD " << i + 1 << " of " << cdCount + << ":\n==========" << std::endl; + + fillCd(cds[i]); + } + + // Get CD search query type + std::cout << "What type of search would you like to perform?\n" + "0 = artist\n" + "1 = genre\n" + "> "; + std::cin >> searchType; + + // Get CD search query + std::cout << "What would you like to search? "; + std::cin.ignore(1024, '\n'); + std::getline(std::cin, searchQuery); + std::cout << std::endl; + + // Filter CDs based ons search criteria + std::vector<CD> filtered_cds = search(cds, searchType, searchQuery); + + // Display CDs that matched search criteria + displayCds(filtered_cds); + + return 0; +} + +void fillCd(CD &cd) { + // Get CD title + std::cout << "What is the title of the CD? "; + std::getline(std::cin, cd.title); + + // Get CD performers + + // Initialise CD with a maximum of four performers + cd.performers = {{}, {}, {}, {}}; + for (int i = 0; i < 4; ++i) { + std::string author; + + // Get CD performer + std::cout << "Who is performer " << i + 1 + << " of 4 of the CD? (0 to cancel) "; + std::getline(std::cin, author); + + if (author == "0") { + break; + } else { + cd.performers[i] = author; + } + } + + // Get CD tracks + std::cout << "What is the number of tracks on the CD? "; + std::cin >> cd.tracks; + + // Get CD playtime + std::cout << "What is the total playtime of the CD? "; + std::cin >> cd.playtime; + + // Get CD genre + std::cout << "What is the genre of the CD? "; + std::cin >> cd.genre; + + std::cin.ignore(1024, '\n'); + + std::cout << std::endl; +} + +std::vector<CD> search(const std::vector<CD> &cds, int by, + const std::string &query) { + std::vector<CD> found_cds; + + // Query based on query type + if (by == 0) { + // Find CDs where a performer matches the query + for (const CD &cd : cds | std::views::filter([&](const CD &cd) -> bool { + bool contains = false; + + for (auto performer : cd.performers) { + if (query == performer) { + contains = true; + } + } + + return contains; + })) { + found_cds.emplace_back(cd); + } + } else { + // Find CDs where the genre matches the query + for (const CD &cd : cds | std::views::filter([&](const CD &cd) -> bool { + return cd.genre == query[0]; + })) { + found_cds.emplace_back(cd); + } + } + + return found_cds; +} + +void displayCds(const std::vector<CD> &filtered_cds) { + if (filtered_cds.empty()) { + std::cout << "No CDs where found based on your query!" << std::endl; + } else { + std::cout << filtered_cds.size() + << " CDs where found based on your query:" << std::endl; + + for (int i = 0; i < filtered_cds.size(); ++i) { + // Output number and title + std::cout << "CD #" << i + 1 << ":\n=====" << std::endl; + std::cout << "Title: " << filtered_cds[i].title << std::endl; + + // Output authors + for (int j = 0; j < filtered_cds[i].performers.size(); ++j) { + std::string performer = filtered_cds[i].performers[j]; + + if (!performer.empty()) { + std::cout << "Author #" << j + 1 << ": " << performer << std::endl; + } + } + + // Output tracks, playtime, and genre + std::cout << "Tracks: " << filtered_cds[i].tracks << '\n' + << "Playtime: " << filtered_cds[i].playtime << '\n' + << "Genre: " << filtered_cds[i].genre << '\n' + << std::endl; + } + } +} diff --git a/cs162/wk4/BUILD b/cs162/wk4/BUILD new file mode 100644 index 0000000..7c82b2b --- /dev/null +++ b/cs162/wk4/BUILD @@ -0,0 +1,15 @@ +cc_binary( + name = "dateClass", + srcs = glob([ + "dateClass/**/*.cc", + "dateClass/**/*.hh", + ]), +) + +filegroup( + name = "build_all", + srcs = [ + "dateClass", + ], + visibility = ["//visibility:public"], +) diff --git a/cs162/wk4/CMakeLists.txt b/cs162/wk4/CMakeLists.txt new file mode 100644 index 0000000..c63f514 --- /dev/null +++ b/cs162/wk4/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(dateClass) diff --git a/cs162/wk4/dateClass/CMakeLists.txt b/cs162/wk4/dateClass/CMakeLists.txt new file mode 100644 index 0000000..23dc066 --- /dev/null +++ b/cs162/wk4/dateClass/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk4_dateClass) + +add_executable(wk4_dateClass testDate.cc date.cc) diff --git a/cs162/wk4/dateClass/date.cc b/cs162/wk4/dateClass/date.cc new file mode 100644 index 0000000..b3b52b8 --- /dev/null +++ b/cs162/wk4/dateClass/date.cc @@ -0,0 +1,79 @@ +#include "date.hh" + +// Public constructor to initialise private variables upon construction +Date::Date(unsigned int _month, unsigned int _day, unsigned int _year) { + this->month = _month; + this->day = _day; + this->year = _year; +} + +// Public getters to get private variables +unsigned int Date::getMonth() const { return this->month; } +unsigned int Date::getDay() const { return this->day; } +unsigned int Date::getYear() const { return this->year; } +unsigned int Date::getJulian() const { + // https://quasar.as.utexas.edu/BillInfo/JulianDatesG.html + int A = static_cast<int>(this->year) / 100; + int B = A / 4; + int C = 2 - A + B; + double E = 365.25 * (this->year + 4716); + double F = 30.6001 * (this->month + 1); + + // https://www.aavso.org/jd-calculator + return static_cast<unsigned int>(C + this->day + E + F - 1524.5); +} + +// Public setters to set private variables +void Date::setMonth(unsigned int _month) { this->month = _month; } +void Date::setDay(unsigned int _day) { this->day = _day; } +void Date::setYear(unsigned int _year) { this->year = _year; } +void Date::set(unsigned int _month, unsigned int _day, unsigned int _year) { + this->month = _month; + this->day = _day; + this->year = _year; +} + +// Public function which returns `month` as an `std::string` +std::string Date::monthAsString() const { + switch (this->month) { + case 1: { + return "January"; + } + case 2: { + return "February"; + } + case 3: { + return "March"; + } + case 4: { + return "April"; + } + case 5: { + return "May"; + } + case 6: { + return "June"; + } + case 7: { + return "July"; + } + case 8: { + return "August"; + } + case 9: { + return "September"; + } + case 10: { + return "October"; + } + case 11: { + return "November"; + } + case 12: { + return "December"; + } + default: { + return "Unknown"; + } + } +} diff --git a/cs162/wk4/dateClass/date.hh b/cs162/wk4/dateClass/date.hh new file mode 100644 index 0000000..1aead8f --- /dev/null +++ b/cs162/wk4/dateClass/date.hh @@ -0,0 +1,35 @@ +#ifndef DATE_HH +#define DATE_HH + +#include <string> + +// Date class to keep track of a date +class Date { +private: + // Private variables to keep track of date + unsigned int month; + unsigned int day; + unsigned int year; + +public: + // Public constructors to initialise private variables upon construction + Date() : month(0), day(0), year(0) {} + Date(unsigned int _month, unsigned int _day, unsigned int _year); + + // Public getters to get private variables + [[nodiscard]] unsigned int getMonth() const; + [[nodiscard]] unsigned int getDay() const; + [[nodiscard]] unsigned int getYear() const; + [[nodiscard]] unsigned int getJulian() const; + + // Public setters to set private variables + void setMonth(unsigned int _month); + void setDay(unsigned int _day); + void setYear(unsigned int _year); + void set(unsigned int _month, unsigned int _day, unsigned int _year); + + // Public function which returns `month` as an `std::string` + [[nodiscard]] std::string monthAsString() const; +}; + +#endif // DATE_HH diff --git a/cs162/wk4/dateClass/testDate.cc b/cs162/wk4/dateClass/testDate.cc new file mode 100644 index 0000000..4c80bdf --- /dev/null +++ b/cs162/wk4/dateClass/testDate.cc @@ -0,0 +1,58 @@ +#include <iostream> + +#include "date.hh" + +int main() { + // Test `Date` class with default constructor + { + Date date; + + std::cout << "date after default constructor:\n" + << " month = " << date.getMonth() << '\n' + << " day = " << date.getDay() << '\n' + << " year = " << date.getYear() << '\n' + << std::endl; + } + + { + // Test `Date` class with overloaded constructor + Date date(1, 2, 3); + + std::cout << "date after overloaded constructor:\n" + << " month = " << date.getMonth() << '\n' + << " day = " << date.getDay() << '\n' + << " year = " << date.getYear() << '\n' + << std::endl; + + // Test `Date` class with mutator functions + date.setMonth(4); + date.setDay(5); + date.setYear(6); + + std::cout << "date after using mutator functions:\n" + << " month = " << date.getMonth() << '\n' + << " day = " << date.getDay() << '\n' + << " year = " << date.getYear() << '\n' + << std::endl; + + date.set(7, 8, 9); + + // Test `Date` class with `set` + std::cout << "date after using mutator function set:\n" + << " month = " << date.getMonth() << '\n' + << " day = " << date.getDay() << '\n' + << " year = " << date.getYear() << '\n' + << std::endl; + + // Test `Date` class with `monthAsString` + std::cout << "date's month after using monthAsString: " + << date.monthAsString() << '\n' + << std::endl; + + // Test `Date` class with `julian` + std::cout << "date's month after using julian: " << date.getJulian() + << std::endl; + } + + return 0; +} diff --git a/cs162/wk5/BUILD b/cs162/wk5/BUILD new file mode 100644 index 0000000..efcab31 --- /dev/null +++ b/cs162/wk5/BUILD @@ -0,0 +1,24 @@ +cc_binary( + name = "country", + srcs = glob([ + "country/**/*.cc", + "country/**/*.hh", + ]), +) + +cc_binary( + name = "gradesHelpers", + srcs = glob([ + "gradesHelpers/**/*.cc", + "gradesHelpers/**/*.hh", + ]), +) + +filegroup( + name = "build_all", + srcs = [ + "country", + "gradesHelpers", + ], + visibility = ["//visibility:public"], +) diff --git a/cs162/wk5/CMakeLists.txt b/cs162/wk5/CMakeLists.txt new file mode 100644 index 0000000..7752b0f --- /dev/null +++ b/cs162/wk5/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(country) +add_subdirectory(gradesHelpers) diff --git a/cs162/wk5/country/CMakeLists.txt b/cs162/wk5/country/CMakeLists.txt new file mode 100644 index 0000000..57d984b --- /dev/null +++ b/cs162/wk5/country/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk5_country) + +add_executable(wk5_country country.cc testCountry.cc) diff --git a/cs162/wk5/country/country.cc b/cs162/wk5/country/country.cc new file mode 100644 index 0000000..cbc0bc1 --- /dev/null +++ b/cs162/wk5/country/country.cc @@ -0,0 +1,22 @@ +#include "country.hh" + +float Country::futurePop() const { return this->population * 1.05f * 10.f; } + +// Figure out which of the countries have the largest population +Country Country::largestCountry(Country country2, Country country3) { + if ((this->population >= country2.population) && + (this->population >= country3.population)) { + return *this; + } else if ((country2.population >= this->population) && + (country2.population >= country3.population)) { + return country2; + } else { + return country3; + } +} + +void Country::resetValues(const Country &country) { + this->name = country.name; + this->capital = country.capital; + this->population = country.population; +} diff --git a/cs162/wk5/country/country.hh b/cs162/wk5/country/country.hh new file mode 100644 index 0000000..66bdf1f --- /dev/null +++ b/cs162/wk5/country/country.hh @@ -0,0 +1,54 @@ +#ifndef COUNTRY_HH +#define COUNTRY_HH +#pragma once + +#include <string> +#include <utility> + +class Country { +private: + // Member variables + // + // I shared this... + std::string name; + std::string capital; + float population; + +public: + // Constructor + // + // this... + explicit Country(std::string _name = "Unknown", + std::string _capital = "Unknown", float _population = 0) + : name(std::move(_name)), capital(std::move(_capital)), + population(_population) {} + + // Destructor + // + // and this to my breakout room! Hope they learned from it! + ~Country() = default; // Quite literally `{}` + + // Accessors + std::string getName() { return this->name; } + std::string getCapital() { return this->capital; } + [[nodiscard]] float getPopulation() const { return this->population; } + + // Mutators + void setName(std::string _name) { this->name = std::move(_name); } + void setCapital(std::string _capital) { this->capital = std::move(_capital); } + void setPopulation(float _population) { this->population = _population; } + + // Predict the population in ten years + [[nodiscard]] float futurePop() const; + + // Return the largest of three populations + // + // I wish these would have been `const` references, since they are copied for + // each invocation but only used as a `const` references. + Country largestCountry(Country, Country); + + // Reset the values + void resetValues(const Country &); +}; + +#endif // COUNTRY_HH diff --git a/cs162/wk5/country/testCountry.cc b/cs162/wk5/country/testCountry.cc new file mode 100644 index 0000000..ba061f3 --- /dev/null +++ b/cs162/wk5/country/testCountry.cc @@ -0,0 +1,103 @@ +#include <functional> +#include <iostream> + +#include "country.hh" + +// Print a countries name, capital, and population +void printCountry(Country); +// A test adapter which informs of context and executes a test in the form of a +// lambda, then, asserts if the test was successful. +void testContext(const std::string &, const std::function<bool()> &); + +int main() { + // "populate a Country object with values for name, capital and population" + Country country("United States of America", "Washington D.C.", + 326.69f); // 326.69 + + testContext("\"populate a Country object with values for name, capital and " + "population\"", + // Separate ... *anonymous* ... functions + [&]() -> bool { + printCountry(country); + + return country.getName() == "United States of America"; + }); + testContext( + "\"print the values held in a Country object - in a function in the " + "driver file\"", + [&]() -> bool { + printCountry(country); + + return country.getCapital() == "Washington D.C."; + }); + testContext("\"test resetting the values of a County ( sample function call: " + "myCountry." + "resetValues(yourCountry); )\"", + [&]() -> bool { + country.resetValues( + Country("Hungary", "Budapest", 9.67f)); // 9.67 + printCountry(country); + + return country.getName() == "Hungary"; + }); + testContext( + "\"test the function that returns the population increase of a Country " + "specified by the user\"", + [&]() -> bool { + float futurePop = country.futurePop(); + + std::cout << futurePop << std::endl; + + return futurePop == country.getPopulation() * 1.05f * 10.f; + }); + testContext("\"test the function that returns the Country with largest " + "population (of " + "3)\"", + [&]() -> bool { + Country country2 = + Country("Not the largest", "Not even close", 0); + Country country3 = Country("Still not the largest", + "Still not even close", 3021); + float largest = + country.largestCountry(country2, country3).getPopulation(); + + std::cout << "Country #1: " << country.getPopulation() << '\n' + << "Country #2: " << country2.getPopulation() << '\n' + << "Country #3: " << country3.getPopulation() << '\n' + << "Largest: " << largest << std::endl; + + return largest == 3021; + }); + testContext("test setters", [&]() -> bool { + country.setName("1"); + country.setCapital("2"); + country.setPopulation(3); + + printCountry(country); + + return country.getName() == "1"; + }); + + return 0; +} + +void testContext(const std::string &context, + const std::function<bool()> &function) { + std::cout << context << std::endl; + + bool test_result = function(); + + if (test_result) { + std::cout << "test was successful" << std::endl; + } else { + std::cout << "test was unsuccessful" << std::endl; + } + + std::cout << std::endl; +} + +void printCountry(Country country) { + std::cout << "Name: " << country.getName() << '\n' + << "Capital: " << country.getCapital() << '\n' + << "Population: " << country.getPopulation() << std::endl; +}
\ No newline at end of file diff --git a/cs162/wk5/gradesHelpers/CMakeLists.txt b/cs162/wk5/gradesHelpers/CMakeLists.txt new file mode 100644 index 0000000..ce034f0 --- /dev/null +++ b/cs162/wk5/gradesHelpers/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk5_gradesHelpers) + +add_executable(wk5_gradesHelpers grades.cc testGrades.cc) diff --git a/cs162/wk5/gradesHelpers/grades.cc b/cs162/wk5/gradesHelpers/grades.cc new file mode 100644 index 0000000..35bf753 --- /dev/null +++ b/cs162/wk5/gradesHelpers/grades.cc @@ -0,0 +1,64 @@ +#include "grades.hh" + +Grades::Grades() { defaultTests(); } + +void Grades::computeAverage() { + int testAccumulated = 0; + + // Total up all test scores + for (int &test : this->testScores) { + testAccumulated += test; + } + + // Find the average by dividing the total test scores by the amount of test + // scores + this->averageScore = + static_cast<float>(testAccumulated) / static_cast<float>(this->tests); +} + +void Grades::checkLowest(int score) { + // If the test new `score` is lower than the `lowestScore`, make it the new + // lowest score + if (score < this->lowestScore) { + this->lowestScore = score; + } +} + +bool Grades::validScore(int score) { + // If the new `score` is within the range 0 - 100, mark it as valid + return 0 <= score && score <= 100; +} + +bool Grades::checkNumTests() const { + // If the number of tests is less than the max number of test, inform the + // caller that they may add a new test score + return this->tests < Grades::MAX_TESTS; +} + +void Grades::defaultTests() { + // Initialises all test scores to zero + for (int &test : this->testScores) { + test = 0; + } +} + +void Grades::addTest(int newTest) { + // If the number of tests is less than the max number of tests... + if (this->checkNumTests()) { + // and if the `newTest` is within the range 0 - 100... + if (this->validScore(newTest)) { + // track the `newTest`, ... + this->testScores[this->tests] = newTest; + // make sure we know that we added a `newTest`, ... + this->tests += 1; + + // compute the new average of all test scores, ... + this->computeAverage(); + // and check, possibly assigning, if the new test is the lowest of + // all tests scores. + this->checkLowest(newTest); + } + } +} + +float Grades::getAverage() const { return this->averageScore; } diff --git a/cs162/wk5/gradesHelpers/grades.hh b/cs162/wk5/gradesHelpers/grades.hh new file mode 100644 index 0000000..89e1022 --- /dev/null +++ b/cs162/wk5/gradesHelpers/grades.hh @@ -0,0 +1,41 @@ +#ifndef GRADES_HH +#define GRADES_HH +#pragma once + +#include <limits> + +class Grades { +private: + /// Maximum amount of `testScores` + static const size_t MAX_TESTS = 4; + /// All test scores + int testScores[MAX_TESTS]{}; + /// The lowest score of all test scores + int lowestScore = std::numeric_limits<int>::max(); + /// The average of all test scores + float averageScore = 0.0; + /// The amount of tests kept track of + size_t tests = 0; + + /// Computes the average every time a new test is added + void computeAverage(); + /// Checks to see if test added has the lowest score. + void checkLowest(int); + /// Before a test is added to the array, its value is checked to make sure + /// the score is in the range 0 - 100, inclusive + static bool validScore(int); + /// Used to make sure the array is not full before adding a score + [[nodiscard]] bool checkNumTests() const; + /// Initialises value in the array of tests to zero + void defaultTests(); + +public: + Grades(); + + /// Add another test score to keep track of + void addTest(int); + /// Get the average of all test scores + [[nodiscard]] float getAverage() const; +}; + +#endif // GRADES_HH diff --git a/cs162/wk5/gradesHelpers/testGrades.cc b/cs162/wk5/gradesHelpers/testGrades.cc new file mode 100644 index 0000000..04a38cc --- /dev/null +++ b/cs162/wk5/gradesHelpers/testGrades.cc @@ -0,0 +1,53 @@ +#include <functional> +#include <iostream> + +#include "grades.hh" + +/// Tests `Grades` given a few grades, an expected average, and if the test +/// should fail. +void test(const std::vector<int> &, float, bool); + +int main() { + { + test({80, 70, 90, 10, 10}, 62.5, + false); // Test if `checkNumTests` works + test({80, 70, 90, 10}, 62.5, false); + test({80, 70, 90}, 80, false); + test({80, 70, 90}, 70, true); + test({80, 70}, 75, false); + test({80}, 80, false); + test({80}, 70, true); + } + + // This works too. + { + Grades cs162; + + cs162.addTest(80); + cs162.addTest(70); + cs162.addTest(90); + cs162.addTest(10); + + std::cout << cs162.getAverage() << std::endl; + } + + return 0; +} + +void test(const std::vector<int> &values, float expect, bool shouldFail) { + Grades cs162; + + std::cout << "testing getAverage with [ "; + + for (int grade : values) { + std::cout << grade << " "; + + cs162.addTest(grade); + } + + std::cout << ((cs162.getAverage() == expect && !shouldFail || + cs162.getAverage() != expect && shouldFail) + ? "]: pass" + : "]: fail") + << std::endl; +} diff --git a/cs162/wk6/BUILD b/cs162/wk6/BUILD new file mode 100644 index 0000000..6442ad9 --- /dev/null +++ b/cs162/wk6/BUILD @@ -0,0 +1,24 @@ +cc_binary( + name = "friends", + srcs = glob([ + "friends/**/*.cc", + "friends/**/*.hh", + ]), +) + +cc_binary( + name = "overload", + srcs = glob([ + "overload/**/*.cc", + "overload/**/*.hh", + ]), +) + +filegroup( + name = "build_all", + srcs = [ + "friends", + "overload", + ], + visibility = ["//visibility:public"], +) diff --git a/cs162/wk6/CMakeLists.txt b/cs162/wk6/CMakeLists.txt new file mode 100644 index 0000000..4c5a63d --- /dev/null +++ b/cs162/wk6/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(friends) +add_subdirectory(overload) diff --git a/cs162/wk6/friends/CMakeLists.txt b/cs162/wk6/friends/CMakeLists.txt new file mode 100644 index 0000000..06eadd6 --- /dev/null +++ b/cs162/wk6/friends/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk6_friends) + +add_executable(wk6_friends bankAccount.cc testBankAccount.cc) diff --git a/cs162/wk6/friends/bankAccount.cc b/cs162/wk6/friends/bankAccount.cc new file mode 100644 index 0000000..ede21f8 --- /dev/null +++ b/cs162/wk6/friends/bankAccount.cc @@ -0,0 +1,43 @@ +#include "bankAccount.hh" + +#include <iostream> + +bool BankAccount::withdraw(float amount) { + bool canWithdraw = true; + + if (amount <= this->balance) { + this->balance -= amount; + } else { + canWithdraw = false; + } + + return canWithdraw; +} + +float BankAccount::computeInterest(float interestRate) const { + if (this->balance > 0) { + return this->balance * interestRate; + } else { + return 0; + } +} + +std::string BankAccount::greaterBalance(BankAccount &bankAccount) { + if (this->balance > bankAccount.balance) { + return this->accountNumber; + } else { + return bankAccount.accountNumber; + } +} + +void printAccount(const BankAccount &bankAccount) { + std::cout << bankAccount.accountNumber << std::endl; + std::cout << bankAccount.balance << std::endl; +} + +BankAccount combineAccounts(const BankAccount &bankAccount1, + const BankAccount &bankAccount2) { + return BankAccount(std::to_string(std::stoi(bankAccount1.accountNumber) + + std::stoi(bankAccount2.accountNumber)), + bankAccount1.balance + bankAccount2.balance); +} diff --git a/cs162/wk6/friends/bankAccount.hh b/cs162/wk6/friends/bankAccount.hh new file mode 100644 index 0000000..e85ae47 --- /dev/null +++ b/cs162/wk6/friends/bankAccount.hh @@ -0,0 +1,42 @@ +#ifndef BANK_ACCOUNT_HH +#define BANK_ACCOUNT_HH +#pragma once + +#include <string> +#include <utility> + +class BankAccount { +private: + std::string accountNumber; + float balance; + +public: + // Overloaded default constructor + explicit BankAccount(std::string _accountNumber = "", float _balance = 0.0) + : accountNumber(std::move(_accountNumber)), balance(_balance) {} + + // Accessors + std::string getAccountNumber() { return this->accountNumber; } + [[nodiscard]] float getBalance() const { return this->balance; } + + // Mutators + void setAccountNumber(std::string _accountNumber) { + this->accountNumber = std::move(_accountNumber); + } + void setBalance(float _balance) { this->balance = _balance; } + void deposit(float amount) { this->balance += amount; } + bool withdraw(float); + + // Member functions + [[nodiscard]] float computeInterest(float) const; + std::string greaterBalance(BankAccount &); + + /// Prints out the account number and balance of the parameterized + /// `BankAccount`. + friend void printAccount(const BankAccount &); + /// Combines the balances in two `BankAccount`s into a new `BankAccount`, + /// which is returned. + friend BankAccount combineAccounts(const BankAccount &, const BankAccount &); +}; + +#endif // BANK_ACCOUNT_HH diff --git a/cs162/wk6/friends/testBankAccount.cc b/cs162/wk6/friends/testBankAccount.cc new file mode 100644 index 0000000..10943bc --- /dev/null +++ b/cs162/wk6/friends/testBankAccount.cc @@ -0,0 +1,39 @@ +#include <iostream> + +#include "bankAccount.hh" + +int main() { + BankAccount bankAccount("1234", 100.00); + bool canWithdraw; + + bankAccount.deposit(25.00); + + canWithdraw = bankAccount.withdraw(10.00); + + if (!canWithdraw) { + std::cout << "You cannot withdraw that amount." << std::endl; + } + + std::cout << bankAccount.getAccountNumber() << std::endl; + std::cout << bankAccount.getBalance() << std::endl; + + BankAccount bankAccount2; + + bankAccount2.setBalance(200.00); + bankAccount2.setAccountNumber("4321"); + + std::cout << bankAccount2.getAccountNumber() << std::endl; + std::cout << bankAccount2.getBalance() << std::endl; + + std::cout << "If the interest rate is 5%, you would earn " + << bankAccount2.computeInterest(0.05f) << " in one year.\n" + << std::endl; + + std::cout << bankAccount.greaterBalance(bankAccount2) + << " has a higher balance." << std::endl; + + printAccount(bankAccount); + printAccount(combineAccounts(bankAccount, bankAccount2)); + + return 0; +}
\ No newline at end of file diff --git a/cs162/wk6/overload/CMakeLists.txt b/cs162/wk6/overload/CMakeLists.txt new file mode 100644 index 0000000..683c7a6 --- /dev/null +++ b/cs162/wk6/overload/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk6_overload) + +add_executable(wk6_overload shape.cc testShape.cc) diff --git a/cs162/wk6/overload/shape.cc b/cs162/wk6/overload/shape.cc new file mode 100644 index 0000000..36e5856 --- /dev/null +++ b/cs162/wk6/overload/shape.cc @@ -0,0 +1,74 @@ +#define _USE_MATH_DEFINES + +#include "shape.hh" + +#include <cmath> + +char Shape::getType() const { return this->type; } + +unsigned int Shape::getDimension() const { return this->dimension; } + +float Shape::getArea() const { return this->area; } + +void Shape::setType(char _shapeLetter) { + if (_shapeLetter == 'c' || _shapeLetter == 's' || _shapeLetter == 'h') { + this->type = _shapeLetter; + } +} + +void Shape::setDimension(unsigned int _dimension) { + // Even though this function takes in an `unsigned int`, we make sure that + // the + // `_dimension` is greater than zero. This is in case the user is using a + // compiler or CXX-flags that do not treat sign mismatches as errors... like + // they always should... + if (_dimension > 0) { + this->dimension = _dimension; + + this->computeArea(); + } +} + +void Shape::computeArea() { + switch (this->type) { + case 'c': { + this->area = static_cast<float>(M_PI * std::pow(2, this->dimension)); + } break; + case 's': { + this->area = static_cast<float>(this->dimension * this->dimension); + } break; + case 'h': { + this->area = static_cast<float>((6 * (this->dimension * this->dimension)) / + (4 * std::tan((M_PI / 6)))); + } break; + } +} + +bool Shape::operator==(Shape shape) const { + return this->type == shape.type && this->dimension == shape.dimension; +} + +void Shape::operator+=(Shape shape) { + if (this->type == shape.type) { + this->dimension += shape.dimension; + + this->computeArea(); + } +} + +bool Shape::operator!=(Shape shape) const { return !(*this == shape); } + +Shape Shape::operator+(Shape shape) { + if (*this == shape) { + Shape newShape; + + newShape.type = this->type; + newShape.dimension = this->dimension + shape.dimension; + + newShape.computeArea(); + + return newShape; + } else { + return *this; + } +} diff --git a/cs162/wk6/overload/shape.hh b/cs162/wk6/overload/shape.hh new file mode 100644 index 0000000..f12a615 --- /dev/null +++ b/cs162/wk6/overload/shape.hh @@ -0,0 +1,45 @@ +#ifndef SHAPE_HH +#define SHAPE_HH + +class Shape { +private: + // c, s, or h + char type; + unsigned int dimension; + float area; + +public: + // The wording "default values for the private member variables" was a little + // of to me knowing that in the past we've been using function overloading + // for constructors. I just went ahead and implemented both but kept the one + // that made the most sense in terms of how it was worded. + Shape() : type('n'), dimension(0), area(0){}; + /* explicit Shape(char _type = 'n', unsigned int _dimension = 0, float _area + = 0) : type(_type), dimension(_dimension), area(_area) {}; */ + + // Getters for the three private member variables + [[nodiscard]] char getType() const; + [[nodiscard]] unsigned int getDimension() const; + [[nodiscard]] float getArea() const; + + // Setters for `type` and `dimensions` + // + // These *should* `throw`, but that's just bad practice. + // + // These *could* implement C-like error handling, but that's just + // overcomplicating things. + void setType(char); + void setDimension(unsigned int); + + // Operator overloads + bool operator==(Shape) const; + void operator+=(Shape); + bool operator!=(Shape) const; + Shape operator+(Shape); + +private: + // Area computer + void computeArea(); +}; + +#endif // SHAPE_HH diff --git a/cs162/wk6/overload/testShape.cc b/cs162/wk6/overload/testShape.cc new file mode 100644 index 0000000..fbc8ca8 --- /dev/null +++ b/cs162/wk6/overload/testShape.cc @@ -0,0 +1,76 @@ +#include <iostream> + +#include "shape.hh" + +/* + * # Test Plan + * + * This test plan uses a test framework. + * + * The test framework gives accurate context. + * + * - Test instantiation of `Shape` + * - Test all setters of `Shape` + * - Test all getters of `Shape` + * - Test all valid types: c, s, or h + * - Test two different dimensions for each valid type + */ + +#define INIT_TESTS() \ + int __tested = 0; \ + int __passed = 0; +#define TESTED __tested +#define PASSED __passed + +#define TEST(context, shape, type, dimension, expected) \ + { \ + if (test(context, shape, type, dimension, expected)) { \ + __passed += 1; \ + } \ + __tested += 1; \ + } + +bool test(const std::string &, Shape, char, unsigned int, float); + +int main() { + Shape shape; + + INIT_TESTS() + + TEST("circle with radius of two", shape, 'c', 2, 12.566f) + TEST("circle with radius of twelve", shape, 'c', 4, 50.27f) + TEST("square with side of two", shape, 's', 2, 4) + TEST("square with side of twelve", shape, 's', 12, 144) + TEST("hexagon with side of two", shape, 'h', 2, 10.392f) + TEST("hexagon with side of twelve", shape, 'h', 12, 374.1f) + // This should fail + TEST("hexagon with side of twelve, should fail", shape, 'h', 12, 376.1f) + + // There should be seven tests with six passing tests (because one was meant + // to fail). + std::cout << "! results\n" + << "> performed " << TESTED << " tests with " << PASSED + << " passing" << std::endl; + + return 0; +} + +bool test(const std::string &context, Shape shape, char type, + unsigned int dimension, float expected) { + shape.setType(type); + shape.setDimension(dimension); + + std::cout << "| " << context << std::endl; + + char newType = shape.getType(); + unsigned int newDimension = shape.getDimension(); + float area = shape.getArea(); + // ... + bool passed = static_cast<int>(area) == static_cast<int>(expected); + + std::cout << "> " << (passed ? "pass" : "fail") << ": expected " << expected + << ", got " << area << " using type \"" << newType + << "\" and dimension \"" << newDimension << "\"" << std::endl; + + return passed; +} diff --git a/cs162/wk7/BUILD b/cs162/wk7/BUILD new file mode 100644 index 0000000..6d6d52b --- /dev/null +++ b/cs162/wk7/BUILD @@ -0,0 +1,15 @@ +cc_binary( + name = "course", + srcs = glob([ + "course/**/*.cc", + "course/**/*.hh", + ]), +) + +filegroup( + name = "build_all", + srcs = [ + "course", + ], + visibility = ["//visibility:public"], +) diff --git a/cs162/wk7/CMakeLists.txt b/cs162/wk7/CMakeLists.txt new file mode 100644 index 0000000..1a2e538 --- /dev/null +++ b/cs162/wk7/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(course) diff --git a/cs162/wk7/course/CMakeLists.txt b/cs162/wk7/course/CMakeLists.txt new file mode 100644 index 0000000..d6045de --- /dev/null +++ b/cs162/wk7/course/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.21) +project(wk7_course) + +add_executable(wk7_course course.cc student.cc testCourse.cc) diff --git a/cs162/wk7/course/course.cc b/cs162/wk7/course/course.cc new file mode 100644 index 0000000..bce09a4 --- /dev/null +++ b/cs162/wk7/course/course.cc @@ -0,0 +1,85 @@ +#include <iostream> +#include <utility> + +#include "course.hh" + +[[maybe_unused]] std::string Course::getTitle() { return this->title; } + +[[maybe_unused]] std::string Course::getNumber() { return this->number; } + +[[maybe_unused]] float Course::getCredits() const { return this->credits; } + +void Course::setTitle(std::string _title) { this->title = std::move(_title); } + +void Course::setNumber(std::string _number) { + this->number = std::move(_number); +} + +void Course::setCredits(float _credits) { this->credits = _credits; } + +void Course::displayCourse() const { showCourse(*this); } + +bool Course::operator==(const Course &course) const { + return this->title == course.title && this->number == course.number && + this->credits == course.credits; +} + +Course &Course::operator+=(const Course &course) { + // CBA to implement overflow checks for an already messy C-array, involved + // operator that will only ever even add three new items at a time as + // expressed in the test file. + // + // Update: CBA to use C-arrays, just going to use the more versatile and + // simple `std::vector` STL container so the previous comment is + // non-applicable. + + // if (this->numStudents + course.numStudents > 30) { + // return *this; + // } + // + // auto *newStudentsEnrolled = static_cast<float *>(malloc( + // (this->numStudents + course.numStudents) * sizeof(sizeof(Student)))); + // + // memcpy(newStudentsEnrolled, this->studentsEnrolled, + // this->numStudents * sizeof(Student)); + // memcpy(newStudentsEnrolled + this->numStudents, course.studentsEnrolled, + // course.numStudents * sizeof(Student)); + // + // this->numStudents += course.numStudents; + + for (const Student &student : course.studentsEnrolled) { + if (this->numStudents + course.numStudents >= 30) { + break; + } + + this->studentsEnrolled.emplace_back(student); + + this->numStudents += 1; + } + + return *this; +} + +void showCourse(const Course &course) { + std::cout << "title: " << course.title << std::endl; + std::cout << "number: " << course.number << std::endl; + std::cout << "credits: " << course.credits << std::endl; + std::cout << "students: " << std::endl; + + for (Student student : course.studentsEnrolled) { + std::cout << " last name: " << student.getLastName() << std::endl; + std::cout << " first name: " << student.getFirstName() << std::endl; + std::cout << " id number: " << student.getIdNum() << '\n' << std::endl; + } + + std::cout << "number of students: " << course.numStudents << std::endl; +} + +void Course::addStudents(int studentNum, std::string *firstNames, + std::string *lastNames, int *idNums) { + for (int i = 0; i < studentNum; ++i) { + this->studentsEnrolled.emplace_back( + Student(firstNames[i], lastNames[i], idNums[i])); + this->numStudents += 1; + } +} diff --git a/cs162/wk7/course/course.hh b/cs162/wk7/course/course.hh new file mode 100644 index 0000000..df5f2cb --- /dev/null +++ b/cs162/wk7/course/course.hh @@ -0,0 +1,52 @@ +#ifndef COURSE_HH +#define COURSE_HH + +#include <string> +#include <utility> +#include <vector> + +#include "student.hh" + +class Course { +public: + static const std::size_t MAX_STUDENTS = 30; + +private: + std::string title; + std::string number; + float credits; + // Student studentsEnrolled[Course::MAX_STUDENTS]; + std::vector<Student> studentsEnrolled; + std::size_t numStudents{}; + +public: + // Constructor + explicit Course(std::string _title = "", std::string _number = "", + float _credits = 0) + : title(std::move(_title)), number(std::move(_number)), + credits(_credits) {} + + // Getters + [[maybe_unused]] std::string getTitle(); + [[maybe_unused]] std::string getNumber(); + [[maybe_unused]] [[nodiscard]] float getCredits() const; + + // Setters + void setTitle(std::string); + void setNumber(std::string); + void setCredits(float); + + void displayCourse() const; + void addStudents(int, std::string[Course::MAX_STUDENTS], + std::string[Course::MAX_STUDENTS], + int[Course::MAX_STUDENTS]); + + // Operators + bool operator==(const Course &) const; + Course &operator+=(const Course &); + + // Friends + friend void showCourse(const Course &course); +}; + +#endif // COURSE_HH diff --git a/cs162/wk7/course/student.cc b/cs162/wk7/course/student.cc new file mode 100644 index 0000000..6add4f2 --- /dev/null +++ b/cs162/wk7/course/student.cc @@ -0,0 +1,21 @@ +#include <utility> + +#include "student.hh" + +std::string Student::getLastName() { return this->lastName; } + +std::string Student::getFirstName() { return this->firstName; } + +std::size_t Student::getIdNum() const { return this->idNum; } + +[[maybe_unused]] void Student::setLastName(std::string _lastName) { + this->lastName = std::move(_lastName); +} + +[[maybe_unused]] void Student::setFirstName(std::string _firstName) { + this->firstName = std::move(_firstName); +} + +[[maybe_unused]] void Student::setIdNum(std::size_t _idNum) { + this->idNum = _idNum; +} diff --git a/cs162/wk7/course/student.hh b/cs162/wk7/course/student.hh new file mode 100644 index 0000000..571a5e0 --- /dev/null +++ b/cs162/wk7/course/student.hh @@ -0,0 +1,30 @@ +#ifndef STUDENT_HH +#define STUDENT_HH + +#include <string> + +class Student { +private: + std::string lastName; + std::string firstName; + std::size_t idNum; + +public: + // Constructor + explicit Student(std::string _lastName = "", std::string _firstName = "", + std::size_t _idNum = 0) + : lastName(std::move(_lastName)), firstName(std::move(_firstName)), + idNum(_idNum) {} + + // Getters + std::string getLastName(); + std::string getFirstName(); + [[nodiscard]] std::size_t getIdNum() const; + + // Setters + [[maybe_unused]] void setLastName(std::string); + [[maybe_unused]] void setFirstName(std::string); + [[maybe_unused]] void setIdNum(std::size_t); +}; + +#endif // STUDENT_HH diff --git a/cs162/wk7/course/testCourse.cc b/cs162/wk7/course/testCourse.cc new file mode 100644 index 0000000..e3e723b --- /dev/null +++ b/cs162/wk7/course/testCourse.cc @@ -0,0 +1,104 @@ +/******************************************************************************* + * Filename: wk7_courseDriver.cpp + * Summary: Program to test the Course class (which uses the Student class) + * Test program declares 2 Course objects, fills each with values, + * uses the += operator to copy the students from one Course into + * the other, and prints out the information about the 2 objects. + * Author: + * Date: + *******************************************************************************/ + +// There were only two instances where I had to replace something in this file +// to get it to work with my configuration, line 16, 20, and 69. As per my +// Emacs configuration, this file was also automatically formatted. Other than +// those changes, everything is 1:1 with the posted file. + +#include "course.hh" // Replaced #include "Course.h" +#include <iostream> +#include <string> +using std::cout, std::endl, std::cin; +using namespace std; // Added + +void enterCourseInfo(Course &); +// Prompts user to enter course title, designator, and credits +void enterStudents(Course &); +// Prompts user to enter up to 3 students + +const int MAX_STUDENTS = 3; + +int main() { + Course c1; + Course c2("Data Structures", "CS260", 4); // title, number, credits + + cout << "Testing the showCourse friend function\n"; + showCourse(c2); + cout << endl; + + cout << "Testing mutator functions\n"; + enterCourseInfo(c1); + showCourse(c1); + cout << endl; + + cout << "Testing the += operator\n"; + enterStudents(c2); + cout << "Before the += operator\n"; + showCourse(c1); + showCourse(c2); + c1 += c2; + cout << "After the += operator\n"; + showCourse(c1); + cout << endl; + + return 0; +} + +void enterCourseInfo(Course &crs) { + string userInput; + int creditIn; + + cout << "What is the course title? "; + getline(cin, userInput); + crs.setTitle(userInput); + + cout << "What is the course identifier? "; + getline(cin, userInput); + crs.setNumber(userInput); + + cout << "How many credits? "; + cin >> creditIn; + crs.setCredits(static_cast<float>(creditIn)); + + enterStudents(crs); + + crs.displayCourse(); + + return; +} + +void enterStudents(Course &crs) { + string firstNames[MAX_STUDENTS]; + string lastNames[MAX_STUDENTS]; + int idNums[MAX_STUDENTS]; + + int studentNum; + + cout << "How many students are in the class? (up to " << MAX_STUDENTS + << ")\n"; + cin >> studentNum; + cin.ignore(80, '\n'); + + cout << "Enter the information about " << studentNum << " students:\n"; + for (int i = 0; i < studentNum; i++) { + cout << "First name: "; + getline(cin, firstNames[i]); + cout << "Last name: "; + getline(cin, lastNames[i]); + cout << "ID number: "; + cin >> idNums[i]; + cin.ignore(80, '\n'); + } + + crs.addStudents(studentNum, firstNames, lastNames, idNums); + + return; +} diff --git a/cs162/wk8/BUILD b/cs162/wk8/BUILD new file mode 100644 index 0000000..a2e6835 --- /dev/null +++ b/cs162/wk8/BUILD @@ -0,0 +1,15 @@ +cc_binary( + name = "inherit", + srcs = glob([ + "inherit/**/*.cc", + "inherit/**/*.hh", + ]), +) + +filegroup( + name = "build_all", + srcs = [ + "inherit", + ], + visibility = ["//visibility:public"], +) diff --git a/cs162/wk8/CMakeLists.txt b/cs162/wk8/CMakeLists.txt new file mode 100644 index 0000000..fe529a4 --- /dev/null +++ b/cs162/wk8/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(inherit) diff --git a/cs162/wk8/inherit/CMakeLists.txt b/cs162/wk8/inherit/CMakeLists.txt new file mode 100644 index 0000000..7df8cdc --- /dev/null +++ b/cs162/wk8/inherit/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.21) +project(wk8_inherit) + +add_executable( + wk8_inherit + employee.cc + hourlyEmployee.cc + salesperson.cc + testEmployeeADTs.cc +)
\ No newline at end of file diff --git a/cs162/wk8/inherit/employee.cc b/cs162/wk8/inherit/employee.cc new file mode 100644 index 0000000..3d72686 --- /dev/null +++ b/cs162/wk8/inherit/employee.cc @@ -0,0 +1,25 @@ +#include <utility> + +#include "employee.hh" + +int Employee::getIDNo() const { return this->idNo; } + +std::string Employee::getFName() { return this->fName; } + +std::string Employee::getLName() { return this->lName; } + +std::string Employee::getPosition() { return this->position; } + +int Employee::getDeptNo() const { return deptno; } + +void Employee::setIDNo(int _idNo) { this->idNo = _idNo; } + +void Employee::setFName(std::string _fName) { this->fName = std::move(_fName); } + +void Employee::setLName(std::string _lName) { this->lName = std::move(_lName); } + +void Employee::setPos(std::string _position) { + this->position = std::move(_position); +} + +void Employee::setDeptNo(int _deptNo) { this->deptno = _deptNo; } diff --git a/cs162/wk8/inherit/employee.hh b/cs162/wk8/inherit/employee.hh new file mode 100644 index 0000000..df4067f --- /dev/null +++ b/cs162/wk8/inherit/employee.hh @@ -0,0 +1,49 @@ +#ifndef EMPLOYEE_HH +#define EMPLOYEE_HH + +#include <string> +#include <utility> + +class Employee { +private: + // Members + /// employee ID number + int idNo; + /// first name + std::string fName; + /// last name + std::string lName; + /// position title + std::string position; + /// department number + int deptno; + +public: + // Constructor + explicit Employee(int _idNo = 0, std::string _fName = "", + std::string _lName = "", std::string _position = "", + int _deptno = 0) + : idNo(_idNo), fName(std::move(_fName)), lName(std::move(_lName)), + position(std::move(_position)), deptno(_deptno) {} + + // Getters + /// returns ID number + [[nodiscard]] int getIDNo() const; + /// returns first name + std::string getFName(); + /// returns last name + std::string getLName(); + /// returns position title + std::string getPosition(); + /// returns department # + [[nodiscard]] int getDeptNo() const; + + // Setters + void setIDNo(int); + void setFName(std::string); + void setLName(std::string); + void setPos(std::string); + void setDeptNo(int); +}; + +#endif // EMPLOYEE_HH diff --git a/cs162/wk8/inherit/hourlyEmployee.cc b/cs162/wk8/inherit/hourlyEmployee.cc new file mode 100644 index 0000000..f89bcc8 --- /dev/null +++ b/cs162/wk8/inherit/hourlyEmployee.cc @@ -0,0 +1,7 @@ +#include "hourlyEmployee.hh" + +float HourlyEmployee::getHourlyRate() const { return this->hourlyRate; } + +void HourlyEmployee::setHourlyRate(float _hourlyRate) { + this->hourlyRate = _hourlyRate; +} diff --git a/cs162/wk8/inherit/hourlyEmployee.hh b/cs162/wk8/inherit/hourlyEmployee.hh new file mode 100644 index 0000000..f555b2a --- /dev/null +++ b/cs162/wk8/inherit/hourlyEmployee.hh @@ -0,0 +1,31 @@ +#ifndef HOURLY_EMPLOYEE_HH +#define HOURLY_EMPLOYEE_HH + +#include <utility> + +#include "employee.hh" + +class HourlyEmployee : public Employee { +private: + // Member + /// hourly rate of pay + float hourlyRate; + +public: + // Constructor + explicit HourlyEmployee(float _hourlyRate = 0, int _idNo = 0, + std::string _fName = "", std::string _lName = "", + std::string _position = "", int _deptno = 0) + : hourlyRate(_hourlyRate), + Employee(_idNo, std::move(_fName), std::move(_lName), + std::move(_position), _deptno) {} + + // Getter + /// returns hourly rate + [[nodiscard]] float getHourlyRate() const; + + // Setter + void setHourlyRate(float); +}; + +#endif // HOURLY_EMPLOYEE_HH diff --git a/cs162/wk8/inherit/salesperson.cc b/cs162/wk8/inherit/salesperson.cc new file mode 100644 index 0000000..a4d484a --- /dev/null +++ b/cs162/wk8/inherit/salesperson.cc @@ -0,0 +1,11 @@ +#include "salesperson.hh" + +float Salesperson::getFlatIncome() const { return this->flatIncome; } + +float Salesperson::getCommRate() const { return this->commRate; } + +void Salesperson::setFlatIncome(float _flatIncome) { + this->flatIncome = _flatIncome; +} + +void Salesperson::setCommRate(float _commRate) { this->commRate = _commRate; } diff --git a/cs162/wk8/inherit/salesperson.hh b/cs162/wk8/inherit/salesperson.hh new file mode 100644 index 0000000..4a9c358 --- /dev/null +++ b/cs162/wk8/inherit/salesperson.hh @@ -0,0 +1,35 @@ +#ifndef SALESPERSON_HH +#define SALESPERSON_HH + +#include "employee.hh" + +class Salesperson : public Employee { +private: + // Members + /// monthly flat income + float flatIncome; + /// commission rate + float commRate; + +public: + // Constructor + explicit Salesperson(float _flatIncome = 0, float _commRate = 0, + int _idNo = 0, std::string _fName = "", + std::string _lName = "", std::string _position = "", + int _deptno = 0) + : flatIncome(_flatIncome), commRate(_commRate), + Employee(_idNo, std::move(_fName), std::move(_lName), + std::move(_position), _deptno) {} + + // Getters + /// returns flat income + [[nodiscard]] float getFlatIncome() const; + /// returns commission rate + [[nodiscard]] float getCommRate() const; + + // Setters + void setFlatIncome(float); + void setCommRate(float); +}; + +#endif // SALESPERSON_HH diff --git a/cs162/wk8/inherit/testEmployeeADTs.cc b/cs162/wk8/inherit/testEmployeeADTs.cc new file mode 100644 index 0000000..8500b5b --- /dev/null +++ b/cs162/wk8/inherit/testEmployeeADTs.cc @@ -0,0 +1,214 @@ +#include <chrono> +#include <iostream> + +#include "employee.hh" +#include "hourlyEmployee.hh" +#include "salesperson.hh" + +#define INIT_TESTS() \ + int __test_tested = 0; \ + int __test_passed = 0; \ + auto __test_clock = std::chrono::high_resolution_clock::now(); + +#define TESTS_TESTED __test_tested +#define TESTS_PASSED __test_passed +#define TEST_TIME \ + std::chrono::duration_cast<std::chrono::milliseconds>( \ + std::chrono::high_resolution_clock::now() - __test_clock) \ + .count() + +#define TEST(context, from, field, value) \ + { \ + if (test(context, from, field, value)) { \ + __test_passed += 1; \ + } \ + __test_tested += 1; \ + } + +template <class C, typename K, typename V> +bool test(const std::string &, C, K, V); + +int main() { + INIT_TESTS() + + // Test everything on `Employee` using a full constructor + { + Employee employee(1, "2", "3", "4", 5); + + TEST(".getIDNo()", employee, employee.getIDNo(), 1) + TEST(".getFName()", employee, employee.getFName(), "2") + TEST(".getLName()", employee, employee.getLName(), "3") + TEST(".getPosition()", employee, employee.getPosition(), "4") + TEST(".getDeptNo()", employee, employee.getDeptNo(), 5) + + employee.setIDNo(6); + employee.setFName("7"); + employee.setLName("8"); + employee.setPos("9"); + employee.setDeptNo(10); + + TEST(".setIDNo()", employee, employee.getIDNo(), 6) + TEST(".setFName()", employee, employee.getFName(), "7") + TEST(".setLName()", employee, employee.getLName(), "8") + TEST(".setPos()", employee, employee.getPosition(), "9") + TEST(".setDeptNo()", employee, employee.getDeptNo(), 10) + } + + // Test everything on `Employee` using an empty constructor + { + Employee employee; + + TEST(".getIDNo()", employee, employee.getIDNo(), 0) + TEST(".getFName()", employee, employee.getFName(), "") + TEST(".getLName()", employee, employee.getLName(), "") + TEST(".getPosition()", employee, employee.getPosition(), "") + TEST(".getDeptNo()", employee, employee.getDeptNo(), 0) + + employee.setIDNo(6); + employee.setFName("7"); + employee.setLName("8"); + employee.setPos("9"); + employee.setDeptNo(10); + + TEST(".setIDNo()", employee, employee.getIDNo(), 6) + TEST(".setFName()", employee, employee.getFName(), "7") + TEST(".setLName()", employee, employee.getLName(), "8") + TEST(".setPos()", employee, employee.getPosition(), "9") + TEST(".setDeptNo()", employee, employee.getDeptNo(), 10) + } + + // Test everything on `HourlyEmployee` using a full constructor + { + HourlyEmployee employee(0, 1, "2", "3", "4", 5); + + TEST(".getHourlyRate()", employee, employee.getHourlyRate(), 0) + TEST(".getIDNo()", employee, employee.getIDNo(), 1) + TEST(".getFName()", employee, employee.getFName(), "2") + TEST(".getLName()", employee, employee.getLName(), "3") + TEST(".getPosition()", employee, employee.getPosition(), "4") + TEST(".getDeptNo()", employee, employee.getDeptNo(), 5) + + employee.setIDNo(6); + employee.setFName("7"); + employee.setLName("8"); + employee.setPos("9"); + employee.setDeptNo(10); + employee.setHourlyRate(11); + + TEST(".setIDNo()", employee, employee.getIDNo(), 6) + TEST(".setFName()", employee, employee.getFName(), "7") + TEST(".setLName()", employee, employee.getLName(), "8") + TEST(".setPos()", employee, employee.getPosition(), "9") + TEST(".setDeptNo()", employee, employee.getDeptNo(), 10) + TEST(".setHourlyRate()", employee, employee.getHourlyRate(), 11) + } + + // Test everything on `HourlyEmployee` using an empty constructor + { + HourlyEmployee employee; + + TEST(".getHourlyRate()", employee, employee.getHourlyRate(), 0) + TEST(".getIDNo()", employee, employee.getIDNo(), 0) + TEST(".getFName()", employee, employee.getFName(), "") + TEST(".getLName()", employee, employee.getLName(), "") + TEST(".getPosition()", employee, employee.getPosition(), "") + TEST(".getDeptNo()", employee, employee.getDeptNo(), 0) + + employee.setIDNo(6); + employee.setFName("7"); + employee.setLName("8"); + employee.setPos("9"); + employee.setDeptNo(10); + employee.setHourlyRate(11); + + TEST(".setIDNo()", employee, employee.getIDNo(), 6) + TEST(".setFName()", employee, employee.getFName(), "7") + TEST(".setLName()", employee, employee.getLName(), "8") + TEST(".setPos()", employee, employee.getPosition(), "9") + TEST(".setDeptNo()", employee, employee.getDeptNo(), 10) + TEST(".setHourlyRate()", employee, employee.getHourlyRate(), 11) + } + + // Test everything on `Salesperson` using a full constructor + { + Salesperson employee(-1, 0, 1, "2", "3", "4", 5); + + TEST(".getFlatIncome()", employee, employee.getFlatIncome(), -1) + TEST(".getCommRate()", employee, employee.getCommRate(), 0) + TEST(".getIDNo()", employee, employee.getIDNo(), 1) + TEST(".getFName()", employee, employee.getFName(), "2") + TEST(".getLName()", employee, employee.getLName(), "3") + TEST(".getPosition()", employee, employee.getPosition(), "4") + TEST(".getDeptNo()", employee, employee.getDeptNo(), 5) + + employee.setIDNo(6); + employee.setFName("7"); + employee.setLName("8"); + employee.setPos("9"); + employee.setDeptNo(10); + employee.setFlatIncome(11); + employee.setCommRate(12); + + TEST(".setIDNo()", employee, employee.getIDNo(), 6) + TEST(".setFName()", employee, employee.getFName(), "7") + TEST(".setLName()", employee, employee.getLName(), "8") + TEST(".setPos()", employee, employee.getPosition(), "9") + TEST(".setDeptNo()", employee, employee.getDeptNo(), 10) + TEST(".setFlatIncome()", employee, employee.getFlatIncome(), 11) + TEST(".setCommRate()", employee, employee.getCommRate(), 12) + } + + // Test everything on `Salesperson` using an empty constructor + { + Salesperson employee; + + TEST(".getFlatIncome()", employee, employee.getFlatIncome(), 0) + TEST(".getCommRate()", employee, employee.getCommRate(), 0) + TEST(".getIDNo()", employee, employee.getIDNo(), 0) + TEST(".getFName()", employee, employee.getFName(), "") + TEST(".getLName()", employee, employee.getLName(), "") + TEST(".getPosition()", employee, employee.getPosition(), "") + TEST(".getDeptNo()", employee, employee.getDeptNo(), 0) + + employee.setIDNo(6); + employee.setFName("7"); + employee.setLName("8"); + employee.setPos("9"); + employee.setDeptNo(10); + employee.setFlatIncome(11); + employee.setCommRate(12); + + TEST(".setIDNo()", employee, employee.getIDNo(), 6) + TEST(".setFName()", employee, employee.getFName(), "7") + TEST(".setLName()", employee, employee.getLName(), "8") + TEST(".setPos()", employee, employee.getPosition(), "9") + TEST(".setDeptNo()", employee, employee.getDeptNo(), 10) + TEST(".setFlatIncome()", employee, employee.getFlatIncome(), 11) + TEST(".setCommRate()", employee, employee.getCommRate(), 12) + } + + TEST(": this **should** fail to prove that the test harness works", + Employee(), true, false) + + std::cout << "! results: performed " << TESTS_TESTED << " tests in " + << TEST_TIME << "ms with " << TESTS_PASSED << " passing and " + << TESTS_TESTED - TESTS_PASSED << " failing" << std::endl; + + return 0; +} + +// I didn't want to overcomplicate things and mess with function pointers in +// maps, symbol resolution, etc. to get the name of a function from its +// function pointer, so I just pass it as the context. :) +template <class C, typename K, typename V> +bool test(const std::string &context, C _from, K field, V expected) { + bool passed = field == expected; + + std::cout << "| " << std::string(typeid(_from).name()).substr(6) << context + << ": "; + + std::cout << (passed ? "pass" : "fail") << ": expected " << expected + << ", got " << field << std::endl; + + return passed; +} diff --git a/cs162/wk9/BUILD b/cs162/wk9/BUILD new file mode 100644 index 0000000..4bb86d3 --- /dev/null +++ b/cs162/wk9/BUILD @@ -0,0 +1,15 @@ +cc_binary( + name = "vectors", + srcs = glob([ + "vectors/**/*.cc", + "vectors/**/*.hh", + ]), +) + +filegroup( + name = "build_all", + srcs = [ + "vectors", + ], + visibility = ["//visibility:public"], +) diff --git a/cs162/wk9/CMakeLists.txt b/cs162/wk9/CMakeLists.txt new file mode 100644 index 0000000..9c5fae2 --- /dev/null +++ b/cs162/wk9/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(vectors) diff --git a/cs162/wk9/vectors/CMakeLists.txt b/cs162/wk9/vectors/CMakeLists.txt new file mode 100644 index 0000000..d476693 --- /dev/null +++ b/cs162/wk9/vectors/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.21) +project(wk9_vectors) + +add_executable( + wk9_vectors + vectors.cc +)
\ No newline at end of file diff --git a/cs162/wk9/vectors/vectors.cc b/cs162/wk9/vectors/vectors.cc new file mode 100644 index 0000000..8aad0fe --- /dev/null +++ b/cs162/wk9/vectors/vectors.cc @@ -0,0 +1,172 @@ +#include <iomanip> +#include <iostream> +#include <numeric> +#include <random> + +#define DEBUG +#define FINITE + +/** + * @brief vector related operations and types + * @see std::vector + */ +namespace vectors { + +/** + * @brief A generic "real" number type + * @see double + */ +typedef double real_type; + +/** + * @brief Get the largest value of a vector. + * @return real_type + * @see real_type + * @see std::vector + */ +real_type largest_vector_value(const std::vector<real_type> &); +/** + * @brief Get the smallest value of a vector. + * @return real_type + * @see real_type + * @see std::vector + */ +real_type smallest_vector_value(const std::vector<real_type> &); +/** + * @brief Get the average value of a vector. + * @return real_type + * @see real_type + * @see std::vector + */ +real_type average_vector_value(const std::vector<real_type> &); + +} // namespace vectors + +int main() { + // Settings and RNG-related producers and criteria + int user_choice; + int value_precision = 2; + vectors::real_type minimum_value = 0; + vectors::real_type maximum_value = 1000; + std::size_t random_values_size; + const std::string &rt = typeid(vectors::real_type).name(); + const std::string &st = typeid(std::size_t).name(); + std::vector<vectors::real_type> random_values; + std::random_device random_device; + std::default_random_engine random_engine{random_device()}; + + // Get the users input for settings and RNG criteria +#ifdef FINITE + std::cout << "minimum random value(" + rt + "): "; + std::cin >> minimum_value; + std::cout << "maximum random value(" + rt + "): "; + std::cin >> maximum_value; +#endif + std::cout << "number of initial random values(" + st + "): "; + std::cin >> random_values_size; +#ifdef FINITE + std::cout << "value precision(" + st + "): "; + std::cin >> value_precision; +#endif + // Set the precision of random number output based on the users choice. + std::cout << std::fixed << std::setprecision(value_precision); + + // Set up the RNG producer based on the user's criteria + std::uniform_real_distribution<vectors::real_type> uniform_distribution{ + minimum_value, maximum_value}; + + // Append the user's preference of maximum random values to the random value + // pool + for (std::size_t i = 0; i < random_values_size; ++i) { + random_values.push_back(uniform_distribution(random_engine)); + } + + std::cout << "what operation would you like to perform?\n" + " 1. find the largest value\n" + " 2. find the smallest value\n" + " 3. compute the average value\n" + " 4. emplace more random values into the value pool\n" +#ifdef DEBUG + " 5. number of random values in the value pool\n" +#endif + " 0. quit" + << std::endl; + + // Keep performing until the user would like + do { + // Get the user's operation choice + std::cout << "your choice(" + std::string(typeid(int).name()) + "): "; + std::cin >> user_choice; + + // Perform the user's operation choice + switch (user_choice) { + case 0: { + // Say "goodbye." and free up any used resources. + std::cout << "goodbye." << std::endl; + + return 0; + } // break; + case 1: { + // Output the largest value of the vector and run again. + std::cout << "largest value: " + << vectors::largest_vector_value(random_values) << std::endl; + } break; + case 2: { + // Output the smallest value of the vector and run again. + std::cout << "smallest value: " + << vectors::smallest_vector_value(random_values) << std::endl; + } break; + case 3: { + // Output the average value of the vector and run again. + std::cout << "average value: " + << vectors::average_vector_value(random_values) << std::endl; + } break; + case 4: { + std::size_t append_maximum_random_values; + + // Get the number of random values to append to the random value pool from + // the user. + std::cout + << "number of random values to append to the random value pool: "; + std::cin >> append_maximum_random_values; + + // Append the user's choice of extra random values to the random value + // pool + for (std::size_t i = 0; i < append_maximum_random_values; ++i) { + random_values.push_back(uniform_distribution(random_engine)); + } + } break; +#ifdef DEBUG + case 5: { + // Output the number of values in the random value pool and run again. + std::cout << "number of values in the random value pool: " + << random_values.size() << std::endl; + } break; +#endif + default: { + // Inform the user the operation is invalid and run gain. + std::cout << "you chose an invalid choice. please choice a valid choice " + "the next time around." + << std::endl; + } break; + } + } while (user_choice != 0); + + return 0; +} + +namespace vectors { + +real_type largest_vector_value(const std::vector<real_type> &v) { + return *std::max_element(v.begin(), v.end()); +} + +real_type smallest_vector_value(const std::vector<real_type> &v) { + return *std::min_element(v.begin(), v.end()); +} + +real_type average_vector_value(const std::vector<real_type> &v) { + return std::reduce(v.begin(), v.end()) / v.size(); +} + +} // namespace vectors |