Formatting equations? - java

I'm new to Java, and I'm trying to format an equation with int elements in an array (I keep getting the error "not a statement"). This is the bit of code:
int n = 0;
int[] time = {mins, mins2, mins3, mins4, mins5};
for(int j = 0; j <= 3; j++){
if (time[j] < time[j+1]){
n = time[j];
}
}
for(int k = 0; k <= 4; k++){
time[k] - n;
}
I found the smallest int (all elements are from a random number generator), and now I want to subtract the smallest from every element and permanently change the elements of the given array to those smaller numbers. I don't know how to format the "time[k] - n;" segment correctly.
Thank you for your help.

The line:
time[k] - n
Does nothing. It takes the value time[k] and subtracts the value n from it. It then discards the result.
What you want is to subtract n from the variable and assign the result back to the same variable:
time[k] = time[k] - n
In Java, this is equivalent to a compound assignment operator:
time[k] -= n
If you have Java 8 you could in fact do:
int[] time = {mins, mins2, mins3, mins4, mins5};
int min = IntStream.of(time).min().getAsInt();
int[] normalised = IntStream.of(time).map(i -> i - min).toArray();
And even with earlier versions of Java I would recommend:
int[] time = {mins, mins2, mins3, mins4, mins5};
int n = Integer.MAX_VALUE;
for (int t : time) {
n = Math.min(n, t);
}
for (int i = 0; i < time.length; ++i) {
time[i] -= n;
}
i.e. use a foreach loop where you can and otherwise use the length property of the array rather than hardcoding the length.

Change time[k] - n; to time[k] =- n;. So it will store time[k] - n in time[k]

Related

Solving a matrix equation in Java

I have been trying to implement the given formula in JAVA but i was unsuccessful. Can someone help me find what I am doing wrong?
Do i need to shift the summation index and if so how?
My code:
public final class LinearSystem {
private LinearSystem() {
}
public static int[] solve(int [][]A , int []y) {
int n = A.length;
int[] x = new int[n];
for (int i = 0 ; i < n; i++) {
x[i] = 0;
int sum = 0;
for(int k = i + 1 ; k == n; k++) {
sum += A[i][k]*x[k]; // **java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3**
}
x[i] = 1/A[i][i] * (y[i] - sum);
}
return x;
}
public static void main(String[] args) {
int[][]A = new int[][]{{2,-1,-3},{0,4,-1},{0,0,3}};
int [] y = new int[] {4,-1,23};
System.out.println(Arrays.toString(solve(A,y))); **// awaited result [2, -3, 1]**
}
}
Just trying to collect all my comments under the question into one coherent answer, since there are quite a few different mistakes in your program.
This method of solving linear equations relies on your calculating the components of the answer in reverse order - that is, from bottom to top. That's because each x[i] value depends on the values below it in the vector, but not on the values above it. So your outer loop, where you iterate over the x values needs to start at the biggest index, and work down to the smallest. In other words, instead of being for (int i = 0; i < n; i++), it needs to be for (int i = n - 1; i >= 0; i++).
The inner loop has the wrong stopping condition. With a for loop, the part between the two semicolons is the condition to continue iterating, not the condition to stop. So instead of for(int k = i + 1; k == n; k++), you need for(int k = i + 1; k < n; k++).
You're doing an integer division at the beginning of 1 / A[i][i] * (y[i] - sum);, which means the value is rounded to an integer before carrying on. When you divide 1 by another integer, you always get -1, 0 or 1 because of the rounding, and that makes your answer incorrect. The fix from point 4 below will deal with this.
The formula relies on the mathematical accuracy that comes with working with either floating point types or decimal types. Integers aren't going to be accurate. So you need to change the declarations of some of your variables, as follows.
public static double[] solve(double[][] A, double[] y)
double x[] = new double[n];
double sum = 0.0;
along with the corresponding changes in the main method.
First, you need the second loop to go until k < n, otherwise this throws the ArrayOutOfBounds Exceptions.
Second, you need to calculate your x in reverse order as #Dawood ibn Kareem said.
Also, you probably want x[] to be a double-array to not only get 0-values as result.
I am sorry I don't know much about math side so I couldn't fix it to the right solution but I noticed a few things wrong about your code.
1-You shouldn't initialize your arrays as integer arrays, because you will be doing integer division all over the place. For example 1/A[i][i] will result in 0 even if A[i][i] = 2
2-You shouldn't write k == n, if you do it like this then your for loop will only execute if k equals n, which is impossible for your case.
I think you want to do k < n, which loops from i+1 to the point where k = n - 1
Here is my code:
import java.util.Arrays;
public final class LinearSystem {
private LinearSystem() {
}
public static double[] solve(double [][]A , double []y) {
int n = A.length;
double[] x = new double[n];
for (int i = 0 ; i < n; i++) {
x[i] = 0;
int sum = 0;
for(int k = i + 1 ; k < n; k++) {
sum += A[i][k] * x[k]; // **java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3**
}
x[i] = 1/A[i][i] * (y[i] - sum);
}
return x;
}
public static void main(String[] args) {
double[][]A = new double[][]{{2,-1,-3},{0,4,-1},{0,0,3}};
double [] y = new double[] {4,-1,23};
System.out.println(Arrays.toString(solve(A,y))); // awaited result [2, -3, 1]**
}
}
Remember that arrays are indexed from 0, so the last element is at index n - 1, not n.

Divide an Array in equal size, such that value of given function is minimum

I've came across the following problem statement.
You have a list of natural numbers of size N and you must distribute the values in two lists A and B of size N/2, so that the squared sum of A elements is the nearest possible to the multiplication of the B elements.
Example:
Consider the list 7 11 1 9 10 3 5 13 9 12.
The optimized distribution is:
List A: 5 9 9 12 13
List B: 1 3 7 10 11
which leads to the difference abs( (5+9+9+12+13)^2 - (1*3*7*10*11) ) = 6
Your program should therefore output 6, which is the minimum difference that can be achieved.
What I've tried:
I've tried Greedy approach in order to solve this problem. I took two variables sum and mul. Now I started taking elements from the given set one by one and tried adding it in both the variables and calculated current
square of sum and multiplication. Now finalize the element in one of the two sets, such that the combination gives minimum possible value.
But this approach is not working in the given example itselt. I can't figure out what approach could be used here.
I'm not asking for exact code for the solution. Any possible approach and the reason why it is working, would be fine.
EDIT:
Source: CodinGame, Community puzzle
Try out this:
import java.util.Arrays;
public class Test {
public static void main(String [] args){
int [] arr = {7, 11, 1, 9, 10, 3, 5, 13, 9, 12};
int [][] res = combinations(5, arr);
int N = Arrays.stream(arr).reduce(1, (a, b) -> a * b);
int min = Integer.MAX_VALUE;
int [] opt = new int [5];
for (int [] i : res){
int k = (int) Math.abs( Math.pow(Arrays.stream(i).sum(), 2) - N/(Arrays.stream(i).reduce(1, (a, b) -> a * b)));
if(k < min){
min = k;
opt = i;
}
}
Arrays.sort(opt);
System.out.println("minimum difference is "+ min + " with the subset containing this elements " + Arrays.toString(opt));
}
// returns all k-sized subsets of a n-sized set
public static int[][] combinations(int k, int[] set) {
int c = (int) binomial(set.length, k);
int[][] res = new int[c][Math.max(0, k)];
int[] ind = k < 0 ? null : new int[k];
for (int i = 0; i < k; ++i) {
ind[i] = i;
}
for (int i = 0; i < c; ++i) {
for (int j = 0; j < k; ++j) {
res[i][j] = set[ind[j]];
}
int x = ind.length - 1;
boolean loop;
do {
loop = false;
ind[x] = ind[x] + 1;
if (ind[x] > set.length - (k - x)) {
--x;
loop = x >= 0;
} else {
for (int x1 = x + 1; x1 < ind.length; ++x1) {
ind[x1] = ind[x1 - 1] + 1;
}
}
} while (loop);
}
return res;
}
// returns n choose k;
// there are n choose k combinations without repetition and without observance of the sequence
//
private static long binomial(int n, int k) {
if (k < 0 || k > n) return 0;
if (k > n - k) {
k = n - k;
}
long c = 1;
for (int i = 1; i < k+1; ++i) {
c = c * (n - (k - i));
c = c / i;
}
return c;
}
}
Code taken from this stackoverflow answer, also take a look at this wikipedia article about Combinations.
I am not sure if there is any exact solution in polynomial time. But you could try a simulated annealing based approach.
My approach would be:
Initialize listA and listB to a random state
With probability p run greedy step, otherwise run a random step
Keep track of the state and corresponding error (with a HashMap)
Greedy step: Find one element you can move between the list that optimizes the error.
Random Step: Pick a random element from either of these two sets and calculate the error. If the error is better, keep it. Otherwise with probability of q keep it.
At either of these two steps make sure that the new state is not already explored (or at least discourage it).
Set p to a small value (<0.1) and q could depend on the error difference.

How to fill a 2D array with random non duplicate numbers in Java

I'm having a hard time figuring out how to fill my 2D array with random numbers without duplicates. I currently have it filed with random numbers within the correct range, but I just cant think of a solution to have non duplicates. How could i do this using very basic java methods? I have not yet learned anything such as arraylists, or anything like that, only the very basic methods.
Given a MxN integer array, you could fill the array with numbers from 1 to M*N using two for-loops, and then swap them using the Fisher-Yates algorithm.
EDIT:
I changed the algorithm so that it now does not create a new integer-array every time the algorithm is called. It uses one loop, and calculates m, n, i j from a random value and the iterating varaible l. Assuming the given array is not null, rectangular and at least 1x0 in size:
public static void fillRandomlyUniqe(int[][] a) {
/*
fill up the array with incrementing values
if the values should start at another value, change here
*/
int value = 1;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++)
a[i][j] = value++;
}
// swap them using Fisher-Yates algorithm
Random r = new Random();
int max = a.length * a[0].length;
for (int l = max - 1; l > 0; l--) {
//calculate a two dimensional index from random number
int index = r.nextInt(l + 1);
int m = index % a.length;
int n = index / a.length;
//calculate two dimensional index from the iterating value
int i = l % a.length;
int j = l / a.length;
int temp = a[i][j];
a[i][j] = a[m][n];
a[m][n] = temp;
}
}
If your 2D array is NxM, and you want numbers from (say) 1 to NxM randomly placed in your 2D array, the simplest is to create an array/list with the numbers from 1 to NxM, shuffle it, then fill in your 2D array sequentially from the shuffled data. You are guaranteed to not have any duplicates because the original non-shuffled data is full of unique values.
List<Integer> data = IntStream.rangeClosed(1, M * N).boxed().collect(Collectors.toList());
Collections.shuffle(data);
Iterator<Integer> iter = data.iterator();
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
array[i][j] = iter.next();
}
}
There is probably a way to do the second half with the stream API too, but it escapes me at the moment.

Trying to determine smallest amount and position in a Java array

I am new to the site, and new to programming in general, so please be gentle. I'm doing an assignment and I've built everything it needs, but I'm having problems with one particular part.
So the code below is just the for loop part of the overall program that I'm having trouble with. I created an array to store the user's quarterly input. When I go to determine which quarter had the largest rainfall, the code works no problem.
Where I'm having problems however is when I try to determine the quarter with the least amount. I basically set them both up the same way, but it doesn't work. I'm sure I must have a logic problem somewhere in there, but I've racked my brain trying to figure it out. Any help would be greatly appreciated. I'm sure its something small and stupid that I'm doing.
double largest=0;
for (int k = 0; k < quarterlyArray.length; k++) { // Determines the largest quarterly rainfall.
if ( quarterlyArray[k] >= largest ) {
largest = quarterlyArray[k];
}
}
for (int k = 0; k < quarterlyArray.length; k++) { // Determines in which quarter had largest rainfall.
if (quarterlyArray[k] == largest) {
System.out.println("Quarter " + (k+1) + " saw the most rain this year with " + largest + " inches.");
}
}
double smallest = 0;
for (int p = (quarterlyArray.length-1); p == 0; p--) { // This is not working right now.
if (quarterlyArray[p] < quarterlyArray [quarterlyArray.length-1] || quarterlyArray[p] < smallest) {
quarterlyArray[p] = smallest;
}
}
for (int l = quarterlyArray.length; l == 0; l--) { // Nor this.
if (quarterlyArray[l] == smallest) {
System.out.println("Quarter " + (l+1) + " saw the least rain this year with " + smallest + " inches.");
}
}
A few things that I notice, that are contributing to your problem:
for (int p = (quarterlyArray.length-1); p == 0; p--) {
The p == 0 is the termination expression. Your loop will only iterate while this condition is true. Your loop will not execute because the condition is false on the first iteration.
for (int l = quarterlyArray.length; l == 0; l--) {
Same problem in this loop, too. Look at your condition in your first for loop - k < quarterlyArray.length. When this is false, your loop will terminate.
quarterlyArray[p] = smallest
You are modifying the array rather than your local variable smallest.
You also need to be careful about bounds of the arrays. Your loop sets l to the array length - int l = quarterlyArray.length. If you then try to index into this array using quarterlyArray[l] you would get an ArrayIndexOutOfBoundsException because Java arrays (and most programming languages I would say) are 0-based.
Another thing to point out is how you are calculating both the min and max. Say, for example, that your quarterlyArray contains all negative values. What would largest be? Well, none of the items in the array are greater than 0, so largest would be 0. That would be incorrect because that value is not in the array.
In your first case, it looks like you are starting with an element that you know will always be lower than the elements in the array. This works out fine if you know all the elements will be greater than that. Your double largest = 0 will be changed to the maximum value of the array based on the constraints of the problem you are solving.
A better way to approach this is to start with a known element from the array. If you simply change your largest to be the first/last element from the array, and then go through the rest, you will always come out with the desired result.
double largest = quarterlyArray[0];
for (int k = 1; k < quarterlyArray.length; k++) { // Determines the largest quarterly rainfall.
if ( quarterlyArray[k] >= largest ) {
largest = quarterlyArray[k];
}
}
Notice how all I changed was the initialization of largest, and int k = 1. You can do the same thing for smallest. In this case, I start from the end of the array.
double smallest = quarterlyArray[quarterlyArray.length - 1];
for (int p = quarterlyArray.length - 2; p >= 0; p--) {right now.
if (quarterlyArray[p] < smallest) {
smallest = quarterlyArray[p];
}
}
Another note for after you get through this, is how could do both in 1 for loop?
Start the last loop form quarterlyArray.length-1.Change to
for (int l = quarterlyArray.length-1; l >= 0; l--)
The last element of the array would be at quarterlyArray.length-1 not at quarterlyArray.length
And l == 0(termination expression) should be l >= 0 because when the termination expression evaluates to false, the loop terminates.
Your loop for the smallest is all wrong - you are setting the array values, not finding the smallest.
Do it all in one loop:
double largest=Double.MIN_VALUE;
double smallest = Double.MAX_VALUE;
for (int k = 0; k < quarterlyArray.length; k++) {
if ( quarterlyArray[k] > largest ) {
largest = quarterlyArray[k];
}
if ( quarterlyArray[k] < smallest ) {
smallest = quarterlyArray[k];
}
}
You can also refine this in the manner shown by #mkobit to make it a bit faster:
double largest=quarterlyArray[0];
double smallest = largets;
for (int k = 1; k < quarterlyArray.length; k++) {
if ( quarterlyArray[k] > largest ) {
largest = quarterlyArray[k];
} else if ( quarterlyArray[k] < smallest ) {
smallest = quarterlyArray[k];
}
}
Of course, you should first check to ensure that quarterlyArray has a length greater than zero.

in Java, design linear algorithm that finds contiguous subsequence with highest sum

this is the question, and yes it is homework, so I don't necessarily want anyone to "do it" for me; I just need suggestions: Maximum sum: Design a linear algorithm that finds a contiguous subsequence of at most M in a sequence of N long integers that has the highest sum among all such subsequences. Implement your algorithm, and confirm that the order of growth of its running time is linear.
I think that the best way to design this program would be to use nested for loops, but because the algorithm must be linear, I cannot do that. So, I decided to approach the problem by making separate for loops (instead of nested ones).
However, I'm really not sure where to start. The values will range from -99 to 99 (as per the range of my random number generating program).
This is what I have so far (not much):
public class MaxSum {
public static void main(String[] args){
int M = Integer.parseInt(args[0]);
int N = StdIn.readInt();
long[] a = new long[N];
for (int i = 0; i < N; i++) {
a[i] = StdIn.readLong();}}}
if M were a constant, this wouldn't be so difficult. For example, if M==3:
public class MaxSum2 {
public static void main(String[] args){
int N = StdIn.readInt(); //read size for array
long[] a = new long[N]; //create array of size N
for (int i = 0; i < N; i++) { //go through values of array
a[i] = StdIn.readLong();} //read in values and assign them to
//array indices
long p = a[0] + a[1] + a[2]; //start off with first 3 indices
for (int i =0; i<N-4; i++)
{if ((a[i]+a[i+1]+a[1+2])>=p) {p=(a[i]+a[i+1]+a[1+2]);}}
//if sum of values is greater than p, p becomes that sum
for (int i =0; i<N-4; i++) //prints the subsequence that equals p
{if ((a[i]+a[i+1]+a[1+2])==p) {StdOut.println((a[i]+a[i+1]+a[1+2]));}}}}
If I must, I think MaxSum2 will be acceptable for my lab report (sadly, they don't expect much). However, I'd really like to make a general program, one that takes into consideration the possibility that, say, there could be only one positive value for the array, meaning that adding the others to it would only reduce it's value; Or if M were to equal 5, but the highest sum is a subsequence of the length 3, then I would want it to print that smaller subsequence that has the actual maximum sum.
I also think as a novice programmer, this is something I Should learn to do. Oh and although it will probably be acceptable, I don't think I'm supposed to use stacks or queues because we haven't actually covered that in class yet.
Here is my version, adapted from Petar Minchev's code and with an important addition that allows this program to work for an array of numbers with all negative values.
public class MaxSum4 {
public static void main(String[] args)
{Stopwatch banana = new Stopwatch(); //stopwatch object for runtime data.
long sum = 0;
int currentStart = 0;
long bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
int M = Integer.parseInt(args[0]); // read in highest possible length of
//subsequence from command line argument.
int N = StdIn.readInt(); //read in length of array
long[] a = new long[N];
for (int i = 0; i < N; i++) {//read in values from standard input
a[i] = StdIn.readLong();}//and assign those values to array
long negBuff = a[0];
for (int i = 0; i < N; i++) { //go through values of array to find
//largest sum (bestSum)
sum += a[i]; //and updates values. note bestSum, bestStart,
// and bestEnd updated
if (sum > bestSum) { //only when sum>bestSum
bestSum = sum;
bestStart = currentStart;
bestEnd = i; }
if (sum < 0) { //in case sum<0, skip to next iteration, reseting sum=0
sum = 0; //and update currentStart
currentStart = i + 1;
continue; }
if (i - currentStart + 1 == M) { //checks if sequence length becomes equal
//to M.
do { //updates sum and currentStart
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
//if sum or a[currentStart]
} //is less than 0 and currentStart<=i,
} //update sum and currentStart again
if(bestSum==0){ //checks to see if bestSum==0, which is the case if
//all values are negative
for (int i=0;i<N;i++){ //goes through values of array
//to find largest value
if (a[i] >= negBuff) {negBuff=a[i];
bestSum=negBuff; bestStart=i; bestEnd=i;}}}
//updates bestSum, bestStart, and bestEnd
StdOut.print("best subsequence is from
a[" + bestStart + "] to a[" + bestEnd + "]: ");
for (int i = bestStart; i<=bestEnd; i++)
{
StdOut.print(a[i]+ " "); //prints sequence
}
StdOut.println();
StdOut.println(banana.elapsedTime());}}//prints elapsed time
also, did this little trace for Petar's code:
trace for a small array
M=2
array: length 5
index value
0 -2
1 2
2 3
3 10
4 1
for the for-loop central to program:
i = 0 sum = 0 + -2 = -2
sum>bestSum? no
sum<0? yes so sum=0, currentStart = 0(i)+1 = 1,
and continue loop with next value of i
i = 1 sum = 0 + 2 = 2
sum>bestSum? yes so bestSum=2 and bestStart=currentStart=1 and bestEnd=1=1
sum<0? no
1(i)-1(currentStart)+1==M? 1-1+1=1 so no
i = 2 sum = 2+3 = 5
sum>bestSum? yes so bestSum=5, bestStart=currentStart=1, and bestEnd=2
sum<0? no
2(i)-1(currentStart)+1=M? 2-1+1=2 so yes:
sum = sum-a[1(curentstart)] =5-2=3. currentStart++=2.
(sum<0 || a[currentStart]<0)? no
i = 3 sum=3+10=13
sum>bestSum? yes so bestSum=13 and bestStart=currentStart=2 and bestEnd=3
sum<0? no
3(i)-2(currentStart)+1=M? 3-2+1=2 so yes:
sum = sum-a[1(curentstart)] =13-3=10. currentStart++=3.
(sum<0 || a[currentStart]<0)? no
i = 4 sum=10+1=11
sum>bestSum? no
sum<0? no
4(i)-3(currentStart)+1==M? yes but changes to sum and currentStart now are
irrelevent as loop terminates
Thanks again! Just wanted to post a final answer and I was slightly proud for catching the all negative thing.
Each element is looked at most twice (one time in the outer loop, and one time in the while loop).
O(2N) = O(N)
Explanation: each element is added to the current sum. When the sum goes below zero, it is reset to zero. When we hit M length sequence, we try to remove elements from the beginning, until the sum is > 0 and there are no negative elements in the beginning of it.
By the way, when all elements are < 0 inside the array, you should take only the largest negative number. This is a special edge case which I haven't written below.
Beware of bugs in the below code - it only illustrates the idea. I haven't run it.
int sum = 0;
int currentStart = 0;
int bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
for (int i = 0; i < N; i++) {
sum += a[i];
if (sum > bestSum) {
bestSum = sum;
bestStart = currentStart;
bestEnd = i;
}
if (sum < 0) {
sum = 0;
currentStart = i + 1;
continue;
}
//Our sequence length has become equal to M
if (i - currentStart + 1 == M) {
do {
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
}
}
I think what you are looking for is discussed in detail here
Find the subsequence with largest sum of elements in an array
I have explained 2 different solutions to resolve this problem with O(N) - linear time.

Categories

Resources