Dynamic Programming-RodCutting - java

I've recently started learning algorithms.
I tried to implement the classic Rod cutting problem using a Dynamic programming approach. I'm unable to get the correct output. Here is my code:
public class RodCuttingProblem {
public static void main(String[] args) {
int len=5;
int prices[]={2,5,7,3};
rodCuttingImplementation(prices,len);
}
public static void rodCuttingImplementation(int prices[],int len){
prices=reAdjustPrice(prices);
System.out.println("");
for(int i=0;i<prices.length;i++){
System.out.print(prices[i]+" ");
}
System.out.println(" ");
int dp[][]=new int[prices.length+1][len+1];
for(int i=1;i<prices.length;++i){
for(int j=1;j<=len;++j){
if(i<=j){
dp[i][j]=Math.max(dp[i-1][j], prices[i]+dp[i][j-1]);
}
else{
dp[i][j]=dp[i-1][j];
}
System.out.print(dp[i][j]+" ");
}
System.out.println();
}
System.out.println("Optimal Profit : "+dp[prices.length-1][len]);
}
static int[] reAdjustPrice(int prices[]){
int[] newPrices=new int[prices.length+1];
newPrices[0]=0;
for(int i=0;i<prices.length;i++){
newPrices[i+1]=prices[i];
}
return newPrices;
}
}
Output:
2 4 6 8 10
2 7 12 17 22
2 7 14 21 28
2 7 14 21 28
Optimal Profit : 28
As per my understanding, the output should be 12.

I really tried to understand what your algorithm is supposed to do, but I cannot, thus I cannot find out what the problem is
some concerns:
reAdjustPrice is doing very weird shift, I suppose you want to indicate that length is always >= 1 and thus index in array cannot be 0, it could work, though I suggest you to think in terms of 0-based arrays
you have array with 4 prices, but want to split rod with length 5. Usually this is done by appending 0 at the end of array, ie initial price for length 5 is 0
array dp - it has 2 dimensions, but maximal price for every length is 1 value, so you need 1 value for each step, this is for sure one dimensional array
Here is "canonical" implementation of rod splitting algorithm:
static int maxPrice(final int len, final int[] prices) {
// if len > prices.length, adjust it to have zeroes at the end
for (int i = 0; i < len; i++)
for (int j = 0; j < ((i + 1) >>> 1); j++)
prices[i] = Math.max(prices[i], prices[j] + prices[i - j - 1]);
return prices[len - 1];
}
note: this variant modifies input array, to decrease memory usage, but its very easy to modify it

Related

Find Maximum Positive Index

You are given an array A. We define a term Positive difference index as the count of elements between the two indexes i and j (both inclusive) such that i<j and A[i]<A[j].
Now for the given array, you have to find the maximum positive difference index. It is assured that the test case will be valid such that there exists an answer.
Input format
First line : T i.e Number of test cases.
For each test case :
First line : N
Second line : N space separated integers denoting the element of the array.
Output format
Print the answer to each test case in a separate line and it is given that answer always exists.
Sample Input
1
6
5 3 2 1 1 4
Sample Output
5
Explanation
let i=2 and j=6 then A[i]<A[j] and total elements between them is 5 so the maximum answer that can be achieved is 5.
I had tried to find maximun number from an array and minimum number from array such that A[i]<A[j]. With sample input it worked but for when I submitted the question on hackerearth it displayed none test cases were passed. Can anyone please me help to understand the question and program?
Below program I have written
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
int totalTest = Integer.parseInt(line);
for(int i=0;i<totalTest;i++) {
line = br.readLine();
int totalElements = Integer.parseInt(line);
line = br.readLine();
String strArr[] = line.split(" ");
int elements[] = new int[strArr.length];
for(int j=0;j<strArr.length;j++) {
elements[j] = Integer.parseInt(strArr[j]);
}
System.out.println(findMaximumPositiveIndex(elements));
}
}catch(Exception e) {
e.printStackTrace();
}
finally {
if(br!=null)
br.close();
}
}
public static int findMaximumPositiveIndex(int[] arr) {
int max=arr[0];
int maxIndex = 0;
int minIndex=arr[0];
int min=0;
for(int i=0;i<arr.length;i++) {
if( min==0 ) {
min = arr[i];
minIndex=i;
}
if(arr[i] < min) {
min = arr[i];
minIndex = i;
}
if(arr[i] > max) {
max = arr[i];
maxIndex = i;
}
}
return (max - min) + 1;
}
}
The maximum and minimum values from the array, in most cases they won’t help you. So don’t find those. In the example in the question the maximum value is 5 and the minimum is 1. Neither of those two values are involved in calculating the output. Instead the values 3 and 4 are because they are the farthest apart values that fulfil the condition A[i] < A[j]. The output should be 5 because the part of the array 3 2 1 1 4 has length 5. Or “the count of elements between the two indexes i and j (both inclusive)”, as the challenge puts it.
Instead you find the output from the min and max values as (5 – 1) + 1 = 5 (I think; I haven’t studied your code thoroughly). Coincidentally you hit the correct output in this single case. You haven’t done it correctly.
Other examples:
For 2 1 2 1 2 1 the answer is 4 because the part 1 2 1 2 has length 4 and 1 < 2.
For 40 90 10 60 the answer is 4 too because 40 90 10 60 has 4 elements in it and 40 < 60.
I understood that you asked for help understanding the problem, not for solving it, so I am happy to leave that pleasure to yourself.
Thanks for helping to understand the problem statement.
I have modified the code
public static int findMaximumPositiveIndex(int[] arr) {
int min=arr[0],max=arr[0],minIndex=0,maxIndex=0;
int maximumIndex = 0;
for(int i=0;i<arr.length;i++){
min = arr[i];
minIndex=i;
boolean isMaxPresent = false;
for(int j=i;j<arr.length;j++)
{
if(arr[j] > min){
max = arr[j];
maxIndex = j;
isMaxPresent = true;
}
}
if(maximumIndex < ((maxIndex - minIndex) +1) )
maximumIndex = (maxIndex - minIndex) + 1;
}
return maximumIndex;
}
which fulfills all the test cases. Thanks

Java For Loop Practice

Was doing some Java practices and I got stuck at this particular question, I am given the following code:
public class DistanceSeparator {
public static void main(String[] args) {
printSeparatorSequence(3);
printSeparatorSequence(5);
printSeparatorSequence(8);
}
public static void printSeparatorSequence(int numberOfElements) {
for () {
}
System.out.println();
} //end of method printSeparatorSequence
} // end of class
And I am supposed to modify the code using A SINGLE FOR LOOP to show that:
If numberOfElements = 5
1 3 7 13 21
If numberOfElements = 7
1 3 7 13 21 31 43
Each showing an increment of + 2, +4, +6, +8, +10 and +12
The final output is to be this:
1 3 7
1 3 7 13 21
1 3 7 13 21 31 43 57
I just can't seem to get my head around how to get that outcome, and this is after 2hours of trying (yes I am that bad). Any help, please?
edit This was what I had, before deciding to seek help, it's obviously not working.
int j = 0;
for (int i = 1; i <= numberOfElements; i++) {
j = i * 2; // + by how much
int z = i + j; //sum
System.out.print(z + "");
}
edit 2 now I get it, oh my, to think I was so close. Guess I was too cluttered after being stuck for some time. Thanks a ton!
Here is the code to accomplish result you expected.
int current = 1;
for(int i = 0; i < numberOfElements; i++) {
current += i*2;
System.out.print(current + " ");
}
You just need to keep another variable to keep track of the difference (the change), and then constantly update it by the power of 2 of the iteration, i.e. for the first loop only increase it by 2^1, then by 2^2, then 2^3 and so on).
An example of how to achieve that:
for (int i = 0, diff = 0; i < numberOfElements; i++, diff += 2*i) {
System.out.print((1 + diff) + " ");
}
UPDATE: After you've edited your question with your code segment, you can see your problem was with this line:
int z = i + j; //sum
Since both i and j advance with each iteration, you lose your offset (you constantly reset it). You need to keep it static (like in my example: 1), and only update j by 2*i each iteration, otherwise your "base" for calculation is constantly changing and the formula doesn't hold anymore.
In your case, you are regenerating int z everytime the loop is called,
All you have to do is define z outside the loop and instantiate z as 1 and also, you are not retaining the previous values of z so that's why it wasn't working. So it should be z = z + j and put this line below the print statement and you are done.
Here is an snippet of code which would help you my way:
int j = 1;
for(int i=1; i<=numberOfElements; i++) {
System.out.println(j);
j = j + 2*i;
}
And, here is an snippet of code which would help you your way:
int j = 0;
int z = 1;
for (int i = 1; i <= numberOfElements; i++)
{
j = i * 2; // + by how much
System.out.print(z + " ");
z = z + j; //sum
}
Note the trend.
You are adding a multiple of 2 to the previous number to get the next number. The multiple of 2 to be added depends upon the position of the number. For example, to get the 1st number, you add 2 x 0 to 1. To get the 2nd number, you add 2 x 1 to the previous number (that gives 3). To get the 3rd number, you add 2 x 2 to the previous number (that gives 7). To get the 4th number, you add 2 x 3 to the previous number (that gives 13).
To get the number at nth position, you add 2 x (n-1) to the previous number.
Now take a look at the example below, keeping the above explanation in mind.
public static void printSeparatorSequence(int numberOfElements) {
int number = 1;
for (int i = 0; i<numberOfElements;i++) {
number = number + 2 * i;
System.out.print(number);
}
System.out.println();
} //end of method printSeparatorSequence
} // end of class
This is the solution of your problem. I have discussed the code by the comment lines given within the code.
public class DistanceSeparator
{
/* Main Method */
public static void main(String[] args)
{
/* printSeparatorSequence Function is Called */
printSeparatorSequence(3);
printSeparatorSequence(5);
printSeparatorSequence(8);
}
/* printSeparatorSequence Function Definition */
public static void printSeparatorSequence(int NumberOfElements)
{
/* variable j is used to get the multiples of
2 by multiplying with variable i within the for loop
and variable sum is used to get the total value */
int j=2,sum=1;
for(int i=0;i<NumberOfElements;i++)
{
sum=sum+(j*i);
/* Here total sum is printed with a space */
System.out.print(sum+" ");
}
/* It is used for new line */
System.out.println();
}
}

JAVA ArrayIndexoutofBoundException issue

A perfect number is one that is the sum of its factors, excluding itself. The 1st perfect number is 6 because 6 = 1 + 2 + 3. The 2nd perfect number is 28 which equals 1 + 2 + 4 + 7 + 14. The third is 496 = 1 + 2 + 4 + 8 + 16 + 31 + 62 + 124 + 248. In each case, the number is the sum of all its factors excluding itself.
Write a method named henry that takes two integer arguments, i and j and returns the sum of the ith and jth perfect numbers. So for example, henry (1, 3) should return 502 because 6 is the 1st perfect number and 496 is the 3rd perfect number and 6 + 496 = 502.
I have done this far:: but this is showing ArrayIndexOutOfBoundException at this line temp[index] = j; please help me to solve this OutOfBound issue, Thanks..
public static int henry (int a, int b){
List<Integer> arr = new ArrayList<Integer>();
int henryNumber = 0;
for(int i=4;;i++){
List<Integer> temp = new ArrayList<Integer>();
int sum = 0;
for(int j = 1; j<i; j++){
if(i%j == 0 ) { temp.add(j); }
}
for (Integer item : temp) { sum+=item; }
if(sum == i) arr.add(i);
if(arr.size() == b) {
henryNumber = arr.get(a-1) + arr.get(b-1);
break;
}
}
return henryNumber;
}
int[] temp = {};
This sets temp to an array of 0 elements. So when you try to access temp[index] where index is = to 0 its out of bounds because the array doesn't have even a single element
You would need to create an array of x number elements by doing:
int[] temp = new int[x];
and then you can set the value at each of the indicies to whatever value you want.
An array has a fixed length as soon as it it created, and that length cannot be changed.
int[] temp = {};
This creates an empty array. Its length is zero. You can't change that, you can't add any items to it.
temp[index] = j;
This tries to put something in the temp array. However, as I said, the array is empty, its length is zero, so any value of index would be out of bounds.
Using a List (which is commented out in your source) will allow you to create a growing collection of elements. Alternatively, you have to think of a proper size for your array, that will hold all the elements you'll be using, and use that size when you create the array.
Try doing
int[] temp=new int[i];
instead of
int[] temp={};
I have never assigned an array like this before.

Add Elements of a 2-Dimensional Array using recursion

Hey guys I am having problems writing this part of my code. I have to sum up the elements of this 2-dimensional array using recursion. I understand what I need to do but I am not understanding how to implement this to step through the array. I keep receiving errors. Could someone please help me out?
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int[][] a;
a = new int[3][4];
int sum = 0;
System.out.println("Enter 12 numbers: ");
Scanner scan = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
a[i][j] = scan.nextInt();
}
}
sum = sum2D(a, 0, 0);
System.out.println("The sum of the array: " + sum);
}
public static int sum2D(int a[][], int row, int col) {
if (row == a.length-1) {
return a[row][col];
}
if (col == a[row].length-1) {
return a[row][col] + sum2D(a, row++, 0);
}
return a[row][col] + sum2D(a, row, col++);
}
}
The basic plan, when you need a recursive solution, is to look for a way to break down the problem so that it contains a smaller problem (or more than one smaller problem) that looks just like the original problem, only smaller.
For a 2-D array, this can be tricky. Say your array looks like
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
One's first thought might be to write a recursive function that takes a row and column, and adds a[row][column] to the sum of the rest of the array. The problem is that if, for example, row=0 and column=0, the "smaller problem" you have to solve looks like
+---------------------+
1 | 2 3 4 5 |
+---+ |
| 6 7 8 9 10 |
| 11 12 13 14 15 |
+-------------------------+
(please excuse the bad ASCII art). So now your smaller problem doesn't look like an array at all, but some weird polygon. It's still possible to use this approach, by writing a recursive function like
int sumOfWeirdShapedSectionOfArray(int[][] array, int firstRow, int firstCol)
But that's definitely an abuse of recursion. Better would be to break down the array into the "first row" and "the rest of the rows":
1 2 3 4 5
+-------------------------+
| 6 7 8 9 10 |
| 11 12 13 14 15 |
+-------------------------+
(Or you could break it into "the last row" and "the rest of the rows".)
Now, your smaller problem looks a lot like the original problem, right? So your answer would be that "the sum of the elements in the array is the sum of the first row, plus the sum of the elements in the smaller array starting with the next row". The second part of this is a recursive call. The first part, the sum of the first row, would require that you call a new function to add up a row; and since you're still not allowed to use loops, the "add up a row" function would also be recursive, but that should be easy.
Having said all this, nobody would ever use recursion in the real world on this problem. However, if the point is to get familiar with recursion so that you can use it when it's called for, then this sort of thought process is what you need to follow.
To do it without recursion, just have two nested for loops:
int sum = 0;
for(int i=0;i<array.length;i++)
for(int j=0;j<array[i].length;j++)
sum += array[i][j];
return sum;
To do it with recursion:
int sum2D(int a[][], int row, int col) {
if (row == a.length-1)
return a[row][col];
if(col == a[row].length-1)
return a[row][col]+sum2D(a,row+1,0);
return a[row][col]+sum2D(a,row,col+1);
}
Basically you're doing the same thing: going through each row and column and adding it together.
However, note that ther is a limit on how many recursive routines you can use. If you recurse too deep, you'll get a StackOverflow error.
The base condition was wrong in the above code:
Here is the code that works:
public static int addMatrix(int a[][],int r,int c){
if(r==a.length-1 && c==a[r].length-1)
return a[r][c];
if(c==a[r].length-1)
return a[r][c]+addMatrix(a,r+1,0);
return a[r][c]+addMatrix(a,r,c+1);
}
Equivalent "C" program here, but for number of Rows 4 and Number of columns 1 , I get unpredictable result why?
#include <stdio.h>
#include <string.h>
#include <conio.h>
int row,col;
main()
{
int a[][];
int nrow,ncols,summ = 0;
printf("Enter No of Rows:");
scanf("%d",&nrow);
printf("Enter No of Columns:");
scanf("%d",&ncols);
int arraylength,rowlength;
printf("Enter %d numbers: \n",nrow*ncols);
for (int i = 0; i < nrow; i++) {
for (int j = 0; j < ncols; j++) {
scanf("%d",&a[i][j]);
}
}
arraylength=sizeof(a)/sizeof(int);
summ = sum(a,0, 0,nrow,ncols);
printf("\n The sum of the array: %d ",summ);
getch();
}
int sum( int a[row][col],int row,int col,int RowLen,int ColLen)
{
if ((row == RowLen-1) && (col==(ColLen)-1)) {
return a[row][col];
}
if (col == (ColLen)-1)
{
return (a[row][col] + sum(a,row+1,0,RowLen,ColLen));
}
return (a[row][col] + sum(a,row, col+1,RowLen,ColLen));
}

Length and location of longest contiguous sequence of equal values where just before and just after are smaller

I have a problem that asks:
Write a program that converts its input arguments into an array of
integers, and then finds the length and location of the longest
contiguous sequence of equal values where the values of the elements
just before and just after this sequence are smaller.
For example, if
the command line arguments are “1 2 2 2 2 5 5 5 3” your program should
output the numbers 5 3 (the first number is a zero-based offset, and
the second number is the length of the subsequence). If a contiguous
subsequence appears at the beginning or end of the array, treat this
as a special case;e.g.,for input “5 5 5 5 3 8 8 8 1”your output should
be 0 4 (and not 5 3). If there are multiple subsequences that satisfy
the above condition, then output the first one.
Updated code:
public class LongestPlateau {
public static void main(String[] args) {
// TODO - Your solution
int N= args.length;
int [] array = new int [N];
int new_length=0;
int location=0;
int max=0;
int current_length=0;
//assign digits into array
for (int i=0; i < N; i++){
int number = Integer.parseInt(args[i]);
array [i] = number;
}
int compare=array[0];
for (int l=0; l<N; l++){
if (array[l] < compare){
current_length=0;
compare = array[l];
}
else if (array[l] == compare){
current_length+=1;
compare = array[l];
}
else if (array[l] > compare){
compare=array[l];
l++;
}
compare= array[l];
for (int b=0; b<N; b++){
if (current_length > max){
max = current_length;
location = array[l];
new_length=max-1;
}
else if (current_length==1){
new_length=max;
}
}
}
System.out.println(location);
System.out.println(new_length);
}
}
Issue is that for the input of "1 2 3 4" I continously get an Array Index out of bounds error.
Before you start writing code, try and think how a human would have solved it.
e.g.
For every item in the input, compare it to the previous, if it's larger, start a new sequence length check (write 0 in your notebook under - "current sequence length)), if it's the same, increase it by 1, if it's less, mark that sequence length as complete. if it's larger than your largest sequence length so far (started with 0) then this is now your largest sequence, if not, ignore that sequence length and move on to the next character. (or something like this)
write these instructions to yourself as a human, and try to follow them, and fix them as you find edge cases. Once you have a working human language algorithm, writing the code will be almost self driven.
You really need to post the specific issue you are seeing, how your actual results differ from your expected results, and what solutions you have attempted.
In any case, as for the general "how to proceed" question, I find that it often helps to work out these types of problems on paper first. Write down your sequence and step through it, observe what information you need to keep track of and what logic you need to apply to produce the desired results. Once you are able to do this, it will be far more straightforward to translate your clearly thought out algorithm into concrete code.
It appears you are at least somewhat on the right track parsing and storing your integer array, but you are a bit misguided with your [t+?] lookaheads. If you write this out and step through it by hand, you may be surprised at what you come up with.
Here is a full program description with test cases:
Given an array of integers int A[], find the length and location of the longest contiguous sequence of equal values for which the values of the elements just before and just after this sequence are smaller.
You should just print these two numbers (first is the length and second is the starting index of the plateau).
To complete the definition, we can consider there are imaginary index positions at A[-1] and A[A.length] where A[-1] < A[0] and A[A.length] < A[A.length-1]. Therefore, the plateau can start/end at both ends of array A. This condition guarantees the existence of a plateau. A plateau can be of length 1.
Example 1:
java LongestPlateau 1 2 2 2 2 1
With this command line arguments, program should print:
4
1
Example 2:
java LongestPlateau 1 2 2 2 2 3
With this command line arguments, program should print:
1
5
Example 2:
java LongestPlateau 3 2 2 2 1 2 1 1 1 2 2 0 1 1 1 1 0
With this command line arguments, program should print:
4
12
Example 2:
java LongestPlateau 3 2 2 2 2 2 2 1 2 1 1 1 2 2 0 1 1 1 1
With these command-line arguments, the program should print:
4
15
Here is my solution:
public class LongestPlateau {
private static int[] parseInputArray(String[] args) {
int[] value = new int[args.length+1];
for(int i = 0 ; i < args.length; i++){
if (i == args.length-1) value[i] = 0; // this imaginary last value of the array ensures that if the plateau is the last value of the array, then it outputs the correct answer
value[i] = Integer.parseInt(args[i]);
}
return value;
}
public static void printLargestPlateau(int[] values) {
int biggestStartIndex = -1;
int biggestLength = 0;
int currentIndex = 1;
int currentPlateauStartIndex = 1;
int currentLength = 1;
boolean plateauStarted = false;
while (currentIndex < values.length) {
if(isStartOfPlateau(currentIndex, values)){
currentLength = 1;
plateauStarted = true;
currentPlateauStartIndex = currentIndex;
} else if (isEndOfPlateau(currentIndex, values)) {
if(plateauStarted && currentLength > biggestLength){
biggestLength = currentLength;
biggestStartIndex = currentPlateauStartIndex;
}
plateauStarted = false;
currentLength = 1;
} else {
currentLength++;
}
currentIndex++;
}
System.out.println(biggestLength +"\n"+biggestStartIndex);
}
private static boolean isStartOfPlateau(int index, int[] values){
if(index <= 0){
return false;
}
return values[index-1] < values[index];
}
private static boolean isEndOfPlateau(int index, int[] values){
if(index <= 0){
return false;
}
return values[index - 1] > values[index];
}
public static void main(String[] args) {
int[] values = parseInputArray(args);
printLargestPlateau(values);
}
}

Categories

Resources