diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:08:27 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:08:27 +0200 |
| commit | c9b6b9a5ca082fe7c1b6f58d7713f785a9eb6a5c (patch) | |
| tree | 3e4f42f93c7ae89a364e4d51fff6e5cec4e55fa9 /graphs/cpp | |
add: graphs et rushs
Diffstat (limited to 'graphs/cpp')
157 files changed, 4351 insertions, 0 deletions
diff --git a/graphs/cpp/.clang-format b/graphs/cpp/.clang-format new file mode 100644 index 0000000..6c10a16 --- /dev/null +++ b/graphs/cpp/.clang-format @@ -0,0 +1,80 @@ +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: false +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterEnum: true + AfterClass: true + AfterControlStatement: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: BeforeComma +BreakStringLiterals: true +ColumnLimit: 80 +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +FixNamespaceComments: true +ForEachMacros: ['ILIST_FOREACH', 'ILIST_FOREACH_ENTRY'] +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '<.*>' + Priority: 1 + - Regex: '.*' + Priority: 2 +IndentCaseLabels: false +IndentPPDirectives: AfterHash +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +Language: Cpp +NamespaceIndentation: All +PointerAlignment: Left +ReferenceAlignment: Left +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: Never diff --git a/graphs/cpp/.gitignore b/graphs/cpp/.gitignore new file mode 100644 index 0000000..4cf8e3f --- /dev/null +++ b/graphs/cpp/.gitignore @@ -0,0 +1,6 @@ +*/.gitignore +.idea/ +*.out +*.tar +cmake* +build/ diff --git a/graphs/cpp/CMakeLists.txt b/graphs/cpp/CMakeLists.txt new file mode 100644 index 0000000..a40c5d7 --- /dev/null +++ b/graphs/cpp/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.21.2) +project(cproutprout) + +add_executable(cpipi hello_world/hello_world.cc + directories_infos/directory_info.cc + directories_infos/read_info.cc + war/soldier.hh + war/soldier.cc + war/knight.hh + war/knight.cc + war/regiment.hh + war/regiment.cc)
\ No newline at end of file diff --git a/graphs/cpp/address_book/address_book.cc b/graphs/cpp/address_book/address_book.cc new file mode 100644 index 0000000..92e74cf --- /dev/null +++ b/graphs/cpp/address_book/address_book.cc @@ -0,0 +1,75 @@ +// +// Created by martial.simon on 2/26/25. +// + +#include "address_book.hh" + +#include <iostream> +#include <stdexcept> +bool AddressBook::add(const std::string& full_name, const std::string& email, + const std::string& number) +{ + try + { + ContactDetails details = ContactDetails::makeDetails(number, email); + if (full_name.empty()) + return false; + contact_map_.insert({ full_name, details }); + return true; + } + catch (std::invalid_argument& e) + { + return false; + } +} +std::vector<ContactDetails> AddressBook::find(const std::string& full_name) +{ + std::vector<ContactDetails> res; + for (auto detail = contact_map_.find(full_name); + detail != contact_map_.end() && detail->first == full_name; detail++) + { + res.push_back(detail->second); + } + return res; +} +std::size_t AddressBook::count(const std::string& full_name) +{ + size_t res = 0; + for (auto detail = contact_map_.find(full_name); + detail != contact_map_.end(); detail++) + { + res++; + } + return res; +} +bool AddressBook::remove(const std::string& full_name, std::size_t index) +{ + auto range = contact_map_.equal_range(full_name); + for (auto contact = range.first; contact != range.second; contact++) + { + if (contact->first == full_name) + { + if (index == 0) + { + contact_map_.erase(contact); + return true; + } + index--; + } + } + return false; +} +void AddressBook::remove_all(const std::string& full_name) +{ + auto range = contact_map_.equal_range(full_name); + contact_map_.erase(range.first, range.second); +} +std::ostream& operator<<(std::ostream& os, const AddressBook& b) +{ + os << b.contact_map_.size() << " contact(s) in the address book.\n"; + for (auto& pair : b.contact_map_) + { + os << "- " << pair.first << ": " << pair.second; + } + return os; +}
\ No newline at end of file diff --git a/graphs/cpp/address_book/address_book.hh b/graphs/cpp/address_book/address_book.hh new file mode 100644 index 0000000..9e59ac9 --- /dev/null +++ b/graphs/cpp/address_book/address_book.hh @@ -0,0 +1,25 @@ +// +// Created by martial.simon on 2/26/25. +// + +#pragma once +#include <map> +#include <string> +#include <vector> + +#include "contact_details.hh" + +class AddressBook +{ +public: + bool add(const std::string& full_name, const std::string& email, + const std::string& number); + std::vector<ContactDetails> find(const std::string& full_name); + std::size_t count(const std::string& full_name); + bool remove(const std::string& full_name, std::size_t index); + void remove_all(const std::string& full_name); + friend std::ostream& operator<<(std::ostream& os, const AddressBook& b); + +private: + std::multimap<std::string, ContactDetails> contact_map_; +}; diff --git a/graphs/cpp/address_book/contact_details.cc b/graphs/cpp/address_book/contact_details.cc new file mode 100644 index 0000000..3880d14 --- /dev/null +++ b/graphs/cpp/address_book/contact_details.cc @@ -0,0 +1,38 @@ +// +// Created by martial.simon on 2/26/25. +// + +#include "contact_details.hh" + +#include <iostream> +#include <stdexcept> +ContactDetails ContactDetails::makeDetails(const std::string& telephone_number, + const std::string& personal_email) +{ + for (auto digit : telephone_number) + { + if (!isdigit(digit)) + throw std::invalid_argument{ + "Phone number must only contain digits." + }; + } + size_t i; + for (i = 0; i < personal_email.length(); ++i) + { + if (personal_email[i] == '@') + break; + } + if (i == personal_email.length()) + throw std::invalid_argument{ "Email must contain at least one '@'." }; + return ContactDetails{ telephone_number, personal_email }; +} +std::ostream& operator<<(std::ostream& os, const ContactDetails& dt) +{ + os << dt.phone_ << ", " << dt.email_ << "\n"; + return os; +} +ContactDetails::ContactDetails(const std::string& telephone_number, + const std::string& personal_email) + : phone_{ telephone_number } + , email_{ personal_email } +{}
\ No newline at end of file diff --git a/graphs/cpp/address_book/contact_details.hh b/graphs/cpp/address_book/contact_details.hh new file mode 100644 index 0000000..57a6438 --- /dev/null +++ b/graphs/cpp/address_book/contact_details.hh @@ -0,0 +1,15 @@ +#pragma once +#include <string> + +struct ContactDetails +{ + static ContactDetails makeDetails(const std::string& telephone_number, + const std::string& personal_email); + friend std::ostream& operator<<(std::ostream& os, const ContactDetails& dt); + +private: + const std::string phone_; + const std::string email_; + ContactDetails(const std::string& telephone_number, + const std::string& personal_email); +};
\ No newline at end of file diff --git a/graphs/cpp/address_book/main.cc b/graphs/cpp/address_book/main.cc new file mode 100644 index 0000000..ffdb324 --- /dev/null +++ b/graphs/cpp/address_book/main.cc @@ -0,0 +1,42 @@ +#include <iostream> +#include <string> +#include <vector> + +#include "address_book.hh" + +int main() +{ + AddressBook b = AddressBook(); + + std::cout << "Adding multiple contacts to the address book.\n"; + + b.add("Cyril Berger", "cyril.berger@epita.fr", "33612983402"); + b.add("Thibault Allancon", "thibault.allancon@epita.fr", "33612983409"); + b.add("Cyril Berger", "cyril.berger@epita.fr", "33628359602"); + b.add("Hugo Wahl", "hugo.wahl@epita.fr", "3398560923"); + b.add("Dominique Michel", "dominique.michel@epita.fr", "3345096792"); + + std::cout << "Searching for Maya El Gemayel:\n"; + auto v = b.find("Maya El Gemayel"); + for (auto it = v.begin(); it != v.end(); it++) + std::cout << *it; + + std::cout << "Searching for Thibault Allancon:\n"; + v = b.find("Thibault Allancon"); + for (auto it = v.begin(); it != v.end(); it++) + std::cout << *it; + + std::cout << "Searching for Cyril Berger:\n"; + v = b.find("Cyril Berger"); + for (auto it = v.begin(); it != v.end(); it++) + std::cout << *it; + + std::cout << b; + + std::cout << "Erasing the second Cyril Berger.\n"; + b.remove("Cyril Berger", 1); + + std::cout << b; + + return 0; +} diff --git a/graphs/cpp/antagonist/CMakeLists.txt b/graphs/cpp/antagonist/CMakeLists.txt new file mode 100644 index 0000000..7620cb4 --- /dev/null +++ b/graphs/cpp/antagonist/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.21.2) +project(beaver_run) + +add_executable(beaver_run) +add_subdirectory(test) +target_compile_options(beaver_run PRIVATE -Wall -Wextra -Werror -pedantic -std=c++20 -Wold-style-cast) +set_target_properties(beaver_run PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF) +add_subdirectory(src) + +target_link_libraries(beaver_run PUBLIC libbeaver) +target_include_directories(beaver_run PUBLIC + "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/include" +) +target_include_directories(libbeaver PUBLIC + "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/include" +)
\ No newline at end of file diff --git a/graphs/cpp/antagonist/include/libbeaver/beaver.hh b/graphs/cpp/antagonist/include/libbeaver/beaver.hh new file mode 100644 index 0000000..ac5cbe4 --- /dev/null +++ b/graphs/cpp/antagonist/include/libbeaver/beaver.hh @@ -0,0 +1,18 @@ +#include <memory> + +namespace beaver +{ + class Beaver + { + public: + virtual ~Beaver() = default; + + virtual const std::string& get_name() const = 0; + + virtual void display_video() = 0; + }; + + std::unique_ptr<Beaver> make_beaver(const std::string& name, + const std::string& video_path); + +} // namespace beaver diff --git a/graphs/cpp/antagonist/src/CMakeLists.txt b/graphs/cpp/antagonist/src/CMakeLists.txt new file mode 100644 index 0000000..8dd9272 --- /dev/null +++ b/graphs/cpp/antagonist/src/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.21.2) + +add_library(libbeaver SHARED) + +target_compile_options(libbeaver PUBLIC -Wall -Wextra -Werror -pedantic -std=c++20 -Wold-style-cast) +set_target_properties(libbeaver PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" + OUTPUT_NAME "beaver" ) +target_include_directories(libbeaver PRIVATE + "${PROJECT_SOURCE_DIR}/include" + "${PROJECT_SOURCE_DIR}/src" +) + +find_package(OpenCV REQUIRED) +target_link_libraries(libbeaver PUBLIC ${OpenCV_LIBS}) +add_subdirectory(video_player) +add_subdirectory(beaver)
\ No newline at end of file diff --git a/graphs/cpp/antagonist/src/beaver/CMakeLists.txt b/graphs/cpp/antagonist/src/beaver/CMakeLists.txt new file mode 100644 index 0000000..13a04a6 --- /dev/null +++ b/graphs/cpp/antagonist/src/beaver/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.21.2) + +target_sources(libbeaver PRIVATE beaver.cc beaver_impl.cc) +set_target_properties(libbeaver PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF)
\ No newline at end of file diff --git a/graphs/cpp/antagonist/src/beaver/beaver.cc b/graphs/cpp/antagonist/src/beaver/beaver.cc new file mode 100644 index 0000000..57a612c --- /dev/null +++ b/graphs/cpp/antagonist/src/beaver/beaver.cc @@ -0,0 +1,12 @@ +#include <string> + +#include "beaver_impl.hh" + +namespace beaver +{ + std::unique_ptr<Beaver> make_beaver(const std::string& name, + const std::string& video_path) + { + return std::make_unique<BeaverImpl>(name, video_path); + } +} // namespace beaver diff --git a/graphs/cpp/antagonist/src/beaver/beaver_impl.cc b/graphs/cpp/antagonist/src/beaver/beaver_impl.cc new file mode 100644 index 0000000..27757b5 --- /dev/null +++ b/graphs/cpp/antagonist/src/beaver/beaver_impl.cc @@ -0,0 +1,24 @@ +#include "beaver_impl.hh" + +#include <string> + +#include "video_player/video_player.hh" + +namespace beaver +{ + BeaverImpl::BeaverImpl(const std::string& name, std::string filename) + : beaver_name_(name) + , file_path_(filename) + {} + + const std::string& BeaverImpl::get_name() const + { + return beaver_name_; + } + + void BeaverImpl::display_video() + { + play_video(file_path_); + } + +} // namespace beaver diff --git a/graphs/cpp/antagonist/src/beaver/beaver_impl.hh b/graphs/cpp/antagonist/src/beaver/beaver_impl.hh new file mode 100644 index 0000000..02b84cc --- /dev/null +++ b/graphs/cpp/antagonist/src/beaver/beaver_impl.hh @@ -0,0 +1,21 @@ +#include <libbeaver/beaver.hh> +#include <string> + +namespace beaver +{ + class BeaverImpl : public Beaver + { + public: + BeaverImpl(const std::string& name, std::string filename); + + ~BeaverImpl() override = default; + + const std::string& get_name() const override; + + void display_video() override; + + private: + const std::string& beaver_name_; + std::string file_path_; + }; +} // namespace beaver diff --git a/graphs/cpp/antagonist/src/video_player/CMakeLists.txt b/graphs/cpp/antagonist/src/video_player/CMakeLists.txt new file mode 100644 index 0000000..0420a11 --- /dev/null +++ b/graphs/cpp/antagonist/src/video_player/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.21.2) + +target_sources(libbeaver PRIVATE video_player.cc) +set_target_properties(libbeaver PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF)
\ No newline at end of file diff --git a/graphs/cpp/antagonist/src/video_player/video_player.cc b/graphs/cpp/antagonist/src/video_player/video_player.cc new file mode 100644 index 0000000..f3b724c --- /dev/null +++ b/graphs/cpp/antagonist/src/video_player/video_player.cc @@ -0,0 +1,59 @@ +#include "video_player.hh" + +#include <iostream> +#include <thread> + +static char pixelToAscii(int pixelValue) +{ + const std::string ascii_chars = ".:-=+*#%@8WM"; + int index = pixelValue * ascii_chars.length() / 256; + return ascii_chars[index]; +} + +static std::string rgbToAnsi(int r, int g, int b) +{ + return "\033[38;2;" + std::to_string(r) + ";" + std::to_string(g) + ";" + + std::to_string(b) + "m"; +} + +void play_video(std::string& video_path) +{ + std::cout << std::endl; + cv::VideoCapture video(video_path); + + if (!video.isOpened()) + { + std::cerr << "Error: Impossible to open video." << std::endl; + return; + } + + cv::Mat frame, resizedFrame; + while (true) + { + video >> frame; + if (frame.empty()) + break; + + cv::resize(frame, resizedFrame, cv::Size(105, 56)); + for (int i = 0; i < resizedFrame.rows; ++i) + { + for (int j = 0; j < resizedFrame.cols; ++j) + { + cv::Vec3b pixel = resizedFrame.at<cv::Vec3b>(i, j); + int blue = pixel[0]; + int green = pixel[1]; + int red = pixel[2]; + + char asciiChar = pixelToAscii((red + green + blue) / 3); + std::string colorCode = rgbToAnsi(red, green, blue); + + std::cout << "\033[" << i + 1 << ";" << j + 1 << "H"; + std::cout << colorCode << asciiChar; + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + std::cout << "\033[0m"; + } + video.release(); + std::cout << std::endl; +} diff --git a/graphs/cpp/antagonist/src/video_player/video_player.hh b/graphs/cpp/antagonist/src/video_player/video_player.hh new file mode 100644 index 0000000..3854bdf --- /dev/null +++ b/graphs/cpp/antagonist/src/video_player/video_player.hh @@ -0,0 +1,12 @@ +#pragma once + +#include <iostream> +#include <opencv2/opencv.hpp> +#include <string> + +/** + * @brief Plays a given video file. + * + * @param video_path The path to the video file to play. + */ +void play_video(std::string& video_path); diff --git a/graphs/cpp/antagonist/test/CMakeLists.txt b/graphs/cpp/antagonist/test/CMakeLists.txt new file mode 100644 index 0000000..b05b260 --- /dev/null +++ b/graphs/cpp/antagonist/test/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.21.2) + +target_sources(beaver_run PUBLIC main.cc) +set_target_properties(beaver_run PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF) +file( + COPY ${CMAKE_CURRENT_SOURCE_DIR}/video/ + DESTINATION "${CMAKE_BINARY_DIR}/video" +)
\ No newline at end of file diff --git a/graphs/cpp/antagonist/test/main.cc b/graphs/cpp/antagonist/test/main.cc new file mode 100644 index 0000000..96d267d --- /dev/null +++ b/graphs/cpp/antagonist/test/main.cc @@ -0,0 +1,10 @@ +#include <iostream> +#include <libbeaver/beaver.hh> + +int main(void) +{ + auto bearer_roll = beaver::make_beaver("Frankulin", "video/video.mp4"); + + bearer_roll->display_video(); + std::cout << bearer_roll->get_name() << std::endl; +} diff --git a/graphs/cpp/antagonist/test/video/video.mp4 b/graphs/cpp/antagonist/test/video/video.mp4 Binary files differnew file mode 100644 index 0000000..7b788c6 --- /dev/null +++ b/graphs/cpp/antagonist/test/video/video.mp4 diff --git a/graphs/cpp/bimap/bimap.hh b/graphs/cpp/bimap/bimap.hh new file mode 100644 index 0000000..25f459d --- /dev/null +++ b/graphs/cpp/bimap/bimap.hh @@ -0,0 +1,36 @@ +#pragma once + +#include <map> + + template <typename Lhs, typename Rhs> + class Bimap +{ + static_assert(!std::is_same_v<Lhs, Rhs>, + "Lhs and Rhs must be different types"); + using mapLhs = std::map<Lhs, Rhs>; + using mapRhs = std::map<Rhs, Lhs>; + using iteratorLhs = typename mapLhs::const_iterator; + using iteratorRhs = typename mapRhs::const_iterator; + +public: + bool insert(const Lhs& vl, const Rhs& vr); + bool insert(const Rhs& vr, const Lhs& vl); + + std::size_t erase(const Lhs& vl); + std::size_t erase(const Rhs& vr); + + iteratorLhs find(const Lhs& vl) const; + iteratorRhs find(const Rhs& vr) const; + + std::size_t size() const; + void clear(); + + const mapLhs& get_lhs() const; + const mapRhs& get_rhs() const; + +private: + mapLhs lhs_; + mapRhs rhs_; +}; + +#include "bimap.hxx" diff --git a/graphs/cpp/bimap/bimap.hxx b/graphs/cpp/bimap/bimap.hxx new file mode 100644 index 0000000..9b1eb1f --- /dev/null +++ b/graphs/cpp/bimap/bimap.hxx @@ -0,0 +1,74 @@ +#pragma once +#include "bimap.hh" + +template <typename Lhs, typename Rhs> +bool Bimap<Lhs, Rhs>::insert(const Lhs& vl, const Rhs& vr) +{ + if (lhs_.contains(vl) || rhs_.contains(vr)) + return false; + if (lhs_.contains(vl) || !lhs_.insert({ vl, vr }).second) + return false; + if (rhs_.contains(vr) || !rhs_.insert({ vr, vl }).second) + return false; + return true; +} +template <typename Lhs, typename Rhs> +bool Bimap<Lhs, Rhs>::insert(const Rhs& vr, const Lhs& vl) +{ + return insert(vl, vr); +} +template <typename Lhs, typename Rhs> +std::size_t Bimap<Lhs, Rhs>::erase(const Lhs& vl) +{ + if (lhs_.size() <= 0) + return 0; + auto range = lhs_.find(vl); + if (range == lhs_.end()) + return 0; + rhs_.erase(range->second); + size_t n = lhs_.erase(range->first); + return n; +} +template <typename Lhs, typename Rhs> +std::size_t Bimap<Lhs, Rhs>::erase(const Rhs& vr) +{ + if (lhs_.size() <= 0) + return 0; + auto range = rhs_.find(vr); + if (range == rhs_.end()) + return 0; + lhs_.erase(range->second); + size_t n = rhs_.erase(range->first); + return n; +} +template <typename Lhs, typename Rhs> +typename Bimap<Lhs, Rhs>::iteratorLhs Bimap<Lhs, Rhs>::find(const Lhs& vl) const +{ + return lhs_.find(vl); +} +template <typename Lhs, typename Rhs> +typename Bimap<Lhs, Rhs>::iteratorRhs Bimap<Lhs, Rhs>::find(const Rhs& vr) const +{ + return rhs_.find(vr); +} +template <typename Lhs, typename Rhs> +std::size_t Bimap<Lhs, Rhs>::size() const +{ + return lhs_.size(); +} +template <typename Lhs, typename Rhs> +void Bimap<Lhs, Rhs>::clear() +{ + lhs_ = {}; + rhs_ = {}; +} +template <typename Lhs, typename Rhs> +const typename Bimap<Lhs, Rhs>::mapLhs& Bimap<Lhs, Rhs>::get_lhs() const +{ + return lhs_; +} +template <typename Lhs, typename Rhs> +const typename Bimap<Lhs, Rhs>::mapRhs& Bimap<Lhs, Rhs>::get_rhs() const +{ + return rhs_; +}
\ No newline at end of file diff --git a/graphs/cpp/bimap/bimap_example.cc b/graphs/cpp/bimap/bimap_example.cc new file mode 100644 index 0000000..771a2b0 --- /dev/null +++ b/graphs/cpp/bimap/bimap_example.cc @@ -0,0 +1,26 @@ +#include <iostream> +#include <string> + +#include "bimap.hh" + +int main() +{ + Bimap<int, std::string> bm; + + bm.insert(16, "Test."); + bm.insert("Prologin", 29); + + std::cout << "The bimap contains: " << bm.size() << " elements\n"; + + auto it1 = bm.find("Test."); + auto it2 = bm.find(29); + + std::cout << it1->first << ' ' << it1->second << '\n'; + std::cout << it2->first << ' ' << it2->second << '\n'; + + bm.erase(16); + bm.erase("Prologin"); + + bm.clear(); + return 0; +} diff --git a/graphs/cpp/cartesian_vector/format_numerical_data.cc b/graphs/cpp/cartesian_vector/format_numerical_data.cc new file mode 100644 index 0000000..b6355d2 --- /dev/null +++ b/graphs/cpp/cartesian_vector/format_numerical_data.cc @@ -0,0 +1,13 @@ +#include "format_numerical_data.hh" +std::ostream& FormatNumericalData::formatOs(std::ostream& os) const +{ + if (precision >= 0) + { + os.precision(precision); + } + if (scientific_notation) + std::scientific(os); + if (display_plus) + std::showpos(os); + return os; +}
\ No newline at end of file diff --git a/graphs/cpp/cartesian_vector/format_numerical_data.hh b/graphs/cpp/cartesian_vector/format_numerical_data.hh new file mode 100644 index 0000000..359e297 --- /dev/null +++ b/graphs/cpp/cartesian_vector/format_numerical_data.hh @@ -0,0 +1,22 @@ +#pragma once + +#include <ostream> +#include <string> + +struct FormatNumericalData +{ + //! string to be printed before the data + std::string prefix; + //! string to be printed after the data + std::string suffix; + //! gives the minimum number of digits to appear (after the radix if + //! scientific_notation is enabled) + int precision = -1; + //! define if scientific notation is enabled + bool scientific_notation = false; + //! define if a sign + should be placed before a number + bool display_plus = false; + + //! format the given stream according to class attributes + std::ostream& formatOs(std::ostream& os) const; +}; diff --git a/graphs/cpp/cartesian_vector/state_saver.cc b/graphs/cpp/cartesian_vector/state_saver.cc new file mode 100644 index 0000000..4b4a244 --- /dev/null +++ b/graphs/cpp/cartesian_vector/state_saver.cc @@ -0,0 +1,11 @@ +#include "state_saver.hh" +StateSaver::StateSaver(std::ostream& os) + : saved_stream_{ os } + , saved_flags_{ os.flags() } + , saved_precision_{ os.precision() } +{} +StateSaver::~StateSaver() +{ + saved_stream_.flags(saved_flags_); + saved_stream_.precision(saved_precision_); +}
\ No newline at end of file diff --git a/graphs/cpp/cartesian_vector/state_saver.hh b/graphs/cpp/cartesian_vector/state_saver.hh new file mode 100644 index 0000000..f52127c --- /dev/null +++ b/graphs/cpp/cartesian_vector/state_saver.hh @@ -0,0 +1,20 @@ +#pragma once + +#include <iostream> + +class StateSaver +{ +public: + //! constructor should save all flags and precision + StateSaver(std::ostream& os); + //! destructor should restore all flags and precision + ~StateSaver(); + +private: + //! original stream + std::ostream& saved_stream_; + //! flags of the original stream + std::ios_base::fmtflags saved_flags_; + //! precision of the original stream + std::streamsize saved_precision_; +}; diff --git a/graphs/cpp/cartesian_vector/vector.cc b/graphs/cpp/cartesian_vector/vector.cc new file mode 100644 index 0000000..1291f69 --- /dev/null +++ b/graphs/cpp/cartesian_vector/vector.cc @@ -0,0 +1,69 @@ +#include "vector.hh" + +#include "state_saver.hh" + +Vector::Vector(double x, double y) + : x_{ x } + , y_{ y } +{} +double Vector::get_x() const +{ + return x_; +} +double Vector::get_y() const +{ + return y_; +} +Vector& Vector::operator+=(const Vector& rhs) +{ + x_ += rhs.get_x(); + y_ += rhs.get_y(); + return *this; +} +Vector& Vector::operator-=(const Vector& rhs) +{ + x_ -= rhs.get_x(); + y_ -= rhs.get_y(); + return *this; +} +Vector& Vector::operator*=(double scalar) +{ + x_ *= scalar; + y_ *= scalar; + return *this; +} +Vector operator+(const Vector& lhs, const Vector& rhs) +{ + Vector lhs1{ lhs }; + return lhs1 += rhs; +} +Vector operator-(const Vector& lhs, const Vector& rhs) +{ + Vector lhs1{ lhs }; + return lhs1 -= rhs; +} +Vector operator*(const Vector& lhs, double scalar) +{ + Vector lhs1{ lhs }; + return lhs1 *= scalar; +} +Vector operator*(double scalar, const Vector& rhs) +{ + return rhs * scalar; +} +double operator*(const Vector& lhs, const Vector& rhs) +{ + return lhs.get_x() * rhs.get_x() + lhs.get_y() * rhs.get_y(); +} + +FormatNumericalData Vector::format_numerical_data_{ "[ ", " ]", 12, true, + true }; + +std::ostream& operator<<(std::ostream& os, const Vector& vec) +{ + StateSaver savestate{ os }; + Vector::format_numerical_data_.formatOs(os); + os << Vector::format_numerical_data_.prefix << vec.get_x() << " , " + << vec.get_y() << Vector::format_numerical_data_.suffix; + return os; +}
\ No newline at end of file diff --git a/graphs/cpp/cartesian_vector/vector.hh b/graphs/cpp/cartesian_vector/vector.hh new file mode 100644 index 0000000..b18838c --- /dev/null +++ b/graphs/cpp/cartesian_vector/vector.hh @@ -0,0 +1,29 @@ +#pragma once +#include <iostream> + +#include "format_numerical_data.hh" + +class Vector +{ +public: + Vector() = default; + Vector(double x, double y); + double get_x() const; + double get_y() const; + + Vector& operator+=(const Vector& rhs); + Vector& operator-=(const Vector& rhs); + Vector& operator*=(double scalar); + + friend Vector operator+(const Vector& lhs, const Vector& rhs); + friend Vector operator-(const Vector& lhs, const Vector& rhs); + friend Vector operator*(const Vector& lhs, double scalar); + friend Vector operator*(double scalar, const Vector& rhs); + friend double operator*(const Vector& lhs, const Vector& rhs); + friend std::ostream& operator<<(std::ostream& os, const Vector& vec); + +private: + double x_ = 0; + double y_ = 0; + static FormatNumericalData format_numerical_data_; +}; diff --git a/graphs/cpp/cartesian_vector/vector_test.cc b/graphs/cpp/cartesian_vector/vector_test.cc new file mode 100644 index 0000000..d822c9f --- /dev/null +++ b/graphs/cpp/cartesian_vector/vector_test.cc @@ -0,0 +1,27 @@ +#include <cmath> +#include <iostream> + +#include "vector.hh" + +double pi() +{ + return std::atan2(0., -1.); +} + +int main() +{ + std::cout << "default state pi (double) : " << pi() << '\n'; + Vector piVector{ pi(), pi() }; + Vector t(-1.0E-7, 6.812031E-4); + std::cout << "piVector :\n" << piVector << '\n'; + std::cout << "t + piVector :\n" << t + piVector << '\n'; + + Vector u{ 1923, 8 }; + std::cout << "u :\n" << u << '\n'; + std::cout << "default state (double) : " << u * t << '\n'; + t -= u; + std::cout << "t :\n" << t << '\n'; + std::cout << "t * 3 :\n" << t * 3 << '\n'; + + return 0; +} diff --git a/graphs/cpp/caste_or_cast/Makefile b/graphs/cpp/caste_or_cast/Makefile new file mode 100644 index 0000000..c49f282 --- /dev/null +++ b/graphs/cpp/caste_or_cast/Makefile @@ -0,0 +1,15 @@ +CXX ?= g++ +CXXFLAGS= -std=c++20 -Wall -Wextra -Werror -pedantic \ + -Wold-style-cast + +OBJS = ant.o worker.o nurturer.o provider.o queen.o colony.o main_example.o + +all: my_colony + +my_colony: $(OBJS) + $(CXX) -o $@ $^ + +clean: + $(RM) $(OBJS) my_colony +.PHONY: + clean diff --git a/graphs/cpp/caste_or_cast/ant.cc b/graphs/cpp/caste_or_cast/ant.cc new file mode 100644 index 0000000..2875815 --- /dev/null +++ b/graphs/cpp/caste_or_cast/ant.cc @@ -0,0 +1,87 @@ +#include "ant.hh" + +// The Colony class was forward declared in Ant header +// We need to include its header here so we know Colony implementation +#include "colony.hh" + +Ant::Ant(std::shared_ptr<Colony> colony, DevelopmentStage stage) + : stage_(stage) + , colony_(colony) +{} + +Ant::Ant(const Ant& o) + : stage_(o.stage_) + , colony_(o.colony_) + , hp_(o.hp_) + , food_level_(o.food_level_) +{} + +Ant& Ant::operator=(const Ant& o) +{ + stage_ = o.stage_; + colony_ = o.colony_; + hp_ = o.hp_; + food_level_ = o.food_level_; + return *this; +} + +std::shared_ptr<Colony> Ant::check_colony_access() +{ + std::shared_ptr<Colony> colony = colony_.lock(); + if (colony == nullptr) + throw std::runtime_error("The Colony pointer is expired."); + return colony; +} + +bool Ant::communicate(std::weak_ptr<Ant> wk_receiver) +{ + std::shared_ptr<Ant> receiver = wk_receiver.lock(); + if (receiver == nullptr || stage_ != DevelopmentStage::ADULT + || receiver->get_stage() != DevelopmentStage::ADULT) + return false; + if (receiver->get_passport_pheromone() != get_passport_pheromone()) + return attack(receiver); + return true; +} + +bool Ant::attack(std::weak_ptr<Ant> wk_ant) +{ + if (std::shared_ptr<Ant> ant = wk_ant.lock()) + { + ant->hp_ -= 1; + return true; + } + else + return false; +} + +uint32_t Ant::get_passport_pheromone() +{ + auto c = check_colony_access(); + return c->passport_pheromone_; +} + +DevelopmentStage Ant::get_stage() const +{ + return stage_; +} + +int Ant::get_hp() const +{ + return hp_; +} + +void Ant::set_hp(int hp) +{ + hp_ = hp; +} + +float Ant::get_food_level() const +{ + return food_level_; +} + +void Ant::increment_food_level_by(float value) +{ + food_level_ += value; +} diff --git a/graphs/cpp/caste_or_cast/ant.hh b/graphs/cpp/caste_or_cast/ant.hh new file mode 100644 index 0000000..6a0a0ee --- /dev/null +++ b/graphs/cpp/caste_or_cast/ant.hh @@ -0,0 +1,70 @@ +#pragma once + +#include <memory> + +//! forward declaration +class Colony; + +/* + * Enum Class representing the stage of life for + * an ant + */ +enum class DevelopmentStage : unsigned int +{ + // from the youngest to the oldest stage + EGG = 0, + LARVA, + COCOON, + ADULT +}; + +/* + * Base Class for every ant caste + */ +class Ant +{ +public: + //! delete constructor + Ant() = delete; + //! constructor + Ant(std::shared_ptr<Colony> colony, + DevelopmentStage stage = DevelopmentStage::EGG); + //! copy constructor + Ant(const Ant&); + //! copy assignement + Ant& operator=(const Ant&); + //! default virtual destructor + virtual ~Ant() = default; + //! communicate with another Ant + virtual bool communicate(std::weak_ptr<Ant> wk_receiver); + //! attack given Ant and check if it is dead + bool attack(std::weak_ptr<Ant> wk_ant); + + //! getter for passport_pheromone_ of Colony class + uint32_t get_passport_pheromone(); + //! getter for stage_ + DevelopmentStage get_stage() const; + //! getter for hp_ + int get_hp() const; + //! setter for hp_ + void set_hp(int hp); + //! getter for food_level_ + float get_food_level() const; + //! increment by value food_level_ + void increment_food_level_by(float value); + +protected: + //! return by value the colony shared_ptr if not expired else throw error + std::shared_ptr<Colony> check_colony_access(); + //! development stage + DevelopmentStage stage_; + //! Colony of this Ant + std::weak_ptr<Colony> colony_; + //! health points + int hp_ = 4; + //! represent the energy / food the ant ate for its + // current Development stage + float food_level_ = 0; + //! friend class + friend class Colony; +}; diff --git a/graphs/cpp/caste_or_cast/colony.cc b/graphs/cpp/caste_or_cast/colony.cc new file mode 100644 index 0000000..2c0697a --- /dev/null +++ b/graphs/cpp/caste_or_cast/colony.cc @@ -0,0 +1,116 @@ +#include "colony.hh" + +#include <iostream> + +#include "nurturer.hh" +#include "provider.hh" + +Colony::Colony(uint32_t passport) + : passport_pheromone_(passport) + , workers_() +{} +bool Colony::addAnt(const Ant& ant, std::shared_ptr<Colony> colony) +{ + auto q = dynamic_cast<const Queen*>(&ant); + if (q) + { + if (colony->queen_ || q->get_stage() != DevelopmentStage::ADULT) + return false; + colony->queen_ = std::make_unique<Queen>(*q); + return true; + } + auto n = dynamic_cast<const Nurturer*>(&ant); + if (n) + { + colony->workers_.push_back(std::make_shared<Nurturer>(*n)); + return true; + } + auto p = dynamic_cast<const Provider*>(&ant); + if (p) + { + colony->workers_.push_back(std::make_shared<Provider>(*p)); + return true; + } + return false; +} + +void Colony::manageQueen() +{ + if (queen_ == nullptr) + throw std::runtime_error("Cannot manage a colony without a Queen."); + // check if the queen should lose health points + if (queen_->food_level_ < 0) + queen_->hp_ -= 1; + if (queen_->hp_ <= 0) + { + queen_ = nullptr; + throw std::runtime_error("The Queen died."); + } + // Append to workers_ all the new workers contained in the queen's + // eggs_queue_ + while (!queen_->eggs_queue_.empty()) + { + //! we insert eggs that were laid by the queen + workers_.emplace_back(queen_->eggs_queue_.front()); + queen_->eggs_queue_.pop(); + } +} + +void Colony::removeDeadWorkers() +{ + auto dead_count = std::erase_if( + workers_, [](const std::shared_ptr<Worker> w) { return w->hp_ <= 0; }); + if (dead_count > 0) + { + std::cout << dead_count << " workers_ died.\n"; + // each dead worker decrease the cleanliness of the colony + cleanliness -= 0.5 * dead_count; + } +} + +// this method can be considered as one round of management +void Colony::manageAnts() +{ + // We first manage the queen + manageQueen(); + // We remove all dead workers contained in workers_ + removeDeadWorkers(); + std::cout << "-- THERE ARE " << workers_.size() << " WORKERS --\n"; + // We iterate over all workers + for (auto worker : workers_) + { + if (worker->stage_ == DevelopmentStage::ADULT) + { + /* + * Because work() is a virtual method, dynamic dispatch will be + * used. Which means that the overridden work method of the true + * type (either Nurturer or Provider) will actually be called + * instead of Worker::work(). + */ + worker->work(); + } + else + { + /* + * We increment their food_level_ as if it is a ticking time, + * EXCEPT for the larvae, as they are fed by nurturers. + */ + if (worker->stage_ != DevelopmentStage::LARVA) + worker->food_level_ += 1; + if (worker->food_level_ >= 4.0) + { + /* FIXME : Make the worker change stage_ and reset their + * food_level_ to 0. HINT : This can take only 2/3 lines if + * you use a certain C++ cast instead of a switch. + */ + worker->food_level_ = 0; + auto ant = static_cast<Ant*>(worker.get()); + ant->stage_ = static_cast<DevelopmentStage>( + static_cast<int>(ant->stage_) + 1); + } + } + } + queen_->food_level_ -= 0.2; +} + +// FIXME : Implements addAnt() static method. diff --git a/graphs/cpp/caste_or_cast/colony.hh b/graphs/cpp/caste_or_cast/colony.hh new file mode 100644 index 0000000..917ebf8 --- /dev/null +++ b/graphs/cpp/caste_or_cast/colony.hh @@ -0,0 +1,43 @@ +#pragma once + +#include <vector> + +#include "queen.hh" +#include "worker.hh" + +//! forward declarations +class Provider; +class Nurturer; + +/* + * Colony class that acts as one entity and manage all of its ants + */ +class Colony +{ +public: + //! constructor + Colony(uint32_t passport); + //! static method that adds a COPY of the given ant to the given colony + static bool addAnt(const Ant& ant, std::shared_ptr<Colony> colony); + //! manage all the ants, can be understood as one round + void manageAnts(); + //! overall cleanliness of the colony + float cleanliness = 100; + +private: + //! manage the queen (is alive etc.) + void manageQueen(); + //! remove all the dead workers of the workers_ vector + void removeDeadWorkers(); + //! attribute used to recognise if an Ant is from the same colony + uint32_t passport_pheromone_; + //! vector of all workers of the colony, each worker is stored in a + //! shared_ptr + std::vector<std::shared_ptr<Worker>> workers_; + //! unique queen, only its colony have the ownership of it. + std::unique_ptr<Queen> queen_ = nullptr; + + //! friend classes + friend class Ant; + friend class Nurturer; +}; diff --git a/graphs/cpp/caste_or_cast/main_example.cc b/graphs/cpp/caste_or_cast/main_example.cc new file mode 100644 index 0000000..9708df0 --- /dev/null +++ b/graphs/cpp/caste_or_cast/main_example.cc @@ -0,0 +1,37 @@ +#include <iostream> + +#include "colony.hh" +#include "nurturer.hh" +#include "provider.hh" + +int main() +{ + std::shared_ptr<Colony> myColony = std::make_shared<Colony>(10); + + Queen queen(myColony, DevelopmentStage::ADULT); + queen.increment_food_level_by(3.4); + + std::cout << std::boolalpha << Colony::addAnt(queen, myColony) << " "; + + // create provider with luck_ = 1.32 + Provider provider(myColony, 1.32, DevelopmentStage::ADULT); + + // create nurturer with default luck and 54.289 food_stock_ + Nurturer nurturer(myColony, DevelopmentStage::ADULT); + nurturer.increment_food_stock_by(54.289); + + // create larva with food_level_ = 3 + Provider larva(myColony, DevelopmentStage::LARVA); + larva.increment_food_level_by(3); + + std::cout << std::boolalpha << Colony::addAnt(nurturer, myColony) << " "; + std::cout << std::boolalpha << Colony::addAnt(larva, myColony) << " "; + std::cout << std::boolalpha << Colony::addAnt(provider, myColony) << '\n'; + + for (size_t i = 0; i < 8; i++) + myColony->manageAnts(); + /* + * Don't forget to test the communication methods of your ants. + */ + return 0; +} diff --git a/graphs/cpp/caste_or_cast/nurturer.cc b/graphs/cpp/caste_or_cast/nurturer.cc new file mode 100644 index 0000000..09faa79 --- /dev/null +++ b/graphs/cpp/caste_or_cast/nurturer.cc @@ -0,0 +1,98 @@ +#include "nurturer.hh" + +#include <iostream> + +// The Colony class was forward declared in Ant header +// We need to include its header here so we know Colony implementation +#include "colony.hh" +#include "provider.hh" + +void Nurturer::feedLarvae() +{ + if (food_stock_ < 0.5) + return; + size_t count = 0; + std::shared_ptr<Colony> colony = check_colony_access(); + for (auto i = colony->workers_.begin(); i < colony->workers_.end(); i++) + { + // if it doesn't have food anymore, can't feed more larvae + if (food_stock_ < 0.5) + break; + std::shared_ptr<Worker> worker = *i; + // only feed if it is a larvae and if it is not already full (its + // food_level_ => 4) + if (DevelopmentStage::LARVA == worker->get_stage() + && worker->get_food_level() < 4) + { + worker->increment_food_level_by(0.5); + food_stock_ -= 0.5; + colony->cleanliness -= 0.3; + food_level_ -= 0.03; + count++; + } + } + std::cout << count << " larvae were fed by nurturer.\n"; +} + +void Nurturer::work() +{ + if (stage_ != DevelopmentStage::ADULT) + return; + if (food_stock_ > 0.5) + { + // eat before working + food_level_ += 0.5; + food_stock_ -= 0.5; + // complete its tasks + feedLarvae(); + feedQueen(); + cleanNest(); + } + else + // make the ant more hungry + food_level_ -= 0.042; + //! call base class work() method + Worker::work(); +} +bool Nurturer::communicate(std::weak_ptr<Ant> wk_receiver) +{ + if (wk_receiver.lock() == nullptr) + return false; + if (!Ant::communicate(wk_receiver)) + return false; + std::cout << "Nurturer initiates communication.\n"; + auto p = dynamic_cast<Provider*>(wk_receiver.lock().get()); + if (p) + { + p->transferFood(*this); + } + return true; +} +void Nurturer::feedQueen() +{ + if (food_stock_ < 1) + return; + std::cout << "Feeding Queen.\n"; + auto c = check_colony_access(); + c->queen_->increment_food_level_by(1); + food_stock_--; + if (static_cast<int>(c->queen_->get_food_level()) > 0 + && static_cast<int>(c->queen_->get_food_level()) % 6 == 0) + c->queen_->layEgg(); + c->cleanliness -= .2; +} + +void Nurturer::cleanNest() +{ + std::shared_ptr<Colony> colony = check_colony_access(); + if (colony->cleanliness < 100) + { + // clean the nest according to the luck of the Nurturer + std::cout << "Cleaning nest: gained " << luck_ << " of cleanliness.\n"; + auto cleanliness = colony->cleanliness + luck_; + colony->cleanliness = (cleanliness > 100) ? 100 : cleanliness; + } +} + +// FIXME : Implements communicate(std::weak_ptr<Ant>) virtual overridden method +// and feedQueen() diff --git a/graphs/cpp/caste_or_cast/nurturer.hh b/graphs/cpp/caste_or_cast/nurturer.hh new file mode 100644 index 0000000..af7eec7 --- /dev/null +++ b/graphs/cpp/caste_or_cast/nurturer.hh @@ -0,0 +1,27 @@ +#pragma once + +#include "worker.hh" + +/* + * Nurturers worker sub-caste + */ +class Nurturer : public Worker +{ +public: + //! inherit Worker Constructors + using Worker::Worker; + //! final override of the work() Worker virtual method + void work() override final; + + /*! + * @details final override of the communicate() Ant virtual method + * @return true if the communication succeeded + * */ + bool communicate(std::weak_ptr<Ant> wk_receiver) override final; + //! feed the queen + void feedQueen(); + //! feed larvae + void feedLarvae(); + //! clean the nest / colony + void cleanNest(); +}; diff --git a/graphs/cpp/caste_or_cast/provider.cc b/graphs/cpp/caste_or_cast/provider.cc new file mode 100644 index 0000000..5767743 --- /dev/null +++ b/graphs/cpp/caste_or_cast/provider.cc @@ -0,0 +1,47 @@ +// +// Created by martial.simon on 2/26/25. +// +#include "provider.hh" + +#include <iostream> + +#include "nurturer.hh" +#include "queen.hh" +void Provider::work() +{ + if (stage_ != DevelopmentStage::ADULT) + return; + food_level_ += food_stock_ - static_cast<int>(food_stock_); + food_stock_ -= food_stock_ - static_cast<int>(food_stock_); + harvestFood(); + Worker::work(); +} +void Provider::transferFood(Nurturer& nurturer) +{ + if (food_stock_ < 1) + return; + nurturer.increment_food_stock_by(static_cast<int>(food_stock_)); + food_stock_ -= static_cast<int>(food_stock_); + std::cout << "Transferring food.\n"; +} +void Provider::harvestFood() +{ + float harvest = luck_; + std::cout << "Harvested " << harvest << " food.\n"; + food_stock_ += harvest; + food_level_ -= (harvest - static_cast<int>(harvest)) * 0.5; +} +bool Provider::communicate(std::weak_ptr<Ant> wk_receiver) +{ + if (wk_receiver.lock() == nullptr) + return false; + if (!Ant::communicate(wk_receiver)) + return false; + std::cout << "Provider initiates communication.\n"; + auto p = dynamic_cast<Nurturer*>(wk_receiver.lock().get()); + if (p) + { + transferFood(*p); + } + return true; +}
\ No newline at end of file diff --git a/graphs/cpp/caste_or_cast/provider.hh b/graphs/cpp/caste_or_cast/provider.hh new file mode 100644 index 0000000..5076585 --- /dev/null +++ b/graphs/cpp/caste_or_cast/provider.hh @@ -0,0 +1,29 @@ +#pragma once + +#include "worker.hh" + +//! forward declaration +class Nurturer; + +/* + * Provider worker sub-caste : + * harvest Food in the Outside World and transmit it to + * Nurturers ants + */ +class Provider : public Worker +{ +public: + //! inherit Worker Constructors + using Worker::Worker; + //! final override of the work() Worker virtual method + void work() override final; + //! transfer food to Nurturer workers only + void transferFood(Nurturer& nurturer); + /*! + * @details final override of the communicate() Ant virtual method + * @return true if the communication succeeded + * */ + bool communicate(std::weak_ptr<Ant> wk_receiver) override final; + //! go to the outside world and harvest food + void harvestFood(); +}; diff --git a/graphs/cpp/caste_or_cast/queen.cc b/graphs/cpp/caste_or_cast/queen.cc new file mode 100644 index 0000000..d1a998f --- /dev/null +++ b/graphs/cpp/caste_or_cast/queen.cc @@ -0,0 +1,30 @@ +#include "queen.hh" + +#include <iostream> + +#include "colony.hh" +#include "nurturer.hh" +#include "provider.hh" + +void Queen::layEgg() +{ + std::cout << "Queen is laying an Egg.\n"; + // if the queen tries to lay an egg without enough food_level + // it loses a health point + if (food_level_ < 0) + hp_ -= 1; + // checking if the colony_ attribute is not expired + std::shared_ptr<Colony> colony = check_colony_access(); + // either create a new Provider or a new Nurturer + static bool choose = false; + if (choose) + eggs_queue_.emplace(std::make_shared<Provider>( + colony, food_level_ * 0.5 + 0.2, DevelopmentStage::EGG)); + else + eggs_queue_.emplace(std::make_shared<Nurturer>( + colony, food_level_ * 0.1 + 0.13, DevelopmentStage::EGG)); + choose = !choose; + // consequences of laying an egg + colony->cleanliness -= 0.6; + food_level_ -= 5.7; +} diff --git a/graphs/cpp/caste_or_cast/queen.hh b/graphs/cpp/caste_or_cast/queen.hh new file mode 100644 index 0000000..9192f4c --- /dev/null +++ b/graphs/cpp/caste_or_cast/queen.hh @@ -0,0 +1,32 @@ +#pragma once + +#include <queue> + +#include "ant.hh" + +//! forward declaration +class Worker; + +/* + * Class representing the Queen Caste + */ +class Queen : public Ant +{ +public: + //! inherit Ant Constructors + using Ant::Ant; + //! the queen will create either a new Provider or Nurturer and push it to + //! eggs_queue_ + void layEgg(); + +private: + /*! + * We should not modify the Colony::workers vector while we + * iterate over it (because in some cases it can lead to undefined behavior) + * To solve this problem, we use a queue so we can save the eggs that the + * queen lay in one round (i.e. one call of Colony::manageAnts) and insert + * them in workers_ vector after we finished iterating. + * */ + std::queue<std::shared_ptr<Worker>> eggs_queue_; + friend class Colony; +}; diff --git a/graphs/cpp/caste_or_cast/worker.cc b/graphs/cpp/caste_or_cast/worker.cc new file mode 100644 index 0000000..e5cb532 --- /dev/null +++ b/graphs/cpp/caste_or_cast/worker.cc @@ -0,0 +1,28 @@ +#include "worker.hh" + +Worker::Worker(std::shared_ptr<Colony> colony, float luck, + DevelopmentStage stage) + : Ant(colony, stage) + , luck_(luck) +{} + +void Worker::work() +{ + if (food_level_ < 0) + hp_ -= 0.5; +} + +float Worker::get_luck() const +{ + return luck_; +} + +float Worker::get_food_stock() const +{ + return food_stock_; +} + +void Worker::increment_food_stock_by(float value) +{ + food_stock_ += value; +} diff --git a/graphs/cpp/caste_or_cast/worker.hh b/graphs/cpp/caste_or_cast/worker.hh new file mode 100644 index 0000000..cb8c5ef --- /dev/null +++ b/graphs/cpp/caste_or_cast/worker.hh @@ -0,0 +1,30 @@ +#pragma once + +#include "ant.hh" + +/* + * Class representing the generic Worker Caste + */ +class Worker : public Ant +{ +public: + //! inherit Ant constructors + using Ant::Ant; + //! constructor + Worker(std::shared_ptr<Colony> colony, float luck, + DevelopmentStage stage = DevelopmentStage::EGG); + //! the Worker will do all of its tasks + virtual void work(); + //! getter for food_stock_ + float get_food_stock() const; + //! add given value to food_stock_ + void increment_food_stock_by(float value); + //! return the luck of the worker + float get_luck() const; + +protected: + //! current food that the worker store on her. + float food_stock_ = 0.0; + //! luck of the worker + float luck_ = 3.141592; +}; diff --git a/graphs/cpp/chain_of_responsibility/director.cc b/graphs/cpp/chain_of_responsibility/director.cc new file mode 100644 index 0000000..af4072f --- /dev/null +++ b/graphs/cpp/chain_of_responsibility/director.cc @@ -0,0 +1,10 @@ +#include "director.hh" + +#include <iostream> +void Director::handle_request(int level) +{ + if (level <= 3) + std::cout << "Director handles\n"; + else + forward_request(level); +}
\ No newline at end of file diff --git a/graphs/cpp/chain_of_responsibility/handler.cc b/graphs/cpp/chain_of_responsibility/handler.cc new file mode 100644 index 0000000..256933b --- /dev/null +++ b/graphs/cpp/chain_of_responsibility/handler.cc @@ -0,0 +1,19 @@ +#include "handler.hh" + +#include <iostream> +Handler::Handler(Handler* next) + : next_{ next } +{} +void Handler::set_successor(Handler* h) +{ + next_ = h; +} +void Handler::forward_request(int level) +{ + if (next_ == nullptr) + { + std::cout << "Nobody can handle this request\n"; + } + else + next_->handle_request(level); +}
\ No newline at end of file diff --git a/graphs/cpp/chain_of_responsibility/president.cc b/graphs/cpp/chain_of_responsibility/president.cc new file mode 100644 index 0000000..9ee0566 --- /dev/null +++ b/graphs/cpp/chain_of_responsibility/president.cc @@ -0,0 +1,10 @@ +#include "president.hh" + +#include <iostream> +void President::handle_request(int level) +{ + if (level <= 9) + std::cout << "President handles\n"; + else + forward_request(level); +}
\ No newline at end of file diff --git a/graphs/cpp/chain_of_responsibility/vice_president.cc b/graphs/cpp/chain_of_responsibility/vice_president.cc new file mode 100644 index 0000000..0316d63 --- /dev/null +++ b/graphs/cpp/chain_of_responsibility/vice_president.cc @@ -0,0 +1,10 @@ +#include "vice_president.hh" + +#include <iostream> +void VicePresident::handle_request(int level) +{ + if (level <= 6) + std::cout << "VicePresident handles\n"; + else + forward_request(level); +}
\ No newline at end of file diff --git a/graphs/cpp/closer_to/closer_to.cc b/graphs/cpp/closer_to/closer_to.cc new file mode 100644 index 0000000..779d3b5 --- /dev/null +++ b/graphs/cpp/closer_to/closer_to.cc @@ -0,0 +1,15 @@ +// +// Created by martial.simon on 2/25/25. +// +#include "closer_to.hh" +CloserTo::CloserTo(int i) + : i_{ i } +{} +bool CloserTo::operator()(int a, int b) const +{ + const int da = a - i_ >= 0 ? a - i_ : i_ - a; + const int db = b - i_ >= 0 ? b - i_ : i_ - b; + if (da == db) + return a < b; + return da < db; +}
\ No newline at end of file diff --git a/graphs/cpp/closer_to/closer_to.hh b/graphs/cpp/closer_to/closer_to.hh new file mode 100644 index 0000000..a2462ca --- /dev/null +++ b/graphs/cpp/closer_to/closer_to.hh @@ -0,0 +1,11 @@ +#pragma once + +struct CloserTo +{ + CloserTo(int i); + + bool operator()(int a, int b) const; + +private: + int i_; +}; diff --git a/graphs/cpp/closer_to/closer_to_test.cc b/graphs/cpp/closer_to/closer_to_test.cc new file mode 100644 index 0000000..0edfd5e --- /dev/null +++ b/graphs/cpp/closer_to/closer_to_test.cc @@ -0,0 +1,29 @@ +#include <algorithm> +#include <iostream> +#include <vector> + +#include "closer_to.hh" + +void print_elt(int i) +{ + std::cout << ' ' << i; +} + +int main() +{ + auto v = std::vector<int>{ 1, 2, 3, 4, 5 }; + + std::cout << "Unsorted vector:"; + std::for_each(v.begin(), v.end(), print_elt); + std::cout << '\n'; + + auto n = 3; + + std::sort(v.begin(), v.end(), CloserTo(n)); + + std::cout << "Sorted vector closed to " << n << ':'; + std::for_each(v.begin(), v.end(), print_elt); + std::cout << '\n'; + + return 0; +} diff --git a/graphs/cpp/const-td/CMakeLists.txt b/graphs/cpp/const-td/CMakeLists.txt new file mode 100644 index 0000000..cbda23e --- /dev/null +++ b/graphs/cpp/const-td/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.30) +project(const) + +set(CMAKE_CXX_STANDARD 20) + +add_executable(const main.cc) diff --git a/graphs/cpp/const-td/main.cc b/graphs/cpp/const-td/main.cc new file mode 100644 index 0000000..0368d13 --- /dev/null +++ b/graphs/cpp/const-td/main.cc @@ -0,0 +1,25 @@ +#include <iostream> + +std::string ohio_sigma(const std::string& name) +{ + return "Hello, " + name + "!"; +} + +size_t skibidi(std::string& name) +{ + name = "Hello, " + name + "!"; + return name.length(); +} + +void strlen(const std::string& str, size_t* len) +{} + +int main() +{ + auto name = "Martial"; + std::cout << ohio_sigma(name); + auto new_name = std::string("Martial"); + std::cout << "String length: " << skibidi(new_name) + << "\tNew string: " << new_name << "\n"; + return 0; +} diff --git a/graphs/cpp/const/CMakeLists.txt b/graphs/cpp/const/CMakeLists.txt new file mode 100644 index 0000000..800759f --- /dev/null +++ b/graphs/cpp/const/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.21.2) +project(const) + +add_compile_options(-Wall -Wextra -Werror -pedantic -std=c++20 -Wold-style-cast) + +add_executable(const test_person.cc person.cc)
\ No newline at end of file diff --git a/graphs/cpp/const/person.cc b/graphs/cpp/const/person.cc new file mode 100644 index 0000000..63e8d73 --- /dev/null +++ b/graphs/cpp/const/person.cc @@ -0,0 +1,25 @@ +// +// Created by martial.simon on 2/24/25. +// +#include "person.hh" + +Person::Person(const std::string& name, const unsigned int age) + : name_{ name } + , age_{ age } +{} +std::string Person::get_name() const +{ + return name_; +} +unsigned int Person::get_age() const +{ + return age_; +} +void Person::set_name(const std::string& name) +{ + name_ = name; +} +void Person::set_age(const unsigned int age) +{ + age_ = age; +} diff --git a/graphs/cpp/const/person.hh b/graphs/cpp/const/person.hh new file mode 100644 index 0000000..0b44308 --- /dev/null +++ b/graphs/cpp/const/person.hh @@ -0,0 +1,17 @@ +#pragma once + +#include <string> + +class Person +{ +public: + Person(const std::string& name, const unsigned int age); + std::string get_name() const; + unsigned int get_age() const; + void set_name(const std::string& name); + void set_age(unsigned int age); + +private: + std::string name_; + unsigned int age_; +}; diff --git a/graphs/cpp/const/test_person.cc b/graphs/cpp/const/test_person.cc new file mode 100644 index 0000000..f59286e --- /dev/null +++ b/graphs/cpp/const/test_person.cc @@ -0,0 +1,20 @@ +#include <iostream> + +#include "person.hh" + +int main() +{ + Person my_person("Gordon Freeman", 47); + + const Person& my_person2 = my_person; + + std::cout << "name: " << my_person2.get_name() + << ", years: " << my_person2.get_age() << std::endl; + + std::string name = "Alyx Vance"; + my_person.set_name(name); + my_person.set_age(24); + + std::cout << "name: " << my_person2.get_name() + << ", years: " << my_person2.get_age() << std::endl; +} diff --git a/graphs/cpp/directories_infos/directory_info.cc b/graphs/cpp/directories_infos/directory_info.cc new file mode 100644 index 0000000..2c28150 --- /dev/null +++ b/graphs/cpp/directories_infos/directory_info.cc @@ -0,0 +1,34 @@ +// +// Created by martial.simon on 2/24/25. +// +#include "directory_info.hh" + +DirectoryInfo::DirectoryInfo(const std::string& name, size_t size, + uint16_t rights, const std::string& owner) + : name_{ name } + , size_{ size } + , rights_{ rights } + , owner_{ owner } +{ + is_valid_ = true; +} +const std::string& DirectoryInfo::get_name() const +{ + return name_; +} +const std::string& DirectoryInfo::get_owner() const +{ + return owner_; +} +size_t DirectoryInfo::get_size() const +{ + return size_; +} +uint16_t DirectoryInfo::get_rights() const +{ + return rights_; +} +bool DirectoryInfo::is_valid() const +{ + return is_valid_; +} diff --git a/graphs/cpp/directories_infos/directory_info.hh b/graphs/cpp/directories_infos/directory_info.hh new file mode 100644 index 0000000..eaf7c62 --- /dev/null +++ b/graphs/cpp/directories_infos/directory_info.hh @@ -0,0 +1,24 @@ +#pragma once + +#include <cstdint> +#include <string> + +class DirectoryInfo +{ +public: + DirectoryInfo() = default; + DirectoryInfo(const std::string& name, size_t size, uint16_t rights, + const std::string& owner); + const std::string& get_name() const; + const std::string& get_owner() const; + size_t get_size() const; + uint16_t get_rights() const; + bool is_valid() const; + +private: + std::string name_; + size_t size_; + uint16_t rights_; + std::string owner_; + bool is_valid_ = false; +}; diff --git a/graphs/cpp/directories_infos/main_example.cc b/graphs/cpp/directories_infos/main_example.cc new file mode 100644 index 0000000..db4bfa0 --- /dev/null +++ b/graphs/cpp/directories_infos/main_example.cc @@ -0,0 +1,32 @@ +#include <fstream> +#include <iomanip> +#include <iostream> + +#include "directory_info.hh" +#include "read_info.hh" + +int main(int argc, char** argv) +{ + if (argc < 2) + return 1; + + auto file = std::ifstream(argv[1]); + + DirectoryInfo dir_info; + + while ((dir_info = read_info(file)).is_valid()) + { + std::stringstream str_stream; + str_stream << dir_info.get_name() << ' ' << dir_info.get_size() << ' ' + << std::oct << dir_info.get_rights() << std::dec << ' ' + << dir_info.get_owner() << '\n'; + + dir_info = read_info(str_stream); + if (!dir_info.is_valid()) + break; + + std::cout << dir_info.get_name() << '|' << dir_info.get_size() << '|' + << std::oct << dir_info.get_rights() << std::dec << '|' + << dir_info.get_owner() << '\n'; + } +} diff --git a/graphs/cpp/directories_infos/read_info.cc b/graphs/cpp/directories_infos/read_info.cc new file mode 100644 index 0000000..327d004 --- /dev/null +++ b/graphs/cpp/directories_infos/read_info.cc @@ -0,0 +1,39 @@ +#include "read_info.hh" + +#include <sstream> + +#include "directory_info.hh" + +DirectoryInfo read_info(std::istream& stream) +{ + if (stream.eof()) + { + return DirectoryInfo{}; + } + std::string l; + std::getline(stream, l); + std::istringstream line{ l }; + std::string name; + size_t size; + uint16_t rights; + std::string owner; + if (!(line >> name)) + { + return DirectoryInfo{}; + } + if (!(line >> size)) + { + return DirectoryInfo{}; + } + if (!(line >> std::oct >> rights >> std::dec)) + { + return DirectoryInfo{}; + } + if (!(line >> owner)) + { + return DirectoryInfo{}; + } + if (line.eof()) + return DirectoryInfo{ name, size, rights, owner }; + return DirectoryInfo{}; +}
\ No newline at end of file diff --git a/graphs/cpp/directories_infos/read_info.hh b/graphs/cpp/directories_infos/read_info.hh new file mode 100644 index 0000000..72f64b4 --- /dev/null +++ b/graphs/cpp/directories_infos/read_info.hh @@ -0,0 +1,7 @@ +#pragma once +#include <iostream> + +#include "directory_info.hh" + +// use ref to istream +DirectoryInfo read_info(std::istream& stream);
\ No newline at end of file diff --git a/graphs/cpp/doubly_linked_list/CMakeLists.txt b/graphs/cpp/doubly_linked_list/CMakeLists.txt new file mode 100644 index 0000000..37204f6 --- /dev/null +++ b/graphs/cpp/doubly_linked_list/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.21.2) +project(doubly_linked_list) + +add_library(doubly_linked_list SHARED node.cc list.cc) +target_compile_options(doubly_linked_list PRIVATE -Wall -Wextra -Werror -pedantic -std=c++20 -Wold-style-cast) +set_target_properties(doubly_linked_list PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF)
\ No newline at end of file diff --git a/graphs/cpp/doubly_linked_list/list.cc b/graphs/cpp/doubly_linked_list/list.cc new file mode 100644 index 0000000..36cf5ad --- /dev/null +++ b/graphs/cpp/doubly_linked_list/list.cc @@ -0,0 +1,88 @@ +#include "list.hh" +List::List() + : nb_elts_{ 0 } +{} +void List::push_front(int i) +{ + nb_elts_++; + if (nb_elts_ == 1) + { + first_ = std::make_shared<Node>(i); + last_ = first_; + return; + } + std::shared_ptr<Node> ns = std::make_shared<Node>(i); + ns->set_next(first_); + first_->set_prev(ns); + first_ = ns; +} +std::optional<int> List::pop_front() +{ + if (nb_elts_ == 0) + { + return std::nullopt; + } + nb_elts_--; + int res = first_->get_val(); + if (nb_elts_ == 0) + { + first_ = nullptr; + last_ = nullptr; + return res; + } + std::shared_ptr<Node> tmp = first_->get_next(); + first_->set_next(nullptr); + tmp->set_prev(nullptr); + first_ = tmp; + return res; +} +void List::push_back(int i) +{ + nb_elts_++; + if (nb_elts_ == 1) + { + first_ = std::make_shared<Node>(i); + last_ = first_; + return; + } + std::shared_ptr<Node> ns = std::make_shared<Node>(i); + ns->set_prev(last_); + last_->set_next(ns); + last_ = ns; +} +std::optional<int> List::pop_back() +{ + if (nb_elts_ == 0) + { + return std::nullopt; + } + nb_elts_--; + int res = last_->get_val(); + if (nb_elts_ == 0) + { + first_ = nullptr; + last_ = nullptr; + return res; + } + std::shared_ptr<Node> tmp = last_->get_prev(); + last_->set_prev(nullptr); + tmp->set_next(nullptr); + last_ = tmp; + return res; +} +void List::print(std::ostream& os) const +{ + if (nb_elts_ == 0) + return; + os << first_->get_val(); + for (Node* node = first_->get_next().get(); node; + node = node->get_next().get()) + { + os << " " << node->get_val(); + } + // os << "\n"; +} +size_t List::length() const +{ + return nb_elts_; +}
\ No newline at end of file diff --git a/graphs/cpp/doubly_linked_list/list.hh b/graphs/cpp/doubly_linked_list/list.hh new file mode 100644 index 0000000..50f71c6 --- /dev/null +++ b/graphs/cpp/doubly_linked_list/list.hh @@ -0,0 +1,24 @@ +#pragma once + +#include <optional> +#include <ostream> + +#include "node.hh" + +class List +{ +public: + List(); + + void push_front(int i); + void push_back(int i); + std::optional<int> pop_front(); + std::optional<int> pop_back(); + void print(std::ostream& os) const; + size_t length() const; + +private: + size_t nb_elts_; + std::shared_ptr<Node> first_; + std::shared_ptr<Node> last_; +}; diff --git a/graphs/cpp/doubly_linked_list/main.cc b/graphs/cpp/doubly_linked_list/main.cc new file mode 100644 index 0000000..cd9ab32 --- /dev/null +++ b/graphs/cpp/doubly_linked_list/main.cc @@ -0,0 +1,36 @@ +#include <iostream> + +#include "list.hh" + +int main() +{ + List l = List(); + l.print(std::cout); + std::cout << '\n'; + + l.push_back(13); + l.print(std::cout); + std::cout << '\n'; + + l.push_front(5); + l.print(std::cout); + std::cout << '\n'; + + l.push_back(42); + l.print(std::cout); + std::cout << '\n'; + + l.pop_back(); + l.print(std::cout); + std::cout << '\n'; + + l.push_back(42); + l.print(std::cout); + std::cout << '\n'; + + l.pop_front(); + l.print(std::cout); + std::cout << '\n'; + + std::cout << "Nb elts: " << l.length() << '\n'; +} diff --git a/graphs/cpp/doubly_linked_list/node.cc b/graphs/cpp/doubly_linked_list/node.cc new file mode 100644 index 0000000..b6db962 --- /dev/null +++ b/graphs/cpp/doubly_linked_list/node.cc @@ -0,0 +1,29 @@ +#include "node.hh" + +Node::Node(int v) + : val_{ v } +{} +int Node::get_val() const +{ + return val_; +} +void Node::set_val(int val) +{ + val_ = val; +} +std::shared_ptr<Node> Node::get_next() const +{ + return next_; +} +void Node::set_next(std::shared_ptr<Node> next) +{ + next_ = next; +} +std::shared_ptr<Node> Node::get_prev() const +{ + return prev_.lock(); +} +void Node::set_prev(std::shared_ptr<Node> prev) +{ + prev_ = prev; +}
\ No newline at end of file diff --git a/graphs/cpp/doubly_linked_list/node.hh b/graphs/cpp/doubly_linked_list/node.hh new file mode 100644 index 0000000..9eb2e50 --- /dev/null +++ b/graphs/cpp/doubly_linked_list/node.hh @@ -0,0 +1,23 @@ +#pragma once + +#include <memory> + +class Node +{ +public: + Node(int v); + + int get_val() const; + void set_val(int val); + + std::shared_ptr<Node> get_next() const; + void set_next(std::shared_ptr<Node> next); + + std::shared_ptr<Node> get_prev() const; + void set_prev(std::shared_ptr<Node> prev); + +private: + int val_; + std::shared_ptr<Node> next_; + std::weak_ptr<Node> prev_; +}; diff --git a/graphs/cpp/exception/Makefile b/graphs/cpp/exception/Makefile new file mode 100644 index 0000000..01107c5 --- /dev/null +++ b/graphs/cpp/exception/Makefile @@ -0,0 +1,14 @@ +CC=g++ +CXXFLAGS= -Wall -Wextra -Werror -std=c++20 -pedantic -Wold-style-cast + +OBJS= main.o game.o player.o invalid_argument.o +BIN= main + +all: ${BIN} + +${BIN}: ${OBJS} + +clean: + ${RM} ${OBJS} ${BIN} + +.PHONY: clean all diff --git a/graphs/cpp/exception/game.cc b/graphs/cpp/exception/game.cc new file mode 100644 index 0000000..88d435c --- /dev/null +++ b/graphs/cpp/exception/game.cc @@ -0,0 +1,23 @@ +#include "game.hh" + +#include <iostream> + +Game::Game(int secret) + : secret_(secret) +{} + +void Game::play(const Player& p1, const Player& p2) const +{ + if (p1 == p2) + throw InvalidArgumentException{ "Stop playing by yourself!" }; + + auto d1 = std::abs(p1.get_guess() - secret_); + auto d2 = std::abs(p2.get_guess() - secret_); + + if (d1 > d2) + std::cout << p1 << " wins!" << std::endl; + else if (d1 < d2) + std::cout << p2 << " wins!" << std::endl; + else + std::cout << "Draw!" << std::endl; +} diff --git a/graphs/cpp/exception/game.hh b/graphs/cpp/exception/game.hh new file mode 100644 index 0000000..e162bda --- /dev/null +++ b/graphs/cpp/exception/game.hh @@ -0,0 +1,14 @@ +#pragma once + +#include "invalid_argument.hh" +#include "player.hh" + +class Game +{ +public: + Game(int secret); + void play(const Player& p1, const Player& p2) const; + +private: + int secret_; +}; diff --git a/graphs/cpp/exception/invalid_argument.cc b/graphs/cpp/exception/invalid_argument.cc new file mode 100644 index 0000000..aafa4e3 --- /dev/null +++ b/graphs/cpp/exception/invalid_argument.cc @@ -0,0 +1,9 @@ +#include "invalid_argument.hh" + +InvalidArgumentException::InvalidArgumentException(const std::string& msg) + : msg_{ msg } +{} +const char* InvalidArgumentException::what() const noexcept +{ + return msg_.c_str(); +}
\ No newline at end of file diff --git a/graphs/cpp/exception/invalid_argument.hh b/graphs/cpp/exception/invalid_argument.hh new file mode 100644 index 0000000..25356df --- /dev/null +++ b/graphs/cpp/exception/invalid_argument.hh @@ -0,0 +1,15 @@ +#pragma once + +#include <exception> +#include <string> + +class InvalidArgumentException : public std::exception +{ +public: + InvalidArgumentException(const std::string& msg); + + virtual const char* what() const noexcept; + +private: + std::string msg_; +}; diff --git a/graphs/cpp/exception/main.cc b/graphs/cpp/exception/main.cc new file mode 100644 index 0000000..7881a4c --- /dev/null +++ b/graphs/cpp/exception/main.cc @@ -0,0 +1,80 @@ +#include <iostream> + +#include "game.hh" +#include "invalid_argument.hh" +#include "player.hh" + +int main() +{ + Game g(42); + std::string n1 = "Toto"; + std::string n2 = "Frodo"; + std::string n3 = "Feanor"; + std::string n4 = "Pikachu"; + std::string n5 = "Baby"; + std::string n6 = ""; + + try + { + Player p1 = Player(n1, 9, 3); + } + catch (InvalidArgumentException& e) + { + std::cout << e.what() << std::endl; + } + try + { + Player p2 = Player(n2, 51, 5); + } + catch (InvalidArgumentException& e) + { + std::cout << e.what() << std::endl; + } + try + { + Player p3 = Player(n3, 3142, 42); + } + catch (InvalidArgumentException& e) + { + std::cout << e.what() << std::endl; + } + try + { + Player p4 = Player(n4, 25, 5000); + } + catch (InvalidArgumentException& e) + { + std::cout << e.what() << std::endl; + } + try + { + Player p5 = Player(n5, -1, 1); + } + catch (InvalidArgumentException& e) + { + std::cout << e.what() << std::endl; + } + try + { + Player p6 = Player(n6, 19, 1); + } + catch (InvalidArgumentException& e) + { + std::cout << e.what() << std::endl; + } + + try + { + Player p1 = Player(n1, 9, 3); + Player p2 = Player(n2, 51, -18); + g.play(p1, p1); + } + catch (InvalidArgumentException& e) + { + std::cout << e.what() << std::endl; + } + + Player p1 = Player(n1, 9, 3); + Player p2 = Player(n2, 51, -18); + g.play(p1, p2); +} diff --git a/graphs/cpp/exception/player.cc b/graphs/cpp/exception/player.cc new file mode 100644 index 0000000..4a0b378 --- /dev/null +++ b/graphs/cpp/exception/player.cc @@ -0,0 +1,34 @@ +#include "player.hh" + +Player::Player(const std::string& name, int age, int guess) + : name_(name) + , age_(age) + , guess_(guess) +{ + if (name.empty()) + throw InvalidArgumentException{ "Name can't be empty." }; + if (age < 0) + throw InvalidArgumentException{ + "Well, it seems you are not born yet." + }; + if (age > 150) + throw InvalidArgumentException{ "Sorry gramp, too old to play." }; +} + +int Player::get_guess() const +{ + return guess_; +} +bool Player::operator==(const Player& p) const +{ + return this == &p; +} +bool Player::operator!=(const Player& p) const +{ + return this != &p; +} + +std::ostream& operator<<(std::ostream& os, const Player& p) +{ + return os << p.name_ << '(' << p.age_ << ')'; +} diff --git a/graphs/cpp/exception/player.hh b/graphs/cpp/exception/player.hh new file mode 100644 index 0000000..3ee8060 --- /dev/null +++ b/graphs/cpp/exception/player.hh @@ -0,0 +1,26 @@ +#pragma once + +#include <iostream> + +#include "invalid_argument.hh" + +class Player +{ +public: + Player(const std::string& name, int age, int guess); + + int get_guess() const; + + friend std::ostream& operator<<(std::ostream& os, const Player& b); + + bool operator==(const Player& p) const; + bool operator!=(const Player& p) const; + +private: + std::string name_; + int age_; + + int guess_; +}; + +std::ostream& operator<<(std::ostream& os, const Player& p); diff --git a/graphs/cpp/exist_functor/example.cc b/graphs/cpp/exist_functor/example.cc new file mode 100644 index 0000000..d580f7b --- /dev/null +++ b/graphs/cpp/exist_functor/example.cc @@ -0,0 +1,24 @@ +#include <iostream> + +#include "exist.hh" + +int main() +{ + Exist<int> exist_int; + Exist<std::string> exist_str; + + // Test with integers + std::cout << std::boolalpha; + std::cout << exist_int(1) << std::endl; // Prints false + std::cout << exist_int(2) << std::endl; // Prints false + std::cout << exist_int(1) << std::endl; // Prints true + std::cout << exist_int(3) << std::endl; // Prints false + + // Test with strings + std::cout << exist_str(std::string("Hello")) << std::endl; // Prints false + std::cout << exist_str(std::string("World")) << std::endl; // Prints false + std::cout << exist_str(std::string("Hello")) << std::endl; // Prints true + std::cout << exist_str(std::string("C++")) << std::endl; // Prints false + + return 0; +} diff --git a/graphs/cpp/exist_functor/exist.hh b/graphs/cpp/exist_functor/exist.hh new file mode 100644 index 0000000..49cafd6 --- /dev/null +++ b/graphs/cpp/exist_functor/exist.hh @@ -0,0 +1,14 @@ +#pragma once +#include <vector> + +template <class T> +class Exist +{ +public: + bool operator()(T x); + +private: + std::vector<T> seen_; +}; + +#include "exist.hxx" diff --git a/graphs/cpp/exist_functor/exist.hxx b/graphs/cpp/exist_functor/exist.hxx new file mode 100644 index 0000000..638c4e3 --- /dev/null +++ b/graphs/cpp/exist_functor/exist.hxx @@ -0,0 +1,15 @@ +#pragma once +#include <algorithm> + +#include "exist.hh" + +template <class T> +bool Exist<T>::operator()(T x) +{ + if (std::find(seen_.begin(), seen_.end(), x) == seen_.end()) + { + seen_.push_back(x); + return false; + } + return true; +}
\ No newline at end of file diff --git a/graphs/cpp/for_each/for_each.hh b/graphs/cpp/for_each/for_each.hh new file mode 100644 index 0000000..195c3c6 --- /dev/null +++ b/graphs/cpp/for_each/for_each.hh @@ -0,0 +1,6 @@ +#pragma once + +template <class IT, class F> +void my_foreach(IT begin, IT end, auto fun); + +#include "for_each.hxx"
\ No newline at end of file diff --git a/graphs/cpp/for_each/for_each.hxx b/graphs/cpp/for_each/for_each.hxx new file mode 100644 index 0000000..dcfa0fa --- /dev/null +++ b/graphs/cpp/for_each/for_each.hxx @@ -0,0 +1,9 @@ +#pragma once +#include "for_each.hh" + +template <class IT, class F> +void my_foreach(IT begin, IT end, F fun) +{ + for (; begin != end; ++begin) + fun(*begin); +}
\ No newline at end of file diff --git a/graphs/cpp/for_each/main.cc b/graphs/cpp/for_each/main.cc new file mode 100644 index 0000000..08da792 --- /dev/null +++ b/graphs/cpp/for_each/main.cc @@ -0,0 +1,10 @@ +#include <iostream> + +#include "for_each.hh" + +int main() +{ + auto v = { 'M', 'y', 'S', 'T', 'L', '\n' }; + + my_foreach(v.begin(), v.end(), [](auto c) { std::cout << c; }); +} diff --git a/graphs/cpp/forward_multiplication/forward_multiplication.cc b/graphs/cpp/forward_multiplication/forward_multiplication.cc new file mode 100644 index 0000000..72abc91 --- /dev/null +++ b/graphs/cpp/forward_multiplication/forward_multiplication.cc @@ -0,0 +1,7 @@ +#include "forward_multiplication.hh" +// +// Created by martial.simon on 2/26/25. +// +outer_lambda_type mult_by = [](int val) { + return [val](int mul) { return val * mul; }; +};
\ No newline at end of file diff --git a/graphs/cpp/forward_multiplication/forward_multiplication.hh b/graphs/cpp/forward_multiplication/forward_multiplication.hh new file mode 100644 index 0000000..9cca5e6 --- /dev/null +++ b/graphs/cpp/forward_multiplication/forward_multiplication.hh @@ -0,0 +1,7 @@ +#pragma once + +#include <functional> + +using inner_lambda_type = const std::function<int(int rhs)>; +using outer_lambda_type = const std::function<inner_lambda_type(int lhs)>; +extern outer_lambda_type mult_by; diff --git a/graphs/cpp/forward_multiplication/forward_multiplication_test.cc b/graphs/cpp/forward_multiplication/forward_multiplication_test.cc new file mode 100644 index 0000000..21be1a6 --- /dev/null +++ b/graphs/cpp/forward_multiplication/forward_multiplication_test.cc @@ -0,0 +1,21 @@ +#include <iostream> +#include <string> + +#include "forward_multiplication.hh" + +int main(int argc, char** argv) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] << " 'number' 'number'" << std::endl; + return 1; + } + + auto lhs = std::stoi(argv[1]); + auto rhs = std::stoi(argv[2]); + + auto mult_by_lhs = mult_by(lhs); + + std::cout << mult_by(lhs)(rhs) << '\n'; + std::cout << mult_by_lhs(rhs) << std::endl; +} diff --git a/graphs/cpp/hello_world/hello_world.cc b/graphs/cpp/hello_world/hello_world.cc new file mode 100644 index 0000000..f3ac0cf --- /dev/null +++ b/graphs/cpp/hello_world/hello_world.cc @@ -0,0 +1,6 @@ +#include <iostream> +int main() +{ + std::cout << "Hello World!\n"; + return 0; +}
\ No newline at end of file diff --git a/graphs/cpp/hot_potato/bomb.cc b/graphs/cpp/hot_potato/bomb.cc new file mode 100644 index 0000000..256e3d7 --- /dev/null +++ b/graphs/cpp/hot_potato/bomb.cc @@ -0,0 +1,28 @@ +#include "bomb.hh" + +#include <iostream> +#include <stdexcept> + +Bomb::Bomb(int ticks) +{ + if (ticks <= 0) + throw std::runtime_error{ + "Number of ticks should be strictly positive" + }; + max_ticks_ = ticks; + count_ = 0; +} +void Bomb::tick() +{ + if (count_ >= max_ticks_) + throw std::runtime_error{ "Bomb should have already exploded." }; + if (count_ % 2) + std::cout << "Tac!\n"; + else + std::cout << "Tic!\n"; + count_++; +} +bool Bomb::has_exploded() const +{ + return count_ >= max_ticks_; +}
\ No newline at end of file diff --git a/graphs/cpp/hot_potato/bomb.hh b/graphs/cpp/hot_potato/bomb.hh new file mode 100644 index 0000000..41e0bd3 --- /dev/null +++ b/graphs/cpp/hot_potato/bomb.hh @@ -0,0 +1,11 @@ +#pragma once + +class Bomb { +public: + Bomb(int ticks); + void tick(); + bool has_exploded() const; +private: + int max_ticks_; + int count_; +};
\ No newline at end of file diff --git a/graphs/cpp/hot_potato/game.cc b/graphs/cpp/hot_potato/game.cc new file mode 100644 index 0000000..3e0889a --- /dev/null +++ b/graphs/cpp/hot_potato/game.cc @@ -0,0 +1,48 @@ +// +// Created by martial.simon on 2/25/25. +// + +#include "game.hh" + +#include <iostream> +#include <stdexcept> +void Game::add_player(const std::string& name, size_t nb_presses) +{ + auto new_player = std::make_unique<Player>(name, nb_presses); + if (head_ == nullptr) + { + head_ = std::move(new_player); + tail_ = head_.get(); + } + else + { + tail_->set_next(std::move(new_player)); + tail_ = tail_->get_next(); + } +} +void Game::play(int bomb_ticks) +{ + if (!head_ || !head_->get_next()) + throw std::runtime_error{ "Not enough players." }; + head_->set_bomb(std::make_unique<Bomb>(bomb_ticks)); + Player* p = head_.get(); + while (true) + { + p->press_bomb(); + if (p->is_dead()) + { + std::cout << p->get_name() << " has exploded.\n"; + return; + } + if (p == tail_) + { + p->pass_bomb(*head_); + p = head_.get(); + } + else + { + p->pass_bomb(*p->get_next()); + p = p->get_next(); + } + } +}
\ No newline at end of file diff --git a/graphs/cpp/hot_potato/game.hh b/graphs/cpp/hot_potato/game.hh new file mode 100644 index 0000000..fd65b28 --- /dev/null +++ b/graphs/cpp/hot_potato/game.hh @@ -0,0 +1,17 @@ +// +// Created by martial.simon on 2/25/25. +// + +#pragma once +#include <memory> + +#include "player.hh" + +class Game { +public: + void add_player(const std::string& name, size_t nb_presses); + void play(int bomb_ticks); +private: + std::unique_ptr<Player> head_; + Player* tail_ = nullptr; +}; diff --git a/graphs/cpp/hot_potato/main.cc b/graphs/cpp/hot_potato/main.cc new file mode 100644 index 0000000..ce491d0 --- /dev/null +++ b/graphs/cpp/hot_potato/main.cc @@ -0,0 +1,20 @@ +// +// Created by martial.simon on 2/25/25. +// +#include "game.hh" +int main() +{ + auto game = Game(); + game.add_player("Benjamin", 2); + game.add_player("Andy", 1); + game.add_player("Geoffrey", 3); + game.add_player("Hugo", 1); + game.add_player("Maayane", 2); + game.add_player("Quentin", 1); + game.add_player("Lucas", 5); // Likes risks + game.add_player("Tom", 1); + game.add_player("Alexis", 0); // Cheater + game.add_player("FX", 3); + game.add_player("Lois", 2); + game.play(12); +}
\ No newline at end of file diff --git a/graphs/cpp/hot_potato/player.cc b/graphs/cpp/hot_potato/player.cc new file mode 100644 index 0000000..3ab0f28 --- /dev/null +++ b/graphs/cpp/hot_potato/player.cc @@ -0,0 +1,63 @@ +// +// Created by martial.simon on 2/25/25. +// + +#include "player.hh" + +#include <iostream> +Player::Player(const std::string& name, size_t nb_presses) + : name_{ name } + , bomb_{ nullptr } + , nb_presses_{ nb_presses } + , next_{ nullptr } +{} +Player* Player::get_next() const +{ + return next_.get(); +} +void Player::set_next(std::unique_ptr<Player> next) +{ + next_ = std::move(next); +} +void Player::pass_bomb(Player& receiver) +{ + if (!this->has_bomb() || receiver.has_bomb()) + throw std::runtime_error{ + "Passer doesn't have the bomb or receiver already has it." + }; + std::cout << this->get_name() << " passes the bomb to " + << receiver.get_name() << ".\n"; + receiver.set_bomb(std::move(this->bomb_)); + this->bomb_ = nullptr; +} +void Player::press_bomb() +{ + if (bomb_ == nullptr) + throw std::runtime_error{ + "Can't press bomb if player doesn't have it." + }; + if (bomb_->has_exploded()) + return; + for (size_t i = 0; i < nb_presses_ && !bomb_->has_exploded(); ++i) + { + bomb_->tick(); + } +} +void Player::set_bomb(std::unique_ptr<Bomb> bomb) +{ + this->bomb_ = std::move(bomb); +} +const std::string& Player::get_name() const +{ + return name_; +} +bool Player::has_bomb() const +{ + return bomb_ != nullptr; +} +bool Player::is_dead() const +{ + if (has_bomb()) + return bomb_->has_exploded(); + return false; +}
\ No newline at end of file diff --git a/graphs/cpp/hot_potato/player.hh b/graphs/cpp/hot_potato/player.hh new file mode 100644 index 0000000..0439305 --- /dev/null +++ b/graphs/cpp/hot_potato/player.hh @@ -0,0 +1,25 @@ +#pragma once +#include <memory> +#include <string> + +#include "bomb.hh" + +class Player +{ +public: + Player(const std::string& name, size_t nb_presses); + Player* get_next() const; + void set_next(std::unique_ptr<Player> next); + void pass_bomb(Player& receiver); + void press_bomb(); + void set_bomb(std::unique_ptr<Bomb> bomb); + const std::string& get_name() const; + bool has_bomb() const; + bool is_dead() const; + +private: + std::string name_; + std::unique_ptr<Bomb> bomb_; + size_t nb_presses_; + std::unique_ptr<Player> next_; +};
\ No newline at end of file diff --git a/graphs/cpp/implements/implements.hh b/graphs/cpp/implements/implements.hh new file mode 100644 index 0000000..bd80d8e --- /dev/null +++ b/graphs/cpp/implements/implements.hh @@ -0,0 +1,47 @@ +#pragma once + +template <typename T, typename T2 = T> +concept impl_basic_op = requires(T a, T2 b) { + +a; + -a; + + -b; + +b; + + a + b; + a - b; + a* b; + a / b; + + b + a; + b - a; + b* a; + b / a; +}; + +template <typename T, typename T2 = T> +concept impl_modulo = requires(T a, T2 b) { + a % b; + b % a; +}; + +template <typename T, typename T2 = T> +concept impl_bitwise_op = requires(T a, T2 b) { + ~a; + ~b; + a & b; + a | b; + a ^ b; + a << b; + a >> b; + + b & a; + b | a; + b ^ a; + b << a; + b >> a; +}; + +template <typename T, typename T2 = T> +concept impl_arith_op = + impl_basic_op<T, T2> && impl_modulo<T, T2> && impl_bitwise_op<T, T2>;
\ No newline at end of file diff --git a/graphs/cpp/int_container/int_container.cc b/graphs/cpp/int_container/int_container.cc new file mode 100644 index 0000000..aabb5ab --- /dev/null +++ b/graphs/cpp/int_container/int_container.cc @@ -0,0 +1,83 @@ +#include "int_container.hh" +MyIntContainer::MyIntContainer(size_t size) + : current_size_{ 0 } + , max_size_{ size } + , elems_{ std::make_unique<int[]>(size) } +{} +void MyIntContainer::print() const +{ + if (current_size_ == 0) + return; + std::cout << elems_[0]; + for (size_t i = 1; i < current_size_; ++i) + { + std::cout << " | " << elems_[i]; + } + std::cout << "\n"; +} +size_t MyIntContainer::get_len() const +{ + return current_size_; +} +bool MyIntContainer::add(int elem) +{ + if (current_size_ == max_size_) + return false; + elems_[current_size_++] = elem; + return true; +} +std::optional<int> MyIntContainer::pop() +{ + if (current_size_ == 0) + return std::nullopt; + int res = elems_[--current_size_]; + elems_[current_size_] = -1; + return res; +} +std::optional<int> MyIntContainer::get(size_t position) const +{ + if (position >= current_size_) + return std::nullopt; + return elems_[position]; +} +std::optional<size_t> MyIntContainer::find(int elem) const +{ + size_t i; + for (i = 0; i < current_size_ && elems_[i] != elem; ++i) + continue; + if (i == current_size_) + return std::nullopt; + return i; +} +void swap(int& a, int& b) +{ + int tmp = a; + a = b; + b = tmp; +} +void MyIntContainer::sort() +{ + for (size_t i = 0; i < current_size_ - 1; i++) + { + bool flag = false; + for (size_t j = 0; j < current_size_ - i - 1; j++) + { + if (elems_[j] > elems_[j + 1]) + { + swap(elems_[j], elems_[j + 1]); + flag = true; + } + } + if (!flag) + break; + } +} +bool MyIntContainer::is_sorted() const +{ + for (size_t i = 1; i < current_size_; i++) + { + if (elems_[i - 1] > elems_[i]) + return false; + } + return true; +}
\ No newline at end of file diff --git a/graphs/cpp/int_container/int_container.hh b/graphs/cpp/int_container/int_container.hh new file mode 100644 index 0000000..2df772a --- /dev/null +++ b/graphs/cpp/int_container/int_container.hh @@ -0,0 +1,45 @@ +#pragma once + +#include <iostream> +#include <memory> +#include <optional> + +class MyIntContainer +{ +public: + MyIntContainer(size_t size); + + // Print the content of the container + void print() const; + + // Get the current number of elements inside the array + size_t get_len() const; + + // Add an element inside the array + bool add(int elem); + + // Get the last element inside the array and remove it + std::optional<int> pop(); + + // Get the element at a given position + std::optional<int> get(size_t position) const; + + // Get the index inside the array of a given element + std::optional<size_t> find(int elem) const; + + // Sort the array + void sort(); + + // Checks if the array is sorted + bool is_sorted() const; + +private: + // Current size of the elems_ array + size_t current_size_; + + // Maximum size of the elems_ array + size_t max_size_; + + // Array containing the elements + std::unique_ptr<int[]> elems_; +}; diff --git a/graphs/cpp/is_prime/is_prime.hh b/graphs/cpp/is_prime/is_prime.hh new file mode 100644 index 0000000..ae83249 --- /dev/null +++ b/graphs/cpp/is_prime/is_prime.hh @@ -0,0 +1,5 @@ +#pragma once + +constexpr bool is_prime(unsigned n); + +#include "is_prime.hxx"
\ No newline at end of file diff --git a/graphs/cpp/is_prime/is_prime.hxx b/graphs/cpp/is_prime/is_prime.hxx new file mode 100644 index 0000000..da2b94d --- /dev/null +++ b/graphs/cpp/is_prime/is_prime.hxx @@ -0,0 +1,21 @@ +#pragma once + +#include "is_prime.hh" +constexpr bool is_prime(unsigned n) +{ + if (n == 0 || n == 1) + { + return false; + } + else + { + for (unsigned i = 2; i <= n / 2; ++i) + { + if (n % i == 0) + { + return false; + } + } + } + return true; +}
\ No newline at end of file diff --git a/graphs/cpp/logger/CMakeLists.txt b/graphs/cpp/logger/CMakeLists.txt new file mode 100644 index 0000000..3a705e9 --- /dev/null +++ b/graphs/cpp/logger/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.21.2) +project(logger) + +add_compile_options(-Wall -Wextra -Werror -pedantic -std=c++20 -Wold-style-cast) + +add_library(logger_a SHARED logger.cc) +add_executable(logger main.cc) +target_link_libraries(logger PUBLIC logger_a)
\ No newline at end of file diff --git a/graphs/cpp/logger/logger.cc b/graphs/cpp/logger/logger.cc new file mode 100644 index 0000000..fa2fed1 --- /dev/null +++ b/graphs/cpp/logger/logger.cc @@ -0,0 +1,73 @@ +#include "logger.hh" + +#include <iostream> +#include <string> + +void LogMe::Logger::set_debug_level(logging_level level) +{ + level_ = level; +} +void LogMe::Logger::log(logging_level level, const std::string& msg) +{ + if (level_ >= level) + { + switch (level) + { + case DEBUG: + debug(msg); + break; + case INFO: + info(msg); + break; + case WARN: + warn(msg); + break; + case CRITICAL: + critical(msg); + break; + case ERROR: + error(msg); + break; + } + } +} + +void LogMe::Logger::debug(const std::string& msg) +{ + if (!output_stream_.is_open()) + std::cerr << "[DEBUG] - " << msg << "\n"; + else + output_stream_ << "[DEBUG] - " << msg << "\n"; +} + +void LogMe::Logger::info(const std::string& msg) +{ + if (!output_stream_.is_open()) + std::cerr << "[INFO] - " << msg << "\n"; + else + output_stream_ << "[INFO] - " << msg << "\n"; +} + +void LogMe::Logger::warn(const std::string& msg) +{ + if (!output_stream_.is_open()) + std::cerr << "[WARN] - " << msg << "\n"; + else + output_stream_ << "[WARN] - " << msg << "\n"; +} + +void LogMe::Logger::error(const std::string& msg) +{ + if (!output_stream_.is_open()) + std::cerr << "[ERROR] - " << msg << "\n"; + else + output_stream_ << "[ERROR] - " << msg << "\n"; +} + +void LogMe::Logger::critical(const std::string& msg) +{ + if (!output_stream_.is_open()) + std::cerr << "[CRITICAL] - " << msg << "\n"; + else + output_stream_ << "[CRITICAL] - " << msg << "\n"; +}
\ No newline at end of file diff --git a/graphs/cpp/logger/logger.hh b/graphs/cpp/logger/logger.hh new file mode 100644 index 0000000..4b3a43b --- /dev/null +++ b/graphs/cpp/logger/logger.hh @@ -0,0 +1,47 @@ +#pragma once +#include <fstream> +#include <string> + +namespace LogMe +{ + enum logging_level + { + DEBUG, + INFO, + WARN, + ERROR, + CRITICAL + }; + class Logger + { + public: + Logger(logging_level level, const std::string& log_file) + : level_{ level } + { + output_stream_.open(log_file); + } + Logger(logging_level level) + : level_{ level } + {} + + ~Logger() + { + if (output_stream_.is_open()) + { + output_stream_.close(); + } + } + + void set_debug_level(logging_level level); + void log(logging_level level, const std::string& msg); + void debug(const std::string& msg); + void info(const std::string& msg); + void warn(const std::string& msg); + void critical(const std::string& msg); + void error(const std::string& msg); + + private: + logging_level level_; + std::ofstream output_stream_; + }; +} // namespace LogMe diff --git a/graphs/cpp/logger/main.cc b/graphs/cpp/logger/main.cc new file mode 100644 index 0000000..483ffdd --- /dev/null +++ b/graphs/cpp/logger/main.cc @@ -0,0 +1,13 @@ +#include <iostream> + +#include "logger.hh" + +int main() +{ + LogMe::Logger logger{ LogMe::INFO }; + logger.log(LogMe::INFO, "Program starting."); + std::cout << "Hello, World!" << std::endl; + logger.log(LogMe::ERROR, "Error log."); + logger.log(LogMe::DEBUG, "Program end."); + return 0; +}
\ No newline at end of file diff --git a/graphs/cpp/lookup_table/fibo.cc b/graphs/cpp/lookup_table/fibo.cc new file mode 100644 index 0000000..80b72b1 --- /dev/null +++ b/graphs/cpp/lookup_table/fibo.cc @@ -0,0 +1,15 @@ +#include "fibo.hh" + +long Fibo::operator()(int x) +{ + if (x <= 1) + return x; + + std::optional<long> opt_lookup_table = lookup_table_.get(x); + if (opt_lookup_table) + return *opt_lookup_table; + + auto res = (*this)(x - 1) + (*this)(x - 2); + lookup_table_.set(x, res); + return res; +} diff --git a/graphs/cpp/lookup_table/fibo.hh b/graphs/cpp/lookup_table/fibo.hh new file mode 100644 index 0000000..8f30851 --- /dev/null +++ b/graphs/cpp/lookup_table/fibo.hh @@ -0,0 +1,12 @@ +#pragma once + +#include "lookup_table.hh" + +class Fibo +{ +private: + LookupTable lookup_table_; + +public: + long operator()(int x); +}; diff --git a/graphs/cpp/lookup_table/lookup_table.cc b/graphs/cpp/lookup_table/lookup_table.cc new file mode 100644 index 0000000..0440e61 --- /dev/null +++ b/graphs/cpp/lookup_table/lookup_table.cc @@ -0,0 +1,14 @@ +// +// Created by martial.simon on 2/26/25. +// +#include "lookup_table.hh" +std::optional<long> LookupTable::get(int x) +{ + if (table_.count(x) == 0) + return std::nullopt; + return table_.at(x); +} +void LookupTable::set(int x, long value) +{ + table_.insert_or_assign(x, value); +}
\ No newline at end of file diff --git a/graphs/cpp/lookup_table/lookup_table.hh b/graphs/cpp/lookup_table/lookup_table.hh new file mode 100644 index 0000000..eb25d43 --- /dev/null +++ b/graphs/cpp/lookup_table/lookup_table.hh @@ -0,0 +1,14 @@ +#pragma once + +#include <optional> +#include <unordered_map> + +class LookupTable +{ +public: + std::optional<long> get(int x); + void set(int x, long value); + +private: + std::unordered_map<int, long> table_; +}; diff --git a/graphs/cpp/lookup_table/lookup_table_test.cc b/graphs/cpp/lookup_table/lookup_table_test.cc new file mode 100644 index 0000000..a17101e --- /dev/null +++ b/graphs/cpp/lookup_table/lookup_table_test.cc @@ -0,0 +1,9 @@ +#include <iostream> + +#include "fibo.hh" + +int main() +{ + Fibo fibo; + std::cout << fibo(42) << '\n'; +} diff --git a/graphs/cpp/merge_sort/merge_sort.cc b/graphs/cpp/merge_sort/merge_sort.cc new file mode 100644 index 0000000..ed7afdf --- /dev/null +++ b/graphs/cpp/merge_sort/merge_sort.cc @@ -0,0 +1,12 @@ +#include "merge_sort.hh" +void merge_sort(iterator_type begin, iterator_type end) +{ + if (const auto diff = distance(begin, end); diff > 1) + { + const auto m = begin + diff / 2; + + merge_sort(begin, m); + merge_sort(m, end); + return std::inplace_merge(begin, m, end); + } +}
\ No newline at end of file diff --git a/graphs/cpp/merge_sort/merge_sort.hh b/graphs/cpp/merge_sort/merge_sort.hh new file mode 100644 index 0000000..7e7f02f --- /dev/null +++ b/graphs/cpp/merge_sort/merge_sort.hh @@ -0,0 +1,16 @@ +#pragma once + +#include <algorithm> +#include <vector> + +#define while forbidden_use_of_while +#define for forbidden_use_of_for +#define goto forbidden_use_of_goto +#define sort forbidden_use_of_sort +#define partial_sort forbidden_use_of_sort +#define stable_sort forbidden_use_of_sort +#define sort_heap forbidden_use_of_sort + +using iterator_type = std::vector<int>::iterator; + +void merge_sort(iterator_type begin, iterator_type end); diff --git a/graphs/cpp/my_nfts/auction.cc b/graphs/cpp/my_nfts/auction.cc new file mode 100644 index 0000000..534c61d --- /dev/null +++ b/graphs/cpp/my_nfts/auction.cc @@ -0,0 +1,45 @@ +#include "auction.hh" + +#include <algorithm> +Auction::Auction(Person& organizer, NFT nft, uint initial_bid) + : organizer_{ organizer } + , nft_{ std::move(nft) } + , highest_bidder_{ nullptr } + , highest_bid_{ initial_bid } +{ + if (!nft_ || nft_->empty()) + throw std::invalid_argument{ "Invalid nft!" }; +} +Auction::~Auction() +{ + if (highest_bidder_ == nullptr) + organizer_.add_nft(std::move(nft_)); + else + { + highest_bidder_->add_nft(std::move(nft_)); + organizer_.add_money(highest_bid_); + } +} +bool Auction::bid(Person& person, uint money) +{ + if (money > highest_bid_) + { + if (highest_bidder_ == nullptr) + highest_bidder_ = &person; + else + highest_bidder_->add_money(highest_bid_); + highest_bid_ = money; + highest_bidder_ = &person; + highest_bidder_->remove_money(money); + return true; + } + return false; +} +const std::string& Auction::get_nft_name() const +{ + return *nft_; +} +uint Auction::get_highest_bid() const +{ + return highest_bid_; +}
\ No newline at end of file diff --git a/graphs/cpp/my_nfts/auction.hh b/graphs/cpp/my_nfts/auction.hh new file mode 100644 index 0000000..9a1d162 --- /dev/null +++ b/graphs/cpp/my_nfts/auction.hh @@ -0,0 +1,34 @@ +#pragma once + +#include "nft.hh" +#include "person.hh" + +// Smart contract to auction a NFT. +// It is a RAII class. +class Auction +{ +public: + // Start the auction with the given (non-null) NFT. + Auction(Person& organizer, NFT nft, uint initial_bid); + // Close the auction. + ~Auction(); + + // https://en.cppreference.com/w/cpp/language/rule_of_three#Rule_of_five + Auction(const Auction&&) = delete; + Auction(const Auction&) = delete; + Auction& operator=(const Auction&&) = delete; + Auction& operator=(const Auction&) = delete; + + // Allow a person to bid at the auction. + bool bid(Person& person, uint money); + + // Getters for the nft name and highest bid. + const std::string& get_nft_name() const; + uint get_highest_bid() const; + +private: + Person& organizer_; + NFT nft_; + Person* highest_bidder_; + uint highest_bid_; +}; diff --git a/graphs/cpp/my_nfts/main.cc b/graphs/cpp/my_nfts/main.cc new file mode 100644 index 0000000..2e9f462 --- /dev/null +++ b/graphs/cpp/my_nfts/main.cc @@ -0,0 +1,37 @@ +#include <iostream> + +#include "auction.hh" +#include "person.hh" + +int main(void) +{ + auto p1 = Person("JP", 100); + auto p2 = Person("Claude", 50); + + p1.add_nft(create_nft("Singe")); + + std::cout << p1; + std::cout << p2; + + p2.add_nft(p1.remove_nft("Singe")); + + std::cout << p1; + std::cout << p2; + + auto p3 = Person("Marie", 20); + std::cout << p1; + std::cout << p2; + std::cout << p3; + + { + Auction auction(p2, p2.remove_nft("Singe"), 10); + std::cout << p1; + std::cout << p2; + std::cout << p3; + + auction.bid(p1, 20); + } + std::cout << p1; + std::cout << p2; + std::cout << p3; +} diff --git a/graphs/cpp/my_nfts/nft.hh b/graphs/cpp/my_nfts/nft.hh new file mode 100644 index 0000000..2147545 --- /dev/null +++ b/graphs/cpp/my_nfts/nft.hh @@ -0,0 +1,15 @@ +#pragma once + +#include <memory> +#include <string> + +// NFT declaration +using NFT = std::unique_ptr<std::string>; + +// Create an empty NFT (convient in some scenarios). +NFT create_empty_nft(); +// Create a NFT with the given name. +NFT create_nft(const std::string& name); + +// Define the functions in the nft.hxx file. +#include "nft.hxx" diff --git a/graphs/cpp/my_nfts/nft.hxx b/graphs/cpp/my_nfts/nft.hxx new file mode 100644 index 0000000..083f10f --- /dev/null +++ b/graphs/cpp/my_nfts/nft.hxx @@ -0,0 +1,11 @@ +#pragma once + +#include "nft.hh" +inline NFT create_empty_nft() +{ + return nullptr; +} +inline NFT create_nft(const std::string& name) +{ + return std::make_unique<std::string>(name); +}
\ No newline at end of file diff --git a/graphs/cpp/my_nfts/person.cc b/graphs/cpp/my_nfts/person.cc new file mode 100644 index 0000000..cf4b291 --- /dev/null +++ b/graphs/cpp/my_nfts/person.cc @@ -0,0 +1,61 @@ +#include "person.hh" + +#include <algorithm> +Person::Person(const std::string& name, uint money) + : name_{ name } + , money_{ money } +{} +std::vector<std::string> Person::enumerate_nfts() const +{ + std::vector<std::string> res; + for (auto nft = nfts_.begin(); nft != nfts_.end(); nft++) + { + res.push_back(**nft); + } + return res; +} +void Person::add_nft(NFT nft) +{ + nfts_.push_back(std::move(nft)); +} +NFT Person::remove_nft(const std::string& name) +{ + auto pos = std::find_if(nfts_.begin(), nfts_.end(), + [&](NFT const& nft) { return *nft == name; }); + if (pos == nfts_.end()) + return create_empty_nft(); + nfts_.erase(pos); + return create_nft(name); +} +void Person::add_money(uint money) +{ + money_ += money; +} +bool Person::remove_money(uint money) +{ + if (money > money_) + return false; + money_ -= money; + return true; +} +uint Person::get_money() const +{ + return money_; +} +const std::string& Person::get_name() const +{ + return name_; +} +std::ostream& operator<<(std::ostream& os, const Person& p) +{ + os << "Name: " << p.get_name() << "\nMoney: " << p.get_money() << "\nNFTs:"; + if (const std::vector<std::string> nfts = p.enumerate_nfts(); !nfts.empty()) + { + for (size_t i = 0; i < nfts.size(); ++i) + { + os << " " << nfts.at(i); + } + } + os << "\n"; + return os; +} diff --git a/graphs/cpp/my_nfts/person.hh b/graphs/cpp/my_nfts/person.hh new file mode 100644 index 0000000..90a2e16 --- /dev/null +++ b/graphs/cpp/my_nfts/person.hh @@ -0,0 +1,39 @@ +#pragma once + +#include <ostream> +#include <vector> + +#include "nft.hh" + +// A person +class Person +{ +public: + // Initiliaze its member attributes. + Person(const std::string& name, uint money); + + // Returns the list of NFTs it owns. + std::vector<std::string> enumerate_nfts() const; + + // Give it a NFT. + void add_nft(NFT nft); + // Take away a NFT. + NFT remove_nft(const std::string& name); + + // Add money. + void add_money(uint money); + // Remove money, if possible. + bool remove_money(uint money); + + // Getters for money and name. + uint get_money() const; + const std::string& get_name() const; + +private: + std::string name_; + uint money_; + std::vector<NFT> nfts_; +}; + +// Write informations about the person on the given stream. +std::ostream& operator<<(std::ostream& os, const Person& p); diff --git a/graphs/cpp/path/path.cc b/graphs/cpp/path/path.cc new file mode 100644 index 0000000..bff3a55 --- /dev/null +++ b/graphs/cpp/path/path.cc @@ -0,0 +1,10 @@ +#include "path.hh" + +Path& Path::join(const std::string& tail, bool is_file) +{ + if (final_) + return *this; + path_.push_back(tail); + final_ = is_file; + return *this; +}
\ No newline at end of file diff --git a/graphs/cpp/path/path.hh b/graphs/cpp/path/path.hh new file mode 100644 index 0000000..0a09d05 --- /dev/null +++ b/graphs/cpp/path/path.hh @@ -0,0 +1,25 @@ +#pragma once + +#include <string> +#include <vector> + +class Path +{ +public: + Path() = default; + virtual ~Path() = default; + + /* + ** Return the complete path as a string. + */ + virtual std::string to_string() const = 0; + + /* + ** Add a directory or a file at the end of the path. + */ + virtual Path& join(const std::string& tail, bool is_file = false); + +protected: + std::vector<std::string> path_; + bool final_ = false; +}; diff --git a/graphs/cpp/path/path_example.cc b/graphs/cpp/path/path_example.cc new file mode 100644 index 0000000..f35c605 --- /dev/null +++ b/graphs/cpp/path/path_example.cc @@ -0,0 +1,22 @@ +#include <iostream> + +#include "unix_path.hh" +#include "windows_path.hh" + +int main() +{ + auto windows_path = WindowsPath('E'); + + std::cout << windows_path.join("Users").join("YAKA").join("cpp").to_string() + << '\n'; /* E:\Users\YAKA\cpp\ */ + + auto unix_path = UnixPath(); + + std::cout << unix_path.join("home").join("yaka").join("cpp").to_string() + << '\n'; // /home/yaka/cpp/ + + std::cout << unix_path.join("main.cc", true).to_string() + << '\n'; // /home/yaka/cpp/main.cc + + return 0; +} diff --git a/graphs/cpp/path/unix_path.cc b/graphs/cpp/path/unix_path.cc new file mode 100644 index 0000000..dfd51b5 --- /dev/null +++ b/graphs/cpp/path/unix_path.cc @@ -0,0 +1,25 @@ +// +// Created by martial.simon on 2/25/25. +// + +#include "unix_path.hh" + +#include <sstream> +UnixPath::UnixPath() + : Path() +{} + +std::string UnixPath::to_string() const +{ + if (path_.empty()) + return "/"; + std::ostringstream os; + os << "/" << path_[0]; + for (size_t i = 1; i < path_.size(); i++) + { + os << "/" << path_[i]; + } + if (!final_) + os << "/"; + return os.str(); +}
\ No newline at end of file diff --git a/graphs/cpp/path/unix_path.hh b/graphs/cpp/path/unix_path.hh new file mode 100644 index 0000000..22976ed --- /dev/null +++ b/graphs/cpp/path/unix_path.hh @@ -0,0 +1,13 @@ +// +// Created by martial.simon on 2/25/25. +// + +#pragma once +#include "path.hh" + +class UnixPath : public Path +{ +public: + UnixPath(); + std::string to_string() const override; +}; diff --git a/graphs/cpp/path/windows_path.cc b/graphs/cpp/path/windows_path.cc new file mode 100644 index 0000000..cc94afa --- /dev/null +++ b/graphs/cpp/path/windows_path.cc @@ -0,0 +1,37 @@ +// +// Created by martial.simon on 2/25/25. +// + +#include "windows_path.hh" + +#include <sstream> +WindowsPath::WindowsPath(char drive) + : Path() +{ + path_.push_back(std::string{ drive } + std::string{ ':' }); +} +std::string WindowsPath::to_string() const +{ + if (path_.empty()) + return ""; + std::ostringstream os; + os << path_[0]; + for (size_t i = 1; i < path_.size(); i++) + { + os << "\\" << path_[i]; + } + if (!final_) + os << "\\"; + return os.str(); +} +Path& WindowsPath::join(const std::string& tail, bool is_file) +{ + // :, ", |, ?, * + if (tail.find(':') != std::string::npos + || tail.find('\"') != std::string::npos + || tail.find('|') != std::string::npos + || tail.find('?') != std::string::npos + || tail.find('*') != std::string::npos) + return *this; + return Path::join(tail, is_file); +}
\ No newline at end of file diff --git a/graphs/cpp/path/windows_path.hh b/graphs/cpp/path/windows_path.hh new file mode 100644 index 0000000..4bd9e2b --- /dev/null +++ b/graphs/cpp/path/windows_path.hh @@ -0,0 +1,14 @@ +// +// Created by martial.simon on 2/25/25. +// + +#pragma once +#include "path.hh" + +class WindowsPath : public Path +{ +public: + WindowsPath(char drive); + std::string to_string() const override; + Path& join(const std::string& tail, bool is_file = false) override; +}; diff --git a/graphs/cpp/point/CMakeLists.txt b/graphs/cpp/point/CMakeLists.txt new file mode 100644 index 0000000..0933e1c --- /dev/null +++ b/graphs/cpp/point/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.30) +project(point) + +set(CMAKE_CXX_STANDARD 20) + +add_executable(point main.cc + point.cc) diff --git a/graphs/cpp/point/main.cc b/graphs/cpp/point/main.cc new file mode 100644 index 0000000..df28b27 --- /dev/null +++ b/graphs/cpp/point/main.cc @@ -0,0 +1,7 @@ +#include <iostream> + +int main() +{ + std::cout << "Hello, World!" << std::endl; + return 0; +}
\ No newline at end of file diff --git a/graphs/cpp/point/point.cc b/graphs/cpp/point/point.cc new file mode 100644 index 0000000..557cab9 --- /dev/null +++ b/graphs/cpp/point/point.cc @@ -0,0 +1,14 @@ +#include "point.hh" + +#include <iostream> + +void Point::display() const +{ + std::cout << "(" << x_ << ", " << y_ << ")"; +} + +void Point::shift(const int dx, const int dy) +{ + x_ += dx; + y_ += dy; +} diff --git a/graphs/cpp/point/point.hh b/graphs/cpp/point/point.hh new file mode 100644 index 0000000..1e33fc8 --- /dev/null +++ b/graphs/cpp/point/point.hh @@ -0,0 +1,12 @@ +#pragma once + +class Point +{ +public: + void display() const; + void shift(int dx, int dy); + +private: + int x_ = 0; + int y_ = 0; +};
\ No newline at end of file diff --git a/graphs/cpp/ref_swap/main.cc b/graphs/cpp/ref_swap/main.cc new file mode 100644 index 0000000..487ab6d --- /dev/null +++ b/graphs/cpp/ref_swap/main.cc @@ -0,0 +1,17 @@ +#include <iostream> + +#include "ref_swap.hh" + +int main() +{ + int a = 3; + int b = 19; + + std::cout << "Before: a = " << a << ", b = " << b << '\n'; + ref_swap(a, b); + std::cout << "After: a = " << a << ", b = " << b << '\n'; + + std::cout << "Before: a = " << a << ", b = " << b << '\n'; + ptr_swap(&a, &b); + std::cout << "After: a = " << a << ", b = " << b << '\n'; +} diff --git a/graphs/cpp/ref_swap/ref_swap.cc b/graphs/cpp/ref_swap/ref_swap.cc new file mode 100644 index 0000000..44cb203 --- /dev/null +++ b/graphs/cpp/ref_swap/ref_swap.cc @@ -0,0 +1,18 @@ +// +// Created by martial.simon on 2/24/25. +// +void ref_swap(int& a, int& b) +{ + int tmp = a; + a = b; + b = tmp; +} + +void ptr_swap(int* a, int* b) +{ + if (!a || !b) + return; + int tmp = *a; + *a = *b; + *b = tmp; +}
\ No newline at end of file diff --git a/graphs/cpp/ref_swap/ref_swap.hh b/graphs/cpp/ref_swap/ref_swap.hh new file mode 100644 index 0000000..1f194b3 --- /dev/null +++ b/graphs/cpp/ref_swap/ref_swap.hh @@ -0,0 +1,5 @@ +#pragma once + +void ref_swap(int& a, int& b); + +void ptr_swap(int* a, int* b); diff --git a/graphs/cpp/replace/inputfile b/graphs/cpp/replace/inputfile new file mode 100644 index 0000000..b4e5a2f --- /dev/null +++ b/graphs/cpp/replace/inputfile @@ -0,0 +1 @@ +abcabcbc
\ No newline at end of file diff --git a/graphs/cpp/replace/replace.cc b/graphs/cpp/replace/replace.cc new file mode 100644 index 0000000..c24bf05 --- /dev/null +++ b/graphs/cpp/replace/replace.cc @@ -0,0 +1,39 @@ +#include "replace.hh" + +#include <fstream> +#include <iostream> +#include <string> + +void replace(const std::string& input_filename, + const std::string& output_filename, const std::string& src_token, + const std::string& dst_token) +{ + std::ofstream file_out; + file_out.open(output_filename); + + if (!file_out.is_open()) + { + std::cerr << "Cannot write output file\n"; + return; + } + + std::ifstream file_in; + file_in.open(input_filename); + if (!file_in.is_open()) + { + std::cerr << "Cannot open input file\n"; + return; + } + + std::string token; + while (std::getline(file_in, token)) + { + std::string::size_type n = 0; + while ((n = token.find(src_token, n)) != std::string::npos) + { + token.replace(n, src_token.size(), dst_token); + n += dst_token.size(); + } + file_out << token << "\n"; + } +}
\ No newline at end of file diff --git a/graphs/cpp/replace/replace.hh b/graphs/cpp/replace/replace.hh new file mode 100644 index 0000000..cbb2e46 --- /dev/null +++ b/graphs/cpp/replace/replace.hh @@ -0,0 +1,6 @@ +#pragma once +#include <string> + +void replace(const std::string& input_filename, + const std::string& output_filename, const std::string& src_token, + const std::string& dst_token);
\ No newline at end of file diff --git a/graphs/cpp/replace/test_replace.cc b/graphs/cpp/replace/test_replace.cc new file mode 100644 index 0000000..be7a488 --- /dev/null +++ b/graphs/cpp/replace/test_replace.cc @@ -0,0 +1,16 @@ +#include <iostream> + +#include "replace.hh" + +int main(int argc, char** argv) +{ + if (argc < 5) + { + std::cerr << "Usage: INPUT_FILE OUTPUT_FILE SRC_TOKEN DST_TOKEN\n"; + return 1; + } + + replace(argv[1], argv[2], argv[3], argv[4]); + + return 0; +} diff --git a/graphs/cpp/singleton/singleton.cc b/graphs/cpp/singleton/singleton.cc new file mode 100644 index 0000000..711e702 --- /dev/null +++ b/graphs/cpp/singleton/singleton.cc @@ -0,0 +1,21 @@ +// +// Created by martial.simon on 2/27/25. +// + +#include "singleton.hh" + +#include <iostream> +#include <string> + +void Logger::open_log_file(const std::string& file) +{ + std::cout << "LOG: Opening file " << file << "\n"; +} +void Logger::write_to_log_file() +{ + std::cout << "LOG: Writing into log file ...\n"; +} +void Logger::close_log_file() +{ + std::cout << "LOG: Closing log file ...\n"; +} diff --git a/graphs/cpp/singleton/singleton.hh b/graphs/cpp/singleton/singleton.hh new file mode 100644 index 0000000..715a85f --- /dev/null +++ b/graphs/cpp/singleton/singleton.hh @@ -0,0 +1,33 @@ +// +// Created by martial.simon on 2/27/25. +// + +#pragma once +#include <string> + +template <typename T> +class Singleton +{ +protected: + Singleton() = default; + +private: + Singleton(const Singleton<T>&) = delete; + Singleton& operator=(const Singleton<T>&) = delete; + +public: + static T& instance(); +}; + +class Logger : public Singleton<Logger> +{ + Logger() = default; + friend class Singleton<Logger>; + +public: + void open_log_file(const std::string& file); + void write_to_log_file(); + void close_log_file(); +}; + +#include "singleton.hxx"
\ No newline at end of file diff --git a/graphs/cpp/singleton/singleton.hxx b/graphs/cpp/singleton/singleton.hxx new file mode 100644 index 0000000..04a36b8 --- /dev/null +++ b/graphs/cpp/singleton/singleton.hxx @@ -0,0 +1,9 @@ +#pragma once + +#include "singleton.hh" +template <typename T> +T& Singleton<T>::instance() +{ + static T instance_; + return instance_; +}
\ No newline at end of file diff --git a/graphs/cpp/smtptr/main.cc b/graphs/cpp/smtptr/main.cc new file mode 100644 index 0000000..a574d45 --- /dev/null +++ b/graphs/cpp/smtptr/main.cc @@ -0,0 +1,20 @@ +#include "shared_pointer.hh" + +int main() +{ + // Lifetime of the data + { + SharedPointer<int> p2; + { + SharedPointer<int> p1{ new int{ 5 } }; + p2 = p1; // Now both SharedPointers own the memory + } + // p1 is freed, but the int pointer remains + // Memory still exists, due to p2 + std::cout << "Value of p2: " << *p2 << std::endl; // Output: 5 + } + // p2 is freed, and since no one else owns the memory, + // the int pointer is freed too + + return 0; +} diff --git a/graphs/cpp/smtptr/shared_pointer.hh b/graphs/cpp/smtptr/shared_pointer.hh new file mode 100644 index 0000000..cc24243 --- /dev/null +++ b/graphs/cpp/smtptr/shared_pointer.hh @@ -0,0 +1,166 @@ +#pragma once + +#include <cassert> +#include <iostream> +#include <string> + +template <typename T> +class SharedPointer +{ +public: + // The type pointed to. + using element_type = T; + + /** + ** \brief Construct a counted reference to a newly allocated object. + */ + SharedPointer(element_type* p = nullptr); + + /** + ** \brief Destroy the SharedPointer. + ** The object pointed to is destroyed only if it is not referenced anymore. + ** Take care to free everything ... + */ + ~SharedPointer(); + + /** + ** \brief Copy constructor. + ** \return A new SharedPointer, pointing + ** to the underlying data of \a other. + ** + ** Although the implementation is subsumed by the previous, more + ** generic one, the C++ standard still mandates this specific + ** signature. Otherwise, the compiler will provide a default + ** implementation, which is of course wrong. Note that the + ** same applies for the assignment operator. + */ + SharedPointer(const SharedPointer<element_type>& other); + + /// \name Assignments. + /// \{ + + /** + ** \brief Replace the underlying data with \a p + ** A call to \c reset is strictly equivalent to: + ** \code + ** r = SharedPointer<element_type>(p); + ** \endcode + ** This line implicitly calls the destructor of \a r before assigning + ** it a new value. + ** \warning You can't reset your \c SharedPointer with the + ** same pointer as the current one. In this case, nothing should + ** be done. + ** \warning Be mindful of other \c SharedPointers + ** which could also be pointing to the same data. + */ + void reset(element_type* p); + + /** + ** \brief Reference assignment + ** Its behavior is similar to \c reset() but you + ** have to use the existing SharedPointer \a other + ** instead of creating a new instance. + */ + SharedPointer<element_type>& + operator=(const SharedPointer<element_type>& other); + /// \} + + /// \name Access to data. + /// \{ + + // Access via a reference. + element_type& operator*() const; + // Access via a pointer. + element_type* operator->() const; + + // Returns the underlying data pointer. + element_type* get() const; + + // Returns the number of SharedPointer objects referring to the same managed + // object + long use_count() const; + /// \} + + /// \name Equality operators. + /// \{ + + /** + ** \brief Reference comparison. + ** Returns true if the two references point to the same object. + */ + template <typename U> + bool operator==(const SharedPointer<U>& rhs) const; + + /** + ** \brief Reference comparison. + ** Returns false if the two references point to the same object. + */ + template <typename U> + bool operator!=(const SharedPointer<U>& rhs) const; + + /** + ** \brief Reference comparison. + ** Returns true if this points to \a p. + */ + bool operator==(const element_type* p) const; + + /** + ** \brief Reference comparison. + ** Returns false if this points to \a p. + */ + bool operator!=(const element_type* p) const; + + /** + ** \brief Move assignment operator for SharedPointer. + ** + ** This operator transfers ownership of the managed object from the + ** \a other to this SharePointer. + ** After the assignment, the \a other will be empty. + ** \warning Don't forget to update the reference counter. + ** + ** Returns a reference to this SharedPointer. + */ + SharedPointer<element_type>& operator=(SharedPointer&& other) noexcept; + + /** + ** \brief Move constructor for SharedPointer. + ** + ** This constructor transfers ownership of the managed object from \a other + ** SharedPointer to the newly created SharedPointer. + ** + */ + SharedPointer(SharedPointer&& other); + + /// \} + + /** + ** \brief Test for validity + ** Returns true if the reference is valid, i.e. it points to an object. + ** This conversion operator allows users to write: + ** + ** \code + ** SharedPointer<int> p1; + ** if (p1) // Here false + ** ... + ** \endcode + */ + operator bool() const; + + /** + ** \brief Test fellowship. + ** Returns true if the SharedPointer points to an object which + ** is of the specified type. + ** Look at the given example file shared_pointer_is_a.cc + ** to better understand its purpose. + */ + template <typename U> + bool is_a() const; + +private: + // Pointer to the underlying data. + element_type* data_; + // A counter shared between all ref pointers to \a data_. + long* count_; +}; + +#include "shared_pointer.hxx" diff --git a/graphs/cpp/smtptr/shared_pointer.hxx b/graphs/cpp/smtptr/shared_pointer.hxx new file mode 100644 index 0000000..fbc0792 --- /dev/null +++ b/graphs/cpp/smtptr/shared_pointer.hxx @@ -0,0 +1,144 @@ +#pragma once +#include "shared_pointer.hh" +template <typename T> +SharedPointer<T>::SharedPointer(element_type* p) +{ + if (p == nullptr) + { + data_ = nullptr; + count_ = nullptr; + } + else + { + data_ = p; + count_ = new long{ 1 }; + } +} +template <typename T> +SharedPointer<T>::~SharedPointer() +{ + if (count_ != nullptr) + { + (*count_)--; + if (*count_ == 0) + { + delete count_; + if (data_ != nullptr) + delete data_; + } + } +} +template <typename T> +SharedPointer<T>::SharedPointer(const SharedPointer<element_type>& other) +{ + this->~SharedPointer(); + data_ = other.data_; + if (data_ == nullptr) + count_ = nullptr; + count_ = other.count_; + if (count_ != nullptr) + (*count_)++; +} +template <typename T> +void SharedPointer<T>::reset(element_type* p) +{ + if (data_ == p) + return; + this->~SharedPointer(); + data_ = p; + if (p == nullptr) + count_ = nullptr; + else + count_ = new long{ 1 }; +} +template <typename T> +SharedPointer<T>& SharedPointer<T>::operator=(const SharedPointer<T>& other) +{ + this->~SharedPointer(); + + data_ = other.data_; + count_ = other.count_; + if (nullptr != other.data_) + { + (*this->count_)++; + } + return *this; +} +template <typename T> +T& SharedPointer<T>::operator*() const +{ + return *data_; +} + +template <typename T> +T* SharedPointer<T>::operator->() const +{ + return data_; +} +template <typename T> +T* SharedPointer<T>::get() const +{ + return data_; +} +template <typename T> +long SharedPointer<T>::use_count() const +{ + if (count_ == nullptr) + return 0; + return *count_; +} +template <typename T> +template <typename U> +bool SharedPointer<T>::operator==(const SharedPointer<U>& rhs) const +{ + if (rhs.data_ == this->data_) + return true; + return false; +} +template <typename T> +template <typename U> +bool SharedPointer<T>::operator!=(const SharedPointer<U>& rhs) const +{ + return !(*this == rhs); +} +template <typename T> +bool SharedPointer<T>::operator==(const T* p) const +{ + return this->data_ == p; +} +template <typename T> +bool SharedPointer<T>::operator!=(const T* p) const +{ + return this->data_ != p; +} +template <typename T> +SharedPointer<T>& SharedPointer<T>::operator=(SharedPointer<T>&& other) noexcept +{ + this->~SharedPointer(); + data_ = other.data_; + count_ = other.count_; + other.data_ = nullptr; + other.count_ = nullptr; + return *this; +} +template <typename T> +SharedPointer<T>::SharedPointer(SharedPointer&& other) +{ + this->~SharedPointer(); + data_ = other.data_; + count_ = other.count_; + + other.data_ = nullptr; + other.count_ = nullptr; +} +template <typename T> +SharedPointer<T>::operator bool() const +{ + return data_ != nullptr; +} +template <typename T> +template <typename U> +bool SharedPointer<T>::is_a() const +{ + return dynamic_cast<U*>(data_); +}
\ No newline at end of file diff --git a/graphs/cpp/smtptr/shared_pointer_is_a.cc b/graphs/cpp/smtptr/shared_pointer_is_a.cc new file mode 100644 index 0000000..b6dcb95 --- /dev/null +++ b/graphs/cpp/smtptr/shared_pointer_is_a.cc @@ -0,0 +1,47 @@ +#include "shared_pointer.hh" + +class Animal +{ +public: + virtual ~Animal() + {} +}; + +class Cat : public Animal +{ +public: + void meow() + { + std::cout << "Meow!\n"; + } +}; + +class Dog : public Animal +{ +public: + void bark() + { + std::cout << "Woof!\n"; + } +}; + +int main() +{ + SharedPointer<Animal> animalPtr{ new Cat }; + if (animalPtr.is_a<Cat>()) + { // true + std::cout << "The pointer points to a Cat.\n"; + } + + SharedPointer<Animal> animalPtr2{ new Dog }; + if (animalPtr2.is_a<Cat>()) + { // false + std::cout << "The pointer points to a Cat.\n"; + } + else if (animalPtr2.is_a<Dog>()) + { + std::cout << "The pointer points to a Dog.\n"; + } + + return 0; +} diff --git a/graphs/cpp/stdin_to_file/stdin_to_file.cc b/graphs/cpp/stdin_to_file/stdin_to_file.cc new file mode 100644 index 0000000..c1519e3 --- /dev/null +++ b/graphs/cpp/stdin_to_file/stdin_to_file.cc @@ -0,0 +1,20 @@ +#include "stdin_to_file.hh" + +#include <fstream> +#include <iostream> +long int stdin_to_file(const std::string& filename) +{ + std::ofstream file_out; + std::string token; + // trying to open output file "data.out" + file_out.open(filename); + size_t res = 0; + // Read until eof or an error occurs + while (std::cin >> token) + { + res++; + file_out << token << '\n'; + } + // stream is closed at the end of the scope + return res; +}
\ No newline at end of file diff --git a/graphs/cpp/stdin_to_file/stdin_to_file.hh b/graphs/cpp/stdin_to_file/stdin_to_file.hh new file mode 100644 index 0000000..9aac89d --- /dev/null +++ b/graphs/cpp/stdin_to_file/stdin_to_file.hh @@ -0,0 +1,6 @@ +#pragma once + +#include <fstream> +#include <iostream> + +long int stdin_to_file(const std::string& filename); diff --git a/graphs/cpp/stdin_to_file/stdin_to_file_example.cc b/graphs/cpp/stdin_to_file/stdin_to_file_example.cc new file mode 100644 index 0000000..3bc211d --- /dev/null +++ b/graphs/cpp/stdin_to_file/stdin_to_file_example.cc @@ -0,0 +1,10 @@ +#include <iostream> + +#include "stdin_to_file.hh" + +int main() +{ + auto word_count = stdin_to_file("file.out"); + std::cout << "File has " << word_count << " words\n"; + return 0; +} diff --git a/graphs/cpp/visitor/compute_visitor.cc b/graphs/cpp/visitor/compute_visitor.cc new file mode 100644 index 0000000..1e4e6dd --- /dev/null +++ b/graphs/cpp/visitor/compute_visitor.cc @@ -0,0 +1,62 @@ +// +// Created by martial.simon on 2/27/25. +// + +#include "compute_visitor.hh" + +#include <stdexcept> + +#include "add.hh" +#include "div.hh" +#include "leaf.hh" +#include "mul.hh" +#include "sub.hh" +void visitor::ComputeVisitor::visit(const tree::Tree& e) +{ + Visitor::visit(e); + value_ = get_value(); +} +void visitor::ComputeVisitor::visit(const tree::Node& e) +{ + visit(*e.get_lhs()); + visit(*e.get_rhs()); + value_ = get_value(); +} +void visitor::ComputeVisitor::visit(const tree::AddNode& e) +{ + visit(*e.get_lhs()); + int lhs = get_value(); + Visitor::visit(*e.get_rhs()); + value_ = lhs + get_value(); +} +void visitor::ComputeVisitor::visit(const tree::SubNode& e) +{ + visit(*e.get_lhs()); + int lhs = get_value(); + Visitor::visit(*e.get_rhs()); + value_ = lhs - get_value(); +} +void visitor::ComputeVisitor::visit(const tree::MulNode& e) +{ + visit(*e.get_lhs()); + int lhs = get_value(); + Visitor::visit(*e.get_rhs()); + value_ = lhs * get_value(); +} +void visitor::ComputeVisitor::visit(const tree::DivNode& e) +{ + visit(*e.get_lhs()); + int lhs = get_value(); + visit(*e.get_rhs()); + if (get_value() == 0) + throw std::overflow_error{ "Divide by zero exception" }; + value_ = lhs / get_value(); +} +void visitor::ComputeVisitor::visit(const tree::Leaf& e) +{ + value_ = std::stoi(e.get_value()); +} +int visitor::ComputeVisitor::get_value() +{ + return value_; +} diff --git a/graphs/cpp/visitor/compute_visitor.hh b/graphs/cpp/visitor/compute_visitor.hh new file mode 100644 index 0000000..0426f29 --- /dev/null +++ b/graphs/cpp/visitor/compute_visitor.hh @@ -0,0 +1,26 @@ +// +// Created by martial.simon on 2/27/25. +// + +#pragma once + +#include "visitor.hh" + +namespace visitor +{ + class ComputeVisitor : public Visitor + { + public: + void visit(const tree::Tree& e); + void visit(const tree::Node& e); + void visit(const tree::AddNode& e); + void visit(const tree::SubNode& e); + void visit(const tree::MulNode& e); + void visit(const tree::DivNode& e); + void visit(const tree::Leaf& e); + int get_value(); + + private: + int value_ = 0; + }; +} // namespace visitor diff --git a/graphs/cpp/visitor/print_visitor.cc b/graphs/cpp/visitor/print_visitor.cc new file mode 100644 index 0000000..bcfd565 --- /dev/null +++ b/graphs/cpp/visitor/print_visitor.cc @@ -0,0 +1,58 @@ +// +// Created by martial.simon on 2/27/25. +// + +#include "print_visitor.hh" + +#include <iostream> + +#include "add.hh" +#include "div.hh" +#include "leaf.hh" +#include "mul.hh" +#include "sub.hh" +void visitor::PrintVisitor::visit(const tree::Tree& e) +{ + Visitor::visit(e); +} +void visitor::PrintVisitor::visit(const tree::Node& e) +{ + visit(*e.get_lhs()); + visit(*e.get_rhs()); +} +void visitor::PrintVisitor::visit(const tree::AddNode& e) +{ + std::cout << "("; + visit(*e.get_lhs()); + std::cout << " + "; + visit(*e.get_rhs()); + std::cout << ")"; +} +void visitor::PrintVisitor::visit(const tree::SubNode& e) +{ + std::cout << "("; + visit(*e.get_lhs()); + std::cout << " - "; + visit(*e.get_rhs()); + std::cout << ")"; +} +void visitor::PrintVisitor::visit(const tree::MulNode& e) +{ + std::cout << "("; + visit(*e.get_lhs()); + std::cout << " * "; + visit(*e.get_rhs()); + std::cout << ")"; +} +void visitor::PrintVisitor::visit(const tree::DivNode& e) +{ + std::cout << "("; + visit(*e.get_lhs()); + std::cout << " / "; + visit(*e.get_rhs()); + std::cout << ")"; +} +void visitor::PrintVisitor::visit(const tree::Leaf& e) +{ + std::cout << e.get_value(); +}
\ No newline at end of file diff --git a/graphs/cpp/visitor/print_visitor.hh b/graphs/cpp/visitor/print_visitor.hh new file mode 100644 index 0000000..aa0ea4c --- /dev/null +++ b/graphs/cpp/visitor/print_visitor.hh @@ -0,0 +1,25 @@ +// +// Created by martial.simon on 2/27/25. +// + +#pragma once + +#include "visitor.hh" + +namespace visitor +{ + class PrintVisitor : public Visitor + { + public: + void visit(const tree::Tree& e); + void visit(const tree::Node& e); + void visit(const tree::AddNode& e); + void visit(const tree::SubNode& e); + void visit(const tree::MulNode& e); + void visit(const tree::DivNode& e); + void visit(const tree::Leaf& e); + + private: + int value_ = 0; + }; +} // namespace visitor diff --git a/graphs/cpp/war/assassin.cc b/graphs/cpp/war/assassin.cc new file mode 100644 index 0000000..090ec8b --- /dev/null +++ b/graphs/cpp/war/assassin.cc @@ -0,0 +1,5 @@ +#include "assassin.hh" + +Assassin::Assassin() + : Soldier(10, 9, "Out of the shadows!") +{} diff --git a/graphs/cpp/war/assassin.hh b/graphs/cpp/war/assassin.hh new file mode 100644 index 0000000..548fd8b --- /dev/null +++ b/graphs/cpp/war/assassin.hh @@ -0,0 +1,8 @@ +#pragma once +#include "soldier.hh" + +class Assassin : public Soldier +{ +public: + Assassin(); +};
\ No newline at end of file diff --git a/graphs/cpp/war/knight.cc b/graphs/cpp/war/knight.cc new file mode 100644 index 0000000..be52105 --- /dev/null +++ b/graphs/cpp/war/knight.cc @@ -0,0 +1,5 @@ +#include "knight.hh" + +Knight::Knight() + : Soldier(20, 5, "Be quick or be dead!") +{} diff --git a/graphs/cpp/war/knight.hh b/graphs/cpp/war/knight.hh new file mode 100644 index 0000000..d4f2b5f --- /dev/null +++ b/graphs/cpp/war/knight.hh @@ -0,0 +1,8 @@ +#pragma once +#include "soldier.hh" + +class Knight : public Soldier +{ +public: + Knight(); +};
\ No newline at end of file diff --git a/graphs/cpp/war/regiment.cc b/graphs/cpp/war/regiment.cc new file mode 100644 index 0000000..3534ced --- /dev/null +++ b/graphs/cpp/war/regiment.cc @@ -0,0 +1,38 @@ +#include "regiment.hh" + +#include <vector> + +void Regiment::join_by(Regiment& r) +{ + if (r.soldiers_.empty()) + return; + std::vector<Soldier*> v{ r.soldiers_.rbegin(), r.soldiers_.rend() }; + while (!v.empty()) + { + this->soldiers_.push_back(v.back()); + v.pop_back(); + } + r.soldiers_.clear(); +} +size_t Regiment::count() const +{ + return soldiers_.size(); +} +void Regiment::add_soldier(Soldier* s) +{ + soldiers_.push_back(s); +} +void Regiment::print_state() const +{ + for (auto soldier : soldiers_) + { + soldier->print_state(); + } +} +void Regiment::scream() const +{ + for (auto soldier : soldiers_) + { + soldier->scream(); + } +}
\ No newline at end of file diff --git a/graphs/cpp/war/regiment.hh b/graphs/cpp/war/regiment.hh new file mode 100644 index 0000000..ac54953 --- /dev/null +++ b/graphs/cpp/war/regiment.hh @@ -0,0 +1,17 @@ +#pragma once +#include <vector> + +#include "soldier.hh" + +class Regiment +{ +public: + void join_by(Regiment& r); + size_t count() const; + void add_soldier(Soldier* s); + void print_state() const; + void scream() const; + +private: + std::vector<Soldier*> soldiers_; +};
\ No newline at end of file diff --git a/graphs/cpp/war/soldier.cc b/graphs/cpp/war/soldier.cc new file mode 100644 index 0000000..01dc57c --- /dev/null +++ b/graphs/cpp/war/soldier.cc @@ -0,0 +1,24 @@ +#include "soldier.hh" + +#include <iostream> + +Soldier::Soldier(int hp, int dmg, std::string scream) + : health_points_{ hp } + , damage_{ dmg } + , scream_{ scream } +{} + +void Soldier::print_state() const +{ + std::cout << "I have " << health_points_ << " health points.\n"; +} + +void Soldier::scream() const +{ + std::cout << scream_ << "\n"; +} + +void Soldier::attack(Soldier& s) +{ + s.health_points_ -= this->damage_; +} diff --git a/graphs/cpp/war/soldier.hh b/graphs/cpp/war/soldier.hh new file mode 100644 index 0000000..1406022 --- /dev/null +++ b/graphs/cpp/war/soldier.hh @@ -0,0 +1,16 @@ +#pragma once +#include <string> + +class Soldier +{ +public: + Soldier(int hp, int dmg, std::string scream); + void attack(Soldier& s); + void print_state() const; + virtual void scream() const; + +private: + int health_points_; + int damage_; + std::string scream_; +};
\ No newline at end of file |
