From 41426d0e341f00c95b4a0ffe71247584cf863ced Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Sat, 18 Oct 2025 21:08:49 +0530 Subject: [PATCH 1/4] feature: tiling problem sol added --- .../0008_TilingProblem.h | 25 +++++++++++ .../0008_TilingProblem.cc | 42 +++++++++++++++++++ source/0005_DynamicProgramming/CMakeLists.txt | 1 + .../0008_TilingProblemTest.cc | 33 +++++++++++++++ test/0005_DynamicProgramming/CMakeLists.txt | 1 + 5 files changed, 102 insertions(+) create mode 100644 include/0005_DynamicProgramming/0008_TilingProblem.h create mode 100644 source/0005_DynamicProgramming/0008_TilingProblem.cc create mode 100644 test/0005_DynamicProgramming/0008_TilingProblemTest.cc diff --git a/include/0005_DynamicProgramming/0008_TilingProblem.h b/include/0005_DynamicProgramming/0008_TilingProblem.h new file mode 100644 index 0000000..b1646fb --- /dev/null +++ b/include/0005_DynamicProgramming/0008_TilingProblem.h @@ -0,0 +1,25 @@ +#pragma once + +#include +using namespace std; + +/* +Pattern 1 +Linear Recurrence + +Description +Given a "2 x n" board and tiles of size "2 x 1", the task is to count the number of ways to tile the given board using the 2 x 1 tiles. +A tile can either be placed horizontally i.e., as a 1 x 2 tile or vertically i.e., as 2 x 1 tile. +*/ + +namespace TilingProblem +{ + class DynamicProgramming + { + private: + int NumberOfWaysRecursiveHelper(int n); + public: + int RecursiveNumberOfWays(int n); + int DpNumberOfWays(int n); + }; +} \ No newline at end of file diff --git a/source/0005_DynamicProgramming/0008_TilingProblem.cc b/source/0005_DynamicProgramming/0008_TilingProblem.cc new file mode 100644 index 0000000..ccb37c5 --- /dev/null +++ b/source/0005_DynamicProgramming/0008_TilingProblem.cc @@ -0,0 +1,42 @@ +#include "../../include/0005_DynamicProgramming/0008_TilingProblem.h" + +namespace TilingProblem +{ + int DynamicProgramming::NumberOfWaysRecursiveHelper(int n) + { + if (n < 0) + { + return 0; + } + + if (n == 0) + { + return 1; + } + + int result = 0; + result += this->NumberOfWaysRecursiveHelper(n - 1); + result += this->NumberOfWaysRecursiveHelper(n - 2); + + return result; + } + + int DynamicProgramming::RecursiveNumberOfWays(int n) + { + return this->NumberOfWaysRecursiveHelper(n); + } + + int DynamicProgramming::DpNumberOfWays(int n) + { + vector dp(n + 1, 0); + dp[0] = 1; + dp[1] = 1; + + for (int i = 2; i <= n; i++) + { + dp[i] = dp[i - 1] + dp[i - 2]; + } + + return dp[n]; + } +} \ No newline at end of file diff --git a/source/0005_DynamicProgramming/CMakeLists.txt b/source/0005_DynamicProgramming/CMakeLists.txt index c8a87c5..875e985 100644 --- a/source/0005_DynamicProgramming/CMakeLists.txt +++ b/source/0005_DynamicProgramming/CMakeLists.txt @@ -7,6 +7,7 @@ set(0005DYNAMICPROGRAMMING_SOURCES 0005_HouseRobber1.cc 0006_HouseRobber2.cc 0007_DecodeWays.cc + 0008_TilingProblem.cc ) diff --git a/test/0005_DynamicProgramming/0008_TilingProblemTest.cc b/test/0005_DynamicProgramming/0008_TilingProblemTest.cc new file mode 100644 index 0000000..dbff35e --- /dev/null +++ b/test/0005_DynamicProgramming/0008_TilingProblemTest.cc @@ -0,0 +1,33 @@ +#include +#include "../../include/0005_DynamicProgramming/0008_TilingProblem.h" + +namespace TilingProblem +{ + TEST(TilingProblem, RecursionTest01) + { + // Arrange + DynamicProgramming dp; + int nummberOfRows = 4; + int expectedNumberOfWays = 5; + + // Act + int actualNumberOfWays = dp.RecursiveNumberOfWays(nummberOfRows); + + // Assert + ASSERT_EQ(expectedNumberOfWays, actualNumberOfWays); + } + + TEST(TilingProblem, DpTest01) + { + // Arrange + DynamicProgramming dp; + int nummberOfRows = 4; + int expectedNumberOfWays = 5; + + // Act + int actualNumberOfWays = dp.DpNumberOfWays(nummberOfRows); + + // Assert + ASSERT_EQ(expectedNumberOfWays, actualNumberOfWays); + } +} \ No newline at end of file diff --git a/test/0005_DynamicProgramming/CMakeLists.txt b/test/0005_DynamicProgramming/CMakeLists.txt index 2e44016..a22ed15 100644 --- a/test/0005_DynamicProgramming/CMakeLists.txt +++ b/test/0005_DynamicProgramming/CMakeLists.txt @@ -21,6 +21,7 @@ add_executable( 0005_HouseRobber1Test.cc 0006_HouseRobber2Test.cc 0007_DecodeWaysTest.cc + 0008_TilingProblemTest.cc ) From 3b129192d582623d5b8d174bd4aba44a56f055c8 Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Tue, 11 Nov 2025 01:00:31 +0530 Subject: [PATCH 2/4] core: yaml update for validate and auto tag --- .github/PULL_REQUEST_TEMPLATE.md | 15 -- ...structures-algorithms-tag-and-release.yaml | 212 ++++++++++++++++++ ...> datastructures-algorithms-validate.yaml} | 14 +- 3 files changed, 221 insertions(+), 20 deletions(-) delete mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/datastructures-algorithms-tag-and-release.yaml rename .github/workflows/{datastructures-algorithms-ci-cd.yaml => datastructures-algorithms-validate.yaml} (73%) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 2db2c5d..0000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,15 +0,0 @@ -### Description - - - -### Type of Change - -- [ ] Bug fix -- [ ] New feature -- [ ] Core update -- [ ] Tests added -- [ ] Documentation update - - -### Additional Notes - diff --git a/.github/workflows/datastructures-algorithms-tag-and-release.yaml b/.github/workflows/datastructures-algorithms-tag-and-release.yaml new file mode 100644 index 0000000..b98aaab --- /dev/null +++ b/.github/workflows/datastructures-algorithms-tag-and-release.yaml @@ -0,0 +1,212 @@ +name: datastructures-algorithms-tag-and-release + +# Triggers only when a PR to 'main' is closed +on: + pull_request: + types: [closed] # Run when a PR is closed + branches: + - 'main' # Only when the PR's target branch is 'main' + +# Permissions required for the tag/release job +permissions: + contents: write # To create/push tags AND create releases + pull-requests: read # To read the PR body + +jobs: + # --- Job 1: Lint, Build, and Test --- + lint-build-test: + # This job only runs if the PR was actually merged + if: github.event.pull_request.merged == true + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 # Use v4 + + - name: Setup MSVC + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + + - name: Install dependencies + shell: pwsh + run: | + choco install cmake -y + choco install ninja -y + choco install llvm -y + + - name: Configure CMake + shell: pwsh + run: cmake -S . -B build -G "Ninja" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + + - name: Run clang-tidy + shell: pwsh + run: | + clang-tidy --version + $files = Get-ChildItem -Recurse -Path source -Include *.cpp,*.cc,*.cxx -File + + # These source/.* files would be checked using .clang-tidy maintained at projectroot + foreach ($file in $files) { + Write-Host "Running clang-tidy on source $($file.FullName)" + clang-tidy -p build "$($file.FullName)" --warnings-as-errors=* + } + + - name: Build + shell: pwsh + run: cmake --build build + + - name: Run tests + shell: pwsh + run: ctest --test-dir build --output-on-failure + + # --- Job 2: Create Tag and Release --- + create-tag-and-release: + # This job MUST wait for the 'lint-build-test' job to succeed + needs: lint-build-test + + # This job only runs if: + # 1. The PR was actually merged (implicit from 'needs', but good to be explicit). + # 2. The PR was from a branch named exactly 'release'. + if: github.event.pull_request.merged == true && github.event.pull_request.head.ref == 'release' + runs-on: ubuntu-latest + + steps: + # Step 1: Check out the code on the 'main' branch + # fetch-depth: 0 is crucial to get all tags and history + - name: Checkout main branch + uses: actions/checkout@v4 + with: + ref: 'main' + fetch-depth: 0 + + # Step 2: Configure Git with bot credentials + - name: Configure Git + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + # Step 3: Parse the PR body to find the version bump type + - name: Determine Version Bump + id: version_bump + env: + PR_BODY: ${{ github.event.pull_request.body }} + run: | + if echo "$PR_BODY" | grep -q '\[x\] Major'; then + echo "bump_type=major" >> $GITHUB_OUTPUT + elif echo "$PR_BODY" | grep -q '\[x\] Minor'; then + echo "bump_type=minor" >> $GITHUB_OUTPUT + elif echo "$PR_BODY" | grep -q '\[x\] Patch'; then + echo "bump_type=patch" >> $GITHUB_OUTPUT + else + echo "No version bump type selected in PR body. ([x] Major, [x] Minor, or [x] Patch)." + exit 1 + fi + + # Step 4: Get the latest tag + - name: Get latest tag + id: last_tag + run: | + # Fetch all tags from remote just in case + git fetch --tags + + # Find the latest tag matching vX.Y.Z format, sort by version, get the highest + LATEST_TAG=$(git tag --list 'v*.*.*' --sort=-v:refname | head -n 1) + + if [ -z "$LATEST_TAG" ]; then + echo "No previous vX.Y.Z tag found. Starting from v0.0.0." + LATEST_TAG="v0.0.0" + fi + + echo "Last tag: $LATEST_TAG" + echo "last_tag=$LATEST_TAG" >> $GITHUB_OUTPUT + + # Step 5: Calculate the new tag based on the bump type + - name: Calculate new tag + id: new_tag + run: | + BUMP_TYPE=${{ steps.version_bump.outputs.bump_type }} + LAST_TAG=${{ steps.last_tag.outputs.last_tag }} + + # Strip 'v' prefix + VERSION=${LAST_TAG#v} + + # Split into parts + IFS='.' read -r -a parts <<< "$VERSION" + MAJOR=${parts[0]} + MINOR=${parts[1]} + PATCH=${parts[2]} + + # Increment based on bump type + case "$BUMP_TYPE" in + "major") + MAJOR=$((MAJOR + 1)) + MINOR=0 + PATCH=0 + ;; + "minor") + MINOR=$((MINOR + 1)) + PATCH=0 + ;; + "patch") + PATCH=$((PATCH + 1)) + ;; + esac + + NEW_TAG="v${MAJOR}.${MINOR}.${PATCH}" + echo "new_tag=$NEW_TAG" >> $GITHUB_OUTPUT + echo "New tag will be: $NEW_TAG" + + # Step 6: Create and push the new tag + - name: Create and push new tag + run: | + NEW_TAG=${{ steps.new_tag.outputs.new_tag }} + MERGE_COMMIT_SHA=${{ github.event.pull_request.merge_commit_sha }} + + echo "Tagging commit $MERGE_COMMIT_SHA as $NEW_TAG" + git tag $NEW_TAG $MERGE_COMMIT_SHA + git push origin $NEW_TAG + + # Step 7: Extract Release Summary from PR Body + - name: Extract Release Summary + id: extract_summary + env: + PR_BODY: ${{ github.event.pull_request.body }} + run: | + # Use an awk "state machine" to extract text between the two markers. + # We use "<<<" (a "here string") to safely pass the multiline $PR_BODY to awk. + # We must escape the '*' characters with '\' for the regex. + + # 1. /\*\*Release Summary\*\*/{f=1; next} : When we see the START marker, set flag 'f' to 1 and skip to the next line. + # 2. /\*\*Version Bump Type\*\*/{f=0} : When we see the END marker, set flag 'f' to 0. + # 3. f : If flag 'f' is 1 (true), print the current line. + SUMMARY=$(awk '/\*\*Release Summary\*\*/{f=1; next} /\*\*Version Bump Type\*\*/{f=0} f' <<< "$PR_BODY") + + # Use multiline string syntax for GITHUB_OUTPUT + echo "summary<> $GITHUB_OUTPUT + echo "$SUMMARY" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + # Step 8: Create GitHub Release + - name: Create GitHub Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NEW_TAG: ${{ steps.new_tag.outputs.new_tag }} + SUMMARY: ${{ steps.extract_summary.outputs.summary }} + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + # Check if summary is empty, and provide a default + if [ -z "$SUMMARY" ]; then + echo "Release summary was empty. Using PR title as notes." + RELEASE_NOTES="$PR_TITLE" + else + RELEASE_NOTES="$SUMMARY" + fi + + # Create the release using the GitHub CLI + # --latest: Marks this as the latest official release + # --title: Set to just the tag name as requested + gh release create $NEW_TAG \ + --title "$NEW_TAG" \ + --notes "$RELEASE_NOTES" \ + --target ${{ github.event.pull_request.merge_commit_sha }} \ + --latest \ No newline at end of file diff --git a/.github/workflows/datastructures-algorithms-ci-cd.yaml b/.github/workflows/datastructures-algorithms-validate.yaml similarity index 73% rename from .github/workflows/datastructures-algorithms-ci-cd.yaml rename to .github/workflows/datastructures-algorithms-validate.yaml index 9c8f0e2..db55be6 100644 --- a/.github/workflows/datastructures-algorithms-ci-cd.yaml +++ b/.github/workflows/datastructures-algorithms-validate.yaml @@ -1,18 +1,22 @@ -name: datastructures-algorithms-ci-cd +name: datastructures-algorithms-validate +# Triggers when a PR is opened or updated, targeting the 'release' branch on: - push: - branches: [ main, release ] pull_request: - branches: [ main, release ] + types: [opened, synchronize] + branches: [release] jobs: + # --- Job 1: Lint, Build, and Test --- lint-build-test: + + # This job will ONLY run if the PR's source branch starts with 'feature-' + if: startsWith(github.event.pull_request.head.ref, 'feature-') runs-on: windows-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Use v4 - name: Setup MSVC uses: ilammy/msvc-dev-cmd@v1 From feeb6010c96eceb5a5de94ce302639c181583af1 Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Tue, 11 Nov 2025 01:01:51 +0530 Subject: [PATCH 3/4] core: PR template updated --- .github/pull_request_template.md | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..25a93ee --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,35 @@ +### Pull Request Guidelines + +1. While creating Pull Request from feature to release branch, please provide proper description and check the boxes for specific changes made in this feature branch. +2. While creating Pull Request from release to main branch, please check the appropriate version bump from the provided list. + +--- +### PR from feature to release + +**Description** + + +**Type of Change** + +- [ ] Bug fix +- [ ] New feature +- [ ] Core update +- [ ] Tests added +- [ ] Documentation update + +**Notes** + + +---- +### PR from release to main + +**Release Summary** + + +**Version Bump Type** +- [ ] Major +- [ ] Minor +- [ ] Patch + +**Notes** + From f5a4e4a2d716759249cb80a562901afe5a3a3380 Mon Sep 17 00:00:00 2001 From: Debashis Nandi Date: Tue, 11 Nov 2025 01:21:16 +0530 Subject: [PATCH 4/4] core: validate, deploy yaml fix --- ... => datastructures-algorithms-deploy.yaml} | 54 ++----------------- .../datastructures-algorithms-validate.yaml | 11 ++-- 2 files changed, 11 insertions(+), 54 deletions(-) rename .github/workflows/{datastructures-algorithms-tag-and-release.yaml => datastructures-algorithms-deploy.yaml} (80%) diff --git a/.github/workflows/datastructures-algorithms-tag-and-release.yaml b/.github/workflows/datastructures-algorithms-deploy.yaml similarity index 80% rename from .github/workflows/datastructures-algorithms-tag-and-release.yaml rename to .github/workflows/datastructures-algorithms-deploy.yaml index b98aaab..cca4a5b 100644 --- a/.github/workflows/datastructures-algorithms-tag-and-release.yaml +++ b/.github/workflows/datastructures-algorithms-deploy.yaml @@ -1,4 +1,4 @@ -name: datastructures-algorithms-tag-and-release +name: datastructures-algorithms-deploy # Triggers only when a PR to 'main' is closed on: @@ -13,57 +13,9 @@ permissions: pull-requests: read # To read the PR body jobs: - # --- Job 1: Lint, Build, and Test --- - lint-build-test: - # This job only runs if the PR was actually merged - if: github.event.pull_request.merged == true - runs-on: windows-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 # Use v4 - - - name: Setup MSVC - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: x64 - - - name: Install dependencies - shell: pwsh - run: | - choco install cmake -y - choco install ninja -y - choco install llvm -y - - - name: Configure CMake - shell: pwsh - run: cmake -S . -B build -G "Ninja" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - - - name: Run clang-tidy - shell: pwsh - run: | - clang-tidy --version - $files = Get-ChildItem -Recurse -Path source -Include *.cpp,*.cc,*.cxx -File - - # These source/.* files would be checked using .clang-tidy maintained at projectroot - foreach ($file in $files) { - Write-Host "Running clang-tidy on source $($file.FullName)" - clang-tidy -p build "$($file.FullName)" --warnings-as-errors=* - } - - - name: Build - shell: pwsh - run: cmake --build build - - - name: Run tests - shell: pwsh - run: ctest --test-dir build --output-on-failure - - # --- Job 2: Create Tag and Release --- + # --- Job 1: Create Tag and Release --- create-tag-and-release: - # This job MUST wait for the 'lint-build-test' job to succeed - needs: lint-build-test - + # This job only runs if: # 1. The PR was actually merged (implicit from 'needs', but good to be explicit). # 2. The PR was from a branch named exactly 'release'. diff --git a/.github/workflows/datastructures-algorithms-validate.yaml b/.github/workflows/datastructures-algorithms-validate.yaml index db55be6..6ade440 100644 --- a/.github/workflows/datastructures-algorithms-validate.yaml +++ b/.github/workflows/datastructures-algorithms-validate.yaml @@ -4,14 +4,19 @@ name: datastructures-algorithms-validate on: pull_request: types: [opened, synchronize] - branches: [release] + branches: + - 'release' + - 'main' jobs: # --- Job 1: Lint, Build, and Test --- lint-build-test: - # This job will ONLY run if the PR's source branch starts with 'feature-' - if: startsWith(github.event.pull_request.head.ref, 'feature-') + # This job will ONLY run if: + # 1. (Source is 'feature-*' AND Target is 'release') + # OR + # 2. (Source is 'release' AND Target is 'main') + if: (startsWith(github.event.pull_request.head.ref, 'feature-') && github.event.pull_request.base.ref == 'release') || (github.event.pull_request.head.ref == 'release' && github.event.pull_request.base.ref == 'main') runs-on: windows-latest steps: