Get Immediate Successor in a Given Number Sequence - java

In an infinite sequence of numbers [2, 5, 7, 22, 25, 27, 52, 55, 57, 72, 75, 77, 222, ...].
Given any number in this sequence get the immediate successor number.
Example:
Input Output
22 25
77 222
5 7
I have written the below logic to find the next number in a sequence.
public static int getNextNumInSequence(Integer sequenceCurrentNum) {
List<Integer> sequence = new ArrayList<>();
sequence.add(2);
sequence.add(5);
sequence.add(7);
if(sequence.get(0).equals(sequenceCurrentNum))
return sequence.get(1);
else if(sequence.get(1).equals(sequenceCurrentNum))
return sequence.get(2);
//This is not a finite loop, just for my testing i am running 300 iterations.
for(int i=0;i<300;i++) {
if(sequence.get(i).equals(sequenceCurrentNum)) {
return sequence.get(i+1);
}
int nextVal = sequence.get(i)*10;
Integer firstSeq = nextVal + sequence.get(0);
Integer secondSeq = nextVal + sequence.get(1);
Integer thirdSeq = nextVal + sequence.get(2);
sequence.add(firstSeq);
sequence.add(secondSeq);
sequence.add(thirdSeq);
if(firstSeq.equals(sequenceCurrentNum)) {
return secondSeq;
}else if(secondSeq.equals(sequenceCurrentNum)) {
return thirdSeq;
}
}
return 0;
}
My Approach:
I am constructing the entire sequence from the beginning
Then checking if we have reached to the given number in sequence.
Then return the successor.
Drawbacks:
I am constructing the entire sequence to reach to given number.
Memory wise and performance wise not suggestable.
Please help to understand, is there any better approach to get the successor without constructing entire sequence.
Example: Given 277755 should return 277757. (Without constructing the
entire sequnce)
Note: The sequence will not be provided as an input to our function. The only input we will be given is a valid number from the sequence.

Try this.
public static int getNextNumInSequence(Integer sequenceCurrentNum) {
int head = sequenceCurrentNum / 10;
int tail = sequenceCurrentNum % 10;
int headNext = head == 0 ? 2 : getNextNumInSequence(head);
if (headNext == 0) return 0;
switch (tail) {
case 2: return head * 10 + 5;
case 5: return head * 10 + 7;
case 7: return headNext * 10 + 2;
default: return 0;
}
}
public static void main(String[] args) {
for (int i = 0, k = 2; i < 20; ++i, k = getNextNumInSequence(k))
System.out.println(i + " : " + k);
}
output:
0 : 2
1 : 5
2 : 7
3 : 22
4 : 25
5 : 27
6 : 52
7 : 55
8 : 57
9 : 72
10 : 75
11 : 77
12 : 222
13 : 225
14 : 227
15 : 252
16 : 255
17 : 257
18 : 272
19 : 275
You can also get n-th number.
public static int getNumAtIndex(int n) {
int h = n / 3;
int t = n % 3;
return (h == 0 ? 0 : getNumAtIndex(h) * 10)
+ (t == 0 ? 2 : t == 1 ? 5 : 7);
}
test:
public static void main(String[] args) {
for (int i = 0; i < 10; ++i)
System.out.println(i + " : " + getNumAtIndex(i));
}
output:
0 : 2
1 : 5
2 : 7
3 : 52
4 : 55
5 : 57
6 : 72
7 : 75
8 : 77
9 : 522

First try to understand what is the logic behind the sequence. If you look carefully to the numbers, you may see counting in ternary base. To be more clear, let's replace '2' by '0', '5' by '1' and '7' by '2'. Then your sequence becomes:
(0, 1, 2, 10, 11, 12, 20, 21, 22, 100, 101, 102, ...)
It's just counting.
So the thing is to get the next number in ternary base, but using the digits 2, 5, 7. We must take care of digit 7: if we increment it, we get 2 but we have a carry for the digit before.
Here is a sample code:
public static Integer getNextNumInSequence(Integer number)
{
int digits[] = {2,5,7};
int idx_digits[] = {-1, -1, 0, -1, -1, 1, -1, 2, -1, -1};
Integer next_number = 0;
int carry = 1;
Integer pow10 = 1;
while (number>0)
{
int digit = number%10; //extract last digit
int idx_d = idx_digits[digit]; //get index of digit -- must be 0,1 or 2
if (idx_d==-1)
{
System.out.println("Invalid number");
return -1;
}
next_number += digits[(idx_d+carry)%3]*pow10; //compute next digit in sequence, taking care of the carry
carry = (digit==7)?1:0; //carry is 1 only if the current digit is 7
pow10 *= 10; //increment
number /= 10; //erase last digit
if (carry==0) //if no carry, we can stop the loop here, it's not useful to continue
{
break;
}
}
// at this point, either number>0 or carry==1
return ((carry>0)?2:number)*pow10+next_number; //final number is the digit sequence [2 if carry else number ; next_number]
}

You can solve this recursively.
If the final digit of the given number is 2 or 5, then it is easy: just change that final digit to 5 or 7 respectively.
Otherwise (when the final digit is 7), solve the problem without the last digit, and then append the digit 2 to that result. Of course, "without last digit" means an integer division by 10, and "appending" means multiplying by 10 and then adding the value of the digit.
Here is the function:
public static int getNextNumInSequence(Integer curr) {
if (curr % 10 == 2) return curr + 3;
if (curr % 10 == 5) return curr + 2;
if (curr == 7) return 22;
return getNextNumInSequence(curr / 10) * 10 + 2;
}
Note that one call has worst case time complexity of O(logn) where n is the value of the function argument, but amortised time complexity is O(1) per call.

To construct the list, you can simply do this:
List<Integer> list = Arrays.asList(2, 5, 7, 22, 25, 27, 52, 55, 57, 72, 75, 77, 222);
Note that there are cases where there is not successor. Here I will return null in those cases:
public static Integer getNextNumInSequence(List<Integer> list, Integer num) {
int pos = list.indexOf(num);
if (pos >= 0 && pos+1 < list.size()) {
return list.get(pos+1);
}
return null;
}
Note that I've added a parameter list so that you don't have to build the list each time you want to do a search.
In your example, the list is sorted; If it's always the case, you can use a binary search: Collections.binarySearch(list, num) instead of list.indexOf(num).

OK. If I understand correctly, you have three initial values:
static final int[] initial = {2, 5, 7};
and you can calculate the value at position ix like this:
private static int calculate(int ix) {
int div = ix/initial.length;
int rest = ix%initial.length;
int value = 0;
if (div > 0) {
value = 10*calculate(div-1);
}
return value+initial[rest];
}
To get the successor of num:
public static Integer getNextNumInSequence(int num) {
for (int i = 0; ; ++i) {
int cur = calculate(i);
if (cur == num) {
return calculate(i+1);
} else if (cur > num) {
return null;
}
}
}

Related

How can I print the number of combination and not the actual combination? Java

I'd like to print the number of combination and not the actual combination of bits. How can I code that? I'm looking forward for some solution. Thank you!
The Task:
Write a program that accepts a number. This number corresponds to the number of bits to be taken into account. The program should then display on the screen how many binary combinations there are that do not consist of two adjacent 1s. For example, given a 3-bit number, there are 5 out of 8 possible combinations.
import java.util.Scanner;
public class BinaryS {
public static String toString(char[] a) {
String string = new String(a);
return string;
}
static void generate(int k, char[] ch, int n) {
if (n == k) {
for (int i = 0; i < ch.length; i++) {}
System.out.print(toString(ch) + " ");
return;
}
// If the first Character is
//Zero then adding**
if (ch[n - 1] == '0') {
ch[n] = '0';
generate(k, ch, n + 1);
ch[n] = '1';
generate(k, ch, n + 1);
}
// If the Character is One
// then add Zero to next**
if (ch[n - 1] == '1') {
ch[n] = '0';
// Calling Recursively for the
// next value of Array
generate(k, ch, n + 1);
}
}
static void fun(int k) {
if (k <= 0) {
return;
}
char[] ch = new char[k];
// Initializing first character to Zero
ch[0] = '0';
// Generating Strings starting with Zero--
generate(k, ch, 1);
// Initialized first Character to one--
ch[0] = '1';
generate(k, ch, 1);
}
public static void main(String args[]) {
System.out.print("Number: ");
Scanner scanner = new Scanner(System.in);
int k = scanner.nextInt();
//Calling function fun with argument k
fun(k);
}
}
The program actually works fine , my only problem is I would like to print the number of combinations and not the actual combination. For example for the input 3 we get 000 001 010 100 101 which is 5.
Unfortunately, your code has some problems. For one you have an empty forloop in the generate method. However, I can help you get the count by doing it a different way and printing the results. Forgetting about the loop that goes from 2 to 20, here is what is going on. And this may not be most efficient way of finding the matches but for short runs it exposes the counts as a recognizable pattern (which could also be determined by mathematical analysis).
first, create an IntPredicate that checks for adjacent one bits by masking the lower order two bits.
Generate an IntStream from 0 to 2n where n is the number of bits.
then using aforementioned predicate with a filter count every value that does not contain two adjacent 1 bits.
IntPredicate NoAdjacentOneBits = (n)-> {
while (n > 0) {
if ((n & 3) == 3) {
return false;
}
n>>=1;
}
return true;
};
for (int n = 1; n <= 20; n++) {
long count = IntStream.range(0, (int) Math.pow(2, n))
.filter(NoAdjacentOneBits).count();
System.out.println("For n = " + n + " -> " + count);
}
prints (with annotated comments on first three lines)
For n = 1 -> 2 // not printed but would be 0 and 1
For n = 2 -> 3 // 00, 01, 10
For n = 3 -> 5 // 000, 001, 010, 100, 101
For n = 4 -> 8
For n = 5 -> 13
For n = 6 -> 21
For n = 7 -> 34
For n = 8 -> 55
For n = 9 -> 89
For n = 10 -> 144
For n = 11 -> 233
For n = 12 -> 377
For n = 13 -> 610
For n = 14 -> 987
For n = 15 -> 1597
For n = 16 -> 2584
For n = 17 -> 4181
For n = 18 -> 6765
For n = 19 -> 10946
For n = 20 -> 17711
The counts are directly related to the nth term of the Fibonacci Series that starts with 2 3 5 8 . . .
So you really don't even need to inspect the values for adjacent bits. Just compute the related term of the series.

Java to find if an array is a subset of another

Im having trouble to find out if a specific amount of numbers is in another array.The first array generates 10 random numbers and in the second array the user guesses 5 numbers.Im trying to find out if the user guessed any sequences.I used for loops to find out if numbers of user input is in any of the numbers from 1-5 in the array of 10 , if not it will check numbers 2-6 and so on.
For example, if the program had the following winning numbers:
23 56 67 06 43 22 59 24 90 66 and user entered: 01 06 43 22 89.
I keep getting index out of bounds.How do I fix this ?
// to check if user guessed a sequence
boolean guessed = false;
int counter = 0;
int i , j = 0;
for (i = 4; i < numbers.length; i++) { // users numbers
for ( j = 4; j < lottery.length; j++) { // first 5 numbers from array
if ( lottery[i] == numbers[j]) {
break;
}
if ( j == i) {
guessed = true;
}
}
}
It seems that a method similar to String::indexOf should be implemented in this task for the arrays trying to find an index of a subarray int indexOf(int[] search, int[] input).
Also, it might be needed to look for all possible subarrays of the search subarray (lottery). Thus, the mentioned method should be extended to look for a subrange of the search argument: int indexOf(int[] search, int[] input)
Straightforward implementation would be:
static int indexOf(int search[], int from, int to, int[] input) {
if (null == search || null == input || search.length > input.length) {
return -1;
}
for (int i = 0, n = input.length - (to - from); i <= n; i++) {
boolean found = true;
for (int j = from; found && j < to; j++) {
if (input[i + j - from] != search[j]) {
found = false;
}
}
if (found) {
return i;
}
}
return -1;
}
The widths and appropriate indexes from / to of the search subranges can be generated as follows (from the entire length of lottery to 2):
int[] numbers = {23, 56, 67, 06, 43, 22, 59, 24, 90, 66};
int[] lottery = {01, 06, 43, 22, 89};
for (int n = lottery.length; n > 1; n--) {
for (int m = 0; m <= lottery.length - n; m++) {
int ix = indexOf(lottery, m, m + n, numbers);
if (ix > -1) {
System.out.printf("Found subarray %s, width=%d from: %d to %d ",
Arrays.toString(Arrays.copyOfRange(lottery, m, m + n)), n, m, m + n - 1);
System.out.printf("at index: %d%n", ix);
}
}
}
Output
Found subarray [6, 43, 22], width=3 from: 1 to 3 at index: 3
Found subarray [6, 43], width=2 from: 1 to 2 at index: 3
Found subarray [43, 22], width=2 from: 2 to 3 at index: 4
A more efficient implementation would use Knuth - Morris - Pratt algorithm to bypass recurrent checks of the same values in the input array.

Add one in a number of arraylist

public class Solution {
public ArrayList<Integer> plusOne(ArrayList<Integer> A) {
int n = A.size();
// Add 1 to last digit and find carry
A.set(n - 1, A.get(n - 1) + 1);
int carry = A.get(n - 1) / 10;
A.set(n - 1, A.get(n - 1) % 10);
// Traverse from second last digit
for (int i = n - 2; i >= 0; i--) {
if (carry == 1) {
A.set(i, A.get(i) + 1);
carry = A.get(i) / 10;
A.set(i, A.get(i) % 10);
}
}
// If carry is 1, we need to add
// a 1 at the beginning of vector
if (carry == 1)
A.add(0, 1);
return A;
}
}
Question is:
Given a non-negative number represented as an array of digits,
add 1 to the number ( increment the number represented by the digits ).
The digits are stored such that the most significant digit is at the head of the list.
Example:
If the vector has [1, 2, 3]
the returned vector should be [1, 2, 4]
as 123 + 1 = 124.
Wrong Answer. Your program's output doesn't match the expected output. You can try testing your code with custom input and try putting debug statements in your code.
Your submission failed for the following input:
A : [ 0, 0, 4, 4, 6, 0, 9, 6, 5, 1 ]
Your function returned the following :
0 4 4 6 0 9 6 5 2
The expected returned value :
4 4 6 0 9 6 5 2
Use below method
private ArrayList<Integer> recursiveCheckZero() {
if (arrayList.get(0) == 0) {
arrayList.remove(0);
recursiveCheckZero();
} else {
return arrayList;
}
}
This method will be used to zero at first position, it would be called recursively until all zeros get removed. and when there will be no zero at first position it will return final ArrayList of integers as actual result
int sum=0;
int carry=0;
int i=0;
while (i < A.size() - 1 && A.get(i) == 0) {
A.remove(i); //remove all zeroes in front
}
for(i=A.size()-1;i>=0;i--)
{
int n=A.get(i);
sum=n+carry;
if(i==A.size()-1)
{
sum = sum+1;
}
carry=sum/10;
sum=sum%10;
A.set(i,sum);
}
if (carry !=0)
A.add(0,1);
return A;

Add the consecutive digits of a birthdate recursively till it reaches to a single digit

I am developing a numerology application which has to provide a result which is similar to the following,
1 5 0 8 1 9 9 4
6 5 8 9 1 1 1
1 1 1 1 2 2
2 2 2 3 4
4 4 5 7
8 9 1
1 1
2
It has to add the consecutive digits and retain the first digit if the sum is of 2 digits.
I am missing something. Adding a while loop for the length of intList doesn't seem to work.
int date;
List<Integer> sumList = new ArrayList<Integer>();
Scanner s = new Scanner(System.in);
System.out.println("Enter the date");
date = s.nextInt();
int len = Integer.toString(date).length();
int[] convertarray = new int[len];
for (int index = 0; index < len; index++) {
convertarray[index] = date % 10;
date /= 10;
}
List<Integer> intList = new ArrayList<Integer>();
for (int i : convertarray) {
intList.add(i);
}
Collections.reverse(intList);
System.out.println(intList);
int sum = 0;
int size = intList.size();
for (int i = 0; i < intList.size() - 1; i++) {
sum = intList.get(i) + intList.get(i + 1);
int length = (int) (Math.log10(sum) + 1);
if (length > 1) {
int firstDigit = Integer.parseInt(Integer.toString(sum).substring(0, 1));
sum = firstDigit;
}
System.out.print(sum + " ");
sumList.add(sum);
}
System.out.println("\n");
intList.clear();
intList = sumList;
My output is something like,
1 5 0 8 1 9 9 4
6 5 8 9 1 1 1
A simple recursive solution:
public static void main(String[] args) throws Exception {
String birthday = "01091995";
int[] digits = Arrays.stream(birthday.split("")).mapToInt(Integer::parseInt).toArray();
recursiveFunction(digits);
}
private static void recursiveFunction(int[] digits) {
if(digits.length == 1) {
// Base Case
System.out.println(digits[0]);
} else {
// Recursive Case
System.out.println(Arrays.toString(digits));
int[] digitsProcessed = new int[digits.length -1];
for (int i = 0; i < digits.length - 1; i++) {
digitsProcessed[i] = digits[i] + digits[i+1]; // Logic
}
recursiveFunction(digitsProcessed);
}
}
This produces:
[0, 1, 0, 9, 1, 9, 9, 5] // 8 numbers
[1, 1, 9, 10, 10, 18, 14] // 7 numbers
[2, 10, 19, 20, 28, 32] // 6 numbers
[12, 29, 39, 48, 60] // 5 numbers
[41, 68, 87, 108] // 4 numbers
[109, 155, 195] // 3 numbers
[264, 350] // 2 numbers
614 // 1 number
Adding a while loop for the length of intList doesn't seem to work.
Well it can be done with loops, but it would be harder and messier.
An algorithm with recursion would be the following:
Init the array of integers.
Call the recursive function "F" with the array.
From now, the recursive function behaviour:
Check if the recieved array's length is 1.
If it is, print the element and terminate.
If it is not:
Print the recieved array.
Make a new array.
Put in this new array the result of processing the recieved one adding as intended.
Call the recursive function "F" with this new array.

Omit Digit Method Bug

I'm having an issue with a method that creates an array of consecutive digits (i.e. if you input 1 and 10 as an argument, the array will include every number from 1-10), and then compares each number to another digit (e.g. 4) - if the numbers match (e.g. 4 == 4), then it removes that number from the array. Finally it returns that array.
I've implemented the method below which works sometimes, but not all the time and I'm not sure why?
For example, if I created a new array and printed each array:
ArrayList<Integer> omittedDigitArray = new ArrayList<Integer>(Omit.allIntegersWithout(20, 45, 3));
System.out.println("Array - Numbers with Omitted Digit:");
for (int n : omittedDigitArray) {
System.out.print(n + ", ");
}
The number 29 is omitted from the array? Could anyone tell me why please? Thanks!
// Creates the ArrayList
ArrayList<Integer> numberList = new ArrayList<Integer>();
// Loop creates an array of numbers starting at "from" ending at "to"
for (int i = from; i < to + 1; i++) {
numberList.add(i);
}
// Check the array to see whether number contains digit
// Code checks whether x contains 5, n == one digit
// IMPORTANT: Doesn't work on the first half of numbers i.e / will remove 3 but not 30
for (int j = 0; j < numberList.size(); j++) {
int number = (int) numberList.get(j); // This can be any integer
int thisNumber = number >= 0 ? number: -number; // if statement in case argument is negative
int thisDigit;
while (thisNumber != 0) {
thisDigit = thisNumber % 10; // Always equal to the last digit of thisNumber
thisNumber = thisNumber / 10; // Always equal to thisNumber with the last digit chopped off, or 0 if thisNumber is less than 10
if (thisDigit == omittedDigit) {
numberList.remove(j);
j--;
}
}
}
// Return the completed Array list
return numberList;
}
}
Your inner loop has a problem. Once you remove an element from the list, you should break from that loop. Otherwise you might remove unrelated additional numbers (if the omitted digit appears several times in the same number).
while (thisNumber != 0) {
thisDigit = thisNumber % 10; // Always equal to the last digit of thisNumber
thisNumber = thisNumber / 10; // Always equal to thisNumber with the last digit chopped off, or 0 if thisNumber is less than 10
if (thisDigit == omittedDigit) {
numberList.remove(j);
j--;
break; // add this
}
}
I ran your code (+ my suggested fix) with a range of 1 to 50 and omitted digit 4 and got :
[1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 50]
The problem in your code occurs when 44 is being processed - after you remove it (due to the first 4, you continue the while loop, find another 4 and remove another number, which happens to be 39, since the numbers 40 to 43 were already removed).
My suggested solution:
ArrayList<Integer> numberList = new ArrayList<Integer>();
// Loop creates an array of numbers starting at "from" ending at "to"
for (int i = from; i < to + 1; i++) {
numberList.add(i);
}
//removing all numbers that contain the digit
numberList.removeIf(j->containsDigit(j,thisDigit));
return numberList;
}
boolean containsDigit(int number,int thisDigit){
//making sure thisDigit is positive
thisDigit=Math.abs(thisDigit)
//if thisDigit is not a digit result is false
if(thisDigit>=10) return false;
//breaking the number into its digits
List<Integer> digits=new ArrayList<Integer>();
while(number>0){
digits.add(number%10);
number=(int) number/10;
}
return digits.contains(thisDigit);
}

Categories