From 4904a4201061f15e68075b743c13eff0936d0a21 Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Fri, 4 Jul 2025 02:05:52 +0530 Subject: [PATCH 1/4] feature: dp rod cutting init --- .../0005_DynamicProgramming/0001_RodCutting.h | 16 +++++++++ .../0001_RodCutting.cc | 11 +++++++ source/0005_DynamicProgramming/CMakeLists.txt | 8 +++++ .../0001_RodCuttingTest.cc | 0 test/0005_DynamicProgramming/CMakeLists.txt | 33 +++++++++++++++++++ 5 files changed, 68 insertions(+) create mode 100644 include/0005_DynamicProgramming/0001_RodCutting.h create mode 100644 source/0005_DynamicProgramming/0001_RodCutting.cc create mode 100644 test/0005_DynamicProgramming/0001_RodCuttingTest.cc diff --git a/include/0005_DynamicProgramming/0001_RodCutting.h b/include/0005_DynamicProgramming/0001_RodCutting.h new file mode 100644 index 0000000..cb32d3b --- /dev/null +++ b/include/0005_DynamicProgramming/0001_RodCutting.h @@ -0,0 +1,16 @@ +#pragma once +#include +using namespace std; + +namespace RodCutting +{ + class DynamicProgramming + { + private: + int _length; + vector _price; + public: + DynamicProgramming(int length, vector price); + int RecursiveCutRod(); + }; +} \ No newline at end of file diff --git a/source/0005_DynamicProgramming/0001_RodCutting.cc b/source/0005_DynamicProgramming/0001_RodCutting.cc new file mode 100644 index 0000000..fef9556 --- /dev/null +++ b/source/0005_DynamicProgramming/0001_RodCutting.cc @@ -0,0 +1,11 @@ +#include "../../include/0005_DynamicProgramming/0001_RodCutting.h" + +namespace RodCutting +{ + DynamicProgramming::DynamicProgramming(int length, vector price) + { + this->_length = length; + this->_price = price; + } + +} \ No newline at end of file diff --git a/source/0005_DynamicProgramming/CMakeLists.txt b/source/0005_DynamicProgramming/CMakeLists.txt index e69de29..64fd7f7 100644 --- a/source/0005_DynamicProgramming/CMakeLists.txt +++ b/source/0005_DynamicProgramming/CMakeLists.txt @@ -0,0 +1,8 @@ +# Specify the source files +set(0005DYNAMICPROGRAMMING_SOURCES + 0001_RodCutting.cc + +) + +# Create a library target +add_library(0005DYNAMICPROGRAMMING ${0005DYNAMICPROGRAMMING_SOURCES}) \ No newline at end of file diff --git a/test/0005_DynamicProgramming/0001_RodCuttingTest.cc b/test/0005_DynamicProgramming/0001_RodCuttingTest.cc new file mode 100644 index 0000000..e69de29 diff --git a/test/0005_DynamicProgramming/CMakeLists.txt b/test/0005_DynamicProgramming/CMakeLists.txt index e69de29..83adbdb 100644 --- a/test/0005_DynamicProgramming/CMakeLists.txt +++ b/test/0005_DynamicProgramming/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_policy(SET CMP0135 NEW) + +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) + +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + +enable_testing() + +add_executable( + 0005DynamicProgrammingTests + 0001_RodCuttingTest.cc + +) + +target_link_libraries( + 0005DynamicProgrammingTests + GTest::gtest_main + 0004DYNAMICPROGRAMMING +) + +# Add .clang-tidy configuration to this library. +if(CLANG_TIDY_EXE) + set_target_properties(0005DYNAMICPROGRAMMING PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}") +endif() + +include(GoogleTest) +gtest_discover_tests(0005DynamicProgrammingTests DISCOVERY_TIMEOUT 30) \ No newline at end of file From e1254f868299f281822235b4ed12390377420721 Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Sat, 5 Jul 2025 00:43:33 +0530 Subject: [PATCH 2/4] feature: dp rod cutting impl. added --- .../0005_DynamicProgramming/0001_RodCutting.h | 4 +- .../0001_RodCutting.cc | 36 ++++++++++++++++++ .../0001_RodCuttingTest.cc | 38 +++++++++++++++++++ test/0005_DynamicProgramming/CMakeLists.txt | 2 +- 4 files changed, 78 insertions(+), 2 deletions(-) diff --git a/include/0005_DynamicProgramming/0001_RodCutting.h b/include/0005_DynamicProgramming/0001_RodCutting.h index cb32d3b..4daa03d 100644 --- a/include/0005_DynamicProgramming/0001_RodCutting.h +++ b/include/0005_DynamicProgramming/0001_RodCutting.h @@ -1,4 +1,5 @@ #pragma once +#include #include using namespace std; @@ -11,6 +12,7 @@ namespace RodCutting vector _price; public: DynamicProgramming(int length, vector price); - int RecursiveCutRod(); + int RecursiveRodCutting(int length); + int DynamicProgrammingRodCutting(); }; } \ No newline at end of file diff --git a/source/0005_DynamicProgramming/0001_RodCutting.cc b/source/0005_DynamicProgramming/0001_RodCutting.cc index fef9556..f3c5517 100644 --- a/source/0005_DynamicProgramming/0001_RodCutting.cc +++ b/source/0005_DynamicProgramming/0001_RodCutting.cc @@ -1,4 +1,7 @@ #include "../../include/0005_DynamicProgramming/0001_RodCutting.h" +#include +#include +using namespace std; namespace RodCutting { @@ -8,4 +11,37 @@ namespace RodCutting this->_price = price; } + int DynamicProgramming::RecursiveRodCutting(int length) + { + // Base case + if (length == 0) + { + return 0; + } + + int result = 0; + + for (int cut = 1; cut <= length; cut++) + { + result = max(result, this->_price[cut - 1] + this->RecursiveRodCutting(length - cut)); + } + + return result; + } + + int DynamicProgramming::DynamicProgrammingRodCutting() + { + vector dp(this->_price.size() + 1, 0); + + // Find maximum value for all rod of length i. + for (int i = 1; i <= this->_length; i++) + { + for (int j = 1; j <= i; j++) + { + dp[i] = max(dp[i], this->_price[j - 1] + dp[i-j]); + } + } + + return dp[this->_length]; + } } \ No newline at end of file diff --git a/test/0005_DynamicProgramming/0001_RodCuttingTest.cc b/test/0005_DynamicProgramming/0001_RodCuttingTest.cc index e69de29..b6fe141 100644 --- a/test/0005_DynamicProgramming/0001_RodCuttingTest.cc +++ b/test/0005_DynamicProgramming/0001_RodCuttingTest.cc @@ -0,0 +1,38 @@ +#include +#include "../../include/0005_DynamicProgramming/0001_RodCutting.h" +#include "../0000_CommonUtilities/UnitTestHelper.h" + +namespace RodCutting +{ + UnitTestHelper unitTestHelper; + + TEST(DpRodCutting, RecursiveTest) + { + // Arrange + int length = 8; + vector price = { 1, 5, 8, 9, 10, 17, 17, 20 }; + DynamicProgramming dp(length, price); + int expectedResult = 22; + + // Act + int actualResult = dp.RecursiveRodCutting(length); + + // Assert + EXPECT_EQ(actualResult, expectedResult); + } + + TEST(DpRodCutting, DpTest) + { + // Arrange + int length = 8; + vector price = { 1, 5, 8, 9, 10, 17, 17, 20 }; + DynamicProgramming dp(length, price); + int expectedResult = 22; + + // Act + int actualResult = dp.DynamicProgrammingRodCutting(); + + // Assert + EXPECT_EQ(actualResult, expectedResult); + } +} \ No newline at end of file diff --git a/test/0005_DynamicProgramming/CMakeLists.txt b/test/0005_DynamicProgramming/CMakeLists.txt index 83adbdb..899a9a5 100644 --- a/test/0005_DynamicProgramming/CMakeLists.txt +++ b/test/0005_DynamicProgramming/CMakeLists.txt @@ -21,7 +21,7 @@ add_executable( target_link_libraries( 0005DynamicProgrammingTests GTest::gtest_main - 0004DYNAMICPROGRAMMING + 0005DYNAMICPROGRAMMING ) # Add .clang-tidy configuration to this library. From 6b537d0a49a75a4a903b224ede24bb2786d105c0 Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Sun, 13 Jul 2025 00:06:55 +0530 Subject: [PATCH 3/4] fix: dp rod cutting updated --- .../0005_DynamicProgramming/0001_RodCutting.h | 3 ++- .../0005_DynamicProgramming/0001_RodCutting.cc | 16 ++++++++++++---- .../0001_RodCuttingTest.cc | 4 ++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/include/0005_DynamicProgramming/0001_RodCutting.h b/include/0005_DynamicProgramming/0001_RodCutting.h index 4daa03d..7726323 100644 --- a/include/0005_DynamicProgramming/0001_RodCutting.h +++ b/include/0005_DynamicProgramming/0001_RodCutting.h @@ -10,9 +10,10 @@ namespace RodCutting private: int _length; vector _price; + vector _cutPositions; public: DynamicProgramming(int length, vector price); int RecursiveRodCutting(int length); - int DynamicProgrammingRodCutting(); + pair> DpGetMaximumProfitWithCuts(); }; } \ No newline at end of file diff --git a/source/0005_DynamicProgramming/0001_RodCutting.cc b/source/0005_DynamicProgramming/0001_RodCutting.cc index f3c5517..e9f07a3 100644 --- a/source/0005_DynamicProgramming/0001_RodCutting.cc +++ b/source/0005_DynamicProgramming/0001_RodCutting.cc @@ -18,7 +18,7 @@ namespace RodCutting { return 0; } - + int result = 0; for (int cut = 1; cut <= length; cut++) @@ -29,19 +29,27 @@ namespace RodCutting return result; } - int DynamicProgramming::DynamicProgrammingRodCutting() + pair> DynamicProgramming::DpGetMaximumProfitWithCuts() { vector dp(this->_price.size() + 1, 0); + this->_cutPositions = vector(this->_price.size() + 1, 0); // Find maximum value for all rod of length i. for (int i = 1; i <= this->_length; i++) { for (int j = 1; j <= i; j++) { - dp[i] = max(dp[i], this->_price[j - 1] + dp[i-j]); + if (dp[i] < (this->_price[j - 1] + dp[i - j])) + { + dp[i] = this->_price[j - 1] + dp[i - j]; + this->_cutPositions[i] = j - 1; + } } } - return dp[this->_length]; + // Re-construct the cuts + + + return { dp[this->_length] ,{} }; } } \ No newline at end of file diff --git a/test/0005_DynamicProgramming/0001_RodCuttingTest.cc b/test/0005_DynamicProgramming/0001_RodCuttingTest.cc index b6fe141..eb46cba 100644 --- a/test/0005_DynamicProgramming/0001_RodCuttingTest.cc +++ b/test/0005_DynamicProgramming/0001_RodCuttingTest.cc @@ -30,9 +30,9 @@ namespace RodCutting int expectedResult = 22; // Act - int actualResult = dp.DynamicProgrammingRodCutting(); + pair> actualResult = dp.DpGetMaximumProfitWithCuts(); // Assert - EXPECT_EQ(actualResult, expectedResult); + EXPECT_EQ(actualResult.first, expectedResult); } } \ No newline at end of file From 6d8acfea8a8cb9f797b605e2c4855051de97485e Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Thu, 17 Jul 2025 22:33:37 +0530 Subject: [PATCH 4/4] feature-test: added the cut lengths for dp rod cut --- .../0005_DynamicProgramming/0001_RodCutting.h | 6 +++--- .../0005_DynamicProgramming/0001_RodCutting.cc | 18 ++++++++++++------ .../0001_RodCuttingTest.cc | 18 ++++++++++-------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/include/0005_DynamicProgramming/0001_RodCutting.h b/include/0005_DynamicProgramming/0001_RodCutting.h index 7726323..f39ffe2 100644 --- a/include/0005_DynamicProgramming/0001_RodCutting.h +++ b/include/0005_DynamicProgramming/0001_RodCutting.h @@ -8,12 +8,12 @@ namespace RodCutting class DynamicProgramming { private: - int _length; + int _totalLength; vector _price; vector _cutPositions; public: - DynamicProgramming(int length, vector price); + DynamicProgramming(vector price); int RecursiveRodCutting(int length); - pair> DpGetMaximumProfitWithCuts(); + pair> DpGetMaximumProfitWithCuts(int length); }; } \ No newline at end of file diff --git a/source/0005_DynamicProgramming/0001_RodCutting.cc b/source/0005_DynamicProgramming/0001_RodCutting.cc index e9f07a3..a382702 100644 --- a/source/0005_DynamicProgramming/0001_RodCutting.cc +++ b/source/0005_DynamicProgramming/0001_RodCutting.cc @@ -5,10 +5,10 @@ using namespace std; namespace RodCutting { - DynamicProgramming::DynamicProgramming(int length, vector price) + DynamicProgramming::DynamicProgramming(vector price) { - this->_length = length; this->_price = price; + this->_totalLength = this->_price.size(); } int DynamicProgramming::RecursiveRodCutting(int length) @@ -29,13 +29,13 @@ namespace RodCutting return result; } - pair> DynamicProgramming::DpGetMaximumProfitWithCuts() + pair> DynamicProgramming::DpGetMaximumProfitWithCuts(int length) { vector dp(this->_price.size() + 1, 0); this->_cutPositions = vector(this->_price.size() + 1, 0); // Find maximum value for all rod of length i. - for (int i = 1; i <= this->_length; i++) + for (int i = 1; i <= this->_totalLength; i++) { for (int j = 1; j <= i; j++) { @@ -48,8 +48,14 @@ namespace RodCutting } // Re-construct the cuts + vector cutLengths; + int currentLength = length; + while (currentLength > 0) + { + cutLengths.push_back(this->_cutPositions[currentLength] + 1); + currentLength -= cutLengths.back(); + } - - return { dp[this->_length] ,{} }; + return { dp[length] ,cutLengths }; } } \ No newline at end of file diff --git a/test/0005_DynamicProgramming/0001_RodCuttingTest.cc b/test/0005_DynamicProgramming/0001_RodCuttingTest.cc index eb46cba..966a247 100644 --- a/test/0005_DynamicProgramming/0001_RodCuttingTest.cc +++ b/test/0005_DynamicProgramming/0001_RodCuttingTest.cc @@ -9,30 +9,32 @@ namespace RodCutting TEST(DpRodCutting, RecursiveTest) { // Arrange + vector price = { 1, 5, 8, 9, 10, 17, 17, 20, 24, 30 }; int length = 8; - vector price = { 1, 5, 8, 9, 10, 17, 17, 20 }; - DynamicProgramming dp(length, price); + DynamicProgramming dp(price); int expectedResult = 22; // Act int actualResult = dp.RecursiveRodCutting(length); // Assert - EXPECT_EQ(actualResult, expectedResult); + ASSERT_EQ(actualResult, expectedResult); } TEST(DpRodCutting, DpTest) { // Arrange + vector price = { 1, 5, 8, 9, 10, 17, 17, 20, 24, 30 }; int length = 8; - vector price = { 1, 5, 8, 9, 10, 17, 17, 20 }; - DynamicProgramming dp(length, price); - int expectedResult = 22; + DynamicProgramming dp(price); + int expectedProfit = 22; + vector expectedCuts = { 2, 6 }; // Act - pair> actualResult = dp.DpGetMaximumProfitWithCuts(); + pair> actualResult = dp.DpGetMaximumProfitWithCuts(length); // Assert - EXPECT_EQ(actualResult.first, expectedResult); + ASSERT_EQ(actualResult.first, expectedProfit); + ASSERT_EQ(actualResult.second, expectedCuts); } } \ No newline at end of file