Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions .github/PULL_REQUEST_TEMPLATE.md

This file was deleted.

35 changes: 35 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -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**

164 changes: 164 additions & 0 deletions .github/workflows/datastructures-algorithms-deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
name: datastructures-algorithms-deploy

# 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: Create Tag and Release ---
create-tag-and-release:

# 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<<EOF" >> $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
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
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'
- 'main'

jobs:
# --- Job 1: Lint, Build, and Test ---
lint-build-test:

# 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:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4 # Use v4

- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
Expand Down
25 changes: 25 additions & 0 deletions include/0005_DynamicProgramming/0008_TilingProblem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include<vector>
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);
};
}
42 changes: 42 additions & 0 deletions source/0005_DynamicProgramming/0008_TilingProblem.cc
Original file line number Diff line number Diff line change
@@ -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<int> 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];
}
}
1 change: 1 addition & 0 deletions source/0005_DynamicProgramming/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(0005DYNAMICPROGRAMMING_SOURCES
0005_HouseRobber1.cc
0006_HouseRobber2.cc
0007_DecodeWays.cc
0008_TilingProblem.cc

)

Expand Down
33 changes: 33 additions & 0 deletions test/0005_DynamicProgramming/0008_TilingProblemTest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include<gtest/gtest.h>
#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);
}
}
1 change: 1 addition & 0 deletions test/0005_DynamicProgramming/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ add_executable(
0005_HouseRobber1Test.cc
0006_HouseRobber2Test.cc
0007_DecodeWaysTest.cc
0008_TilingProblemTest.cc

)

Expand Down