I'm trying to write a code which will show the highest, lowest, the difference of them and the average of inputted 30 numbers.
But its not working and is showing the same result for both min and max numbers. Here is the code.
public class aa {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int[] daystemp = new int[30];
int i = 0;
int dayHot = 0;
int dayCold = 0;
while(i < daystemp.length){
daystemp[i] = input.nextInt();
i++;
}
int maxTemp = daystemp[0];
while (i < daystemp.length) {
if (daystemp[i] > maxTemp) {
maxTemp = daystemp[i];
dayHot = i + 1;
i++;
}
}
System.out.println(maxTemp);
int minTemp = daystemp[0];
while (i < daystemp.length) {
if (daystemp[i] < minTemp) {
minTemp = daystemp[i];
dayCold = i + 1;
i++;
}
}
System.out.println(minTemp);
int diff = maxTemp - minTemp;
System.out.println("The difference between them is"+diff);
double sum = 0;
while(i < daystemp.length) {
sum += daystemp[i];
i++;
}
double average = sum / daystemp.length;
System.out.println("Average was"+average);
}
}
After the first loop (the input loop), i value is daystemp.length (i.e. 30).
It's never reset to 0. So each while loop condition is false.
Add i=0 before the loops and do i++outside the ifblocks or your code will never end.
example:
i=0;
int maxTemp = daystemp[0];
while (i < daystemp.length) {
if (daystemp[i] > maxTemp) {
maxTemp = daystemp[i];
dayHot = i + 1;
}
i++;
}
A few notes about this solution:
By declaring the cumulative total double, no casting is required.
Because Java knows you want to convert int to double automatically if you assign an int to a declared double. Similary the fact that you want to express a result as double is implied when dividing a double by an int, such as when the average is taken. That avoids a cast also. If you had two ints and you wanted to produce a double you'd need to cast one or more of them, or in cases like a print statement where the compiler can't deduce the optimal type for the parameter, you'd need to explicitly cast to covert an int value to a double.
Not sure what OS you're running this on. The ideal situation would be to make it work on all platforms without requiring people type a magic word to end input (because how tacky). The easiest way to end input is to use the OS-specific end of input (end of file) key combination, and for Linux it's CTRL/D, which is how I explained it in the prompt. On another OS with a different end of input sequence you could just change the prompt. The trickiest would be if it is supposed to be truly portable Java. In that case I'd personally investigate how I could figure out the OS and/or End of File character or key combination on the current OS and modify the prompt to indicate to end input with whatever that is. That would be a bit of and advanced assignment but a very cool result.
Example illustrates use of a named constant to determine the array and is used limit the amount of input (and could be used to limit loop count of for loops accessing the array).
By setting the min and max to very high and low values respectively (notice the LOW value assigned to max and HIGH value assigned to min, those ensure the first legit temp entered will set the min and max and things will go from there).
Temperature Maximum, Minimum, Average and Difference Calculator
import java.util.Scanner;
public class TemperatureStats {
final static int MAX_DAYS = 31;
public static void main(String[] args) {
int[] dayTemps = new int[MAX_DAYS];
double cumulativeTemp = 0.0;
int minTemp = 1000, maxTemp = -1000;
Scanner input = new Scanner(System.in);
System.out.println("Enter temps for up to 1 month of days (end with CTRL/D):");
int entryCount = 0;
while (input.hasNextInt() && entryCount < MAX_DAYS)
dayTemps[entryCount++] = input.nextInt();
/* Find min, max, cumulative total */
for (int i = 0; i < entryCount; i++) {
int temp = dayTemps[i];
if (temp < minTemp)
minTemp = temp;
if (temp > maxTemp)
maxTemp = temp;
cumulativeTemp += temp;
}
System.out.println("High temp. = " + maxTemp);
System.out.println("Low temp. = " + minTemp);
System.out.println("Difference = " + (maxTemp - minTemp));
System.out.println("Avg temp. = " + cumulativeTemp / entryCount);
}
}
Related
I was doing a java exercise the other day and in the exercise we had to get input from the user and then figure out what the max value was and what the average was. We then had to print out those values. Values could only be positive integers and when the user enters a negative integer the program should stop taking in values and not account for that negative integer into the average calculation. My problem was I couldn't figure out a way to compare the current integer entered by the user to the max value.
I just made it's own if statement for it and I was expecting a compile error that the max variable didn't have a value or something like that, but the code worked just fine. So my question is do if statements have their own scope or not? What even has scope in programming and what doesn't.
import java.util.Scanner;
public class LabProgram {
public static void main(String[] args) {
//Create Scanner.
Scanner inp = new Scanner(System.in);
//Declare and initialize variables.
double average;
int sum = 0;
int num;
int counter = 0;
int max = 0;
//Process.
do
{
num = inp.nextInt();
sum += num;
if(num > max)
{
max = num;
}
if(num < 0)
{
sum -= num;
System.out.print(max);
average = sum/(double)counter;
System.out.printf(" %.2f\n", average);
}
++counter;
}while(num >= 0);
}
}
Do if statements have their own scope?
No, in Java if statements do not by themselves create a new scope (until Java 14, that is!). However, braced statement blocks (i.e. {…}) do create a new, nested scope.
However, this is unrelated with your issue, because nested scopes can access variables from their parent scope (otherwise most code wouldn’t work). So the following works:
int x = 1;
{
System.out.println(x);
}
If {…} didn’t inherit the parent scope, that code wouldn’t work.
As noted by Ivar in the comments, your code works because you did initialise the max variable to 0 outside the loop.
That said, the code can be made simpler and more logical. In particular, the calculation of the average and the output should not be part of the loop but instead happen afterwards:
Scanner inp = new Scanner(System.in);
int sum = 0;
int count = 0;
int max = 0;
int num;
do {
sum += num;
num = inp.nextInt();
if (num > max) {
max = num;
}
++count;
} while (num >= 0);
double average = sum / (double) (count - 1);
System.out.printf("%d %.2f\n", max, average);
A commonly used alternative way of writing this loop is using for(;;) with break;. This variant has the alternative that we can limit the scope to num to the loop: it is generally desirable to make variable scope as small as possible, and to initialise a variable at the site of its declaration.
…
for (;;) {
int num = inp.nextInt();
if (num < 0) break;
sum += num;
if (num > max) {
max = num;
}
++count;
}
…
Im trying to create a program to find the length of a given number. I thought i would do this by taking the number and dividing by 10 and then checking to see if the number was <= 0. I dident want to edit the global number so i created a instance version of the number and used that as the condition in the for loop.
So obviously this dident work so naturally i ended up looking in the debugger to figure out what was going on. It looks as if the program is completely skipping over the for loop any help would be appreciated.
public static void sumFirstAndLastDigit(int number) {
int numberLength = 0;
int instanceNumber = number;
for(int i = 0; instanceNumber <= 0; i++) {
instanceNumber /= 10;
numberLength = i;
}
System.out.println("Number length = " + numberLength);
// to find length of number loop division by 10
}
}
The program should use the for loop to keep dividing by 10 until the number is = to or less than than zero and for how many times the loop ran should be stored in the number length integer. In this case with the number 12321 the answer should be 6 but it prints 0.
You're telling it to loop while instanceNumber <= 0. The "test" in a for loop is a "keep going" test, not a termination test. The loop continues as long as the test is true.
From your description, you want instanceNumber > 0.
Also note Avinash Gupta's point that with your current code, you'll undercount by one. I'd address that by using a completely different loop:
int numberLength = 0;
int instanceNumber = number;
while (instanceNumber > 0) {
++numberLength;
instanceNumber /= 10;
}
That's nice and unambiguous: If instanceNumber > 0, it increments numberLength, then divides by 10 and tries again.
This will print the correct output
public static void sumFirstAndLastDigit(int number) {
int numberLength = 0;
int instanceNumber = number;
for(int i = 0; instanceNumber > 0; i++) {
instanceNumber /= 10;
numberLength = i;
}
System.out.println("Number length = " + (numberLength + 1));
}
Your code will be much more comprehensive if you use while loop for your algorithm.
public static void sumFirstAndLastDigit(int number) {
int numberLength = 0;
int instanceNumber = number;
while(instanceNumber != 0) {
instanceNumber /= 10;
numberLength += 1;
}
System.out.println("Number length = " + numberLength);
// to find length of number loop division by 10
}
Consider even more sophisticated solution:
public static void sumFirstAndLastDigit(int number) {
int numberLength = (int) (Math.log10(number) + 1);
System.out.println("Number length = " + numberLength);
}
Taken from Baeldung
after adding two int variables to (a) and (b),
I have to gamble (a) times values between 10 to 100 and
calculate which square root of these gambled numbers is the closest to (b).
For example a=3 and b=2
output:
Gambled 16,25,49.
The number 16 was chosen since it's square root (4) is the closest to b=2.
I am stuck in the part of calculation of the square root, and saving the closest value to b each time the loop runs, i'm not allowed to use arrays,
this is the third question of my first task and i'd appreciate any experienced ideas to be shared ^^.
(MyConsole is a replacement for the scan command)
int a = MyConsole.readInt("Enter value a:");
int b = MyConsole.readInt("Enter value b:");
for(int i = 0; i<a; a--){
int gambler = ((int)(Math.random() *91)+10);
double Root = Math.sqrt(gambler);
double Distance= Root-b;
{
System.out.println();
Here is how I found the minimum. You can also use arrays to store all the gambling values if you want for future use. I also used Scanner but you can use your MyConsole I'm just not familiar with it. I hope it helps. דש מישראל
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter value a:");
int a = scanner.nextInt();
System.out.println("Enter value b:");
int b = scanner.nextInt();
double min = 100;
for (int i = 0; i < a; i++) {
int gambler = ((int) (Math.random() * 91) + 10);
double root = Math.sqrt(gambler);
double distance = Math.abs(root - b);
if (min > distance)
min = distance;
}
System.out.println("minimum value is: " + min);
}
This question already has answers here:
Integer division: How do you produce a double?
(11 answers)
Closed 5 years ago.
I had a question in my exam. At first it was pretty easy. Let me explain the question:
Make the User Specify how many integers wants to put (Array)
Numbers should be between -1500 to 1500
(Tricky): Create a method that calculates the percentage of the numbers put, what percentage were 0, positive, negative.
(All this should be in ONE method, no return to string, string buffer, the return result should be a double value)
I think I did it right, but when I tested it in real time, the problem that I run is that it returns the values 0.0, 0.0, 0.0 ... Or it returns the correct percentage only if the values fall within the same condition (eg. all zero).
Here is my code: (I hope you can make sense out of it). I'm just curious, I don't know how to solve it. I have also tried it with a static method, I run into the same problem.
import java.util.Scanner;
public class nPNZ {
public int [] number;
public nPNZ (int [] n){
number = n;
}
public double [] allCalcs(){
int countPos = 0; int countNeg = 0; int countZero = 0;
for (int i = 0; i < number.length; i++) {
if (number[i] == 0) {
countZero++;
}else if (number[i] > 0){
countPos++;
}else{
countNeg++;
}
}
//0 = 0 ; 1 = positive ; 2 = negative
double total [] = new double [3];
total[0] = (countZero/number.length)*100;
total[1] = (countPos/number.length)*100;
total[2] = (countNeg/number.length)*100;
return total;
}
public static void main (String args[]){
//min 20 number, -1500 to 1500
Scanner input = new Scanner (System.in);
final int MIN_SIZE = 5;
int size = 0;
while(size < MIN_SIZE){
System.out.println("Specify the size of the array: ");
size = input.nextInt();
while(size<MIN_SIZE){
System.out.println("Size should be greater than: " + MIN_SIZE);
size = input.nextInt();
}
}
input.nextLine();
int num [] = new int [size];
for (int i = 0; i < num.length; i++) {
System.out.println("Write number " + (i+1) + " : ");
num[i] = input.nextInt();
while(num[i] < -1500 || num[i] > 1500) {
System.out.println("The number should within the range of -1500 and 1500");
num[i] = input.nextInt();
}
}
nPNZ n = new nPNZ (num);
System.out.println("Percentage of zero numbers is: " + n.allCalcs()[0] );
System.out.println("Percentage of positive numbers is: " + n.allCalcs()[1] );
System.out.println("Percentage of negative numbers is: " + n.allCalcs()[2]);
}
}
I can see one problem in your code.
double total [] = new double [3];
total[0] = (countZero/number.length)*100;
total[1] = (countPos/number.length)*100;
total[2] = (countNeg/number.length)*100;
return total;
Here, countZero, countPos and countNeg are all integers and number.length is also integer. So, when you divide an integer by another integer, you will get an integer.
Since, countZero, countPos and countNeg are all less than number.length, you will get zero value in the total array.
Example:
System.out.println(2/3); // prints 0
System.out.println(2.0/3); // prints 0.6666666666666666
System.out.println((double)2/3); // prints 0.6666666666666666
There are several alternatives to solve your problem. One of them is, simply multiply the integer by 1.0 while dividing it by another integer.
You can do something like this.
public double [] allCalcs(){
// your code goes here
double total [] = new double [3];
total[0] = (countZero * 1.0 / number.length) * 100;
total[1] = (countPos * 1.0 / number.length) * 100;
total[2] = (countNeg * 1.0 / number.length) * 100;
return total;
}
OR, you can declare the variables (countZero, countPos and countNeg) as double.
It actually is problem to find lucky number - those numbers whose sum of digits and sum of square of digits are prime. I have implemented Sieve of Eratosthenes. Now to optimize it further I commented my getDigitSum method, that I suppose was heavy and replaced with two hard-coded value , but it is still taking minutes to solve one test case. Here is a reference to actual problem asked
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.TreeSet;
public class Solution {
private static int[] getDigitSum(long num) {
long sum = 0;
long squareSum = 0;
for (long tempNum = num; tempNum > 0; tempNum = tempNum / 10) {
if (tempNum < 0) {
sum = sum + tempNum;
squareSum = squareSum + (tempNum * tempNum);
} else {
long temp = tempNum % 10;
sum = sum + temp;
squareSum = squareSum + (temp * temp);
}
}
int[] twosums = new int[2];
twosums[0] = Integer.parseInt(sum+"");
twosums[1] = Integer.parseInt(squareSum+"");
// System.out.println("sum Of digits: " + twoDoubles[0]);
// System.out.println("squareSum Of digits: " + twoDoubles[1]);
return twosums;
}
public static Set<Integer> getPrimeSet(int maxValue) {
boolean[] primeArray = new boolean[maxValue + 1];
for (int i = 2; i < primeArray.length; i++) {
primeArray[i] = true;
}
Set<Integer> primeSet = new TreeSet<Integer>();
for (int i = 2; i < maxValue; i++) {
if (primeArray[i]) {
primeSet.add(i);
markMutiplesAsComposite(primeArray, i);
}
}
return primeSet;
}
public static void markMutiplesAsComposite(boolean[] primeArray, int value) {
for (int i = 2; i*value < primeArray.length; i++) {
primeArray[i * value] = false;
}
}
public static void main(String args[]) throws NumberFormatException,
IOException {
// getDigitSum(80001001000l);
//System.out.println(getPrimeSet(1600));
Set set = getPrimeSet(1600);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int totalCases = Integer.parseInt(br.readLine());
for (int cases = 0; cases < totalCases; cases++) {
String[] str = br.readLine().split(" ");
long startRange = Long.parseLong(str[0]);
long endRange = Long.parseLong(str[1]);
int luckyCount = 0;
for (long num = startRange; num <= endRange; num++) {
int[] longArray = getDigitSum(num); \\this method was commented for testing purpose and was replaced with any two hardcoded values
if(set.contains(longArray[0]) && set.contains(longArray[1])){
luckyCount++;
}
}
System.out.println(luckyCount);
}
}
}
what I should use to cache the result so that it takes lesser amount of time to search, currently it takes huge no. of minutes to complete 10000 test cases with range 1 99999999999999(18 times 9 -the worst case) , even thought the search values have been hard-coded for testing purpose( 1600, 1501 ).
You need a different algorithm. Caching is not your problem.
If the range is large - and you can bet some will be - even a loop doing almost nothing would take a very long time. The end of the range is constrained to be no more than 1018, if I understand correctly. Suppose the start of the range is half that. Then you'd iterate over 5*1017 numbers. Say you have a 2.5 GHz CPU, so you have 2.5*109 clock cycles per second. If each iteration took one cycle, that'd be 2*108 CPU-seconds. A year has about 3.1*107 seconds, so the loop would take roughly six and a half years.
Attack the problem from the other side. The sum of the squares of the digits can be at most 18*92, that's 1458, a rather small number. The sum of the digits itself can be at most 18*9 = 162.
For the primes less than 162, find out all possible decompositions as the sum of at most 18 digits (ignoring 0). Discard those decompositions for which the sum of the squares is not prime. Not too many combinations are left. Then find out how many numbers within the specified range you can construct using each of the possible decompositions (filling with zeros if required).
There are few places in this implementation that can be improved. In order to to start attacking the issues i made few changes first to get an idea of the main problems:
made the total start cases be the value 1 and set the range to be a billion (1,000,000,000) to have a large amount of iterations. also I use the method "getDigitSum" but commented out the code that actually makes the sum of digits to see how the rest runs: following are the methods that were modified for an initial test run:
private static int[] getDigitSum(long num) {
long sum = 0;
long squareSum = 0;
// for (long tempNum = num; tempNum > 0; tempNum = tempNum / 10) {
// if (tempNum < 0) {
// sum = sum + tempNum;
// squareSum = squareSum + (tempNum * tempNum);
// } else {
// long temp = tempNum % 10;
// sum = sum + temp;
// squareSum = squareSum + (temp * temp);
//
// }
// }
int[] twosums = new int[2];
twosums[0] = Integer.parseInt(sum+"");
twosums[1] = Integer.parseInt(squareSum+"");
// System.out.println("sum Of digits: " + twoDoubles[0]);
// System.out.println("squareSum Of digits: " + twoDoubles[1]);
return twosums;
}
and
public static void main(String args[]) throws NumberFormatException,
IOException {
// getDigitSum(80001001000l);
//System.out.println(getPrimeSet(1600));
Set set = getPrimeSet(1600);
//BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int totalCases = 1;
for (int cases = 0; cases < totalCases; cases++) {
//String[] str = br.readLine().split(" ");
long startRange = Long.parseLong("1");
long endRange = Long.parseLong("1000000000");
int luckyCount = 0;
for (long num = startRange; num <= endRange; num++) {
int[] longArray = getDigitSum(num); //this method was commented for testing purpose and was replaced with any two hardcoded values
if(set.contains(longArray[0]) && set.contains(longArray[1])){
luckyCount++;
}
}
System.out.println(luckyCount);
}
}
Running the code takes 5 minutes 8 seconds.
now we can start optimizing it step by step. I will now mention the various points in the implementation that can be optimized.
1- in the method getDigitSum(long num)
int[] twosums = new int[2];
twosums[0] = Integer.parseInt(sum+"");
twosums[1] = Integer.parseInt(squareSum+"");
the above is not good. on every call to this method, two String objects are created , e.g. (sum+"") , before they are parsed into an int. considering the method is called billion times in my test, that produces two billion String object creation operations. since you know that the value is an int (according to the math in there and based on the links you provided), it would be enough to use casting:
twosums[0] = (int)sum;
twosums[1] = (int)squareSum;
2- In the "Main" method, you have the following
for (long num = startRange; num <= endRange; num++) {
int[] longArray = getDigitSum(num); \\this method was commented for testing purpose and was replaced with any two hardcoded values
if(set.contains(longArray[0]) && set.contains(longArray[1])){
luckyCount++;
}
}
here there are few issues:
a- set.contains(longArray[0]) will create an Integer object (with autoboxing) because contains method requires an object. this is a big waste and is not necessary. in our example, billion Integer objects will be created. Also, usage of set, whether it is a treeset or hash set is not the best for our case.
what you are trying to do is to get a set that contains the prime numbers in the range 1 .. 1600. this way, to check if a number in the range is prime, you check if it is contained in the set. This is not good as there are billions of calls to the set contains method. instead, your boolean array that you made when filling the set can be used: to find if the number 1500 is prime, simply access the index 1500 in the array. this is much faster solution. since its only 1600 elements (1600 is greater than max sum of sqaures of digits of your worst case), the wasted memory for the false locations is not an issue compared to the gain in speed.
b- int[] longArray = getDigitSum(num);
an int array is being allocated and returned. that will happen billion times. in our case, we can define it once outside the loop and send it to the method where it gets filled. on billion iterations, this saved 7 seconds, not a big change by itslef. but if the test cases are repeated 1000 times as you plan, that is 7000 second.
therefore, after modifying the code to implement all of the above, here is what you will have:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.TreeSet;
public class Solution {
private static void getDigitSum(long num,int[] arr) {
long sum = 0;
long squareSum = 0;
// for (long tempNum = num; tempNum > 0; tempNum = tempNum / 10) {
// if (tempNum < 0) {
// sum = sum + tempNum;
// squareSum = squareSum + (tempNum * tempNum);
// } else {
// long temp = tempNum % 10;
// sum = sum + temp;
// squareSum = squareSum + (temp * temp);
//
// }
// }
arr[0] = (int)sum;
arr[1] = (int)squareSum;
// System.out.println("sum Of digits: " + twoDoubles[0]);
// System.out.println("squareSum Of digits: " + twoDoubles[1]);
}
public static boolean[] getPrimeSet(int maxValue) {
boolean[] primeArray = new boolean[maxValue + 1];
for (int i = 2; i < primeArray.length; i++) {
primeArray[i] = true;
}
for (int i = 2; i < maxValue; i++) {
if (primeArray[i]) {
markMutiplesAsComposite(primeArray, i);
}
}
return primeArray;
}
public static void markMutiplesAsComposite(boolean[] primeArray, int value) {
for (int i = 2; i*value < primeArray.length; i++) {
primeArray[i * value] = false;
}
}
public static void main(String args[]) throws NumberFormatException,
IOException {
// getDigitSum(80001001000l);
//System.out.println(getPrimeSet(1600));
boolean[] primeArray = getPrimeSet(1600);
//BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int totalCases = 1;
for (int cases = 0; cases < totalCases; cases++) {
//String[] str = br.readLine().split(" ");
long startRange = Long.parseLong("1");
long endRange = Long.parseLong("1000000000");
int luckyCount = 0;
int[] longArray=new int[2];
for (long num = startRange; num <= endRange; num++) {
getDigitSum(num,longArray); //this method was commented for testing purpose and was replaced with any two hardcoded values
if(primeArray[longArray[0]] && primeArray[longArray[1]]){
luckyCount++;
}
}
System.out.println(luckyCount);
}
}
}
Running the code takes 4 seconds.
the billion iterations cost 4 seconds instead of 5 minutes 8 seconds, that is an improvement. the only issue left is the actual calculation of the sum of digits and sum of squares of digits. that code i commented out (as you can see in the code i posted). if you uncomment it, the runtime will take 6-7 minutes. and here, there is nothing to improve except if you find some mathematical way to have incremental calculation based on previous results.