Palindrome Numbers - java

I am writing Java code in which I have to create a method that returns boolean with one parameter. The code has to identify in true or false if the number (parameter) provided to it is palindrome or not. This is my code but the outcome is false all the time. Can someone identify what is wrong here?
public class NumberPalindrome {
public static void main(String[] args) {
System.out.println(isPalindrome(121));
}
public static boolean isPalindrome(int number) {
int reverse = 0;
boolean variable = true;
while (number > 0) {
int lastdigit = number % 10;
reverse *= 10;
reverse += lastdigit;
number = number / 10;
}
if (reverse==number) {
variable = true;
} else variable = false;
return variable;
}
}

You must keep in memory the initial value of number given in parameter to be able to compare it later with reverse. The code will look like this.
public class NumberPalindrome {
public static void main(String[] args) {
System.out.println(isPalindrome(121));
}
public static boolean isPalindrome(int number) {
int initialNumber = number;
int reverse = 0;
boolean variable = true;
while (number > 0) {
int lastdigit = number % 10;
reverse *= 10;
reverse += lastdigit;
number = number / 10;
}
if (reverse==initialNumber) {
variable = true;
} else variable = false;
return variable;
}
}

Related

Connecting a variable in the main method with another method Java

The method should return true if the argument is even, or
false otherwise. The program’s main method should use a loop to generate 100 random integers. It should use the isEven method to determine whether each random number is even, or odd. All this is done!!!
This is the part where I can't figure it out!
When the loop is finished, the program should display the number of even numbers that were generated, and the number of odd numbers.
This is my code:
import java.util.Random;
public class EvenOdd
{
public static void main(String[] args)
{
Random random = new Random();
int randomInteger = 0;
for(int i = 0; i < 100; i++){
randomInteger = random.nextInt();
System.out.println("Random Integer: " + randomInteger);
EvenOdd(randomInteger);
}
}
public static void EvenOdd(int x)
{
int oddNumbers = 0;
int evenNumbers = 0;
if ((x % 2) == 0)
{
System.out.println("Even");
evenNumbers++;
}
else
{
System.out.println("Odd");
oddNumbers++;
}
}
}
Try with this:
public static void main(String[] args)
{
Random random = new Random();
int randomInteger = 0;
int oddNumbers = 0;
int evenNumbers = 0;
for(int i = 0; i < 100; i++){
randomInteger = random.nextInt();
System.out.println("Random Integer: " + randomInteger);
if(evenOdd(randomInteger)) evenNumbers++;
else oddNumbers++;
}
System.out.printf("Even numbers: %d - Odd numbers: %d", evenNumbers, oddNumbers);
}
public static boolean evenOdd(int x)
{
if ((x % 2) == 0)
{
System.out.println("Even");
return true;
}
else
{
System.out.println("Odd");
return false;
}
}
Your original approach doesn't work because you initialize to 0 the oddNumbers and evenNumbers variables everytime you call the method.
Define oddNumbers, evenNumbers variables as static class variables and after the loop you can print these 2 value.
Java is not JavaScript. Also, it does not have the ability of C++ as "Static variables in functions".
Variables declared inside a method are local. Variables initialization occurs every time your code reaches a variable definition inside the method and destroyed after exiting from the method.
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html
So you have such variants:
1) Count numbers inside your main method and return indicator from the utility method.
1.1) boolean
public static boolean isEven(int x){
return (x % 2) == 0;
};
1.2) enum
private enum NumberType {
EVEN,
ODD
}
public static NumberType getNumberType (int x) {
if ((x % 2) == 0) {
return NumberType.EVEN;
} else {
return NumberType.ODD;
}
};
2) Make your variables static:
public class EvenOdd {
private static int evenNumbersCount = 0;
private static int oddNumbersCount = 0;
public static void main(String[] args) {
// your code
}
public static void countNumberType (int x) {
if ((x % 2) == 0) {
++evenNumbersCount;
} else {
++oddNumbersCount;
}
}
}
3) In some sophisticated situations you will need to pass container to your method:
public class EvenOdd {
private static final String EVEN = "even";
private static final String ODD = "odd";
public static void main(String[] args) {
// initialize container
Map<String, Integer> evenOddCounts = new HashMap<>(2, 1);
evenOddCounts.put(EVEN, 0);
evenOddCounts.put(ODD, 0);
Random random = new Random();
int randomInteger = 0;
for (int i = 0; i < 100; i++) {
randomInteger = random.nextInt();
countNumberType(evenOddCounts, randomInteger);
}
System.out.println(evenOddCounts.toString());
}
public static void countNumberType(Map<String, Integer> counts, int x) {
if ((x % 2) == 0) {
counts.compute(EVEN, (numberType, count) -> ++count);
} else {
counts.compute(ODD, (numberType, count) -> ++count);
}
}
}

CountZeroes in java

I don't know where am I going wrong. I want to count zeroes via recursion but I am not getting it:
public class countzeroes {
public static int countZerosRec(int input){
int count=0;
return countZerosRec(input,count);
}
private static int countZerosRec(int input ,int count){
if (input<0) {
return -1;
}
if(input==0) {
return 1;
}
int m = input%10;
input = input/10;
if(m==0){
count++;
}
countZerosRec(input,count);
return count;
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int n = s.nextInt();
System.out.println(countZerosRec(n));
}
}
Put return count in if(input == 0) statement and instead of
countZerosRec(input, count); return count; put return countZerosRec(input, count);.
The correct method would be:
public class countzeroes {
private static int countZerosRec(int input){
if (input<0) {
return -1;
}
if (input==0) {
return 1;
}
if(input < 10) {
return 0;
}
int m = (input%10 == 0)? 1: 0;
input = input/10;
return m + countZerosRec(input);
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int n = s.nextInt();
System.out.println(countZerosRec(n));
}
}
Let me explain 2 problems in your code:
1- First of all, your second if statement (if(input == 0)) ruin everything. Consider 1200100 as an example. In the 6th round of recursion the input would be 1, and if you divide it on 10 the result is 0 (which is the input of next recursion round) and therefore all the answers would be 1.
2- Secondly, it would be nice if you don't change the input parameter in your code. because it's completely error-prone (In complicated codes, you can not trace the changes happen on a parameter and it makes debugging hard). So, I just removed the count parameter from the input.
And finally, It is better to name your classes in CamelCase form. (CountZeroes)
Change your method as below. Return count always
private static int countZerosRec(int input ,int count){
if (input <= 0) { // check if input is negative or zero
return count;
}
int m = input % 10;
input = input / 10;
if (m == 0) {
count++; // increment if current digit is zero
}
return countZerosRec(input,count);
}
public static int zeroCount(int num)
{
if(num == 0)
return 0;
if(num %10 ==0)
return 1 + zeroCount(num / 10);
else
return zeroCount(num/10);
}
this would work
You can use Streams:
System.out.println("11020304".chars().filter(c -> c == '0').count());
Result: 3
Your count logic is excellent.
in below line ... you are making logic mistake.. just fix it.
private static int countZerosRec(int input, int count) {
if (input < 0) {
return -1;
}
if (input == 0) {
return count;
//return 1; /// you need to change your code here, in last its getting zero as (num < 10 )/10 is 0
// its entering here everytime, and returning one.
// since its the base condition to exit the recursion.
// for special case of 0 (zero) count, handle your logic when it is //returned.
//...... rest of your code
}

How to generate a random number without a repeat in Java

I am using this to generate a random number inside a method and return it:
int randomValue = ThreadLocalRandom.current().nextInt(0, filteredArrayList.size());
How can I make sure there are not two random numbers in a row? I don't care if I get a 3, then a 5, then a 3 again. Only if I get a 3 and then a 3.
int temp = -1; // This will be your value to be compared to random value
for(int i = 0; i < 10; i++) { // assuming your filteredArraylist is size 10
int randomValue = ThreadLocalRandom.current().nextInt(0, 10);
if(randomValue == temp) {
i--; // it will repeat the generation of random value if temp and randomValue is same
} else {
temp = randomValue; // you will put here the ne random value to be compared to next value
System.out.println(randomValue);
}
Try following sample
import java.util.Random;
public class RandomTest {
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
System.out.println("####### " + RandomUtil.getRandomInt(10));
}
}
}
class RandomUtil {
private static int lastInt = -1;
private static Random random = new Random();
public synchronized static int getRandomInt(int upperBound) {
return getRandomInt(0, upperBound);
}
public synchronized static int getRandomInt(int lowerBound, int upperBound) {
int newInt = -1;
while( (newInt = lowerBound + random.nextInt(upperBound - lowerBound)) == lastInt) {
//Keep looping
}
lastInt = newInt;
return newInt;
}
}
As Scary Wombat said, you'll want to compare the previous value to the newly randomized value in a loop (which I assume you are using, since we only see the one line.
Something like this...
int prevRandomNumber, currRandomNumber;
while (notFinished) {
currRandomNumber = getRandom(); // your random number generator
if (prevRandomNumber == currRandomNumber) { // if there would be two in a row
continue; // try again
} else { // otherwise, add to array
addNumberToArray(currRandomNumber);
prevRandomNumber = currRandomNumber;
}
}
Just remember the last generated value and if equals then reject. Here is an example:
int lastRandomValue = -1;
boolean stop = false;
int attempts = 0;
final int maxAttempts = 100_000;
while (!stop) {
int currentRandomValue = ThreadLocalRandom.current().nextInt(0, filteredArrayList.size());
if (currentRandomValue != lastRandomValue) {
// Use the value
...
// Reset the counter
attempts = 0;
...
// Stop the generation process if generated enough values
if (...) {
stop = true;
}
} else {
// Increment a counter
attempts++;
}
if (attempts >= maxAttempts) {
stop = true;
}
}
Edited:
I'd do something like this: (requires the last random value/a non-reachable number for the first time, e.g. -1)
private int notPreviousRandom(int previousRandomValue) {
int randomValue;
do {
randomValue = ThreadLocalRandom.current().nextInt(0, filteredArrayList.size());
} while (randomValue == previousRandomValue);
return randomValue;
}
Alternatively you could define previousRandomValue as an attribute:
// class
private int previousRandomValue = -1;
// ...
private int notPreviousRandom() {
int randomValue;
do {
randomValue = ThreadLocalRandom.current().nextInt(0, filteredArrayList.size());
} while (randomValue == previousRandomValue);
previousRandomValue = randomValue; // for the next time you're using the
// method
return randomValue;
}

Find Max Number in String of Numbers

I have run into an interesting problem and wanted to know if anyone had any leads on how to solve it. When given a string of numbers, I want to find the highest number. So if the string is "2836", then the output should be 8, if the string is "12345" then the output should be 5 and so on. Here is the method I am working on:
public static void main(String[] args) {
max("215");
}
public static void max(String number) {
if (number.isEmpty()) {
System.out.println("The string is empty");
System.exit(0);
}
int compCount = 1;
int max = number.charAt(0);
int compare = number.charAt(compCount);
for (int i = 0; i < number.length(); i++) {
if (max > compare) {
compCount++;
} else if (compare > max) {
max = compare;
} else {
System.out.print(max);
}
}
System.out.print(max);
}
When this code executes it gives me 50 and I want 5
Well, you have a lot of wrong stuff going on. Firstly, you never change compare, Second, you take the int in ascii, and don't convert it to its Integer representation. Thirdly, you need only one if statement. All combined, it gives
int max = Character.getNumericValue(number.charAt(0));
for (int i = 1; i < number.length(); i++) {
int compare = Character.getNumericValue(number.charAt(i));
if (max < compare) {
max = compare;
}
}
return max;
I've used Character#getNumericValue to convert the char to int
Since ASCII codes of digits are sorted in ascending order you can easily do it with Java 8 like this:
public static void max(String number) {
if (number == null || number.isEmpty()) {
return;
}
int max = number.chars().max().getAsInt();
System.out.println(Character.getNumericValue((char) max));
}
If your input can has mix of digits and other symbols you also able to handle it:
public static void max(String number) {
if (number == null || number.isEmpty()) {
return;
}
OptionalInt max = number.chars().filter(Character::isDigit).max();
if (max.isPresent()) {
System.out.println(Character.getNumericValue((char) max.getAsInt()));
} else {
System.err.println("Provided string doesn't contain digits");
}
}
you have to modify your max method as given below
public static void max(String number) {
if (number.isEmpty()) {
System.out.println("The string is empty");
System.exit(0);
}
int max = Integer.parseInt(number.charAt(0)+"");
for (int i = 1; i < number.length(); i++) {
int compare = Integer.parseInt(number.charAt(i)+"");
if (compare > max) {
max = compare;
}
}
System.out.print(max);
}

Loop in Credit Card Validation in java

I am a high school student in an introductory Computer Science course. Our assignment was the following:
The last digit of a credit card number is the check digit, which protects against transcription errors such as an error in a single digit or switching two digits. the following method is used to verify actual credit card numbers but, for simplicity, we will describe it for numbers with 8 digits instead of 16:
Starting from the rightmost digit, form the sum of every other digit. For example, if the credit card number is 4358 9795, then you form the sum 5+7+8+3 = 23.
Double each of the digits that were not included in the preceding step. Add all the digits of the resulting numbers. For example, with the numbers given above, doubling the digits, starting with the next-to-last one, yields 18 18 10 8. Adding all the digits in these values yields 1+8+1+8+1+0+8=27.
Add the sums of the two preceding steps. If the last digit of the result is 0, the number is valid. In our case, 23 + 27 = 50, so the number is valid.
Write a program that implements this algorithm. The user should supply an 8-digit number, and you should print out whether the number is valid or not. If it is not valid, you should print out the value of the check digit that would make the number valid.
I have everything done except for the part in bold. My code is listed below:
public class CreditCard
{
private String creditCardNumber;
private boolean valid;
private int checkDigit;
int totalSum;
/**
* Constructor for objects of class CreditCard
*/
public CreditCard(String pCreditCardNumber)
{
creditCardNumber = pCreditCardNumber;
checkDigit = Integer.parseInt(pCreditCardNumber.substring(creditCardNumber.length() - 1));
int sumOfDigits = checkDigit + Integer.parseInt(pCreditCardNumber.substring(6,7)) + Integer.parseInt(pCreditCardNumber.substring(3,4)) + Integer.parseInt(pCreditCardNumber.substring(1,2));
int dig7 = Integer.parseInt(pCreditCardNumber.substring(7,8));
int dig5 = Integer.parseInt(pCreditCardNumber.substring(5,6));
int dig3 = Integer.parseInt(pCreditCardNumber.substring(2,3));
int dig1 = Integer.parseInt(pCreditCardNumber.substring(0,1));
String string7 = Integer.toString(dig7);
int doubledDig7a = Integer.parseInt(string7.substring(0));
int doubledDig7b = 0;
if (dig7 * 2 >= 10)
{
doubledDig7a = Integer.parseInt(string7.substring(0));
doubledDig7b = 0;
}
String string5 = Integer.toString(dig5);
int doubledDig5a = Integer.parseInt(string7.substring(0));
int doubledDig5b = 0;
if (dig5 * 2 >= 10)
{
doubledDig5a = Integer.parseInt(string5.substring(0));
doubledDig5b = 0;
}
String string3 = Integer.toString(dig3);
int doubledDig3a = Integer.parseInt(string3.substring(0));
int doubledDig3b = 0;
if (dig3 * 2 >= 10)
{
doubledDig3a = Integer.parseInt(string3.substring(0));
doubledDig3b = 0;
}
String string1 = Integer.toString(dig1);
int doubledDig1a = Integer.parseInt(string1.substring(0));
int doubledDig1b = 0;
if (dig1 * 2 >= 10)
{
doubledDig1a = Integer.parseInt(string1.substring(0));
doubledDig1b = 0;
}
int doubleDigits = doubledDig1a + doubledDig1b + doubledDig3a + doubledDig3b + doubledDig5a + doubledDig5b + doubledDig7a + doubledDig7b;
totalSum = sumOfDigits + doubleDigits;
if (totalSum % 10 == 0)
{
valid = true;
}
else
{
valid = false;
}
}
public void makeItValid()
{
while (totalSum % 10 != 0)
{
checkDigit--;
if (totalSum % 10 == 0)
{
break;
}
}
}
public boolean isItValid()
{
return valid;
}
}
The loop is what I am having issues with. I always end up in an infinite loop whenever it compiles. It looks like everything should work, though. It's supposed to decrease the value of the check Digit (not increase so I don't end up with a check digit of 10 or higher), and then add that number back into the total sum until the total sum is divisible by 10, and then the loop would end. Is the type of loop I'm using wrong? Any advice would be appreciated.
Your problem is that both of your loop conditions involve totalSum but you only change checkDigit.
while (totalSum % 10 != 0)
{
checkDigit--;
if (totalSum % 10 == 0)
{
break;
}
}
You either need to recalculate totalSum or change the condition to be based on checkDigit. If you want to loop and decrement like you are doing you will need to add a method that performs the algorithm and call it every time. The way you have your class outlined makes this very inconvenient because you don't convert the numbers.
public static int[] cardToNumbers(String cardText) {
// \D is regex for non-digits
cardText = cardText.replaceAll("\\D", "");
int[] cardNumbers = new int[cardText.length()];
// convert unicode to corresponding integers
for (int i = 0; i < cardText.length(); i++)
cardNumbers[i] = cardText.charAt(i) - '0';
return cardNumbers;
}
public static int calcTotalSum(int[] cardNumbers) {
int sum = 0;
/* "every other one" loops
*
* I recommend against the "mod 2 index" scheme
* i % 2 relies on the card number being even
* you can't have your code blow up with unusual inputs
*
*/
for (int i = cardNumbers.length - 1; i >= 0; i -= 2) {
sum += cardNumbers[i];
}
for (int i = cardNumbers.length - 2; i >= 0; i -= 2) {
int dig = cardNumbers[i] * 2;
while (dig > 0) {
sum += dig % 10;
dig /= 10;
}
}
return sum;
}
Now you can do something like:
public void makeItValid() {
int[] invalidNumbers = cardToNumbers(creditCardNumber);
int sum = calcTotalSum(invalidNumbers);
while ((sum = calcTotalSum(invalidNumbers)) % 10 != 0)
invalidNumbers[invalidNumbers.length - 1]--;
totalSum = sum;
checkDigit = invalidNumbers[invalidNumbers.length - 1];
}
But you should be able to just subtract the difference to find the valid check digit:
if (totalSum % 10 != 0) checkDigit -= totalSum % 10;
Or something like:
public void makeItValid() {
int[] invalidNumbers = cardToNumbers(creditCardNumber);
checkDigit = invalidNumbers[invalidNumbers.length - 1] -= totalSum % 10;
totalSum = calcTotalSum(invalidNumbers);
valid = true;
}
Some asides,
I would recommend storing the digits as a field and have checkDigit represent an index in the array. This would simplify some of the operations you are doing.
I would also suggest not to be "silently" changing fields internally IE like in your makeItValid method unless this is a specification of the assignment. I think a better form is to let the "owning" code make the changes itself which is more clear externally. A somewhat complete implementation would look like this:
public class CreditCard {
public static void main(String[] args) {
if (args.length == 0) return;
CreditCard card = new CreditCard(args[0]);
if (!card.isValidNumber()) {
card.setCheckDigit(card.getValidCheckDigit());
}
}
private final String cardText;
private final int[] cardDigits;
private final int cdIndex;
public CreditCard(String ct) {
cardDigits = cardToNumbers(cardText = ct);
if ((cdIndex = cardDigits.length - 1) < 0) {
throw new IllegalArgumentException("# had no digits");
}
}
public boolean isValidNumber() {
return calcTotalSum(cardDigits) % 10 == 0;
}
public void setCheckDigit(int dig) {
cardDigits[cdIndex] = dig;
}
public int getValidCheckDigit() {
int sum = calcTotalSum(cardDigits);
if (sum % 10 != 0) {
return cardNumbers[cdIndex] - sum % 10;
} else {
return cardNumbers[cdIndex];
}
}
// above static methods
}
The best form IMO would be to disallow creation of a credit card object at all unless the check digit is valid. As an OOP principle it should not make sense to create invalid credit cards. The constructor should throw an exception if the card is invalid and have a static method to correct the number.
I would do something like the following (shortened):
public class CreditCard {
public CreditCard(String number) {
if (!validateCheckDigit(number)) {
throw new IllegalArgumentException("check digit failure");
}
}
}
public static void main(String[] args) {
String number = args[0];
CreditCard card = null;
boolean valid = false;
do {
try {
card = new CreditCard(number);
valid = true;
} catch (IllegalArgumentException e) {
number = CreditCard.correctCheckDigit(number);
}
} while (!valid);
}
I guess that's more or less doing your homework for you but I'm sure you can learn from it.
Unless I'm missing something major on how the validation works your makeitvalid method wont work in the way you are approaching it.
It makes more sense (at least to me) to extract everything you have in your constructor into a method ie.
boolean isValid(String cardNumber);
which would do everything that your constructor does except set the valid flag. your constructor then becomes
public CreditCard(String pCreditCardNumber){
valid = isValid(pCreditCardNumber);
}
and then to find what change would make it valid your check valid method does something like
change the value of check digit
if (isValid(Changed String))
return checkdigit
else
continue
repeat until you either find one that works or until you determine that it can't work.
Something along these lines should do. You'll still need to implement a few methods on your own.
public static void main(String[] args) {
String creditCardNumber = readCreditCardNumber();
String correctCreditCardNumber = getCorrectCreditCardNumber(creditCardNumber);
if (creditCardNumber.equals(correctCreditCardNumber)) {
System.out.println("Credit Card Valid");
} else {
System.out.println("Credit Card Invalid. Did you mean " + correctCreditCardNumber + "?");
}
}
public static String getCorrectCreditCardNumber(String creditCardNumber) {
int[] creditCardDigits = getCreditCardDigits(creditCardNumber);
int sum = 0;
for (int i = creditCardDigits.length - 2; i >= 0; i--) {
if (isOdd(i)) {
sum += creditCardDigits[i];
} else {
sum += digitSum(creditCardDigits[i] * 2);
}
}
int last = creditCardDigits.length - 1;
int remainder = sum % 10;
if (remainder != 0) {
creditCardDigits[last] = 10 - remainder;
}
return getCreditCardNumberAsString(creditCardDigits);
}
This program is very dynamic. I did not add too much error handling. You can enter any number that is divisible by 8.
Code in action:
Enter a card number: 4358 9795
Number is valid?: true
Continue? (y/n): y
Enter a card number: 4358 9796
Number is valid?: false
Continue? (y/n): y
Enter a card number: 43-58 97-95
Number is valid?: true
Continue? (y/n): n
Exiting...
CreditCardValidator.java
import java.text.ParseException;
import java.util.Scanner;
public class CreditCardValidator {
Integer[] digits;
public CreditCardValidator(String numberSequence) {
parseNumber(numberSequence);
}
private void parseNumber(String numberSequence) {
try {
String sequence = numberSequence.replaceAll("[\\s-]+", "");
int length = sequence.length();
if (length % 8 != 0) {
throw new IllegalArgumentException("Number length invalid.");
}
digits = new Integer[length];
int pos = 0;
for (Character c : sequence.toCharArray()) {
if (Character.isDigit(c)) {
digits[pos++] = Character.getNumericValue(c);
} else {
throw new ParseException("Invalid digit.", pos);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean validateNumber() {
int sum = 0;
for (int i = digits.length - 1; i >= 0; i--) {
if (i % 2 == 1) {
sum += digits[i];
} else {
sum += NumberUtils.sumDigits(digits[i] * 2);
}
}
return sum % 10 == 0;
}
public static void main(String[] args) {
boolean stop = false;
CreditCardValidator c;
while (!stop) {
System.out.print("Enter a card number: ");
c = new CreditCardValidator(new Scanner(System.in).nextLine());
System.out.println("Number is valid?: " + c.validateNumber());
System.out.print("\nContinue? (y/n): ");
if (new Scanner(System.in).next().charAt(0) == 'n') {
stop = true;
}
System.out.println();
}
System.out.println("Exiting...");
System.exit(0);
}
}
I wrote a separate digit summation utility:
public class NumberUtils {
public static void main(String[] args) {
for(int i = 0; i < 2000; i+=75) {
System.out.printf("%04d: %02d\n", i, sumDigits(i));
}
}
public static int sumDigits(int n) {
if (n < 0)
return 0;
return sumDigitsRecursive(n, 0);
}
private static int sumDigitsRecursive(int n, int total) {
if (n < 10)
return total + n;
else {
return sumDigitsRecursive(n / 10, total + (n % 10));
}
}
}

Categories

Resources