Method to check if number is symmetric in Java [duplicate] - java

This question already has answers here:
How do I check if a number is a palindrome?
(53 answers)
Closed 9 years ago.
I need help with a method to check if a number is symmetric, so from what I understand I need to check equality between all the numbers and to make sure there is no different number amounts them...right?
This is my code:
public boolean isSemetric (int number) {
int temp;
boolean answer = true;
while (number != 0) {
temp = number % 10;
number /= 10;
if (temp != (number%10)) {
answer = false;
} else {
answer = true;
}
}
return answer;
}
I'm kind of new to programming so be forgiven to my code :/
Thanks!

As peter.petrov pointed out in the comment section of your question, your method as it's written will always return false, except for when number is equal to 0. The reason for this can be seen when you pass in a number like 111 and step through the code in a debugger. The final iteration will fail because number /= 10 will result in 0, and temp will be 1, which fails your test.
If you are indeed looking to identify palindromes, consider the following approach that should be simple to implement
1. copy number into temp
2. convert temp to a String, and reverse it (tmpStr)
3. convert tmpStr back to an integer (reversedInt)
4. compare number and reversedInt for equality
viola. Not the most efficient algorithm, but its easy to understand and gets the job done.

I would do it like this (I don't want to use String here and I don't want to use local array variable for the digits).
public static boolean isSymmetric (long number) {
if (number == 0) return true;
else if (number < 0) return false;
long DEG_10 = (long)(Math.pow(10, (int)Math.log10(number)));
while (number > 0){
long dStart = number / DEG_10;
long dEnd = number % 10;
if (dStart != dEnd) return false;
number = (number - dStart * DEG_10 - dEnd) / 10;
DEG_10 /= 100;
}
return true;
}

This is the easiest approach I can think of - Get the String value of the number, if the reverse is the same then it is symmetrical.
// Symmetry
public static boolean isSymmetric(int number) {
String val = String.valueOf(number); // Get the string.
StringBuilder sb = new StringBuilder(val);
return (val.equals(sb.reverse().toString())); // if the reverse is the same...
}

Here's a somewhat fixed up version of your code. However, it checks if all numbers are the same, e.g. 5555 or 111. 11211 would return false.
public boolean areAllDigitsTheSame (int number) {
int temp;
boolean answer = true;
while (number >= 10) {
temp = number % 10;
number /= 10;
if (temp != (number%10)) {
return false
}
}
return true;
}
Edit: The C++ answer in the linked question works by constructing the reverse number gradually in the loop, and finally checking if they're the same. This is a similar to what you are doing.
Here's another version for fun:
public boolean isPalindrome (int number) {
int reversedNumber = 0;
while (number > 0) {
int digit = number % 10;
reversedNumber = reversedNumber*10 + digit;
if (reversedNumber == number) { // odd number of digits
return true;
}
number /= 10;
if (reversedNumber == number) { // even number of digits
return true;
}
}
return false;
}

Related

Digit amount in an integer [duplicate]

This question already has answers here:
Way to get number of digits in an int?
(29 answers)
Closed 24 days ago.
How can I find the amount of digits in an integer? Mathematically, and by using functions if there are any.
I don't really know how to do that, since I'm a somewhat beginner.
Another option would be to do it iteratively by dividing number by 10, until result is 0.
int number = ...;
int count = 1;
while ((number /= 10) != 0) {
count++;
}
In this program we use a for loop without any body.
On each iteration, the value of num is divided by 10 and count is incremented by 1.
The for loop exits when num != 0 is false, i.e. num = 0.
Since, for loop doesn't have a body, you can change it to a single statement in Java as such:
for(; num != 0; num/=10, ++count);
public class Main {
public static void main(String[] args) {
int count = 0, num = 123456;
for (; num != 0; num /= 10, ++count) {
}
System.out.println("Number of digits: " + count);
}
}
There are many ways to calculate the number of digits in a number. The main difference between them is how important performance is to you. The first way is to translate a number into a string and then take its length:
public static int countDigitsFoo(int x) {
if (x == Integer.MIN_VALUE) {
throw new RuntimeException("Cannot invert Integer.MIN_VALUE");
}
if (x < 0) {
return countDigitsFoo(-x); // + 1; if you want count '-'
}
return Integer.toString(x).length();
}
This method is bad for everyone, except that it is easy to write. Here there is an extra allocation of memory, namely the translation of a number into a string. That with private calls to this function will hit performance very hard.
The second way. You can use integer division and sort of go by the number from right to left:
public static int countDigitsBoo(int x) {
if (x == Integer.MIN_VALUE) {
throw new RuntimeException("Cannot invert Integer.MIN_VALUE");
}
if (x < 0) {
return countDigitsBoo(-x); // + 1; if you want count '-'
}
int count = 0;
while (x > 0) {
count++;
x /= 10;
}
return count;
}
but even this method can be improved. I will not write it in full, but I will give part of the code.
P.S. never use this method, it is rather another way to solve this problem, but no more
public static int countDigitsHoo(int x) {
if (x == Integer.MIN_VALUE) {
throw new RuntimeException("Cannot invert Integer.MIN_VALUE");
}
if (x < 0) {
return countDigitsHoo(-x); // + 1; if you want count '-'
}
if (x < 10) {
return 1;
}
if (x < 100) {
return 2;
}
if (x < 1000) {
return 3;
}
// ...
return 10;
}
You also need to decide what is the number of digits in the number. Should I count the minus sign along with this? Also, in addition, you need to add a condition on Integer.MIN_VALUE because
Integer.MIN_VALUE == -Integer.MIN_VALUE
This is due to the fact that taking a unary minus occurs by -x = ~x + 1 at the hardware level, which leads to "looping" on -Integer.MIN_VALUE
In Java, I would convert the integer to a string using the .toString() function and then use the string to determine the number of digits.
Integer digit = 10000;
Integer digitLength = abs(digit).toString().length();

How to prevent a recursive method from changing a value of a variable?

I'm learning Java, and I'm stuck on a recursion problem.
I need to use a recursive method to check if a number is an Armstrong number or not.
My code:
public class ArmstrongChecker {
public boolean isArmstrong(int number) {
// check if the number is a negative number
if (number < 0) {
return false;
}
ArmstrongChecker armstrongChecker = new ArmstrongChecker();
// find the length of the number
int length = armstrongChecker.lengthChecker(number);
// create a variable to store the sum of the digits of the number
int sum = 0;
// find the individual digits and raise to the power of the numbers of digits
if (number != 0) {
int digit = Math.floorMod(number, 10);
int powerRaised = (int) Math.pow(digit, length);
sum = sum + powerRaised;
isArmstrong(number / 10);
}
return sum == number;
}
// method to check the length of the number
public int lengthChecker(int number) {
int length = String.valueOf(number).length();
return length;
}
}
How do I prevent int length in isArmstrong() method from changing its value.
While you are not changing it's value in the posted code, you could mark that variable to be a constant. This way the compiler can error out if you tried to assign a new value.
final int length = armstrongChecker.lengthChecker(number);
As I've already said in the comments, your solution has the following issues:
The result of the recursive call isArmstrong() is being ignored;
There's no need for spawning new instances of ArmstrongChecker. And this method doesn't require object creation at all, it can be implemented as static.
Checking if the number is an Armstrong number boils down to calculating its Armstrong sum, the solution will be cleaner if you implement only this part using recursion.
It might look like this:
public static boolean isArmstrong(int number) {
if (number < 0) return false;
if (number < 10) return true;
return number == getArmstrongSum(number, String.valueOf(number).length());
}
public static int getArmstrongSum(int number, int power) {
if (number == 0) {
return 0;
}
return (int) Math.pow(number % 10, power) + getArmstrongSum(number / 10, power);
}
main()
public static void main(String[] args) {
System.out.println(isArmstrong(370)); // true
System.out.println(isArmstrong(12)); // false
System.out.println(isArmstrong(54)); // false
System.out.println(isArmstrong(153)); // true
}
Output:
true
false
false
true
You need to get the length once for whole recursion, so the cleanest approach would be to pass down both the number and the length into the recursion. An easy way to do this is to have one method that is the public face of the API, and another that does the recursion.
public class ArmstrongChecker {
public boolean isArmstrong(int number) {
if (number < 0) {
return false;
}
int length = lengthChecker(number);
int sum = armstrongSum(number, length);
return sum == number;
}
private int armstrongSum(int number, int length) {
int sum = 0;
if (number != 0) {
int digit = Math.floorMod(number, 10);
int powerRaised = (int) Math.pow(digit, length);
sum += powerRaised;
sum += armstrongSum(number / 10, length);
}
return sum;
}
public int lengthChecker(int number) {
int length = String.valueOf(number).length();
return length;
}
}
This is pretty common in recursion, where the parameters to the recursive part of the algorithm are a little different (usually there are more of them) than what you want a client of the API to have to pass in. The number changes in each recursive call, where number / 10 is passed down, but the same length is passed all the way through.
Notice that the recursive armstrongSum uses the return value from the recursive call, and that there is no need to create another instance of ArmstrongChecker when you are already in an instance method of the class.

Why Does my Palindrome Code not work? My reverse variable does what it is supposed to but I dont get true even when it is printing out a palindrome

public class NumberPalindrome {
public static boolean isPalindrome(int number) {
int reverse = 0;
if (number<0){
number=number* -1;
}
while (number > 0) {
int lastDig = number % 10;
reverse = lastDig + reverse;
if (number<10) {break;}
reverse = reverse * 10 ;
number/=10;
}
if (number==reverse) {
return true;
}
return false;
}
}
why does my code not return true when I enter a palindrome number? I tried using it to print out the reverse value and it does it quite well, but just does not seem to get the boolean value straight though.
The problem was modifying the number variable, but then comparing it with the new generated reverse variable as if it was never edited.
Also, you were adding the last digit to the reverse variable before multiplying it by ten.
See the following code in Java:
public static boolean isPalindrome(int number) {
int reverse = 0;
if(number < 0) {
number *= -1;
}
int initialNumber = number;
while(number > 0) {
int lastDigit = number % 10;
reverse = (reverse * 10) + lastDigit;
if(number < 10) {
break;
}
number /= 10;
}
return initialNumber == reverse;
}
There are a few problems here. You need to save the original number for comparison with the the reversed number. The break statement confuses the logic.
To figure this out, I added some print statements to trace the progress. Adding print statements isn't elegant, but it is very useful.
Here is my version, with comments indicating what I changed.
public static boolean isPalindrome (int original)
{
// Need to save the original number for comparison
int number = original;
int reverse = 0;
if (number < 0)
{
number = number * -1;
}
while (number > 0)
{
int lastDig = number % 10;
// Update and shift reverse in one step
reverse = lastDig + reverse * 10;
number /= 10;
// Don't need extra break to terminate the loop
System.out.printf ("Check %d ; Reverse %d%n", number, reverse);
}
System.out.printf ("Final %d ; Reverse %d%n", number, reverse);
// Compare to original and return boolean value directly
return (original == reverse);
}

Getting weird output while finding prime number in java

I have two methods to find out prime number in java method - 2 working fine but getting wrong output from method one, can any help me where i did wrong in logic. Thanks in advance
My entire code
package prepare;
import java.util.Scanner;
public class Squar {
//Method - 1 to find prime number
boolean isPrime(int num){
int exp = (int)Math.sqrt(num);
for(int i=2;i<exp;i++){
if(exp%2==0){
return false;
}
}return true;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int num = scan.nextInt();
Squar s = new Squar();
System.out.println("From M1 "+s.isPrime(num));
scan.close();
System.out.println("From M2 "+s.isPrimeNumber(num));
}
//Method - 2 to find prime number
public boolean isPrimeNumber(int number) {
if(number == 1){
return false;
}
if (number == 2 || number == 3) {
return true;
}
if (number % 2 == 0) {
return false;
}
int sqrt = (int) Math.sqrt(number) + 1;
for (int i = 3; i < sqrt; i += 2) {
if (number % i == 0) {
return false;
}
}
return true;
}
}
for input : 63 actual out put would be false in prime number but getting
different output from method one
output
63
From M1 true
From M2 false
In isPrime() method, Shouldn't you be checking num % i == 0 rather than exp % 2 == 0?
Change isPrime function like this.
boolean isPrime(int num) {
int exp = (int) Math.sqrt(num);
for (int i = 2; i < exp; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
Because in if condition you are checking exp%2 == 0 . But this statement does not change when iterating on i < exp. So this logic should be on with num % i == 0
Have a look at this line of your code
if(exp%2==0){
it should be num % i
Well I think the culprit is
if(exp%2==0){
and it is causing a problem while iterating i<exp.So you may want to tweak it to
num%i==0
I have tried to give a few other approaches to this issue.
I hope that would be helpful.
I think there is a reason that tempted you to use
(int)Math.sqrt(num);
I have tried to elaborate it below.
Consider below 3 approaches.
All of them are correct but the first 2 approaches have some drawbacks.
Approach 1
boolean isPrime(int num) {
for(int i=2;i<num;i++) {
if(num%i==0)
return false;
}
return true;
}
We have a scope to make it faster.
Consider that if 2 divides some integer n, then (n/2) divides n as well.
This tells us we don't have to try out all integers from 2 to n.
Now we can modify our algorithm:
Approach 2
//checks whether an int is prime or not.
boolean isPrime(int num) {
for(int i=2;2*i<num;i++) {
if(num%i==0)
return false;
}
return true;
}
Finally, we know 2 is the "oddest" prime - it happens to be the only even prime number.
Because of this, we need only check 2 separately, then traverse odd numbers up to the square root of n.
I think this might have tempted you to use (int)Math.sqrt(num);
Approach 3
//checks whether an int is prime or not.
boolean isPrime(int num) {
//check if num is a multiple of 2
if (num%2==0) return false;
//if not, then just check the odds
for(int i=3;i*i<=num;i+=2) {
if(num%i==0)
return false;
}
return true;
}
Hence, we've gone from checking every integer (up to n to find out that a number is prime) to just checking half of the integers up
to the square root.
Is it not an improvement, especially considering when numbers are large.
Well, your first algorithm is almost (replace %2 with %i) correct. I do not know the second algorithm, but i would definitely change it to this form:
public boolean isPrime(int n) {
if (n <= 1) {
return false;
}
for (int i = 2; i < Math.sqrt(n); i++) {
if (n % i == 0) {
return false;
}
}
return true;
}

Java: fast way to check if digits in int are in ascending order

I'm writing a program that finds all of the Armstrong numbers in a range between zero and Integer.MAX_VALUE. Time limit is 10 seconds. I've found that the most time-consuming method is the one that narrows the range of numbers to process by picking only those having their digits in ascending order (with trailing zeros if any). It takes about 57 seconds to run on my machine. Is there any way to make it faster?
static boolean isOK(int x)
{
int prev = 0;
while(x > 0)
{
int digit = x % 10;
if((digit > prev || digit == 0) && prev != 0) return false;
x /= 10;
prev = digit;
}
return true;
}
This method reduces the number of numbers to process from 2.147.483.647 to 140.990.
Perhaps instead of sifting through all the ints, just build up the set of numbers with digits in ascending order. I would argue that you probably want a set of strings (and not ints) because it it is easier to build (recursively by appending/ prepending characters) and then later on you need only the individual "digits" for the power test.
My take on the problem, goes to Long.MAX_VALUE (19 digits) in about 6 seconds and all the way to 39 digits in about an hour
One alternative is to construct the set of Armstrong numbers one by one and count them instead of checking every number to see whether it's an Armstrong number or not.
In constructing the whole set, note that when you choose each digit, the set of digits you can choose for the next position is determined, and so on. Two alternatives to implement such a method are recursion and backtracking (which is basically a cheaper way to implement recursion).
This method will not need the use of time-consuming division and remainder operations.
There is very little optimisable code here. It is likely that your time issue is elsewhere. However, one technique comes to mind and that is Memoization.
static Set<Integer> oks = new HashSet<>();
static boolean isOK(int x) {
if (!oks.contains(x)) {
int prev = 0;
while (x > 0) {
int digit = x % 10;
if ((digit > prev || digit == 0) && prev != 0) {
return false;
}
x /= 10;
prev = digit;
}
// This one is OK.
oks.add(x);
}
return true;
}
This trick uses a Set to remember all of the ok numbers so you don't need to check them. You could also keep a Set of those that failed too to avoid checking them again but keeping all integers in a collection is likely to break something.
You perform two divisions. Divisions are slower than multiplications. So is there a way to change a division into a multiplication? Well... yes, there is.
public static boolean isArmstrongNumber(int n) {
int prev = 0;
while (n > 0) {
int quotient = n / 10;
int digit = n - (quotient * 10);
if ((digit > prev || digit == 0) && prev != 0) {
return false;
}
n = quotient;
prev = digit;
}
return true;
}
The following code doesn't deal with trailing zeroes but is worth checking if it looks promising in terms of performance.
static boolean isOK(int x) {
if (x < 10) {
return true;
}
String xs = Integer.toString(x);
for (int i = 1; i < xs.length(); i++) {
if (xs.charAt(i) < xs.charAt(i - 1)) {
return false;
}
}
return true;
}
The following code runs x4 as fast as the original (3 sec. on my laptop) and prints 140990 in 3 sec.
The method isOK is unchanged
public class Main {
public static boolean isOK(int x) {
int prev = 0;
while (x > 0) {
int digit = x % 10;
if (prev != 0 && (digit > prev || digit == 0)) return false;
x /= 10;
prev = digit;
}
return true;
}
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
Set<Integer> candidates = IntStream.range(0, Integer.MAX_VALUE)
.parallel()
.filter(n -> isOK(n))
.boxed()
.collect(Collectors.toSet());
long stop = System.currentTimeMillis() - start;
System.err.printf("%d in %d sec.", candidates.size(), stop / 1000);
}
}
It has been asked on the MIU test, unfortunately, I was not able to solve it, I later worked on it and it worked fine.
static int isAscending(int n){
int rem, rem1, pval = 0; boolean isAsc = true;
while(n != 0){
rem = n % 10;
n /= 10;
rem1 = n % 10;
n /= 10;
if(rem > rem1){
continue;
} else {
isAsc = false;
break;
}
}
if(isAsc == true){
return 1;
} else {
return 0;
}
}

Categories

Resources