diff --git a/src/main/java/com/thealgorithms/greedyalgorithms/ActivitySelection.java b/src/main/java/com/thealgorithms/greedyalgorithms/ActivitySelection.java new file mode 100644 index 000000000000..0f704dd6ed55 --- /dev/null +++ b/src/main/java/com/thealgorithms/greedyalgorithms/ActivitySelection.java @@ -0,0 +1,40 @@ +package com.thealgorithms.greedyalgorithms; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; + +// Problem Link: https://en.wikipedia.org/wiki/Activity_selection_problem + +public class ActivitySelection { + // Function to perform activity selection + public static ArrayList activitySelection(int startTimes[], int endTimes[]) { + int n = startTimes.length; + int activities[][] = new int[n][3]; + + // Create a 2D array to store activities and their start/end times. + // Each row: [activity index, start time, end time] + + for (int i = 0; i < n; i++) { + activities[i][0] = i; // Assign activity index + activities[i][1] = startTimes[i]; // Assign start time + activities[i][2] = endTimes[i]; // Assign end time + } + + // Sort activities by their end times in ascending order. + Arrays.sort(activities, Comparator.comparingDouble(activity -> activity[2])); + int lastEndTime; + ArrayList selectedActivities = new ArrayList<>(); + selectedActivities.add(activities[0][0]); + lastEndTime = activities[0][2]; + + // Iterate through sorted activities to select compatible ones. + for (int i = 1; i < n; i++) { + if (activities[i][1] >= lastEndTime) { + selectedActivities.add(activities[i][0]); + lastEndTime = activities[i][2]; + } + } + return selectedActivities; + } +} diff --git a/src/main/java/com/thealgorithms/greedyalgorithms/CoinChange.java b/src/main/java/com/thealgorithms/greedyalgorithms/CoinChange.java new file mode 100644 index 000000000000..2109e454fa4d --- /dev/null +++ b/src/main/java/com/thealgorithms/greedyalgorithms/CoinChange.java @@ -0,0 +1,35 @@ +package com.thealgorithms.greedyalgorithms; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; + +// Problem Link : https://en.wikipedia.org/wiki/Change-making_problem + +public class CoinChange { + // Function to solve the coin change problem + public static ArrayList coinChangeProblem(int amount) { + // Define an array of coin denominations in descending order + Integer coins[] = {1, 2, 5, 10, 20, 50, 100, 500, 2000}; + + // Sort the coin denominations in descending order + Arrays.sort(coins, Comparator.reverseOrder()); + + int count = 0; // Variable to keep track of the total number of coins used + ArrayList ans = new ArrayList<>(); // List to store selected coins + + // Iterate through the coin denominations + for (int i = 0; i < coins.length; i++) { + // Check if the current coin denomination can be used to reduce the remaining amount + if (coins[i] <= amount) { + // Repeatedly subtract the coin denomination from the remaining amount + while (coins[i] <= amount) { + count++; // Increment the count of coins used + ans.add(coins[i]); // Add the coin to the list of selected coins + amount -= coins[i]; // Update the remaining amount + } + } + } + return ans; + } +} diff --git a/src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java b/src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java new file mode 100644 index 000000000000..c5570f35c004 --- /dev/null +++ b/src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java @@ -0,0 +1,41 @@ +package com.thealgorithms.greedyalgorithms; + +import java.util.Arrays; +import java.util.Comparator; + +// Problem Link: https://en.wikipedia.org/wiki/Continuous_knapsack_problem + +public class FractionalKnapsack { + // Function to perform fractional knapsack + public static int fractionalKnapsack(int weight[], int value[], int capacity) { + // Create a 2D array to store item indices and their value-to-weight ratios. + double ratio[][] = new double[weight.length][2]; + + // Populate the ratio array with item indices and their value-to-weight ratios. + for (int i = 0; i < weight.length; i++) { + ratio[i][0] = i; // Assign item index. + ratio[i][1] = value[i] / (double) weight[i]; // Calculate and assign value-to-weight ratio. + } + + // Sort items by their value-to-weight ratios in descending order. + Arrays.sort(ratio, Comparator.comparingDouble(o -> o[1])); + + int finalValue = 0; // Variable to store the final knapsack value. + double current = capacity; // Variable to track the remaining capacity of the knapsack. + + // Iterate through the sorted items to select items for the knapsack. + for (int i = ratio.length - 1; i >= 0; i--) { + int index = (int) ratio[i][0]; // Get the item index. + if (current >= weight[index]) { + // If the entire item can fit in the knapsack, add its value. + finalValue += value[index]; + current -= weight[index]; + } else { + // If only a fraction of the item can fit, add a proportionate value. + finalValue += ratio[i][1] * current; + break; // Stop adding items to the knapsack since it's full. + } + } + return finalValue; + } +} diff --git a/src/main/java/com/thealgorithms/greedyalgorithms/JobSequencing.java b/src/main/java/com/thealgorithms/greedyalgorithms/JobSequencing.java new file mode 100644 index 000000000000..bf81e067bac1 --- /dev/null +++ b/src/main/java/com/thealgorithms/greedyalgorithms/JobSequencing.java @@ -0,0 +1,65 @@ +package com.thealgorithms.greedyalgorithms; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; + +// Problem Link: https://en.wikipedia.org/wiki/Job-shop_scheduling + +public class JobSequencing { + + // Define a Job class that implements Comparable for sorting by profit in descending order + static class Job implements Comparable { + char id; + int deadline; + int profit; + + // Compare jobs by profit in descending order + @Override + public int compareTo(Job otherJob) { + return otherJob.profit - this.profit; + } + + public Job(char id, int deadline, int profit) { + this.id = id; + this.deadline = deadline; + this.profit = profit; + } + } + + // Function to print the job sequence + public static String findJobSequence(ArrayList jobs, int size) { + Boolean[] slots = new Boolean[size]; + Arrays.fill(slots, false); + + int result[] = new int[size]; + + // Iterate through jobs to find the optimal job sequence + for (int i = 0; i < size; i++) { + for (int j = jobs.get(i).deadline - 1; j >= 0; j--) { + if (!slots[j]) { + result[j] = i; + slots[j] = true; + break; + } + } + } + + // Create a StringBuilder to build the job sequence string + StringBuilder jobSequenceBuilder = new StringBuilder(); + jobSequenceBuilder.append("Job Sequence: "); + for (int i = 0; i < jobs.size(); i++) { + if (slots[i]) { + jobSequenceBuilder.append(jobs.get(result[i]).id).append(" -> "); + } + } + + // Remove the trailing " -> " from the job sequence + if (jobSequenceBuilder.length() >= 4) { + jobSequenceBuilder.setLength(jobSequenceBuilder.length() - 4); + } + + // Return the job sequence as a string + return jobSequenceBuilder.toString(); + } +} diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/ActivitySelectionTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/ActivitySelectionTest.java new file mode 100644 index 000000000000..42263ac1de8a --- /dev/null +++ b/src/test/java/com/thealgorithms/greedyalgorithms/ActivitySelectionTest.java @@ -0,0 +1,42 @@ +package com.thealgorithms.greedyalgorithms; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Arrays; +import org.junit.jupiter.api.Test; + +public class ActivitySelectionTest { + @Test + public void testActivitySelection() { + int start[] = {1, 3, 0, 5, 8, 5}; + int end[] = {2, 4, 6, 7, 9, 9}; + + ArrayList result = ActivitySelection.activitySelection(start, end); + ArrayList expected = new ArrayList<>(Arrays.asList(0, 1, 3, 4)); + + assertEquals(expected, result); + } + + @Test + public void testSingleActivity() { + int start[] = {1}; + int end[] = {2}; + + ArrayList result = ActivitySelection.activitySelection(start, end); + ArrayList expected = new ArrayList<>(Arrays.asList(0)); + + assertEquals(expected, result); + } + + @Test + public void testNoOverlap() { + int start[] = {1, 2, 3}; + int end[] = {2, 3, 4}; + + ArrayList result = ActivitySelection.activitySelection(start, end); + ArrayList expected = new ArrayList<>(Arrays.asList(0, 1, 2)); + + assertEquals(expected, result); + } +} diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeTest.java new file mode 100644 index 000000000000..e9d267712a05 --- /dev/null +++ b/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeTest.java @@ -0,0 +1,58 @@ +package com.thealgorithms.greedyalgorithms; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; +import java.util.Arrays; +import org.junit.jupiter.api.Test; + +public class CoinChangeTest { + @Test + public void testCoinChangeProblemWithValidAmount() { + ArrayList expected = new ArrayList<>(Arrays.asList(500, 50, 20, 20, 1)); + ArrayList coins = CoinChange.coinChangeProblem(591); + assertEquals(expected, coins); + } + + @Test + public void testCoinChangeProblemWithLargeAmount() { + ArrayList expected = new ArrayList<>(Arrays.asList(2000)); + ArrayList coins = CoinChange.coinChangeProblem(2000); + assertEquals(expected, coins); + } + + @Test + public void testCoinChangeProblemWithPartialCoins2() { + ArrayList expected = new ArrayList<>(Arrays.asList(500, 50, 20)); + ArrayList coins = CoinChange.coinChangeProblem(570); + assertEquals(expected, coins); + } + + @Test + public void testCoinChangeProblemWithSmallAmount() { + ArrayList expected = new ArrayList<>(Arrays.asList(2, 1)); + ArrayList coins = CoinChange.coinChangeProblem(3); + assertEquals(expected, coins); + } + + @Test + public void testCoinChangeProblemWithLargeAmountAndMultipleDenominations() { + ArrayList expected = new ArrayList<>(Arrays.asList(2000, 2000, 2000, 2000, 500, 500, 500, 100, 100, 100, 100, 50, 20, 20, 5, 2, 2)); + ArrayList coins = CoinChange.coinChangeProblem(9999); + assertEquals(expected, coins); + } + + @Test + public void testCoinChangeProblemWithAllDenominations() { + ArrayList expected = new ArrayList<>(Arrays.asList(2000, 500, 100, 100, 100, 50, 20, 10, 5, 2, 1)); + ArrayList coins = CoinChange.coinChangeProblem(2888); + assertEquals(expected, coins); + } + + @Test + public void testCoinChangeProblemWithZeroAmount() { + ArrayList expected = new ArrayList<>(); + ArrayList coins = CoinChange.coinChangeProblem(0); + assertEquals(expected, coins); + } +} diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/FractionalKnapsackTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/FractionalKnapsackTest.java new file mode 100644 index 000000000000..edbf0a09bcbd --- /dev/null +++ b/src/test/java/com/thealgorithms/greedyalgorithms/FractionalKnapsackTest.java @@ -0,0 +1,32 @@ +package com.thealgorithms.greedyalgorithms; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +public class FractionalKnapsackTest { + + @Test + public void testFractionalKnapsackWithExampleCase() { + int weight[] = {10, 20, 30}; + int value[] = {60, 100, 120}; + int capacity = 50; + assertEquals(240, FractionalKnapsack.fractionalKnapsack(weight, value, capacity)); + } + + @Test + public void testFractionalKnapsackWithZeroCapacity() { + int weight[] = {10, 20, 30}; + int value[] = {60, 100, 120}; + int capacity = 0; + assertEquals(0, FractionalKnapsack.fractionalKnapsack(weight, value, capacity)); + } + + @Test + public void testFractionalKnapsackWithEmptyItems() { + int weight[] = {}; + int value[] = {}; + int capacity = 50; + assertEquals(0, FractionalKnapsack.fractionalKnapsack(weight, value, capacity)); + } +} diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/JobSequencingTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/JobSequencingTest.java new file mode 100644 index 000000000000..8dd42bc7c5ec --- /dev/null +++ b/src/test/java/com/thealgorithms/greedyalgorithms/JobSequencingTest.java @@ -0,0 +1,23 @@ +package com.thealgorithms.greedyalgorithms; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +public class JobSequencingTest { + @Test + public void testJobSequencingWithExampleCase() { + ArrayList jobs = new ArrayList<>(); + jobs.add(new JobSequencing.Job('a', 2, 100)); + jobs.add(new JobSequencing.Job('b', 1, 19)); + jobs.add(new JobSequencing.Job('c', 2, 27)); + jobs.add(new JobSequencing.Job('d', 1, 25)); + jobs.add(new JobSequencing.Job('e', 3, 15)); + Collections.sort(jobs); + String jobSequence = JobSequencing.findJobSequence(jobs, jobs.size()); + + assertEquals("Job Sequence: c -> a -> e", jobSequence); + } +}