What's wrong with my logic (Java syntax) - java

I'm trying to make a simple program that picks a random number and takes input from the user. The program should tell the user if the guess was hot (-/+ 5 units) or cold, but I never reach the else condition.
Here's the section of code:
public static void giveHint (int guess) {
int min = guess - 5;
int max = guess + 5;
if ((guess > min) && (guess < max)) {
System.out.println("Hot..");
} else {
System.out.println("Cold..");
}
}

int min = guess - 5;
int max = guess + 5;
Should be:
int min = actualAnswer - 5;
int max = actualAnswer + 5;

Here is your problem:
int min = guess - 5;
int max = guess + 5;
min is ALWAYS lesser than guess and max is ALWAYS greater than guess.

You need to pass in the actual answer, not just the guess, since the logic can't tell what the appropriate mix/max should be otherwise:
public static void giveHint (int guess, int actual) {
int min = actual - 5;
int max = actual + 5;
if ((guess > min) && (guess < max)) {
System.out.println("Hot..");
} else {
System.out.println("Cold..");
}
}

min and max should use the value the player is looking for (secret value) rather than the value the player provided. As it is, min and max change every time the player gives a guess and you're not even using the secret value.

You are defining guess as being both > min (because int min = guess - 1) and < max (because int max = guess + 5). So of course the first condition is always met. You should be using the actual secret value when defining min and max.

You're calculating min and max based on guess, so guess is always between min and max so (guess > min) && (guess < max) is always true.

Lets use an example:
int guess = 20;
int min = guess - 5 = 15;
int max = guess + 5 = 25;
therefore
min < guess < max
Why?
Because you're comparing guess to its self! I think you need to have the actual answer, not the guess

I can't put the full thing in a comment, so here's what your code should be:
public static void giveHint (int guess, int actual) {
int min = actual - 5;
int max = actual + 5;
if ((guess > min) && (guess < max)) {
System.out.println("Hot..");
} else {
System.out.println("Cold..");
}

Another solution :
public static void giveHint (int actual, int guess) {
if(Math.abs(actual - guess) <= 5) {
System.out.println("Hot");
return;
}
System.out.println("Cold");
}

Related

How to solve java reverse integer leetcode problem

Tried all the ways to pass the test case but it still shows only one error. I do not know how to rectify the error.
Input: 1534236469
Actual Output: 1056389759
Expected Output: 0
I do not know why my code does not give output 0.
class Solution
{
public static int reverse(int x)
{
boolean flag = false;
if (x < 0)
{
x = 0 - x;
flag = true;
}
int res = 0;
int p = x;
while (p > 0)
{
int mod = p % 10;
p = p / 10;
res = res * 10 + mod;
}
if (res > Integer.MAX_VALUE)
{
return 0;
}
if (flag)
{
res = 0 - res;
}
return res;
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int revinteger = reverse(x);
System.out.println(revinteger);
}
}
The statement res > Integer.MAX_VALUE will never be true as res is of int datatype. And an int can never be larger than the Integer.MAX_VALUE (MAX_VALUE is itself the max we can store as int).
Use long datatype for reversing the number instead and at the end return the integer value of the result.
Because long based operations are relatively slow, I would only use a long to do the final check to determine if overflow is about to occur.
It should be obvious that no int will cause overflow if all the digits except the last are reversed. So process the last digit outside of the loop before returning the value. The border case for min is eliminated first to facilitate subsequent processing. Now only Integer.MAX_VALUE is of concern for both positive and negative numbers.
public static int reverse(int v) {
if (v == Integer.MIN_VALUE) {
return 0; // guaranteed overflow if reversed.
}
int rev = 0;
long ovflLimit = Integer.MAX_VALUE;
int sign = v < 0 ? -1 : 1;
v *=sign;
while (v > 9) {
int digit = v % 10;
rev = rev * 10 + digit;
v/=10;
}
long ovfl = (long)(rev)*10+v;
return ovfl > ovflLimit ? 0 : (int)(ovfl)*sign;
}
This problem can be solved in various ways but if we stick to Java and your solution then as it already have been pointed out in some of the answers that by using int the condition if(res > Integer.MAX_VALUE) will never be true.
Hence you would not get expected output as 0.
You can put a check before reversing last digit by casting the value in long and check if it's out of int limit. As suggested by WJS.
In case you want to stick to your solution without much change below is the working code for the same.
class Solution {
public static int reverse(int x) {
boolean flag = false;
long input = x;
if (input < 0) {
input = 0 - input;
flag = true;
}
long res = 0;
long p = input;
while (p > 0) {
long mod = p % 10;
p = p / 10;
res = res * 10 + mod;
}
if (res > Integer.MAX_VALUE) {
return 0;
}
if (flag) {
res = 0 - res;
}
return (int) res;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int revInteger = reverse(x);
System.out.println(revInteger);
}
}
if (res > Integer.MAX_VALUE)
If it's the max possible value of the integer, how will it ever be greater than it? You'll have to detect it in another way.
One way would be to use the long data type instead of int. Then, it can become larger than Integer.MAX_VALUE, and that catch will work.
Otherwise, you can probably find another way to catch that case.

Does Java have a limit on loop cycles?

I solved the Project Euler problem #14 https://projecteuler.net/problem=14 on Java, but when I run it in Powershell, it stops iterating at exactly i = 113383 every time. I rewrote the solution on python, and it works perfectly fine, albeit slowly. According to my (identical) python solution, the answer is that the number that produces the longest chain is 837799 and the chain is 524 operations long.
Why does the Java solution not finish the for-loop? Is there some kind of limit in Java on how long it can stay in a loop? I cannot come up with any other explanation. Java code below. I wrote the System.out.println(i) there just to see what is going on.
class ProjectEuler14 {
public static void main(String[] args) {
int largestNumber = 1;
int largestChain = 1;
int currentNumber;
int chainLength;
for (int i = 2; i < 1000000; i++) {
System.out.println(i);
currentNumber = i;
chainLength = 0;
while (currentNumber != 1) {
if (currentNumber % 2 == 0) currentNumber /= 2;
else currentNumber = 3 * currentNumber + 1;
chainLength++;
}
if (chainLength > largestChain) {
largestChain = chainLength;
largestNumber = i;
}
}
System.out.println("\n\nThe number under million that produces the "
+ "longest chain is " + largestNumber +
" and the chain's length is " + largestChain);
}
}
It's not the for loop. It's the while loop. The condition currentNumber != 1 is always true; forever.
In java, an int is specifically defined as an integral number between -2^31 and +2^31 -1, inclusive, and operations 'roll over'. try it!
int x = 2^31 -1;
x++;
System.out.println(x);
this prints a large negative number (in fact, precisely -2^31).
It's happening in your algorithm, and that's why it never finishes.
A trivial solution is to 'upgrade' to longs; they are just as fast, really (yay 64-bit processors!) and use 64 bits, thus giving them a range of -2^63 to +2^63-1.
Python sort of scales up its numbers into slowness silently, java makes different choices (and, for crypto and other purposes, that rollover thing is in fact desired).
If you want to go even further, you can always use BigInteger, which grows as much as you need forever (becoming slower and taking more memory as it goes).
To know rollover occurred, the 3* operation would then result in a number that is lower than the original, and you can check for that:
replace:
else currentNumber = 3 * currentNumber + 1;
with:
else {
int newNumber = currentNumber * 3 + 1;
if (newNumber < currentNumber) throw new IllegalStateException("Overflow has occurred; 3 * " + currentNumber + " + 1 exceeds ints capacities.");
currentNumber = newNumber;
}
and rerun it. You'll see your app nicely explain itself.
The currentNumber is exceeding size of int, use long instead.
Do you hava problem overflow int.
Change int to long.
long largestNumber = 1;
long largestChain = 1;
long currentNumber;
long chainLength;
for (int i = 2; i < 1000000; i++) {
//System.out.println(i);
currentNumber = i;
chainLength = 0;
while (currentNumber != 1) {
//System.out.println("# = " + currentNumber);
if (currentNumber % 2 == 0) {
currentNumber /= 2;
} else {
currentNumber = (3 * currentNumber) +1 ;
}
chainLength++;
}
// System.out.println("################################ " + i);
if (chainLength > largestChain) {
largestChain = chainLength;
largestNumber = i;
}
}
System.out.println("\n\nThe number under million that produces the "
+ "longest chain is " + largestNumber
+ " and the chain's length is " + largestChain);

Largest number of times square root can be calculated on numbers between 2 intervals

I wrote a simple program to calculate the maximum number of times square root can be calculated on a number , input is an interval from num1 to num2
eg:
if the input is (1,20), answer is 2, since square root of 16 is 4 , and square root of 4 is 2 .
int max = 0;
for (int i = num1; i <= num2; i++) {
boolean loop = true;
int count = 0;
int current = i;
if (i == 1) {
count++;
} else {
while (loop) {
double squareRoot = Math.sqrt(current);
if (isCurrentNumberPerfectSquare(squareRoot)) {
count++;
current = (int) squareRoot;
} else {
loop = false;
}
}
}
if (count > max) {
max = count;
}
}
return max;
static boolean isCurrentNumberPerfectSquare(double number) {
return ((number - floor(number)) == 0);
}
I get the answer, but was wondering wether this can be improved using some mathematical way ?
Any suggestions ?
To avoid more confusion here my final answer to this topic.
A combination of both previously mentioned approaches.
What 'Parameswar' is looking for is the largest perfect square formed by the lowest base.
Step 1 -
To get that calculate the largest possible perfect square based on your num2 value.
If it is outside your range, you have no perfect square within.
Step 2 -
If it is within your range, you have to check all perfect square formed by a lower base value with a higher number of times.
Step 3 -
If you find one that is within your range, replace your result with the new result and proceed to check lower values. (go back to Step 2)
Step 4 -
Once the value you check is <= 2 you have already found the answer.
Here some sample implementation:
static class Result {
int base;
int times;
}
static boolean isCurrentNumberPerfectSquare(double number) {
return ((number - Math.floor(number)) == 0);
}
private static int perfectSquare(int base, int times) {
int value = base;
for (int i = times; i > 0; i--) {
value = (int) Math.pow(base, 2);
}
return value;
}
private static Result calculatePerfectSquare(int perfectSquare) {
Result result = new Result();
result.base = (int) Math.sqrt(perfectSquare);
result.times = 1;
while (result.base > 2 && isCurrentNumberPerfectSquare(Math.sqrt(result.base))) {
result.base = (int) Math.sqrt(result.base);
result.times += 1;
}
System.out.println(perfectSquare + " -> " + result.base + " ^ " + result.times);
return result;
}
static int maxPerfectSquares(int num1, int num2) {
int largestPerfectSqr = (int) Math.pow(Math.floor(Math.sqrt(num2)), 2);
if (largestPerfectSqr < num1) {
return 0;
}
Result result = calculatePerfectSquare(largestPerfectSqr);
int currentValue = result.base;
while (currentValue > 2) {
// check lower based values
currentValue--;
int newValue = perfectSquare(currentValue, result.times + 1);
if (newValue >= num1 && newValue < num2) {
result = calculatePerfectSquare(newValue);
currentValue = result.base;
}
}
return result.times;
}
Edit - My assumption is incorrect. Refer to the answer provided by "second".
You can remove the outer loop, num2 can be directly used to determine the number with the maximum number of recursive square roots.
requiredNumber = square(floor(sqrt(num2)));
You just need to check to see if the requiredNumber exists in the range [num1, num2] after finding it.
So the refactoring code would look something like this,
int requiredNumber = Math.pow(floor(Math.sqrt(num2)),2);
int numberOfTimes=0;
if(requiredNumber>=num1) {
if (requiredNumber == 1) {
numberOfTimes=1;
} else{
while (isCurrentNumberPerfectSquare(requiredNumber)) {
numberOfTimes++;
}
}
}
Edit 4: for a more optimal approach check my other answer.
I just leave this here if anybody wants to try to follow my thought process ;)
Edit 3:
Using prime numbers is wrong, use lowest non perfect square instead
Example [35,37]
Edit 2:
Now that I think about it there is a even better approach, especially if you assume that num1 and num2 cover a larger range.
Start with the lowest prime number 'non perfect square' and
calculate the maximum perfect square that fits into your range.
If you have found one, you are done.
If not continue with the next prime number 'non perfect square'.
As a example that works well enough for smaller ranges:
I think you can improve the outerloop. There is no need to test every number.
If you know the smallest perfect square, you can just proceed to the next perfect square in the sequence.
For example:
[16, 26]
16 -> 4 -> 2 ==> 2 perfect squares
No neeed to test 17 to 24
25 -> 5 ==> 1 perfect square
and so on ...
#Chrisvin Jem
Your assumption is not correct, see example above
Edit:
Added some code
static int countPerfectSquares(int current) {
int count = 0;
while (true) {
double squareRoot = Math.sqrt(current);
if (isCurrentNumberPerfectSquare(squareRoot)) {
count++;
current = (int) squareRoot;
} else {
return count;
}
}
}
static boolean isCurrentNumberPerfectSquare(double number) {
return ((number - Math.floor(number)) == 0);
}
static int numPerfectSquares(int num1, int num2) {
int max = 0;
if (num1 == 1) {
max = 1;
}
int sqr = Math.max(2, (int) Math.floor(Math.sqrt(num1)));
int current = (int) Math.pow(sqr, 2);
if (current < num1) {
current = (int) Math.pow(++sqr, 2);
}
while (current <= num2) {
max = Math.max(countPerfectSquares(current), max);
current = (int) Math.pow(++sqr, 2);
}
return max;
}

Finding the smallest integer based on input

I have an assignment to find the minimum, maximum, and average of numbers that a user inputs. Basically, they type in positive integers, seperated by a space and Java scrolls through them and adds them up. I'm able to find the sum, the average, and the largest integers, however, I am unable to find the smallest. I thought the best way to figure this out would be to set the variable representing the smallest int equal to the variable representing the largest int outside of the loop. Then, within the loop, do something like this:
if(getInt < min)
{
min = getInt;
}
Where getInt is the user-inputted value and min is the minimum integer value. Every time I run this, though, min returns as 0.
Here is my full code:
import java.util.Scanner;
public class exc5
{
public static void main (String[] args)
{
System.out.println("Write a list of nonnegative integers, each seperated by a space. To signal the end of the list, write a negative integer. The negative integer will not be counted");
Scanner keyboard = new Scanner (System.in);
keyboard.useDelimiter(" |\n");
int count = 0;
int sum = 0;
int max = 0;
int min = max;
double average = 0;
boolean notNull = true;
while(notNull == true)
{
int getInt = keyboard.nextInt();
if(getInt < 0)
{
notNull = false;
}
else
{
if(getInt > max)
{
max = getInt;
}
if(getInt < min)
{
min = getInt;
}
sum += getInt;
count++;
average = (sum)/(count);
}
}
System.out.println("Sum = " + sum);
System.out.println("Average = " + average);
System.out.println("Max = " + max);
System.out.println("Minimum = " + min);
}
}
Any help is appreciated!
You should initially set min to Integer.MAX_VALUE, and max to Integer.MIN_VALUE.
You need to start with a large min, not 0 (only negative numbers are less then 0). Try this:
int min = Integer.MAX_VALUE;
This is a fairly standard pattern. Also, to be "correct", your code should also include:
int max = Integer.MIN_VALUE;
Then the full range of integer input, positive and negative, is handled.
Edit:
Another, more "classic" approach would be to use an object reference, rather than a primitive (which always has a value), so the initial state can be easily distinguished as null. In this case, using Integer, rather than int for the values would allow testing for null. If I were a university professor marking such work, I would rather see the object approach - using min/max values for primitives will work, but it's a bit of a "trick".
The code wold look like this:
Integer min;
while (...) {
if (min == null || getInt < min) {
min = getInt;
}
}
And similar for max.
This:
int max = 0;
int min = max;
initializes min to zero. (After all, max hasn't become the largest integer yet.) So this:
if(getInt < min)
will never be true. Try changing this:
int min = max;
to this:
int min = Integer.MAX_VALUE; // largest possible Java `int`
That's because you're assigning min = 0, so obviously unless you input a number lower than 0, the minimum is 0. You should initialize min to Integer.MAX_VALUE
int min = Integer.MAX_VALUE;
(
or also:
int min = 0xFFFFFFFF;
Just for hacking around :P. Use the first one! :)
)
You are setting min to zero, so (since the inputs are positive) none of the inputs are less than min.
The normal way to do this is to set the initial value of max to Integer.MIN_VALUE, and the initial value of min to Integer.MAX_VALUE.
This ensures that any input value will affect at least one of min and max - usually both!
You initialize min with 0. Try to initialize with Integer.MAX_VALUE, i.e. it would be best to do:
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
Otherwise, your check:
if(getInt < 0)
will break out of the loop and you will never go over 0.
you have min set as 0 to start with so getInt will never be less. You should set min at the beginning of the loop and that will solve your issue.
Fully working and "cleaned" version of your program:
import java.util.Scanner;
public class exc5
{
public static void main ( String [] args )
{
Scanner keyboard = new Scanner( System.in );
int count = 0;
int sum = 0;
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
double average = 0;
boolean notNull = true;
while ( notNull == true )
{
int getInt = keyboard.nextInt();
if ( getInt < 0 )
notNull = false;
else
{
if ( getInt > max )
max = getInt;
if ( getInt <= min )
min = getInt;
sum += getInt;
count++;
}
}
average = ( sum ) / ( count );
System.out.println( "Sum = " + sum );
System.out.println( "Average = " + average );
System.out.println( "Max = " + max );
System.out.println( "Minimum = " + min );
}
}

Reversing a Number using bitwise shift

I am trying to find a way to reverse a number without
Converting it to a string to find the length
Reversing the string and parsing it back
Running a separate loop to compute the Length
i am currently doing it this way
public static int getReverse(int num){
int revnum =0;
for( int i = Integer.toString(num).length() - 1 ; num>0 ; i-- ){
revnum += num % 10 * Math.pow( 10 , i );
num /= 10;
}
return revnum;
}
But I would Like to implement the above 3 conditions.
I am looking for a way , possibly using the bit wise shift operators or some other kind of bitwise operation.
Is it possible ? If so how ?
PS : If 1234 is given as input it should return 4321. I will only be reversing Integers and Longs
How about:
int revnum = 0;
while (num != 0) {
revnum = revnum * 10 + (num % 10);
num /= 10;
}
return revnum;
The code expects a non-negative input.
This may or may not matter to you, but it's worth noting that getReverse(getReverse(x)) does not necessarily equal x as it won't preserve trailing zeroes.
How about this? It handles negative numbers as well.
public int getReverse(int num){
int rst=0;
int sign;
sign=num>0?1:-1;
num*=sign;
while(num>0){
int lastNum = num%10;
rst=rst*10+lastNum
num=num/10;
}
return rst*sign;
}
Integer.MAX_VALUE or Integer.MIN_VALUE is not at all considered in any of the solutions.
For eg: if the input is -2147483647 or 2147483647 the o/p will be 1126087180 and -1126087180 respectively.
Please try the below solutions where both the conditions are handled, so if at any point of time the number is going beyond the boundary conditions i.e., INPUT_VALUE > Integer.MAX_VALUE or INPUT_VALUE < Integer.MIN_VALUE it would return 0
class ReversingIntegerNumber {
public int reverse(int originalNum) {
boolean originalIsNegative = originalNum > 0 ? false : true;
int reverseNum = 0;
int modValue;
originalNum = Math.abs(originalNum);
while(originalNum != 0) {
modValue = originalNum % 10;
if(reverseNum > (Integer.MAX_VALUE - modValue)/10) {
return 0;
}
reverseNum = (reverseNum * 10) + modValue;
originalNum /= 10;
}
return originalIsNegative ? -1 * reverseNum : reverseNum;
}
}

Categories