diff --git a/exercises-cpp/mohammed_almakki/CMakeLists.txt b/exercises-cpp/mohammed_almakki/CMakeLists.txt new file mode 100644 index 00000000..c233c863 --- /dev/null +++ b/exercises-cpp/mohammed_almakki/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required ( VERSION 3.14 ) + +project(newstarter) + +add_subdirectory ( ex01_basics ) +add_subdirectory ( ex02_oo_basics ) diff --git a/exercises-cpp/mohammed_almakki/README.md b/exercises-cpp/mohammed_almakki/README.md new file mode 100644 index 00000000..ee6f3331 --- /dev/null +++ b/exercises-cpp/mohammed_almakki/README.md @@ -0,0 +1,3 @@ +This directory contains the template CMake projects for each of the exercises. + +Do not write your code for the exercises in here. Instead, make a copy of the directory containing this file and name your new directory `firstname_surname`. The CMake files contain relative paths so the new directory should be at the same level as the parent `template` directory. \ No newline at end of file diff --git a/exercises-cpp/mohammed_almakki/ex01_basics/CMakeLists.txt b/exercises-cpp/mohammed_almakki/ex01_basics/CMakeLists.txt new file mode 100644 index 00000000..e3c2dd3b --- /dev/null +++ b/exercises-cpp/mohammed_almakki/ex01_basics/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required ( VERSION 2.8.5 ) + +############################################################################### +# Setup +############################################################################### +# Name +project ( WordCounter ) + +# Find custom cmake modules +set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../CMake") + +# Common setup +include ( CommonSetup ) + +############################################################################### +# Executable +############################################################################### + +set ( SRC_FILES + src/main.cpp + # add any additional source files here +) + +set ( HDR_FILES + # add any additional header files here +) + +add_executable ( WordCounter ${SRC_FILES} ${HDR_FILES} ) diff --git a/exercises-cpp/mohammed_almakki/ex01_basics/src/main.cpp b/exercises-cpp/mohammed_almakki/ex01_basics/src/main.cpp new file mode 100644 index 00000000..3864b0cf --- /dev/null +++ b/exercises-cpp/mohammed_almakki/ex01_basics/src/main.cpp @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +std::string readFile(const std::string &filepath) +{ + std::ifstream inputStream(filepath); + + if (inputStream) + { + std::ostringstream ss; + ss << inputStream.rdbuf(); + return ss.str(); + } + else + { + throw std::invalid_argument("Invalid path. Please make sure the file path is correct and the file exists."); + } +} + +std::vector tokenizeFile(const std::string &file) +{ + std::regex re("[-\\s]"); + std::sregex_token_iterator first{file.begin(), file.end(), re, -1}, last; + std::vector tokens{first, last}; + return tokens; +} + +std::unordered_map countWords(const std::vector words) +{ + std::unordered_map wordsCounts; + for (auto word : words) + { + std::transform( + word.begin(), word.end(), word.begin(), + [](unsigned char c) + { return std::tolower(c); }); + word.erase(std::remove_if(word.begin(), word.end(), ispunct), word.end()); + if (word.length() > 4) + { + wordsCounts[word]++; + } + } + return wordsCounts; +} + +void sortAndWriteWords(const std::unordered_map &wordsCounts, const std::string &outputDir) +{ + std::vector> wordsCountsPairs; + for (auto &pair : wordsCounts) + { + wordsCountsPairs.push_back(pair); + } + std::sort( + wordsCountsPairs.begin(), wordsCountsPairs.end(), + [](auto &left, auto &right) + { + return left.second > right.second; + }); + + std::ofstream outputFile(outputDir + "\\output.txt"); + + outputFile << std::setw(20) << std::left << "Word" << std::setw(20) << std::left << "Usage" + << "\n\n"; + + for (auto &it : wordsCountsPairs) + { + outputFile << std::setw(20) << std::left << it.first << std::setw(20) << std::left << it.second << "\n"; + } + + outputFile.close(); + std::cout << "Found " << wordsCountsPairs.size() << " words and their counts have been successfully written in this path: " << outputDir + "\\output.txt" + << "\n"; +} + +int main(int, char **) +{ + while (true) + { + std::cout << "Welcome to the Word Counter program!" + << "\n\n"; + std::cout << "This program will count the number of occurrences of unique words (longer than 4 characters and split hyphenated words, treating each part as different words)" + << "\n"; + std::cout << "The count will be case and punctuation insensitive" + << "\n\n"; + std::cout << "Please enter the path of the file:" + << "\n"; + std::string inputFilePath; + getline(std::cin, inputFilePath); + + std::string file; + try + { + file = readFile(inputFilePath); + if (file.empty()) + { + std::cout << "Note: " + << "This file is empty so the output will be an empty file." + << "\n"; + } + } + catch (std::invalid_argument e) + { + std::cerr << "Error:" << e.what() << "\n\n"; + continue; + } + + std::vector tokenizedFile = tokenizeFile(file); + std::unordered_map wordsCounts = countWords(tokenizedFile); + + std::string outputFileDir = inputFilePath.substr(0, inputFilePath.rfind('\\')); + sortAndWriteWords(wordsCounts, outputFileDir); + + break; + } + + return 0; +} \ No newline at end of file diff --git a/exercises-cpp/mohammed_almakki/ex02_oo_basics/CMakeLists.txt b/exercises-cpp/mohammed_almakki/ex02_oo_basics/CMakeLists.txt new file mode 100644 index 00000000..20fd0178 --- /dev/null +++ b/exercises-cpp/mohammed_almakki/ex02_oo_basics/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required ( VERSION 2.8.5 ) + +############################################################################### +# Setup +############################################################################### +# Name +project ( Shapes ) + +# Find custom cmake modules +set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../CMake") + +# Common setup +include ( CommonSetup ) + +############################################################################### +# Executable +############################################################################### + +set ( SRC_FILES + src/main.cpp + src/ShapeSorter.cpp +) + +set ( HDR_FILES + src/Shape.h + src/ShapeSorter.h +) + +add_executable ( Shapes ${SRC_FILES} ${HDR_FILES} ) diff --git a/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/Shape.h b/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/Shape.h new file mode 100644 index 00000000..a1548577 --- /dev/null +++ b/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/Shape.h @@ -0,0 +1,133 @@ +#pragma once + +#include +#include + +enum class ShapeType { Shape, Rectangle, Square, Circle, Triangle }; + +class Shape +{ +public: + virtual inline double getArea() const = 0; + virtual inline double getPerimeter() const = 0; + + virtual inline ShapeType getType() const = 0; + virtual inline std::string toString() const = 0; + + inline int getSidesCount() const { + return noOfSides; + } + + Shape(const int& noOfSides) : noOfSides{noOfSides} {} + + private: + const int noOfSides; +}; + +class Rectangle : public Shape +{ +public: + Rectangle(const double& side1, const double& side2) : side1{side1}, side2{side2}, Shape(2) {} + + inline ShapeType getType() const override + { + return ShapeType::Rectangle; + } + + inline double getArea() const override + { + return side1 * side2; + } + + inline double getPerimeter() const override + { + return 2 * side1 + 2 * side2; + } + + inline std::string toString() const override + { + return "Rectangle(side1=" + std::to_string(side1) + ", side2=" + std::to_string(side2) + ")"; + } + +private: + double side1; + double side2; +}; + +class Square : public Rectangle +{ +public: + Square(double side1) : side1{side1}, Rectangle(side1, side1) {} + + inline ShapeType getType() const override + { + return ShapeType::Rectangle; + } + + inline std::string toString() const override + { + return "Square(side=" + std::to_string(side1) + ")"; + } + +private: + double side1; +}; + +class Circle : public Shape +{ +public: + Circle(double radius) : radius{radius}, Shape(0) {} + + inline ShapeType getType() const override + { + return ShapeType::Circle; + } + + inline double getArea() const override + { + return M_PI * radius * radius; + } + + inline double getPerimeter() const override + { + return 2 * M_PI * radius; + } + + inline std::string toString() const override + { + return "Circle(radius=" + std::to_string(radius) + ")"; + } + +private: + double radius; +}; + +class Triangle : public Shape +{ +public: + Triangle(double height, double base) : height{height}, base{base}, Shape(3) {} + + inline ShapeType getType() const override + { + return ShapeType::Triangle; + } + + inline double getArea() const override + { + return 0.5 * height * base; + } + + inline double getPerimeter() const override + { + return base + 2 * std::sqrt(height * height + (base * base) / 4); + } + + inline std::string toString() const override + { + return "Triangle(height=" + std::to_string(height) + ", base=" + std::to_string(base) + ")"; + } + +private: + double height; + double base; +}; diff --git a/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/ShapeSorter.cpp b/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/ShapeSorter.cpp new file mode 100644 index 00000000..3beeaf2c --- /dev/null +++ b/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/ShapeSorter.cpp @@ -0,0 +1,54 @@ +#include "ShapeSorter.h" + +void ShapeSorter::filterAndPrintByPredicate(const std::vector> &shapes, const ShapeFilterPredicate &predicate) const +{ + for_each( + shapes.begin(), shapes.end(), [predicate](auto shape) + { + if(predicate(shape)) { + std::cout << shape->toString() << " "; + } }); + std::cout << "\n"; +} + +void ShapeSorter::printShapesWithType(const ShapeType &type) const +{ + filterAndPrintByPredicate(shapes, [type](const std::shared_ptr &shape) + { return shape->getType() == type; }); +} + +void ShapeSorter::printShapesWithSides(const int &sidesCount) const +{ + filterAndPrintByPredicate(shapes, [sidesCount](const std::shared_ptr &shape) + { return shape->getSidesCount() == sidesCount; }); +} + +void ShapeSorter::printOrderedShapesByArea() const +{ + auto sortedShapes = shapes; + + std::sort( + sortedShapes.begin(), sortedShapes.end(), + [](auto left, auto right) + { + return left->getArea() > right->getArea(); + }); + + filterAndPrintByPredicate(sortedShapes, [](const std::shared_ptr &shape) + { return true; }); +} + +void ShapeSorter::printOrderedShapesByPerimeter() const +{ + auto sortedShapes = shapes; + + std::sort( + sortedShapes.begin(), sortedShapes.end(), + [](auto left, auto right) + { + return left->getPerimeter() > right->getPerimeter(); + }); + + filterAndPrintByPredicate(sortedShapes, [](const std::shared_ptr &shape) + { return true; }); +} \ No newline at end of file diff --git a/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/ShapeSorter.h b/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/ShapeSorter.h new file mode 100644 index 00000000..14e5bc63 --- /dev/null +++ b/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/ShapeSorter.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include +#include +#include "Shape.h" + +typedef std::function&)> ShapeFilterPredicate; + +class ShapeSorter +{ +public: + ShapeSorter(const std::vector> &shapes) : shapes{shapes} {} + + void printShapesWithType(const ShapeType &type) const; + void printShapesWithSides(const int &sidesCount) const; + void printOrderedShapesByArea() const; + void printOrderedShapesByPerimeter() const; + +private: + void filterAndPrintByPredicate(const std::vector> &, const ShapeFilterPredicate&) const; + const std::vector> &shapes; +}; diff --git a/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/main.cpp b/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/main.cpp new file mode 100644 index 00000000..709ac9ce --- /dev/null +++ b/exercises-cpp/mohammed_almakki/ex02_oo_basics/src/main.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include "Shape.h" +#include "ShapeSorter.h" + +int main(int, char **) +{ + auto sq1 = std::make_shared(2); + + auto rect1 = std::make_shared(2, 4); + auto rect2 = std::make_shared(4, 14); + + auto c1 = std::make_shared(2); + auto c2 = std::make_shared(10); + + auto t1 = std::make_shared(2, 4); + auto t2 = std::make_shared(4, 10); + + std::vector> shapes; + + shapes.push_back(sq1); + shapes.push_back(rect1); + shapes.push_back(rect1); + shapes.push_back(c1); + shapes.push_back(c2); + shapes.push_back(t1); + shapes.push_back(t2); + + ShapeSorter sorter(shapes); + sorter.printShapesWithType(ShapeType::Rectangle); + sorter.printShapesWithSides(2); + sorter.printOrderedShapesByArea(); + sorter.printOrderedShapesByPerimeter(); + + return 0; +} \ No newline at end of file