diff --git a/.gitignore b/.gitignore
index 19ff643..b28d52c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
-competitive_programming/build/*
-competitive_programming/test/env/*
+**/build/*
+**/env/*
.vscode/*
\ No newline at end of file
diff --git a/README.md b/README.md
index bd9546d..e63667d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,67 @@
-# Competitive Programming C Plus Plus Library
+
Competitive Programming C Plus Plus Library
-A C++ library for competitive programming that includes a wide range of algorithms and data structures. Additionally, the project provides tests to ensure the correctness of its implementations.
+
+ Technologies •
+ Getting Started •
+ Contribute
+
+
+ A C++ library for competitive programming that includes a wide range of algorithms and data structures. Additionally, the project provides tests to ensure the correctness of its implementations.
+
+
+💻 Technologies
+
+- g++ 14
+- Conan
+- gtest
+
+
+🚀 Getting started
+
+Prerequisites
+
+- g++ 14
+- Python 3
+- CMake
+
+Cloning
+
+How to clone your project
+
+```bash
+git clone https://github.com/ThiagoFBastos/Competitive-Programming-C-Plus-Plus-Library.git
+```
+
+Starting
+
+How to start your project
+
+```bash
+cd competitive_programming
+sudo apt install dos2unix
+dos2unix ./scripts/install_deps.sh
+dos2unix ./scripts/test.sh
+sudo chmod +x ./scripts/install_deps.sh
+sudo chmod +x ./scripts/test.sh
+./scripts/install_deps.sh
+```
+
+How to run the tests
+
+```bash
+./scripts/test.sh
+```
+
+📫 Contribute
+
+1. `git clone https://github.com/ThiagoFBastos/Competitive-Programming-C-Plus-Plus-Library.git`
+2. `git checkout -b feature/NAME`
+3. Follow commit patterns
+4. Open a Pull Request explaining the problem solved or feature made, if exists, append screenshot of visual modifications and wait for the review!
+
+Documentations that might help
+
+[📝 How to create a Pull Request](https://www.atlassian.com/br/git/tutorials/making-a-pull-request)
+
+[💾 Commit pattern](https://gist.github.com/joshbuchea/6f47e86d2510bce28f8e7f42ae84c716)
\ No newline at end of file
diff --git a/competitive_programming/scripts/install_deps.sh b/competitive_programming/scripts/install_deps.sh
index a5432f9..e122bf6 100644
--- a/competitive_programming/scripts/install_deps.sh
+++ b/competitive_programming/scripts/install_deps.sh
@@ -2,8 +2,31 @@
set -e
-BUILD_DIR=build
+DIR="$(cd "$(dirname "$0")" && pwd)"
+
+BUILD_DIR=$DIR/../build
BUILD_TYPE=Release
+SRC=$DIR/..
+
+cd $SRC
+
+echo "==> Criando o ambiente virtual"
+python3 -m venv env
+
+echo "==> Ativando o ambiente virtual"
+source ./env/bin/activate
+
+echo "==> Instalando o Conan"
+pip install conan
+
+echo "==> Criando o Conan profile"
+conan profile detect --force
+
+export CC=gcc-14
+export CXX=g++-14
+export CONAN_SETTINGS_COMPILER=gcc
+export CONAN_SETTINGS_COMPILER_VERSION=14
+export CONAN_SETTINGS_COMPILER_LIBCXX=libstdc++11
echo "==> Instalando dependências (Conan)"
conan install . \
diff --git a/competitive_programming/scripts/test.sh b/competitive_programming/scripts/test.sh
index 66ed751..9cd3975 100644
--- a/competitive_programming/scripts/test.sh
+++ b/competitive_programming/scripts/test.sh
@@ -2,7 +2,10 @@
set -e
-BUILD_DIR=build
+DIR="$(cd "$(dirname "$0")" && pwd)"
+
+BUILD_DIR=$DIR/../build
+
if [ -d $BUILD_DIR ]; then
echo "==> Compilando"
diff --git a/competitive_programming/src/bitwise/maximum_xor_subset.hpp b/competitive_programming/src/bitwise/maximum_xor_subset.hpp
new file mode 100644
index 0000000..3e6152f
--- /dev/null
+++ b/competitive_programming/src/bitwise/maximum_xor_subset.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include
+#include
+
+namespace bitset {
+
+using value_type = unsigned long long;
+
+inline value_type maximum_xor_subset(std::vector arr) {
+ constexpr int max_bits = 64;
+
+ value_type result {};
+
+ for (int i = max_bits - 1; i >= 0; --i)
+ {
+ value_type max_element {};
+
+ for (const auto& num : arr)
+ {
+ if((num >> i) & 1)
+ max_element = std::max(max_element, num);
+ }
+
+ if(max_element == 0) continue;
+
+ if((result ^ max_element) > result)
+ result ^= max_element;
+
+ for(auto& num : arr)
+ {
+ if((num >> i) & 1)
+ num ^= max_element;
+ }
+ }
+
+ return result;
+}
+
+}
\ No newline at end of file
diff --git a/competitive_programming/src/data_structures/dynamic_hull.hpp b/competitive_programming/src/data_structures/dynamic_hull.hpp
index b76dca7..d0c2617 100644
--- a/competitive_programming/src/data_structures/dynamic_hull.hpp
+++ b/competitive_programming/src/data_structures/dynamic_hull.hpp
@@ -3,6 +3,8 @@
#include
#include
+/// FIXME
+/// This data structure only handles queries of type (x, 1), which is incomplete
struct line
{
long long m, b;
diff --git a/competitive_programming/src/dp/removal_game.hpp b/competitive_programming/src/dp/removal_game.hpp
new file mode 100644
index 0000000..6f3efba
--- /dev/null
+++ b/competitive_programming/src/dp/removal_game.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+namespace dp
+{
+
+/**
+ * There is a list of n numbers and two players who move alternately.
+ * On each move, a player removes either the first or last number from the list,
+ * and their score increases by that number. Both players try to maximize their scores.
+ * What is the maximum possible score for the first player when both players play optimally?
+ * n <= 5000
+ * -10^9 <= nums[i] <= 10^9
+ * @param nums The list of numbers.
+ * @return The maximum possible score for the first player.
+ */
+inline long long removal_game(const std::vector& nums)
+{
+ const auto n = nums.size();
+ const auto sum = std::accumulate(nums.begin(), nums.end(), 0LL);
+ constexpr long long INF = 0x1000000000000LL;
+
+ std::vector> dp(n, {0LL, 0LL});
+
+ std::size_t turn = ~n & 1;
+
+ for(std::size_t i = 0; i < n; ++i)
+ dp[i][turn] = nums[i];
+
+ for(std::size_t len = n - 1; len > 0; --len)
+ {
+ turn ^= 1;
+
+ std::size_t my = turn, your = turn ^ 1;
+
+ for(std::size_t i = 0; i < len; ++i)
+ dp[i][my] = -INF;
+
+ for(std::size_t i = 0; i < len; ++i)
+ dp[i][my] = std::max(dp[i][my], nums[i] - dp[i + 1][your]);
+
+ for(std::size_t i = 0; i < len; ++i)
+ dp[i][my] = std::max(dp[i][my], nums[i + n - len] - dp[i][your]);
+ }
+
+ return (sum + dp[0][0]) / 2;
+}
+
+}
\ No newline at end of file
diff --git a/competitive_programming/src/dp/removing_digits.hpp b/competitive_programming/src/dp/removing_digits.hpp
new file mode 100644
index 0000000..3bb3a25
--- /dev/null
+++ b/competitive_programming/src/dp/removing_digits.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include
+#include
+
+namespace dp
+{
+
+/**
+ * Given an integer n, return the minimum number of steps to reduce it to zero.
+ * In one step, you can remove any digit from n and subtract it from n.
+ */
+inline int removing_digits(int n)
+{
+ std::vector dp(n + 1);
+
+ dp[0] = 0;
+
+ for(int k = 1; k <= n; ++k)
+ {
+ int digit = 0;
+
+ for(int N = k; N > 0; N /= 10)
+ digit = std::max(N % 10, digit);
+
+ dp[k] = 1 + dp[k - digit];
+ }
+
+ return dp[n];
+}
+
+}
\ No newline at end of file
diff --git a/competitive_programming/src/geometry/circle.hpp b/competitive_programming/src/geometry/circle.hpp
index 41076ca..45a54b5 100644
--- a/competitive_programming/src/geometry/circle.hpp
+++ b/competitive_programming/src/geometry/circle.hpp
@@ -138,14 +138,24 @@ inline circle minimumCircle(std::vector& p)
std::shuffle(p.begin(), p.end(), rng);
int n = p.size();
circle C(p[0], 0.0);
- for(int i = 0; i < n; ++i) {
- if(C.contains(p[i])) continue;
+
+ for(int i = 0; i < n; ++i)
+ {
+ if(C.contains(p[i]))
+ continue;
+
C = circle(p[i], 0.0);
- for(int j = 0; j < i; ++j) {
- if(C.contains(p[j])) continue;
+ for(int j = 0; j < i; ++j)
+ {
+ if(C.contains(p[j]))
+ continue;
+
C = circle((p[j] + p[i]) * 0.5, 0.5 * dist(p[j], p[i]));
- for(int k = 0; k < j; ++k) {
- if(C.contains(p[k])) continue;
+ for(int k = 0; k < j; ++k)
+ {
+ if(C.contains(p[k]))
+ continue;
+
C = circumcircle(p[j], p[i], p[k]);
}
}
diff --git a/competitive_programming/src/geometry/point.hpp b/competitive_programming/src/geometry/point.hpp
index 21c3450..fcc9852 100644
--- a/competitive_programming/src/geometry/point.hpp
+++ b/competitive_programming/src/geometry/point.hpp
@@ -4,7 +4,7 @@
namespace geometry {
-constexpr double EPS = 1e-9;
+inline constexpr double EPS = 1e-9;
struct point
{
diff --git a/competitive_programming/src/math/fft.hpp b/competitive_programming/src/math/fft.hpp
index b24a45a..dd22475 100644
--- a/competitive_programming/src/math/fft.hpp
+++ b/competitive_programming/src/math/fft.hpp
@@ -9,25 +9,31 @@ namespace math {
using cd = std::complex;
-inline void fft(std::vector& a, bool invert) {
+inline void fft(std::vector& a, bool invert)
+{
const double PI = std::acos(-1);
int n = a.size();
- for(int i = 1, j = 0; i < n; ++i) {
+ for(int i = 1, j = 0; i < n; ++i)
+ {
int bit = n >> 1;
for(; j & bit; bit >>= 1) j -= bit;
j += bit;
- if(i < j) std::swap(a[i], a[j]);
+ if(i < j)
+ std::swap(a[i], a[j]);
}
- for(int len = 2; len <= n; len <<= 1) {
+ for(int len = 2; len <= n; len <<= 1)
+ {
double ang = 2 * PI / len * (invert ? -1 : 1);
cd wlen(std::cos(ang), std::sin(ang));
int mid = len >> 1;
- for(int i = 0; i < n; i += len) {
+ for(int i = 0; i < n; i += len)
+ {
cd w(1);
- for(int j = 0; j < mid; ++j) {
+ for(int j = 0; j < mid; ++j)
+ {
cd u = a[i + j], v = a[i + j + mid] * w;
a[i + j] = u + v;
a[i + j + mid] = u - v;
@@ -36,11 +42,12 @@ inline void fft(std::vector& a, bool invert) {
}
}
- if(invert) for(int i = 0; i < n; ++i) a[i] /= n;
+ if(invert)
+ for(int i = 0; i < n; ++i) a[i] /= n;
}
-inline void multiply(std::vector& result, const std::vector& a, const std::vector& b) {
-
+inline void multiply(std::vector& result, const std::vector& a, const std::vector& b)
+{
std::vector fa(a.begin(), a.end()), fb(b.begin(), b.end());
auto lg = [](int x) {
@@ -60,7 +67,9 @@ inline void multiply(std::vector& result, const std::vector& a, const
fft(fa, true);
result.resize(n);
- for(int i = 0; i < n; ++i) result[i] = (int)std::round(fa[i].real());
+
+ for(int i = 0; i < n; ++i)
+ result[i] = (int)std::round(fa[i].real());
}
}
diff --git a/competitive_programming/test/bitwise/CMakeLists.txt b/competitive_programming/test/bitwise/CMakeLists.txt
index c2bcb92..ab0f62d 100644
--- a/competitive_programming/test/bitwise/CMakeLists.txt
+++ b/competitive_programming/test/bitwise/CMakeLists.txt
@@ -3,6 +3,12 @@ add_executable(counting-bits counting_bits.cpp)
target_include_directories(counting-bits PRIVATE ${PROJECT_INCLUDE_DIR})
target_link_libraries(counting-bits PRIVATE GTest::gtest GTest::gtest_main)
+# Maximum Xor Subset
+add_executable(maximum-xor-subset maximum_xor_subset.cpp)
+target_include_directories(maximum-xor-subset PRIVATE ${PROJECT_INCLUDE_DIR})
+target_link_libraries(maximum-xor-subset PRIVATE GTest::gtest GTest::gtest_main)
+
include(GoogleTest)
-gtest_discover_tests(counting-bits)
\ No newline at end of file
+gtest_discover_tests(counting-bits)
+gtest_discover_tests(maximum-xor-subset)
\ No newline at end of file
diff --git a/competitive_programming/test/bitwise/maximum_xor_subset.cpp b/competitive_programming/test/bitwise/maximum_xor_subset.cpp
new file mode 100644
index 0000000..5edd11d
--- /dev/null
+++ b/competitive_programming/test/bitwise/maximum_xor_subset.cpp
@@ -0,0 +1,48 @@
+#include
+
+#include
+#include
+#include
+
+#include "bitwise/maximum_xor_subset.hpp"
+
+using namespace bitset;
+
+TEST(MaximumXorSubset, MaximumXorSubsetTest)
+{
+ EXPECT_EQ(maximum_xor_subset({1, 6, 12, 6}), 13);
+ EXPECT_EQ(maximum_xor_subset({48, 33, 96, 77, 67, 59, 35, 15, 14, 86}), 127);
+ EXPECT_EQ(maximum_xor_subset({5, 1, 2}), 7);
+ EXPECT_EQ(maximum_xor_subset({7, 8, 1, 2, 16, 32}), 63);
+}
+
+TEST(MaximumXorSubset, RandomTest)
+{
+ constexpr std::size_t N = 10;
+
+ std::random_device rd;
+ std::mt19937 gen(rd());
+ std::uniform_int_distribution uid(0, std::numeric_limits::max());
+
+ std::vector arr(N);
+
+ value_type expected_result {};
+
+ for(std::size_t i = 0; i < N; ++i)
+ arr[i] = uid(gen);
+
+ for(std::size_t i = 0; i < (1 << N); ++i)
+ {
+ value_type current_xor {};
+
+ for(std::size_t j = 0; j < N; ++j)
+ {
+ if((i >> j) & 1)
+ current_xor ^= arr[j];
+ }
+
+ expected_result = std::max(expected_result, current_xor);
+ }
+
+ EXPECT_EQ(maximum_xor_subset(std::move(arr)), expected_result);
+}
\ No newline at end of file
diff --git a/competitive_programming/test/dp/CMakeLists.txt b/competitive_programming/test/dp/CMakeLists.txt
index db08c63..0abda76 100644
--- a/competitive_programming/test/dp/CMakeLists.txt
+++ b/competitive_programming/test/dp/CMakeLists.txt
@@ -18,9 +18,21 @@ add_executable(dp-number-of-subsequences number_of_subsequences.cpp)
target_include_directories(dp-number-of-subsequences PRIVATE ${PROJECT_INCLUDE_DIR})
target_link_libraries(dp-number-of-subsequences PRIVATE GTest::gtest GTest::gtest_main)
+# Removing Digits
+add_executable(dp-removing-digits removing_digits.cpp)
+target_include_directories(dp-removing-digits PRIVATE ${PROJECT_INCLUDE_DIR})
+target_link_libraries(dp-removing-digits PRIVATE GTest::gtest GTest::gtest_main)
+
+# Removal Game
+add_executable(dp-removal-game removal_game.cpp)
+target_include_directories(dp-removal-game PRIVATE ${PROJECT_INCLUDE_DIR})
+target_link_libraries(dp-removal-game PRIVATE GTest::gtest GTest::gtest_main)
+
include(GoogleTest)
gtest_discover_tests(dp-edit-distance)
gtest_discover_tests(dp-lcs)
gtest_discover_tests(dp-rectangle-cutting)
-gtest_discover_tests(dp-number-of-subsequences)
\ No newline at end of file
+gtest_discover_tests(dp-number-of-subsequences)
+gtest_discover_tests(dp-removing-digits)
+gtest_discover_tests(dp-removal-game)
\ No newline at end of file
diff --git a/competitive_programming/test/dp/removal_game.cpp b/competitive_programming/test/dp/removal_game.cpp
new file mode 100644
index 0000000..0c2ab33
--- /dev/null
+++ b/competitive_programming/test/dp/removal_game.cpp
@@ -0,0 +1,16 @@
+#include
+
+#include "dp/removal_game.hpp"
+
+using namespace dp;
+
+TEST(RemovalGame, TestPairs)
+{
+ EXPECT_EQ(removal_game({-5, 5, 9, -4, 10, -9, 0, 3, 2, -6}), 16);
+ EXPECT_EQ(removal_game({0, -3, -9, -9, -3, 5, 6, 3, 8, 5}), 2);
+ EXPECT_EQ(removal_game({-5, 5, -5, 6, -8, -9, -6, 3, 0, 2}), 7);
+ EXPECT_EQ(removal_game({-7, 6, -8, -7, -10, -8, -7, 10, -6, -10}), -9);
+ EXPECT_EQ(removal_game({-8, 4, 6, -2, 5, -4, -5, 9, 10, 1}), 13);
+ EXPECT_EQ(removal_game({1, 2, 9}), 10);
+ EXPECT_EQ(removal_game({5}), 5);
+}
\ No newline at end of file
diff --git a/competitive_programming/test/dp/removing_digits.cpp b/competitive_programming/test/dp/removing_digits.cpp
new file mode 100644
index 0000000..2460198
--- /dev/null
+++ b/competitive_programming/test/dp/removing_digits.cpp
@@ -0,0 +1,25 @@
+#include
+
+#include "dp/removing_digits.hpp"
+
+using namespace dp;
+
+TEST(RemovingDigits, TestPairs)
+{
+ EXPECT_EQ(removing_digits(27), 5);
+ EXPECT_EQ(removing_digits(4), 1);
+ EXPECT_EQ(removing_digits(17), 3);
+ EXPECT_EQ(removing_digits(35), 7);
+ EXPECT_EQ(removing_digits(167), 29);
+ EXPECT_EQ(removing_digits(4434), 687);
+ EXPECT_EQ(removing_digits(9722), 1381);
+ EXPECT_EQ(removing_digits(37882), 5406);
+ EXPECT_EQ(removing_digits(103330), 13867);
+ EXPECT_EQ(removing_digits(562167), 75527);
+ EXPECT_EQ(removing_digits(991919), 127308);
+ EXPECT_EQ(removing_digits(999993), 128206);
+ EXPECT_EQ(removing_digits(999999), 128206);
+ EXPECT_EQ(removing_digits(23456), 3364);
+ EXPECT_EQ(removing_digits(1000000), 128207);
+}
+
diff --git a/competitive_programming/test/geometry/CMakeLists.txt b/competitive_programming/test/geometry/CMakeLists.txt
index e69de29..2f11137 100644
--- a/competitive_programming/test/geometry/CMakeLists.txt
+++ b/competitive_programming/test/geometry/CMakeLists.txt
@@ -0,0 +1,14 @@
+# Point
+add_executable(point point.cpp)
+target_include_directories(point PRIVATE ${PROJECT_INCLUDE_DIR})
+target_link_libraries(point PRIVATE GTest::gtest GTest::gtest_main)
+
+# Circle
+add_executable(circle circle.cpp)
+target_include_directories(circle PRIVATE ${PROJECT_INCLUDE_DIR})
+target_link_libraries(circle PRIVATE GTest::gtest GTest::gtest_main)
+
+include(GoogleTest)
+
+gtest_discover_tests(point)
+gtest_discover_tests(circle)
\ No newline at end of file
diff --git a/competitive_programming/test/geometry/circle.cpp b/competitive_programming/test/geometry/circle.cpp
new file mode 100644
index 0000000..a5681da
--- /dev/null
+++ b/competitive_programming/test/geometry/circle.cpp
@@ -0,0 +1,11 @@
+#include
+
+#include "geometry/circle.hpp"
+
+TEST(Circle, CompileTest)
+{
+ geometry::point center(0, 0);
+ geometry::circle c(center, 10);
+
+ EXPECT_TRUE(true);
+}
\ No newline at end of file
diff --git a/competitive_programming/test/geometry/point.cpp b/competitive_programming/test/geometry/point.cpp
new file mode 100644
index 0000000..e20ed8f
--- /dev/null
+++ b/competitive_programming/test/geometry/point.cpp
@@ -0,0 +1,10 @@
+#include
+
+#include "geometry/point.hpp"
+
+TEST(Point, CompileTest)
+{
+ geometry::point p(0, 0);
+
+ EXPECT_TRUE(true);
+}
\ No newline at end of file
diff --git a/competitive_programming/test/math/CMakeLists.txt b/competitive_programming/test/math/CMakeLists.txt
index 055686a..1c97503 100644
--- a/competitive_programming/test/math/CMakeLists.txt
+++ b/competitive_programming/test/math/CMakeLists.txt
@@ -23,10 +23,16 @@ add_executable(pollard-rho pollard_rho.cpp)
target_include_directories(pollard-rho PRIVATE ${PROJECT_INCLUDE_DIR})
target_link_libraries(pollard-rho PRIVATE GTest::gtest GTest::gtest_main)
+# FFT
+add_executable(fft fft.cpp)
+target_include_directories(fft PRIVATE ${PROJECT_INCLUDE_DIR})
+target_link_libraries(fft PRIVATE GTest::gtest GTest::gtest_main)
+
include(GoogleTest)
gtest_discover_tests(bin-exp)
gtest_discover_tests(miller-rabin)
gtest_discover_tests(euclides-ext)
gtest_discover_tests(mint)
-gtest_discover_tests(pollard-rho)
\ No newline at end of file
+gtest_discover_tests(pollard-rho)
+gtest_discover_tests(fft)
\ No newline at end of file
diff --git a/competitive_programming/test/math/fft.cpp b/competitive_programming/test/math/fft.cpp
new file mode 100644
index 0000000..ad67879
--- /dev/null
+++ b/competitive_programming/test/math/fft.cpp
@@ -0,0 +1,14 @@
+#include
+
+#include "math/fft.hpp"
+
+TEST(FFT, CompileTest)
+{
+ std::vector result;
+ std::vector a{0, 1, 0, 0};
+ std::vector b{1, 1, 1, 1};
+
+ math::multiply(result, a, b);
+
+ EXPECT_TRUE(true);
+}
\ No newline at end of file