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
31 changes: 31 additions & 0 deletions dynamic/burstballoons.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package dynamic

import "github.com/TheAlgorithms/Go/math/max"

// MaxCoins returns the maximum coins we can collect by bursting the balloons
func MaxCoins(nums []int) int {
n := len(nums)
if n == 0 {
return 0
}

nums = append([]int{1}, nums...)
nums = append(nums, 1)

dp := make([][]int, n+2)
for i := range dp {
dp[i] = make([]int, n+2)
}

for length := 1; length <= n; length++ {
for left := 1; left+length-1 <= n; left++ {
right := left + length - 1
for k := left; k <= right; k++ {
coins := nums[left-1] * nums[k] * nums[right+1]
dp[left][right] = max.Int(dp[left][right], dp[left][k-1]+dp[k+1][right]+coins)
}
}
}

return dp[1][n]
}
33 changes: 33 additions & 0 deletions dynamic/burstballoons_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dynamic_test

import (
"testing"

"github.com/TheAlgorithms/Go/dynamic"
)

type testCaseBurstBalloons struct {
nums []int
expected int
}

func getBurstBalloonsTestCases() []testCaseBurstBalloons {
return []testCaseBurstBalloons{
{[]int{3, 1, 5, 8}, 167}, // Maximum coins from [3,1,5,8]
{[]int{1, 5}, 10}, // Maximum coins from [1,5]
{[]int{1}, 1}, // Single balloon
{[]int{}, 0}, // No balloons
}

}

func TestMaxCoins(t *testing.T) {
t.Run("Burst Balloons test cases", func(t *testing.T) {
for _, tc := range getBurstBalloonsTestCases() {
actual := dynamic.MaxCoins(tc.nums)
if actual != tc.expected {
t.Errorf("MaxCoins(%v) = %d; expected %d", tc.nums, actual, tc.expected)
}
}
})
}
33 changes: 33 additions & 0 deletions dynamic/dicethrow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// dicethrow.go
// description: Solves the Dice Throw Problem using dynamic programming
// reference: https://www.geeksforgeeks.org/dice-throw-problem/
// time complexity: O(m * n)
// space complexity: O(m * n)

package dynamic

// DiceThrow returns the number of ways to get sum `sum` using `m` dice with `n` faces
func DiceThrow(m, n, sum int) int {
dp := make([][]int, m+1)
for i := range dp {
dp[i] = make([]int, sum+1)
}

for i := 1; i <= n; i++ {
if i <= sum {
dp[1][i] = 1
}
}

for i := 2; i <= m; i++ {
for j := 1; j <= sum; j++ {
for k := 1; k <= n; k++ {
if j-k >= 0 {
dp[i][j] += dp[i-1][j-k]
}
}
}
}

return dp[m][sum]
}
42 changes: 42 additions & 0 deletions dynamic/dicethrow_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package dynamic_test

import (
"testing"

"github.com/TheAlgorithms/Go/dynamic"
)

type testCaseDiceThrow struct {
numDice int
numFaces int
targetSum int
expected int
}

// getDiceThrowTestCases provides the test cases for DiceThrow
func getDiceThrowTestCases() []testCaseDiceThrow {
return []testCaseDiceThrow{
{2, 6, 7, 6}, // Two dice, six faces each, sum = 7
{1, 6, 3, 1}, // One die, six faces, sum = 3
{3, 4, 5, 6}, // Three dice, four faces each, sum = 5
{1, 6, 1, 1}, // One die, six faces, sum = 1
{2, 6, 12, 1}, // Two dice, six faces each, sum = 12
{3, 6, 18, 1}, // Three dice, six faces each, sum = 18
{2, 6, 20, 0}, // Two dice, six faces each, sum = 20 (impossible)
{1, 1, 1, 1}, // One die, one face, sum = 1
{1, 1, 2, 0}, // One die, one face, sum = 2 (impossible)
{2, 1, 2, 1}, // Two dice, one face each, sum = 2
}
}

// TestDiceThrow tests the DiceThrow function with basic test cases
func TestDiceThrow(t *testing.T) {
t.Run("Basic test cases", func(t *testing.T) {
for _, tc := range getDiceThrowTestCases() {
actual := dynamic.DiceThrow(tc.numDice, tc.numFaces, tc.targetSum)
if actual != tc.expected {
t.Errorf("DiceThrow(%d, %d, %d) = %d; expected %d", tc.numDice, tc.numFaces, tc.targetSum, actual, tc.expected)
}
}
})
}
47 changes: 47 additions & 0 deletions dynamic/eggdropping.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package dynamic

import (
"github.com/TheAlgorithms/Go/math/max"
"github.com/TheAlgorithms/Go/math/min"
)

// EggDropping finds the minimum number of attempts needed to find the critical floor
// with `eggs` number of eggs and `floors` number of floors
func EggDropping(eggs, floors int) int {
// Edge case: If there are no floors, no attempts needed
if floors == 0 {
return 0
}
// Edge case: If there is one floor, one attempt needed
if floors == 1 {
return 1
}
// Edge case: If there is one egg, need to test all floors one by one
if eggs == 1 {
return floors
}

// Initialize DP table
dp := make([][]int, eggs+1)
for i := range dp {
dp[i] = make([]int, floors+1)
}

// Fill the DP table for 1 egg
for j := 1; j <= floors; j++ {
dp[1][j] = j
}

// Fill the DP table for more than 1 egg
for i := 2; i <= eggs; i++ {
for j := 2; j <= floors; j++ {
dp[i][j] = int(^uint(0) >> 1) // initialize with a large number
for x := 1; x <= j; x++ {
// Recurrence relation to fill the DP table
res := max.Int(dp[i-1][x-1], dp[i][j-x]) + 1
dp[i][j] = min.Int(dp[i][j], res)
}
}
}
return dp[eggs][floors]
}
35 changes: 35 additions & 0 deletions dynamic/eggdropping_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dynamic_test

import (
"testing"

"github.com/TheAlgorithms/Go/dynamic"
)

type testCaseEggDropping struct {
eggs int
floors int
expected int
}

func getEggDroppingTestCases() []testCaseEggDropping {
return []testCaseEggDropping{
{1, 10, 10}, // One egg, need to test all floors
{2, 10, 4}, // Two eggs and ten floors
{3, 14, 4}, // Three eggs and fourteen floors
{2, 36, 8}, // Two eggs and thirty-six floors
{2, 0, 0}, // Two eggs, zero floors
}

}

func TestEggDropping(t *testing.T) {
t.Run("Egg Dropping test cases", func(t *testing.T) {
for _, tc := range getEggDroppingTestCases() {
actual := dynamic.EggDropping(tc.eggs, tc.floors)
if actual != tc.expected {
t.Errorf("EggDropping(%d, %d) = %d; expected %d", tc.eggs, tc.floors, actual, tc.expected)
}
}
})
}
36 changes: 36 additions & 0 deletions dynamic/interleavingstrings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// interleavingstrings.go
// description: Solves the Interleaving Strings problem using dynamic programming
// reference: https://en.wikipedia.org/wiki/Interleaving_strings
// time complexity: O(m*n)
// space complexity: O(m*n)

package dynamic

// IsInterleave checks if string `s1` and `s2` can be interleaved to form string `s3`
func IsInterleave(s1, s2, s3 string) bool {
if len(s1)+len(s2) != len(s3) {
return false
}

dp := make([][]bool, len(s1)+1)
for i := range dp {
dp[i] = make([]bool, len(s2)+1)
}

dp[0][0] = true
for i := 1; i <= len(s1); i++ {
dp[i][0] = dp[i-1][0] && s1[i-1] == s3[i-1]
}

for j := 1; j <= len(s2); j++ {
dp[0][j] = dp[0][j-1] && s2[j-1] == s3[j-1]
}

for i := 1; i <= len(s1); i++ {
for j := 1; j <= len(s2); j++ {
dp[i][j] = (dp[i-1][j] && s1[i-1] == s3[i+j-1]) || (dp[i][j-1] && s2[j-1] == s3[i+j-1])
}
}

return dp[len(s1)][len(s2)]
}
38 changes: 38 additions & 0 deletions dynamic/interleavingstrings_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package dynamic_test

import (
"testing"

"github.com/TheAlgorithms/Go/dynamic"
)

type testCaseInterleaving struct {
s1, s2, s3 string
expected bool
}

func getInterleavingTestCases() []testCaseInterleaving {
return []testCaseInterleaving{
{"aab", "axy", "aaxaby", true}, // Valid interleaving
{"aab", "axy", "abaaxy", false}, // Invalid interleaving
{"", "", "", true}, // All empty strings
{"abc", "", "abc", true}, // Only s1 matches s3
{"", "xyz", "xyz", true}, // Only s2 matches s3
{"abc", "xyz", "abxcyz", true}, // Valid interleaving
{"aaa", "aaa", "aaaaaa", true}, // Identical strings
{"aaa", "aaa", "aaaaaaa", false}, // Extra character
{"abc", "def", "abcdef", true}, // Concatenation order
{"abc", "def", "adbcef", true}, // Valid mixed interleaving
}
}

func TestIsInterleave(t *testing.T) {
t.Run("Interleaving Strings test cases", func(t *testing.T) {
for _, tc := range getInterleavingTestCases() {
actual := dynamic.IsInterleave(tc.s1, tc.s2, tc.s3)
if actual != tc.expected {
t.Errorf("IsInterleave(%q, %q, %q) = %v; expected %v", tc.s1, tc.s2, tc.s3, actual, tc.expected)
}
}
})
}
34 changes: 34 additions & 0 deletions dynamic/longestarithmeticsubsequence.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// longestarithmeticsubsequence.go
// description: Implementation of the Longest Arithmetic Subsequence problem
// reference: https://en.wikipedia.org/wiki/Longest_arithmetic_progression
// time complexity: O(n^2)
// space complexity: O(n^2)

package dynamic

// LongestArithmeticSubsequence returns the length of the longest arithmetic subsequence
func LongestArithmeticSubsequence(nums []int) int {
n := len(nums)
if n <= 1 {
return n
}

dp := make([]map[int]int, n)
for i := range dp {
dp[i] = make(map[int]int)
}

maxLength := 1

for i := 1; i < n; i++ {
for j := 0; j < i; j++ {
diff := nums[i] - nums[j]
dp[i][diff] = dp[j][diff] + 1
if dp[i][diff]+1 > maxLength {
maxLength = dp[i][diff] + 1
}
}
}

return maxLength
}
38 changes: 38 additions & 0 deletions dynamic/longestarithmeticsubsequence_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package dynamic_test

import (
"testing"

"github.com/TheAlgorithms/Go/dynamic"
)

type testCaseLongestArithmeticSubsequence struct {
nums []int
expected int
}

func getLongestArithmeticSubsequenceTestCases() []testCaseLongestArithmeticSubsequence {
return []testCaseLongestArithmeticSubsequence{
{[]int{3, 6, 9, 12}, 4}, // Arithmetic sequence of length 4
{[]int{9, 4, 7, 2, 10}, 3}, // Arithmetic sequence of length 3
{[]int{20, 1, 15, 3, 10, 5, 8}, 4}, // Arithmetic sequence of length 4
{[]int{1, 2, 3, 4, 5}, 5}, // Arithmetic sequence of length 5
{[]int{10, 7, 4, 1}, 4}, // Arithmetic sequence of length 4
{[]int{1, 5, 7, 8, 5, 3, 4, 3, 1, 2}, 4}, // Arithmetic sequence of length 4
{[]int{1, 3, 5, 7, 9}, 5}, // Arithmetic sequence of length 5
{[]int{5, 10, 15, 20}, 4}, // Arithmetic sequence of length 4
{[]int{1}, 1}, // Single element, length is 1
{[]int{}, 0}, // Empty array, length is 0
}
}

func TestLongestArithmeticSubsequence(t *testing.T) {
t.Run("Longest Arithmetic Subsequence test cases", func(t *testing.T) {
for _, tc := range getLongestArithmeticSubsequenceTestCases() {
actual := dynamic.LongestArithmeticSubsequence(tc.nums)
if actual != tc.expected {
t.Errorf("LongestArithmeticSubsequence(%v) = %v; expected %v", tc.nums, actual, tc.expected)
}
}
})
}
Loading
Loading