permutations of certain digits in Java - java

I realize permutations in programming language is a very frequently asked question, however I feel like my question is sort of unique.
I have received input of a certain length integer N and stored each digit in an array where the index of the array stores the number of times that digit occurs in N.
now I want to test if some function holds true with all permutations of N's original length with no leading zeroes. Ex:
int[] digits = new int[10];
String n = "12345675533789025";
for (char c : n.toCharArray())
digits[c-'0']++;
for (Long f : allPermutationsOf(digits))
if (someCondition(f))
System.out.println(f);
a precondition to the following code is that N must be less than 2^64-1, (long's maximum value.)
The question is, how would I take all permutations of the digits array and return a Long[] or long[] without using some kind of String concatenation? Is there a way to return a long[] with all permutations of digits[] in the "Integer scope of things" or rather using only integer arithmetic?

To elaborate on one of the above comments, putting a digit d in a given place in the resulting long is easy: d*1 puts it in the 1s place, d*1000 puts it in the thousands place, and in general d * (10^k) puts d into the k+1th digit. You have N total digits to fill, so you need to do permutations on the powers of 10 from 1 to 10^(N-1).

If you are expecting the permutations to be Longs anyway, instead of representing n as an array of counts, it might be easier to represent it as a Long too.
Here are a couple of ways you can generate the permutations.
Think of generating permutations as finding the next largest number with the same set of digits, starting from the number consisting of the sorted digits of n. In this case, the answers to this StackOverflow question is helpful. You can use arithmetic operations and modding instead of string concatenation to implement the algorithm there (I can provide more details if you like). A benefit of this is that the permutations you generate will automatically be in order.
If you don't care about the order of the permutations and you expect the number of digit duplicates to be small, you can use the Steinhaus-Johnson-Trotter algorithm, which (according to Robert Sedgewick) is the fastest algorithm for generating permutations of unique elements. To make sure duplicate permutations are not generated, you would have to distinguish every duplicate digit and only emit the permutations where they appear in order (i.e., if 2 appears three times, then create the elements 2_1, 2_2, 2_3 and make sure those three elements always appear in that order in an emitted permutation).

For the requirement, assuming that the length of N is n, we can generate all permutations by going from digit to digit, starting from 0 and end at n - 1. With 0 is the leading digit.
For each digit, we only go through each possibility (0 to 9) once , which will avoid duplicate permutation.
From digit x to digit x + 1, we can easily generate the current value by passing a number called current
For example: at digit 3, we have current = 1234, so at digit 4, if we choose 5 to be at digit 4, the current will be 1234*10 + 5 = 12345
Sample code in Java:
public void generate(int index, int length, int[] digits, long current, ArrayList<Long> result) {
//All the permutation will be stored in result ArrayList
for (int i = 0; i < 10; i++) {
if (digits[i] > 0 && (i != 0 || index != 0)) {
digits[i]--;
if (index + 1 == length) {//If this is the last digit, add its value into result
result.add(current * 10 + i);
} else {//else, go to next digit
generate(index + 1, length, digits, current * 10 + i, result);
}
digits[i]++;
}
}
}

Related

find the maximum possible ones

I have a string of 0's and 1's
Now I want to change 0 to 1 only if adjacent elements for that 0 are not 1'string. Find the maximum ones possible after doing this operation.
Example:
110011000001 is the input string
Option 1:
I can change position 8 and position 10 from 0 to 1 to make the string: 110011010101, here there are 7 ones
Option 2:
Another way is to change position 9 from 0 to 1, to make the string: 110011001001, here there are 6 ones.
So the maximum between 6 and 7 is 7. So the result is 7.
Here is my code, I am able to find only one possible way here:
int process(String s) {
char[] ch = s.toCharArray();
int n = ch.length;
for(int i=1; i<n-1; i++) {
char e = ch[i];
if(e == '0' && ch[i-1] != '1' && ch[i+1] != '1') {
ch[i] = '1';
}
}
int count = 0;
for(char c : ch) {
if(c == '1') count++;
}
return count;
}
How to get the maximum possible ones here.
Notice that if the 0's are surrounded by 1's, you only need 2n + 1
adjacent 0's in order to add n 1's. In order to add one 1, you
need at least three 0's: 2*1+1=3. In order to add two 1's, you
need at least five 0's: 2*2+1=5. Since the number of 0's can be
described as, Z >= 2n + 1, we can instead solve for n. We get n <= (Z - 1) / 2. Thus, when surrounded by 1's, each group of 0's can
fit n=floor((Z-1)/2); we floor the value since we can't add half of a 1.
For groups of 0's only bounded by a 1 on a single side, we notice
that we need at least 2n 0's in order to add n 1's. Again, we
rearrange the equation Z >= 2n in order to get n <= Z / 2. Thus,
for groups bounded by a single 1, n=floor(Z/2).
For our last case, with a string of all 0's, we see that Z >= 2n - 1. So, n <= (Z + 1) / 2, or for our purposes floor((Z+1)/2).
Least common will be category 3. This will only happen if there are no 1's. If this is the case, you cannot have anything from category 1 or 2 -- so check this category first.
Second most common will be category 2. This happens when the beginning OR end of the string is a 0, but there are 1's elsewhere. Check this category second because you can fit more 1's with it than with the formula for the first case. Depending on your solution, you may have to keep track of the places you've already checked before moving on to using case 1 by using a substring of the original.
Most cases will land in category 1, since (in a random combination of 1's and 0's) most groups of 0's will be surrounded by 1's.
Your answer only checks the first case. Using these three cases together will give you the number of 1's that you can add to the string. Add this to the number of 1's you had originally and you'll have your answer.
Edited for clarity.
Count all existing ones as they are going to be a part of the answer.
To convert 0 to 1, count all zeroes between two ones.
If string is 100001, you have total 4 zeroes in between. Here let us leave boundary zeroes as we can't change them as they are adjacent to 1. So, now we are left with 2 zeroes in the middle out of which we can place only in 1 of them.
So count is just ceil(all valid zeroes / 2).
If you have a string like 00001, here you can place 2 ones excluding that boundary 0 adjacent to 1. So, count is ceil(3/2) which is 2. Your string would look like 10101.
Final answer is just step 1 + step 2.

How to generate quasi random numbers that don't immediately repeat (and more)?

I want to generate an endless series of quasi random numbers to the following specification:-
Source of numbers is uniformly distributed and random, ranging 0 through 255 inclusive. It's an existing hardware device.
Required output range is 1 through 8 inclusive.
Two consecutive output numbers are never the same. For example 5 will never follow 5, but you can have 5,2,5.
Exactly one output number is required for every single source number. Rejection sampling therefore cannot be used. And while() loops, shuffles etc. can't be used.
It's this last stipulation that's vexing me. The source generator can only supply random bytes at a constant 1 /s and I want output at a constant 1 /s. Typically you'd simply reject a generated number if it was equal to the previous one, and generate another. In my case you only get one shot at each output. I think that it's some sort of random selection process, but this requirement has me going around in circles as I'm a bad programmer. An algorithm, flowchart or picture will do, but I'll be implementing in Java.
Apologies for the semi generic title, but I couldn't really think of anything more accurate yet concise.
If I understand the problem correctly, the first random number will be chosen randomly from among 8 different numbers (1 to 8), while every successive random number will be chosen from 7 different possibilities (1 to 8 excluding the previous one). Thus, your range of 256 values will need to be divided into 7 possibilities. It won't come out even, but that's the best you can do. So you need something like
public class RandomClass {
public RandomClass(HardwareSource source) {
this.source = source;
first = true;
}
pubic int nextRandom() {
int sourceValue = source.read();
int value;
if (first) {
value = sourceValue % 8 + 1;
prev = value;
} else {
value = sourceValue % 7 + 1;
if (value >= prev) {
value++;
}
prev = value;
first = false;
return value;
}
}
Suppose the first call generates 5. The second time you call it, value is first computed to be a number from 1 to 7; by incrementing it if the value is >= 5, the range of possible outputs becomes 1, 2, 3, 4, 6, 7, 8. The output will be almost evenly distributed between those two values. Since 256 is not divisible by 7, the distribution isn't quite even, and there will be a slight bias toward the lower numbers. You could fix it so that the bias will shift on each call and even out over the entire sequence; I believe one way is
value = (sourceValue + countGenerated) % 7 + 1;
where you keep track of how many numbers you've generated.
I think this is better than solutions that take the input modulo 8 and add 1 if the number equals the previous one. Those solutions will generate prev + 1 with twice the probability of generating other numbers, so it's more skewed than necessary.
int sum=0;
int prev=-1;
int next(int input){
sum=(sum+input)%8;
if(sum==prev)sum=(sum+1)%8;
prev=sum;
return sum+1;
}
(As I interpret even with the new bold emphasis, it is not required to always generate the same output value for the same input value - that would make the task impossible to solve)

Counting isomorphic cyclic shifts in a string

I am trying to solve an algorithmic problem for which I have a O(n²) time, O(n) memory solution (see below) instead of a O(n) time and memory solution.
The problem is to count the number of isomorphic cyclic shifts for a given string s. A cyclic shift is a transformation of the initial string such as if 0 <= k < n (where n is the length of the string) :
cyclicShift(0) = s
cyclicShift(k) = s[k-1]...s[n-1]s[0]...s[k] if k > 0
A cyclic shift is said isomorphic if it is equal to the initial string. I have the feeling that a string can have such cycling shift iff it consists in the repetition of a pattern, but I cannot prove it. If it was the case, the problem would then become to find this pattern and then deduce the number of isomorphic cyclic shift, basing on the length of the pattern and the length of the string.
My current solution constructs all the cyclic shifts and compare them to the initial string, which is a O(n) operation in a loop bounded by n, leading to a complexity of O(n²). Here is my code in Java for reference :
public int solution(String S) {
int count = 1;
int n = S.length();
// We represent the string as a LinkedList to construct the next cyclic shift
// from a given one with a O(1) time complexity
List<Character> list = new LinkedList<>();
for (int i=0 ; i<n ; i++)
list.add(S.charAt(i));
Deque<Character> tmp = new LinkedList<>(list);
for (int k=1 ; k<n ; k++) {
tmp.addFirst(tmp.removeLast());
// this test is O(n) so this solution is O(n^2)
if (tmp.equals(list))
count++;
}
return count;
}
Do you have any idea of how I could solve this problem respecting the O(n) requirement ? Answers can be in Java, Scala, or pseudo-code.
I think you are quite right in that an isomorphic cyclic shift means that the string consists of a repeating pattern.
Consider the first k characters of the original string, by definition of the cyclic shift they are equal to the second k characters of the original string.
Now, consider the second k characters of the original string. These will be equal to the third k characters of the original string, and so on until you have shown that the string consists of a pattern of k characters that repeats n/k times.
Now the problem is to identify the string as a repeating pattern in O(n).
One way of doing this is to use the KMP failure function. The failure function tells you the longest proper prefix of a string that matches at position i. If you compute the value of the failure function at the end of the string it will tell you a number T which is the length of a proper prefix that matches the suffix of the string.
For example, consider the string ABCABCABC. The failure function will be:
-1 0 0 0 1 2 3 4 5 6
So the value at the end of the string is 6, and this tells us that the repeating pattern is of length p=n-T, in this case 9-6=3.
Once you have this length of the smallest repeating pattern, you can simply try all multiples and check that they divide the length of the string:
m=p
count=0
while(m<n)
if n%m==0: count+=1
m+=p
Overall this is O(n) in time and space.
I recently came accross a similar problem again, the only difference being that this time the fact that the string was made of a repeated pattern was explicitly specified instead of just deducible from the specification.
I implemented easily a Python function that finds the length of the smallest repeating pattern in the string. I add it here because if is far simpler that using KMP like suggested by Peter de Rivaz, however his answer also brings a proof that the existence of an isomorphic cyclic shift implies that the string is made of a repeated pattern and also the way to solve the problem once the smallest pattern was found.
Even if it is written in Python, I believe this code is fairly easy to understand :
def smallestPattern(s)
(count,res) = (0,1)
for i,ch in enumerate(s):
if ch != line[count]:
count = 0
res += 1
else:
count += 1
return res

Printing PowerSet with help of bit position

Googling around for a while to find subsets of a String, i read wikipedia and it mentions that
.....For the whole power set of S we get:
{ } = 000 (Binary) = 0 (Decimal)
{x} = 100 = 4
{y} = 010 = 2
{z} = 001 = 1
{x, y} = 110 = 6
{x, z} = 101 = 5
{y, z} = 011 = 3
{x, y, z} = 111 = 7
Is there a possible way to implement this through program and avoid recursive algorithm which uses string length?
What i understood so far is that, for a String of length n, we can run from 0 to 2^n - 1 and print characters for on bits.
What i couldn't get is how to map those on bits with the corresponding characters in the most optimized manner
PS : checked thread but couldnt understood this and c++ : Power set generated by bits
The idea is that a power set of a set of size n has exactly 2^n elements, exactly the same number as there are different binary numbers of length at most n.
Now all you have to do is create a mapping between the two and you don't need a recursive algorithm. Fortunately with binary numbers you have a real intuitive and natural mapping in that you just add a character at position j in the string to a subset if your loop variable has bit j set which you can easily do with getBit() I wrote there (you can inline it but for you I made a separate function for better readability).
P.S. As requested, more detailed explanation on the mapping:
If you have a recursive algorithm, your flow is given by how you traverse your data structure in the recursive calls. It is as such a very intuitive and natural way of solving many problems.
If you want to solve such a problem without recursion for whatever reason, for instance to use less time and memory, you have the difficult task of making this traversal explicit.
As we use a loop with a loop variable which assumes a certain set of values, we need to make sure to map each value of the loop variable, e.g. 42, to one element, in our case a subset of s, in a way that we have a bijective mapping, that is, we map to each subset exactly once. Because we have a set the order does not matter, so we just need whatever mapping that satisfies these requirements.
Now we look at a binary number, e.g. 42 = 32+8+2 and as such in binary with the position above:
543210
101010
We can thus map 42 to a subset as follows using the positions:
order the elements of the set s in any way you like but consistently (always the same in one program execution), we can in our case use the order in the string
add an element e_j if and only if the bit at position j is set (equal to 1).
As each number has at least one digit different from any other, we always get different subsets, and thus our mapping is injective (different input -> different output).
Our mapping is also valid, as the binary numbers we chose have at most the length equal to the size of our set so the bit positions can always be assigned to an element in the set. Combined with the fact that our set of inputs is chosen to have the same size (2^n) as the size of a power set, we can follow that it is in fact bijective.
import java.util.HashSet;
import java.util.Set;
public class PowerSet
{
static boolean getBit(int i, int pos) {return (i&1<<pos)>0;}
static Set<Set<Character>> powerSet(String s)
{
Set<Set<Character>> pow = new HashSet<>();
for(int i=0;i<(2<<s.length());i++)
{
Set<Character> subSet = new HashSet<>();
for(int j=0;j<s.length();j++)
{
if(getBit(i,j)) {subSet.add(s.charAt(j));}
}
pow.add(subSet);
}
return pow;
}
public static void main(String[] args)
{System.out.println(powerSet("xyz"));}
}
Here is easy way to do it (pseudo code) :-
for(int i=0;i<2^n;i++) {
char subset[];
int k = i;
int c = 0;
while(k>0) {
if(k%2==1) {
subset.add(string[c]);
}
k = k/2;
c++;
}
print subset;
}
Explanation :- The code divides number by 2 and calculates remainder which is used to convert number to binary form. Then as you know only selects index in string which has 1 at that bit number.

Turn ArrayList<Integer> into one number?

I am trying to figure out another way other than using String.valueOf() and then using Integer.parseInt()to turn an array of numbers into one type long number, not adding the values up, just like appending a String.
Example: Let's say you have an ArrayList<Integer> of 5 elements and
the numbers are (e = element) ->
e0(1), e1(4), e2(3), e3(6), e4(7)
So I want to turn this into one type long number -> 14367.
I need this to find a so called Miraculous number in java. I am to use lists, and print a miraculous number. (also any tips about that miraculous number?)
Think about this mathematically. What's the relationship between a series of digits and the number they collectively represent?
Each digit represents a power of ten. The last digit is the 100 place, the next is the 101 place, etc.
long number = 0;
for (int digit: digits) {
number *= 10;
number += digit;
}
I suggest understanding doing this by hand. When we write 12345, what does each digit represent? For example, what does the 4 mean?
This gets clever with the toString() representation of an array, but here goes:
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
String theNum = nums.toString().replaceAll("\\D","");
Long.parseLong(theNum);

Categories

Resources