Modify solution to use a single loop - java

I managed to solve this, below is my solution :
public class ProblemA001k {
public static void main(String[] args) {
System.out.println("Sum from 1" + " to " + divQ + ":" + sum2);
System.out.println();
divQ += q;
newQ += q;
sum1 = 0;
sum2 = 0;
}
key.close();
}
}
Now I was told to modify my solution so that it uses ONLY ONE LOOP.
I have 3 loops in the code above, even when I tried using only 2 loops I struggled. but ONE LOOP ? I don't know how to improve my code. Please help me.

This is a Mathematic problem.
If you know that you can find the sum of all integers from 1 to X, you just need to do X * (X+1) / 2.
You can find all the batch values easily.
Sum from 1 to 400: 80200
Sum from 401 to 450: 21275
Sum from 1 to 450: 101475
Will be found like this :
450 * 451 / 2 = 101475 (1 to 450)
400 * 401 / 2 = 80200 (1 to 400)
101475 - 80200 = 21275 (401 to 450)
With this, you can limit the loop to just calculate the values from q to n by incrementing by q
And a quick code to do it :
static void sum(int n, int q){
int i = q;
int sum, tmp=0;
while(i < n){
sum = i * (i+1) / 2;
System.out.println(String.format("Sum from %d to %d : %d", i-q+1 , i, sum - tmp));
System.out.println(String.format("Sum from %d to %d : %d", 1, i, sum));
tmp = sum;
i += q;
}
}
And I run it with
public static void main(String[] args){
sum(500, 50);
}
to have this result
Sum from 1 to 50 : 1275
Sum from 1 to 50 : 1275
Sum from 51 to 100 : 3775
Sum from 1 to 100 : 5050
Sum from 101 to 150 : 6275
Sum from 1 to 150 : 11325
Sum from 151 to 200 : 8775
Sum from 1 to 200 : 20100
Sum from 201 to 250 : 11275
Sum from 1 to 250 : 31375
Sum from 251 to 300 : 13775
Sum from 1 to 300 : 45150
Sum from 301 to 350 : 16275
Sum from 1 to 350 : 61425
Sum from 351 to 400 : 18775
Sum from 1 to 400 : 80200
Sum from 401 to 450 : 21275
Sum from 1 to 450 : 101475
The good think with this solution is the number of loop, this will increment by q instead of 1
Note : The solution is a quick implementation, this could be done better.
EDIT :
Thanks to Margaret Bloom in the comments to point out the name of this formula :) For more information, you are welcome to look at Triangular Number

This should do it:
int totalSum = 0;
int batchSum = 0;
for (int i = 1; i <= n; i++) {
totalSum += i;
batchSum += i;
if (i % q == 0) {
System.out.println("Sum from " + (i - q + 1) + " to " + i + ":" + batchSum);
System.out.println("Sum from 1 to " + i + ":" + totalSum);
batchSum = 0;
}
}
Edit:
The better Math way:
int lastTotalSum = 0;
for (int i = 1; i <= n / q; i++ ) {
int top = i * q;
int totalSum = top * (top + 1) / 2;
int batchSum = totalSum - lastTotalSum;
System.out.println("Sum from " + (top - q + 1) + " to " + top + ":" + batchSum);
System.out.println("Sum from 1 to " + top + ":" + totalSum);
lastTotalSum = totalSum;
}

I found a nice solution with java8 Streams:
int n=1000;
int q=50;
int length = n/q -1;
int[] previousSum={0};
IntStream.range(0, length).map(i -> (i+1)*q).forEach(s -> {
int sum=(s*(s+1))/2;
int batch = sum - previousSum[0];
previousSum[0] = sum;
System.out.println("Sum from " + (s - q + 1) + " to " + s + ":" + batch);
System.out.println("Sum from 1 to " + s + ":" + sum);
});

Do one loop iterating entire range and use indexes to decide whether to add, reset or print your sums.
Hope this gives your right idea, if you still dont know I can illustrate it a bit more.

Related

I want to make arithmetic mean for first half and then for the second half of array

I made the arithmetic mean for whole the sorted array, but now i want to make the arithmetic mean for first sorted half and second sorted half of array.
Ex: My array is: 77, 99, 44, 55, 22, 88, 11, 00, 66, 33.
My code make in first place the sort.
The outcome of program is: 00 11 22 33 44 55 66 77 88 99.
Now i want to make the mean for first half:
00 11 22 33 44 and print it.
Then i want to make the mean for the second half:
55 66 77 88 99 and print it.
public class Array {
private double[] a;
private int NrElmts;
public Array(int max)
{ a = new double[max];
NrElmts = 0;
}
public void elements(double value)
{ a[NrElmts] = value;
NrElmts++;
}
public void print()
{ for(int j=0; j<NrElmts; j++)
System.out.print(a[j] + " ");
System.out.println("");
}
public void selectionSort()
{
int out, in, min;
for(out=0; out< NrElmts -1; out++)
{ min = out;
for(in=out+1; in< NrElmts; in++)
if(a[in] < a[min] )
min = in;
invertPositions(out, min); }
}
private void invertPositions(int one, int two)
{ double temp = a[one];
a[one] = a[two];
a[two] = temp;
}
public void mean()
{
int i;
double sum = 0;
for(i = 0; i < NrElmts; i++) {
sum+=a[i];}
double medie = sum/NrElmts;
System.out.format("Mean is: %.1f", mean);
System.out.println("");
}
}
Try this
public void firstHalfMean(){
int i;
double sum = 0;
int numberOFElements = NrElmts/2;
for (i = 0; i < NrElmts/2; i++) { // take sum only till half.
sum += a[i];
}
double mean = sum / numberOFElements; // sum/half the elements
System.out.format("Mean is: %.1f", mean);
System.out.println("");
}
public void secondHalfMean(){
int i;
double sum = 0;
int numberOFElements = NrElmts % 2 == 0 ? NrElmts/2 : NrElmts/2 + 1; // If odd, this second array will contain one more element.
for (i = NrElmts/2; i < NrElmts; i++) { // take sum for the next half
sum += a[i];
}
double mean = sum / numberOFElements; // sum/half elements (half + 1) in case of odd length.
System.out.format("Mean is: %.1f", mean);
System.out.println("");
}
To calculate the mean for 9, 2 and 7 you have to firstly add them all up, which equals 18 and then divide by how many there are - so 18 / 3 which is 6.
Although, you will have to account for the possibility of an odd list - if there's an odd amount of elements, say for example 1, 2, 3 the middle point of 3 - is 1.5 - and if you're iterating through indexes the iterative variable will count the middle point as 1. So it's a bit tricky, not sure what you'd want to do.Consider the following code though - it does exactly what you want, but with odd list sizes, it will just divide by a decimal value
LinkedList<Integer> numbers = new LinkedList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
numbers.add(40);
int size = numbers.size();
int iterativeHalf = size / 2;
float meanHalf = (float) size / 2;
float lowerMean = 0;
float upperMean = 0;
for (int i = 0; i < size; i++) {
int realRef = i + 1;
Integer value = numbers.get(i);
if (realRef > iterativeHalf) { //Should be calculating upper mean
if (upperMean == 0) { //if lowerMean is just a running total, not divided yet to get the mean
System.out.println("the lower mean for numbers is " + lowerMean + " / " + meanHalf);
lowerMean = (lowerMean) / meanHalf; //add last value + divide to set it to the mean
}
System.out.println("upper mean = " + upperMean + " + " + value + " = " + (upperMean + value));
upperMean = upperMean + value; //keep the upper values up total going
} else {
System.out.println("lower mean = " + lowerMean + " + " + value + " = " + (lowerMean + value));
lowerMean = lowerMean + value; //keep adding the lower halfs values up
}
}
//When it breaks, must divide upperMean by size to get mean
System.out.println("the upper mean for numbers is " + upperMean + " / " + meanHalf);
upperMean = (upperMean) / meanHalf;
System.out.println(" ");
System.out.println("FINAL lower mean = " + lowerMean);
System.out.println("FINAL upper mean = " + upperMean);
Output is:
lower mean = 0.0 + 10 = 10.0
lower mean = 10.0 + 20 = 30.0
the lower mean for numbers is 30.0 / 2.0
upper mean = 0.0 + 30 = 30.0
upper mean = 30.0 + 40 = 70.0
the upper mean for numbers is 70.0 / 2.0
FINAL upper mean = 35.0
FINAL lower mean = 15.0
This, for a [10, 20, 30, 40] will yield the output shown above but essentially (10+20)/2 as the lower mean and (30+40)/2 for the upper mean.
For [10, 20, 30, 40, 50] will yield (10 + 20) / 2.5 the lower mean and (30+40+50)/2.5 for the upper mean
Only take sum of half the array. Give one more element to your second or first half in case if your array size is odd.
public void firstHalfMean(){
int i;
double sum = 0;
int numberOFElements = NrElmts/2;
for (i = 0; i < NrElmts/2; i++) { // take sum only till half.
sum += a[i];
}
double mean = sum / numberOFElements; // sum/half the elements
System.out.format("Mean is: %.1f", mean);
System.out.println("");
}
public void secondHalfMean(){
int i;
double sum = 0;
int numberOFElements = NrElmts % 2 == 0 ? NrElmts/2 : NrElmts/2 + 1; // If odd, this second array will contain one more element.
for (i = NrElmts/2; i < NrElmts; i++) { // take sum for the next half
sum += a[i];
}
double mean = sum / numberOFElements; // sum/half elements (half + 1) in case of odd length.
System.out.format("Mean is: %.1f", mean);
System.out.println("");
}
Since you already have way to make mean for entire array, all you need to do is find mid position of array and then run from and to that point.
In your example: NrElmts is 10, so divide your NrElmnts by 2, so you can get mean for 1 to 5, and then 6 to 10 both 5 each.
Think about situation where you have odd number of elements in array, how do u want to do it, whether in first array or second. let me know if this need help as well.
Steps:
1) create a new variable say a1 to NrElmts/2, and go with your mean function from 1 to a1
2) go from a1+1 to NrElmnts
Let me know if you need any help.

Backtracking Min options to sum a number using 1, 5 and 7 via recursion - JAVA

I want to create a recursion function that returns the minimum options to create a certain number using numbers 1, 5 and 7 (Fixed predetermined numbers). It is important that this is done only by recursion without loops at all.
For example:
if n = 10 then it is given to the scheme by 5 + 5 which is 2 numbers, so this is the minimum and this is what we will get (as opposed to 7 + 1 + 1 + 1 or 5 + 1 + 1 + 1 + 1 + 1 that is 4 or 6 Options that are longer).
If n = 6 then we get a result of 2 (because it is given as a sum of 1 + 5).
If n = 5 (or 7 or 1) then we get a result of 1 (because it is given by the number only).
class TEST {
static int countMin( int S[], int m, int n ,int min)
{
if (n == 0)
return 1;
if (n < 0)
return 0;
if (m <=0 && n >= 1)
return 0;
return Math.min(min,countMin( S, m - 1, n ,min-1) + countMin( S, m, n-S[m-1],min-1 ));
}
public static int f(int n) {
int arr[] = {1, 5, 7};
return countMin(arr, arr.length, n,n);
}
public static void main(String[] args)
{
int n = 10;
System.out.println("The number "+n+ " - " + f(n) + " minimum options to create");
int n2 = 7;
System.out.println("The number "+n2+ " - " + f(n2) + " minimum options to create");
int n3 = 6;
System.out.println("The number "+n3+ " - " + f(n3) + " minimum options to create");
}
}
I get for n = 10 and n = 5 for the correct result but not for n = 6 which should return 2.
*I've used this link: https://www.geeksforgeeks.org/coin-change-dp-7/
Think of a tree where each node has a value and has 3 children with its value decremented respectively by 7, 5, and 1
So node with total 15 would have children with values 8, 10, 14
We can start with first node having your total, and calculate each level and stop when we find a child worth 0. We also stop looking at a child if its value is less than 0.
For 10 for example:
10
/ | \
3 5 9
/ | \ / | \ / | \
-4 -2 2 -2 0 4 2 4 1
We find zero at depth 2
private static int calculate(int total, int depth) {
if (total == 0)
return depth;
else {
int i = total - 7 >= 0 ? calculate(total - 7, depth+1) : Integer.MAX_VALUE;
int j = total - 5 >= 0 ? calculate(total - 5, depth+1) : Integer.MAX_VALUE;
int k = total - 1 >= 0 ? calculate(total - 1, depth+1) : Integer.MAX_VALUE;
return Collections.min(Arrays.asList(i, j, k));
}
}
This
int n = 10;
System.out.println("The number "+n+ " - " + calculate(n, 0) + " minimum options to create");
n = 7;
System.out.println("The number "+n+ " - " + calculate(n, 0) + " minimum options to create");
n = 6;
System.out.println("The number "+n+ " - " + calculate(n, 0) + " minimum options to create");
n = 18;
System.out.println("The number "+n+ " - " + calculate(n, 0) + " minimum options to create");
Outputs this
The number 10 - 2 minimum options to create
The number 7 - 1 minimum options to create
The number 6 - 2 minimum options to create
The number 18 - 4 minimum options to create
EDIT:
The same in a funky lambda style:
private static int calculate(int total, int depth) {
return total == 0 ?
depth :
Stream.of(7, 5, 1)
.map(i -> total - i >= 0 ? calculate(total - i, depth+1) : Integer.MAX_VALUE)
.min(Integer::compare)
.get();
}

How can we find the sum for each subset of array

I am trying to finding the sum of each in the below code in java.What changes should i have to made in this code.
import java.io.IOException;
class as {
static void printSubsets(int set[]) {
int n = set.length;
for (int i = 0; i < (1 << n); i++) {
for (int j = 0; j < n; j++) {
if ((i & (1 << j)) > 0) {
System.out.print(set[j] + " ");
}
}
System.out.println();
}
}
public static void main(String[] args) {
int set[] = { 1, 2, 3 };
printSubsets(set);
}
}
Output of above code is:
1
2
1 2
3
1 3
2 3
1 2 3
I want To Multiply each element of subset by its last number for e.g.
1*1=1
2*2=4
1*2+2*2=6
3*3=9
likewise all elements
and lastly generate sum of all these subset 1+4+6+9+.. and so on.
Above code also print null set and subset are in order.How this program can be edited to make changes such that it does'nt print null set and print random substring.
As far as I understand your question, you want to multiply all the elements with each other and print out each step of iteration with the result. Here you are:
static void printSubsets(int set[]) {
int sum = 0;
for (int i=0; i<set.length; i++) {
for (int j=i; j<set.length; j++) {
int var = set[i] * set[j];
sum += var;
System.out.println("( " + set[i] + " * " + set[j] + " = " + var + " ) -> sum=" + sum);
}
}
System.out.println("final sum=" + sum);
}
In case of input [1,2,3], the sum is supposed to grow according my algorithm by:
1, 3, 6, 10, 16 up to 20
Just a note about << shift operator which shifts a bit pattern to the left. Let's say that number 2 is understood as 10 in binary. Shifting this number by 2 << 4 will result 100000 in binary that is understood as 32 in decimal. I am not sure you really need this pattern.

How to stop summing a harmonic series when it reaches a specified target in Java?

I'm a complete beginner in Java who just recently got introduced to loops. I'm trying to do write a program that reads in a target and finds the first n such that 1 + 1/2 + 1/3 + ... + 1/n > target. The problem supplied a code with the initialization of n and sum missing as well as the condition of while and its statements missing.
I'm able to work out how to make the harmonic series loop, but I'm not sure what to set n with to stop the loop when it exceeds the target.We've not learned about arrays in class yet..
import java.util.Scanner;
/**
This program computes how many steps the sum 1 + 1/2 + 1/3 + ...
needs to exceed a given target.
*/
public class ReciprocalSum
{
public static void main(String[] args)
{
double sum = 0;
int n = ???? ;
Scanner in = new Scanner(System.in);
System.out.print("Target: ");
double target = in.nextDouble();
int i = 0;
//Notes
// 1 + 1/2 + 1/3 + 1/4 + ..... 1/n
//Make a loop that repeats itself starting with n = 1 --> 1/1 + 1/2 + 1/3 + 1/4 + 1/n
// 1.0/n + (1.0/ n - 1) + (1.0/n-2) +.... if n =4 --> 1/4 + 1/3 + 1/2 + 1/1 as long as n >0
while ( n > 0)
{
sum += 1.0/n ;
n--;
}
System.out.println("n: " + n);
System.out.println("sum: " + sum);
}
}
n should be incremented in the loop (and therefore it should start at 0), and the loop should be exited when you reach the target:
int n = 0;
...
while (sum <= target)
{
n++;
sum += 1.0/n;
}
Because Java 8+ has lambdas, and you can generate a range 1 to n and perform your calculation and get the sum in one step. Basically, you could do
Scanner in = new Scanner(System.in);
System.out.print("Target: ");
double target = in.nextDouble(), sum = 1.0;
int n = 1;
while (sum < target) {
sum = IntStream.range(1, n).mapToDouble(i -> 1.0 / i).sum();
n++;
}
System.out.printf("n=%d, sum=%.2f%n", n, sum);
You can achieve that in this way by calculating sum of the series until its sum bigger than the target value:
double sum = 0;
int n = 1;
Scanner in = new Scanner(System.in);
System.out.print("Target: ");
double target = in.nextDouble();
while(sum <= target){
sum = sum + 1.0/n;
n = n + 1;
}
System.out.println(sum);

Getting and assigning values to Java arrays?

I'm currently learning Java and I've just beginned so my knowledge of it is not very good.
I have a problem with a program I wrote that calculates the first 100 values of the Fibonacci sequence. The point is that it just outputs the 2 and no other number.
This is the code of my program:
class MyClass1 {
public static void main(String[ ] args) {
int[] fib = new int[102];
fib[0] = 1;
fib[1] = 1;
int counter = 0;
int n1, n2, fibSum;
while(counter < (fib.length - 2)){
n1 = fib[counter];
System.out.println(fib[counter]);
counter++;
n2 = fib[counter];
System.out.println(n2);
counter++;
fibSum = n1 + n2;
System.out.println(fibSum);
fib[counter] = fibSum;
}
}
}
Thank you for your help.
There are some logical errors in your code.
First loop:-
Initially n1=fib[0]=1 and n2=fib[1]=1 and you print both. fib[2] is the sum and so it is 2. So far so good.
Second loop:-
n1 = fib[2] = 2. n2 = fib[3] = 0 and hence fib[4] = 2. This is where the problem happens. Hence you will always see 2 0 2 in the output from second loop onwards.
For Fibonacci sequence, you need to add the previous 2 values but you are only considering the previous value in your code. Here's a corrected version of your code:-
public static void main(String[ ] args) {
double[] fib = new double[100];
fib[0] = 1;
fib[1] = 1;
int counter = 2;
double n1, n2, fibSum;
System.out.println(fib[0]);
System.out.println(fib[1]);
while(counter < fib.length){
n1 = fib[counter-1];
n2 = fib[counter-2];
fibSum = n1 + n2;
System.out.println(fibSum);
fib[counter] = fibSum;
counter++;
}
}
Note that I am using type double because type int or even long is not enough for going upto the 100th term in this sequence.
Fibonacci number is the sum of the previous 2 numbers:
fibonacci(n) = fibonacci(n - 1) + fibonacci(n - 2)
So it can be evaluated very nice using recursion:
private static long fibonacci(int n) {
if (n <= 1) return n;
else return fibonacci(n - 1) + fibonacci(n - 2); }
public static void main(String[] args) {
int n = 102;
for (int i = 1; i <= n; i++)
System.out.println(i + ": " + fibonacci(i));
}
Your problem is that
A) all array values are initialized to 0
B) you are accessing "the next" array value, before assigning a value to it!
When you change your outputs to:
System.out.println("1. counter: " + counter + "/" + fib[counter]);
counter++;
n2 = fib[counter];
System.out.println("2. counter: " + counter + "/" + fib[counter]);
counter++;
fibSum = n1 + n2;
fib[counter] = fibSum;
System.out.println("3. counter: " + counter + "/" + fib[counter]);
You will find that it prints:
1 counter: 0/1
2 counter: 1/1
3 counter: 2/2
1 counter: 2/2
2 counter: 3/0
The last row shows you what is going on: you fetch the value at index 3 ... before you assigned a value to it. Therefore your whole fibonacci sum ... doesn't "start"; because you keep loosing values.
In other words: you have to ensure that your counter increases properly:
while(counter < (fib.length - 2)){
n1 = fib[counter];
System.out.println("1 counter: " + counter + "/" + fib[counter]);
n2 = fib[counter+1];
System.out.println("2 counter: " + counter + "/" + fib[counter+1]);
fibSum = n1 + n2;
fib[counter+2] = fibSum;
System.out.println("3 counter: " + counter + "/" + fib[counter+2]);
counter++;
}
Meaning: you need one full loop for each value of counter. When you run my solution, you will find that it works nicely (until counter hits 44/45 and we run into int overflow; as the numbers get too big).
After your first iteration you'll have the following values:
n1 = 1
n2 = 1
fibsum = 2
fib[2] = 2
All other values from fib[3] to length are uninitialized.
So in the second iteration :
n1 = 2
now the counter value will be increased by 1 which is counter = 3
n2 = fib[3]
// this one in not calculated properly and hence the issue.

Categories

Resources