How to find sequence of identical numbers using recursion? -- Java - java

I have an assignment where i get an number input from the user, for example : "57779227"
and i need to return the longest sequence of identical numbers. For this example, the longest sequence is "777" and the return should be 3 (as the amount of times the number "7" is in a row.
So far I wrote an iteration method.
***No loops to be used in this method, ONLY RECURSION. ***
Iteration example :
public static int maxSequence(int num) {
int max = 1; //initiate
int currentCount = 1;
int prevDigit = 11;//Because num%10 != 11 Always!
int currentDigit;
while (num!=0) {
currentDigit = num%10;
if (prevDigit == currentDigit)
currentCount++;
else if (currentCount > max)
max = currentCount;
if (prevDigit != currentDigit) //initiate for the next Iteration
currentCount = 1;
prevDigit = currentDigit;
num = num/10;
}
return max;
}

When previousDigit != currentDigit then a new count will be start
public static int maxSequence(int num) {
int previousMax = 1;
int currentMax = 1;
int previousDigit = num % 10;
num /= 10;
while (num != 0) {
int currentDigit = num % 10;
if (previousDigit == currentDigit) {
currentMax++;
} else {
if (previousMax < currentMax) {
previousMax = currentMax;
}
currentMax = 1;
previousDigit = currentDigit;
}
num /= 10;
}
return Math.max(currentMax, previousMax);
}

Related

How can I swap 2 digits (i,j) from a n number?

basically i have an integer n = 23456 and i want to swap the second and fourth digit, so i = 2 and j = 4. So the output would be 25436. I canĀ“t use any Java class, so I supose that one of the ways to do it is by divide the number on powers of 10 and keep the rest on a new variable.
this is what i have so far:
public static int powerOfTen(int n) {
int p = 10;
while(n-1 > 0) {
p = p*10;
n--;
}
return p;
}
public static int swapNum(int n, int i, int j) {
int swap = 1;
int count = numDigits(n);
int digit1 = nDigit(n, i);
int digit2 = nDigit(n, j);
if(i > j) {
swap = n/powerOfTen(i);
int rest = n%powerOfTen(i);
rest = rest/10;
swap = swap*powerOfTen(i);
}
}
Here's your code with some modifications:
public class Main
{
// Count the number of digits in an integer
static int numDigits(int n)
{
if (n == 0) return 1;
int count = 0;
while (n != 0) {
count++;
n /= 10;
}
return count;
}
// Reverse an integer
static int reverseNumber(int n)
{
int result = 0;
while (n != 0) {
result = result * 10 + n % 10;
n /= 10;
}
return result;
}
// Get the nth digit - from the left
static int nDigit(int n, int index)
{
n = reverseNumber(n);
for (int i = 0; i < index; i++) {
n /= 10;
}
return n % 10;
}
static int swapNum(int n, int i, int j)
{
// Make indexes 0-based
i = i - 1;
j = j - 1;
int count = numDigits(n);
int digit1 = nDigit(n, i);
int digit2 = nDigit(n, j);
int result = 0;
for (int k = count - 1; k >= 0; --k) {
int digit;
// Get the correct digit, i, j, or current
if (k == i) digit = digit2;
else if (k == j) digit = digit1;
else digit = n % 10;
result = result * 10 + digit;
n /= 10;
}
return reverseNumber(result);
}
public static void main(String[] args) {
System.out.println(swapNum(12345678 , 4, 5));
}
}
You can't use any class? what about convert number to char array, swap and parse it back?
// helper function to convert char array to int
public static int parseInt(char[] chars) {
int result = 0; // accumulator
int idx_value = 1; // power of ten counter
for (int i = chars.length - 1; i >= 0; i--) { // loop from tail to head
// char - '0' mean it will convert '0' to 0 and '1' will be 1 so on.
result += (chars[i] - '0') * idx_value;
idx_value *= 10;
}
return result;
}
public static int swapNum(int n, int i, int j) {
// convert number to char array
char[] chars = ("" + n).toCharArray();
// use zero based index
i-=1;j-=1;
// perform swap
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
// convert char array back to int
return parseInt(chars);
}

Why there is a logic error with this method. isPalindrome(11) should return true, but it returns false

public static boolean isPalindrome(int number) {
int reverseNumber = 0;
int lastDigit = 0;
if (number < 0) {
number = number * -1;
}
while (number > 0) {
lastDigit = number % 10;
number = number / 10;
if (number == 0) {
reverseNumber += lastDigit;
}
else {
reverseNumber += lastDigit;
reverseNumber *= 10;
}
}
return reverseNumber == number;
}
This method should return for true palindromes, but it doesn't.
You are "destroying" the original number while constructing reverseNumber:
number = number / 10;
So after the while-loop, your number is zero, and the comparison reverseNumber == number doesn't work as you expect. It's always false unless your reverse number is zero.
You could use a new local variable for building reverseNumber, which you modify in the loop, but still use the original number for the final comparison:
public static boolean isPalindrome(int number) {
// ... Handle negatives
int tempNumber = number;
while (tempNumber > 0) {
// ...
tempNumber = tempNumber / 10;
// ...
}
return reverseNumber == number;
}
The output is wrong because you have taken the variable number for all the process. So that the number=11 get reduced during each time and finally when comparing with reverseNumber, it is comparing as 11 == 0. So what the output is false.
Assign a variable temp like, int temp = number .
public static boolean isPalindrome(int number) {
int temp = number;
int reverseNumber = 0;
int lastDigit = 0;
if (number < 0) {
number = number * -1;
}
while (number > 0) {
lastDigit = number % 10;
number = number / 10;
reverseNumber = (reverseNumber * 10) + lastDigit ;
}
return reverseNumber == temp;
}

Determine the largest prime factor using a while loop and a for loop

I wanted to use a for and a while loop to obtain the prime factors of a number. My while loop example works fine which I have posted below my for loop example. However, my for loop does not work, and i am guessing that I can't use a continue in the same manner that I used it in the while loop. If this is true, then how would I accomplish this. I have not been able to find a basic beginners example of this using a for loop. Thanks
// My getting largest prime factor using a for loop
public class LargestPrime{
public static void main(String[] args) {
int number = 36;
int largestPrime = 0;
for ( int i = 2; i <= number; i++){
if (number % i == 0){
largestPrime = i;
number /= i;
continue;
}
System.out.println(" largest prime = " + i);
}
}
}
//*******************************************************************
//*******************************************************************
public class LargestPrime {
// gettting largest prime using a while loop
public static int getLargestPrime(int number) {
if (number <= 1) {
return -1;
}
int largestPrime = 0;
int count = 2;
while (count <= number) {
if (number % count == 0) {
largestPrime = count;
number = number / count;
continue;
}
count++;
}
return largestPrime;
}
}
The problem is that continue in a for loop executes the update part (i++), which your while loop didn't.
The other problem is that you're printing inside the loop.
There are multiple way to fix this:
Do i-- before continue, so it evens out to nothing with the i++. This is a fairly common way to handle this.
Since you don't have any code after the if statement, you don't need the continue.
for (int i = 2; i <= number; i++) {
if (number % i == 0) {
largestPrime = i;
number /= i;
i--; // to retry same `i` value
}
}
Do the i++ "yourself", i.e. not as part of for loop:
for (int i = 2; i <= number; ) {
if (number % i == 0) {
largestPrime = i;
number /= i;
continue;
}
i++;
}
Or:
for (int i = 2; i <= number; ) {
if (number % i == 0) {
largestPrime = i;
number /= i;
} else {
i++;
}
}
Use a while loop inside the for loop:
for (int i = 2; i <= number; i++) {
while (number % i == 0) {
largestPrime = i;
number /= i;
}
}
That can be shortened to:
for (int i = 2; i <= number; i++)
for (; number % i == 0; number /= i)
largestPrime = i;
Though rather than assign largestPrime repeatedly, you could do this:
for (int i = 2; i <= number; i++) {
if (number % i == 0) {
largestPrime = i;
do {
number /= i;
} while (number % i == 0);
}
}

Fibonacci Iterative Move In Array[]

My goal is to write a method showing how the fibonacci sequence moves. I have to use an array and equation to show how the numbers move on the array (thus iterating the value using fibonacci method: previous number + current number = next number).
This is the logic that I want to use with array[] as representation:
n = fibonacci number
i = 1;
previousNumber = 0
nextNumber = 1
sum = previousNumber + nextNumber;
while (i <= n) {
sum = previousNumber + nextNumber;
previousNumber = nextNumber;
nextNumber = sum;
return nextNumber;
I went this far and I am stuck:
long fibonacci(int fibonacci) {
int[] fib = new int[20];
if (fibonacci < 0) {
throw new IllegalArgumentException("n value cannot be negative number");
}
if (fibonacci == 0 || fibonacci == 1) {
return 1;
}
fib[0] = 1;
fib[1] = 1;
int i ;
for (i = 2; i < fibonacci; i++) {
fib[i] = fib[0] + fib[1];
fib[0] = fib[1];
fib[1] = fib[i];
}
return fib[i];
}
The returned value seems ok. In the fibonacci test, fib from 5 is 5 and 4 is 3. What worries me is how this string looks on the debugger. The way I move them makes them look like this : {3,5,2,3,5} and it should be {1,1,2,3,5}.
You don't need an array.
long fibonacci(int fibonacci) {
if (fibonacci < 0) {
throw new IllegalArgumentException("n value cannot be negative number");
}
if (fibonacci == 0 || fibonacci == 1) {
return 1;
}
first = 1;
second = 1;
sum i;
for (i = 2; i <= fibonacci; i++) {
sum = first + second;
first = second;
second = sum;
}
return sum;
}
This implementation is simpler and more readable.
Your loop is wrong. It should be:
for (i = 2; i <= fibonacci; i++) {
fib[i] = fib[i-1] + fib[i-2];
}
return fib[i-1];
You should never change fib[0] and fib[1], and fib[i] should be the sum of the previous two elements.
If the goal was to calculate fib(i) without an array, you would need two variables to keep track of the last two values:
long fibonacci(int fibonacci) {
if (fibonacci < 0) {
throw new IllegalArgumentException("n value cannot be negative number");
}
if (fibonacci == 0 || fibonacci == 1) {
return 1;
}
int beforeLast = 1;
int last = 1;
int i;
int fib = 1;
for (i = 2; i <= fibonacci; i++) {
fib = last + beforeLast;
beforeLast = last;
last = fib;
}
return fib;
}
Here is how your method should look like:
static long fibonacci(int fibonacci) {
int[] fib = new int[20];
if (fibonacci < 0) {
throw new IllegalArgumentException("n value cannot be negative number");
}
if (fibonacci == 0 || fibonacci == 1) {
return 1;
}
fib[0] = 1;
fib[1] = 1;
int i;
for (i = 2; i < fibonacci; i++) {
fib[i] = fib[i - 1] + fib[i - 2]; // change here
}
return fib[i-1]; // change here
}

Converting a long int into separate digits and reverse populating into a vector

First of all this is a school project about credit card number validations.
Basically I am trying to convert a long int (the CC number) into a vector so I can manipulate each digit as required. I am doing it by using the %10 way. Since this will end up with my vector having the number from right to left (backwards), I am setting the vector in increments starting from ccNum.size()-1 and working backwards so that the values in the vector are in the same order as the user input.
The problem is that first values that are processed (so the last 9 or so digits of input) are being put in the vector incorrectly. I've tried restructuring the loop, copying into an array and then reversing it into the vector, and various other things that my mind just can't keep track of. I tried to comment my code as best as I could to outline what is going on, here it is:
public static void main(String[] args) {
long creditCardNumber = 0;
Vector<Integer> ccNum = new Vector<Integer>(13,3);
Vector<Integer> oddNum = new Vector<Integer>(6,1);
Vector<Integer> evenNum = new Vector<Integer>(6,1);
creditCardNumber = getInput(creditCardNumber);
int size = getSize(creditCardNumber);
//Pre-populate the vector so that I can add values starting from behind
//this makes it so that the credit card number isn't backwards. I also
//did it so that it matches the size of the input to prevent false values
//Yes, I verified the getSize method works.
for (int k = 0; k < size; k++) {
ccNum.add(k);
}
//I made a copy of the variable so I don't screw it up in the loop
long ccNumber = creditCardNumber;
//THIS IS WHERE THE PROBLEM IS.
for (int j = 0; ccNumber > 0; j++){
//on the first iteration, set the final index of ccNum array to
//final value of input using %10
if (j == 0){
ccNum.set(ccNum.size() - 1, (int) ccNumber % 10);
ccNumber /= 10;
//This just prints the value of ccNumber afterwards so that I can
//keep track of whats going on and make sure everything is "working"
System.out.println(ccNumber);
} else {
//Here I am continuously setting the values going backwards
//I end up with the same amount of values as the input but some
//are wrong
ccNum.set(ccNum.size() - (j+1), (int) ccNumber % 10);
ccNumber /= 10;
System.out.println(ccNumber);
}
}
//Here is where I print out all the values in the ccNum vector.
for (int l = 0; l < size; l++) {
System.out.print(ccNum.get(l));
}
System.out.println("");
for (int i = 0; i < ccNum.size() - 1; i ++) {
if (i % 2 == 0) {
evenNum.add(getDigit(ccNum.get(i)));
} else {
oddNum.add(ccNum.get(i));
}
}
int prefix = getPrefix(ccNum);
int sumEven = sumOfDoubleEvenPlace(evenNum);
int sumOdd = sumOfOddPlace(oddNum);
if (isValid(ccNum, sumEven, sumOdd, size, prefix)) {
System.out.printf("%d: is valid", creditCardNumber);
} else {
System.out.printf("%d: is invalid", creditCardNumber);
}
}
private static int sumOfOddPlace(Vector<Integer> oddNum) {
int sum = 0;
for (int i = 0; i < oddNum.size() - 1; i++) {
sum += oddNum.get(i);
}
return sum;
}
private static int sumOfDoubleEvenPlace(Vector<Integer> evenNum) {
int sum = 0;
for (int i = 0; i < evenNum.size() - 1; i++) {
sum += evenNum.get(i);
}
return sum;
}
private static int getDigit(int x) {
int y = x*2;
if (y < 10) {
return y;
} else {
int sum = 0;
while (y > 0) {
sum += y % 10;
y /= 10;
}
return sum;
}
}
private static int getPrefix(Vector<Integer> ccNum) {
if (ccNum.get(0) == 4) {
return 4;
} else if (ccNum.get(0) == 5) {
return 5;
} else if (ccNum.get(0) == 6) {
return 6;
} else if (ccNum.get(0) == 3 && ccNum.get(1) == 7) {
return 37;
} else {
return 0;
}
}
private static int getSize(long creditCardNumber) {
int size = (int)(Math.log10(creditCardNumber)+1);
return size;
}
private static long getInput(long creditCardNumber){
Scanner input = new Scanner(System.in);
System.out.print("Enter a credit card number: ");
creditCardNumber = input.nextLong();
input.close();
return creditCardNumber;
}
private static boolean isValid(Vector<Integer> ccNum, int sumEven, int sumOdd, int size, int prefix) {
if (size < 13 || size > 16) {
return false;
} else if (prefixMatched(prefix) == false) {
return false;
} else if ((sumEven + sumOdd) % 10 != 0) {
return false;
} else {
return true;
}
}
private static boolean prefixMatched(int prefix) {
if (prefix == 4 || prefix == 5 || prefix == 6 || prefix == 37) {
return true;
} else {
return false;
}
}
Here is the output:
Enter a credit card number: 4388576018410707
438857601841070
43885760184107
4388576018410
438857601841
43885760184
4388576018
438857601
43885760
4388576
438857
43885
4388
438
43
4
0
438857601249-2-16-3
4388576018410707: is invalid
As You can see, the first half of the number comes out correctly (the last half to be looped). If anybody has a solution that'd be awesome.
For future reference for other people who may get stuck - this is what i ended up doing, looks cleaner as well, Thanks for the help everyone.
public class CreditCardNumberValidation {
public static void main(String[] args) {
long creditCardNumber = 0;
//Using ArrayLists because it makes it easier to manipulate data later
ArrayList<Integer> ccNum = new ArrayList<Integer>();
ArrayList<Integer> oddNum = new ArrayList<Integer>();
ArrayList<Integer> evenNum = new ArrayList<Integer>();
//Getting input in different method to clean up the code
creditCardNumber = getInput(creditCardNumber);
int size = getSize(creditCardNumber);
//Split creditCardNumber into separate integers and store in ArrayList
long ccNumber = creditCardNumber;
for (int j = 0; ccNumber > 0; j++){
ccNum.add((int) (ccNumber % 10));
ccNumber /= 10;
}
//Reverse the collection so that the numbers are in order
Collections.reverse(ccNum);
//Using the main List, even and odd numbers are sorted
for (int i = 0; i < ccNum.size(); i ++) {
if (i % 2 == 0) {
evenNum.add(getDigit(ccNum.get(i)));
} else {
oddNum.add(ccNum.get(i));
}
}
int prefix = getPrefix(ccNum);
int sumEven = sumOfDoubleEvenPlace(evenNum);
int sumOdd = sumOfOddPlace(oddNum);
if (isValid(ccNum, sumEven, sumOdd, size, prefix)) {
System.out.printf("%d is valid", creditCardNumber);
} else {
System.out.printf("%d is invalid", creditCardNumber);
}
}
private static int sumOfOddPlace(ArrayList<Integer> oddNum) {
int sum = 0;
for (int i = 0; i < oddNum.size(); i++) {
sum += oddNum.get(i);
}
return sum;
}
private static int sumOfDoubleEvenPlace(ArrayList<Integer> evenNum) {
int sum = 0;
for (int i = 0; i < evenNum.size(); i++) {
sum += evenNum.get(i);
}
return sum;
}
private static int getDigit(int x) {
int y = x*2;
if (y < 10) {
return y;
} else {
int sum = 0;
while (y > 0) {
sum += y % 10;
y /= 10;
}
return sum;
}
}
private static int getPrefix(ArrayList<Integer> ccNum) {
if (ccNum.get(0) == 4) {
return 4;
} else if (ccNum.get(0) == 5) {
return 5;
} else if (ccNum.get(0) == 6) {
return 6;
} else if (ccNum.get(0) == 3 && ccNum.get(1) == 7) {
return 37;
} else {
return 0;
}
}
private static int getSize(long creditCardNumber) {
//Easy way of getting the size of an integer without modifying it
return (int)(Math.log10(creditCardNumber)+1);
}
private static long getInput(long creditCardNumber){
Scanner input = new Scanner(System.in);
System.out.print("Enter a credit card number: ");
creditCardNumber = input.nextLong();
input.close();
return creditCardNumber;
}
private static boolean isValid(ArrayList<Integer> ccNum, int sumEven, int sumOdd, int size, int prefix) {
// Check size, prefix, and sum, if all tests pass return true
if (size < 13 || size > 16) {
return false;
} else if (prefixMatched(prefix) == false) {
return false;
} else if ((sumEven + sumOdd) % 10 != 0) {
return false;
} else {
return true;
}
}
private static boolean prefixMatched(int prefix) {
if (prefix == 4 || prefix == 5 || prefix == 6 || prefix == 37) {
return true;
} else {
return false;
}
}
}
Try to replace
(int) ccNumber % 10
by
(int) (ccNumber % 10)
If you cast to int first and then do the modulo 10, it won't work when the int value overflows.
I recomend you using ArrayList like in my listing. My function returns simple arraylist of integers that was in Long.
public List<Integer>getCardNumbers(Long longCardNumber){
String cardNumber = longCardNumber.toString();
List<Integer> intCardNumberList = new ArrayList<Integer>();
for(int i=0;i<cardNumber.length();i++){
intCardNumberList.add(Integer.parseInt(String.valueOf(cardNumber.charAt(i))));
}
return intCardNumberList;
}

Categories

Resources