summaryrefslogtreecommitdiff
path: root/graphs/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'graphs/cpp')
-rw-r--r--graphs/cpp/.clang-format80
-rw-r--r--graphs/cpp/.gitignore6
-rw-r--r--graphs/cpp/CMakeLists.txt12
-rw-r--r--graphs/cpp/address_book/address_book.cc75
-rw-r--r--graphs/cpp/address_book/address_book.hh25
-rw-r--r--graphs/cpp/address_book/contact_details.cc38
-rw-r--r--graphs/cpp/address_book/contact_details.hh15
-rw-r--r--graphs/cpp/address_book/main.cc42
-rw-r--r--graphs/cpp/antagonist/CMakeLists.txt20
-rw-r--r--graphs/cpp/antagonist/include/libbeaver/beaver.hh18
-rw-r--r--graphs/cpp/antagonist/src/CMakeLists.txt19
-rw-r--r--graphs/cpp/antagonist/src/beaver/CMakeLists.txt6
-rw-r--r--graphs/cpp/antagonist/src/beaver/beaver.cc12
-rw-r--r--graphs/cpp/antagonist/src/beaver/beaver_impl.cc24
-rw-r--r--graphs/cpp/antagonist/src/beaver/beaver_impl.hh21
-rw-r--r--graphs/cpp/antagonist/src/video_player/CMakeLists.txt6
-rw-r--r--graphs/cpp/antagonist/src/video_player/video_player.cc59
-rw-r--r--graphs/cpp/antagonist/src/video_player/video_player.hh12
-rw-r--r--graphs/cpp/antagonist/test/CMakeLists.txt10
-rw-r--r--graphs/cpp/antagonist/test/main.cc10
-rw-r--r--graphs/cpp/antagonist/test/video/video.mp4bin0 -> 533288 bytes
-rw-r--r--graphs/cpp/bimap/bimap.hh36
-rw-r--r--graphs/cpp/bimap/bimap.hxx74
-rw-r--r--graphs/cpp/bimap/bimap_example.cc26
-rw-r--r--graphs/cpp/cartesian_vector/format_numerical_data.cc13
-rw-r--r--graphs/cpp/cartesian_vector/format_numerical_data.hh22
-rw-r--r--graphs/cpp/cartesian_vector/state_saver.cc11
-rw-r--r--graphs/cpp/cartesian_vector/state_saver.hh20
-rw-r--r--graphs/cpp/cartesian_vector/vector.cc69
-rw-r--r--graphs/cpp/cartesian_vector/vector.hh29
-rw-r--r--graphs/cpp/cartesian_vector/vector_test.cc27
-rw-r--r--graphs/cpp/caste_or_cast/Makefile15
-rw-r--r--graphs/cpp/caste_or_cast/ant.cc87
-rw-r--r--graphs/cpp/caste_or_cast/ant.hh70
-rw-r--r--graphs/cpp/caste_or_cast/colony.cc116
-rw-r--r--graphs/cpp/caste_or_cast/colony.hh43
-rw-r--r--graphs/cpp/caste_or_cast/main_example.cc37
-rw-r--r--graphs/cpp/caste_or_cast/nurturer.cc98
-rw-r--r--graphs/cpp/caste_or_cast/nurturer.hh27
-rw-r--r--graphs/cpp/caste_or_cast/provider.cc47
-rw-r--r--graphs/cpp/caste_or_cast/provider.hh29
-rw-r--r--graphs/cpp/caste_or_cast/queen.cc30
-rw-r--r--graphs/cpp/caste_or_cast/queen.hh32
-rw-r--r--graphs/cpp/caste_or_cast/worker.cc28
-rw-r--r--graphs/cpp/caste_or_cast/worker.hh30
-rw-r--r--graphs/cpp/chain_of_responsibility/director.cc10
-rw-r--r--graphs/cpp/chain_of_responsibility/handler.cc19
-rw-r--r--graphs/cpp/chain_of_responsibility/president.cc10
-rw-r--r--graphs/cpp/chain_of_responsibility/vice_president.cc10
-rw-r--r--graphs/cpp/closer_to/closer_to.cc15
-rw-r--r--graphs/cpp/closer_to/closer_to.hh11
-rw-r--r--graphs/cpp/closer_to/closer_to_test.cc29
-rw-r--r--graphs/cpp/const-td/CMakeLists.txt6
-rw-r--r--graphs/cpp/const-td/main.cc25
-rw-r--r--graphs/cpp/const/CMakeLists.txt6
-rw-r--r--graphs/cpp/const/person.cc25
-rw-r--r--graphs/cpp/const/person.hh17
-rw-r--r--graphs/cpp/const/test_person.cc20
-rw-r--r--graphs/cpp/directories_infos/directory_info.cc34
-rw-r--r--graphs/cpp/directories_infos/directory_info.hh24
-rw-r--r--graphs/cpp/directories_infos/main_example.cc32
-rw-r--r--graphs/cpp/directories_infos/read_info.cc39
-rw-r--r--graphs/cpp/directories_infos/read_info.hh7
-rw-r--r--graphs/cpp/doubly_linked_list/CMakeLists.txt8
-rw-r--r--graphs/cpp/doubly_linked_list/list.cc88
-rw-r--r--graphs/cpp/doubly_linked_list/list.hh24
-rw-r--r--graphs/cpp/doubly_linked_list/main.cc36
-rw-r--r--graphs/cpp/doubly_linked_list/node.cc29
-rw-r--r--graphs/cpp/doubly_linked_list/node.hh23
-rw-r--r--graphs/cpp/exception/Makefile14
-rw-r--r--graphs/cpp/exception/game.cc23
-rw-r--r--graphs/cpp/exception/game.hh14
-rw-r--r--graphs/cpp/exception/invalid_argument.cc9
-rw-r--r--graphs/cpp/exception/invalid_argument.hh15
-rw-r--r--graphs/cpp/exception/main.cc80
-rw-r--r--graphs/cpp/exception/player.cc34
-rw-r--r--graphs/cpp/exception/player.hh26
-rw-r--r--graphs/cpp/exist_functor/example.cc24
-rw-r--r--graphs/cpp/exist_functor/exist.hh14
-rw-r--r--graphs/cpp/exist_functor/exist.hxx15
-rw-r--r--graphs/cpp/for_each/for_each.hh6
-rw-r--r--graphs/cpp/for_each/for_each.hxx9
-rw-r--r--graphs/cpp/for_each/main.cc10
-rw-r--r--graphs/cpp/forward_multiplication/forward_multiplication.cc7
-rw-r--r--graphs/cpp/forward_multiplication/forward_multiplication.hh7
-rw-r--r--graphs/cpp/forward_multiplication/forward_multiplication_test.cc21
-rw-r--r--graphs/cpp/hello_world/hello_world.cc6
-rw-r--r--graphs/cpp/hot_potato/bomb.cc28
-rw-r--r--graphs/cpp/hot_potato/bomb.hh11
-rw-r--r--graphs/cpp/hot_potato/game.cc48
-rw-r--r--graphs/cpp/hot_potato/game.hh17
-rw-r--r--graphs/cpp/hot_potato/main.cc20
-rw-r--r--graphs/cpp/hot_potato/player.cc63
-rw-r--r--graphs/cpp/hot_potato/player.hh25
-rw-r--r--graphs/cpp/implements/implements.hh47
-rw-r--r--graphs/cpp/int_container/int_container.cc83
-rw-r--r--graphs/cpp/int_container/int_container.hh45
-rw-r--r--graphs/cpp/is_prime/is_prime.hh5
-rw-r--r--graphs/cpp/is_prime/is_prime.hxx21
-rw-r--r--graphs/cpp/logger/CMakeLists.txt8
-rw-r--r--graphs/cpp/logger/logger.cc73
-rw-r--r--graphs/cpp/logger/logger.hh47
-rw-r--r--graphs/cpp/logger/main.cc13
-rw-r--r--graphs/cpp/lookup_table/fibo.cc15
-rw-r--r--graphs/cpp/lookup_table/fibo.hh12
-rw-r--r--graphs/cpp/lookup_table/lookup_table.cc14
-rw-r--r--graphs/cpp/lookup_table/lookup_table.hh14
-rw-r--r--graphs/cpp/lookup_table/lookup_table_test.cc9
-rw-r--r--graphs/cpp/merge_sort/merge_sort.cc12
-rw-r--r--graphs/cpp/merge_sort/merge_sort.hh16
-rw-r--r--graphs/cpp/my_nfts/auction.cc45
-rw-r--r--graphs/cpp/my_nfts/auction.hh34
-rw-r--r--graphs/cpp/my_nfts/main.cc37
-rw-r--r--graphs/cpp/my_nfts/nft.hh15
-rw-r--r--graphs/cpp/my_nfts/nft.hxx11
-rw-r--r--graphs/cpp/my_nfts/person.cc61
-rw-r--r--graphs/cpp/my_nfts/person.hh39
-rw-r--r--graphs/cpp/path/path.cc10
-rw-r--r--graphs/cpp/path/path.hh25
-rw-r--r--graphs/cpp/path/path_example.cc22
-rw-r--r--graphs/cpp/path/unix_path.cc25
-rw-r--r--graphs/cpp/path/unix_path.hh13
-rw-r--r--graphs/cpp/path/windows_path.cc37
-rw-r--r--graphs/cpp/path/windows_path.hh14
-rw-r--r--graphs/cpp/point/CMakeLists.txt7
-rw-r--r--graphs/cpp/point/main.cc7
-rw-r--r--graphs/cpp/point/point.cc14
-rw-r--r--graphs/cpp/point/point.hh12
-rw-r--r--graphs/cpp/ref_swap/main.cc17
-rw-r--r--graphs/cpp/ref_swap/ref_swap.cc18
-rw-r--r--graphs/cpp/ref_swap/ref_swap.hh5
-rw-r--r--graphs/cpp/replace/inputfile1
-rw-r--r--graphs/cpp/replace/replace.cc39
-rw-r--r--graphs/cpp/replace/replace.hh6
-rw-r--r--graphs/cpp/replace/test_replace.cc16
-rw-r--r--graphs/cpp/singleton/singleton.cc21
-rw-r--r--graphs/cpp/singleton/singleton.hh33
-rw-r--r--graphs/cpp/singleton/singleton.hxx9
-rw-r--r--graphs/cpp/smtptr/main.cc20
-rw-r--r--graphs/cpp/smtptr/shared_pointer.hh166
-rw-r--r--graphs/cpp/smtptr/shared_pointer.hxx144
-rw-r--r--graphs/cpp/smtptr/shared_pointer_is_a.cc47
-rw-r--r--graphs/cpp/stdin_to_file/stdin_to_file.cc20
-rw-r--r--graphs/cpp/stdin_to_file/stdin_to_file.hh6
-rw-r--r--graphs/cpp/stdin_to_file/stdin_to_file_example.cc10
-rw-r--r--graphs/cpp/visitor/compute_visitor.cc62
-rw-r--r--graphs/cpp/visitor/compute_visitor.hh26
-rw-r--r--graphs/cpp/visitor/print_visitor.cc58
-rw-r--r--graphs/cpp/visitor/print_visitor.hh25
-rw-r--r--graphs/cpp/war/assassin.cc5
-rw-r--r--graphs/cpp/war/assassin.hh8
-rw-r--r--graphs/cpp/war/knight.cc5
-rw-r--r--graphs/cpp/war/knight.hh8
-rw-r--r--graphs/cpp/war/regiment.cc38
-rw-r--r--graphs/cpp/war/regiment.hh17
-rw-r--r--graphs/cpp/war/soldier.cc24
-rw-r--r--graphs/cpp/war/soldier.hh16
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
new file mode 100644
index 0000000..7b788c6
--- /dev/null
+++ b/graphs/cpp/antagonist/test/video/video.mp4
Binary files differ
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