I need to build each combination of length L from an String Array/ArrayList, where L is greater than the Array length
I currently have a recursive method (not of my own creation) that will generate each combination of a String[], as long as the combinations are shorter than the Array.
example/psudoCode:
input (2, {A,B,C})
returns {AA, AB, AC, BA, BC, CB, CA}
As of now, if the requested combination length (2 in the example) is greater than the Array length (4,5,6... instead of 2), the recursive method shoots out that sweet sweet ArrayIndexOutOfBounds error.
What I need is a method (recursive or not) that will return every combination of the array, regardless of whether the combinations are longer than the Array itself. Would this be done better by adding more letters to the Array and crossing my fingers or is there a legitimate way to accomplish this? Thank you!
Here is the method I have been using. If u know where the credit lies please say so, this is not of my own creation.
public class bizzBam
{
// Driver method to test below methods
public static void main(String[] args) {
System.out.println("First Test");
String set1[] = {"a", "b","c"};
printAllKLength(set1, pointX);
}
// The method that prints all possible strings of length k. It is
// mainly a wrapper over recursive function printAllKLengthRec()
static void printAllKLength(String set[], int k) {
int n = set.length+2;
printAllKLengthRec(set, "", n, k);
}
// The main recursive method to print all possible strings of length k
static void printAllKLengthRec(String set[], String prefix, int n, int length) {
// Base case: k is 0, print prefix
if (length == 0) {
System.out.println(prefix);
return;
}
// One by one add all characters from set and recursively
// call for k equals to k-1
for (int i = 0; i < n; ++i) {
// Next character of input added
String newPrefix = prefix + set[i];
// k is decreased, because we have added a new character
printAllKLengthRec(set, newPrefix, n, length - 1);
}
}
}
(Edit forgot to say:)
For this algorithim at least, if "PointX" is greater than the input array's length, it will return the indexoutofbounds.
Strictly speaking these are permutations rather than combinations. You're generating all permutations of k elements selected from a set of n candidates, with replacement (or repitition). There will be n^k such permutations.
Here's a non-recursive solution.
public class Permutations
{
public static void main(String[] args)
{
permutationsKN(new String[]{"a", "b", "c"}, 4);
}
static void permutationsKN(String[] arr, int k)
{
int n = arr.length;
int[] idx = new int[k];
String[] perm = new String[k];
while (true)
{
for(int i=0; i<k; i++) perm[i] = arr[idx[i]];
System.out.println(String.join("", perm));
// generate the next permutation
int i = idx.length - 1;
for (; i >= 0; i--)
{
idx[i]++;
if (idx[i] < n) break;
idx[i] = 0;
}
// if the first index wrapped around then we're done
if (i < 0) break;
}
}
}
You have two problems here:
int n = set.length+2; -> This is giving you your "sweet sweet" IndexArrayOutOfBoundsException. Change it to set.length-1. I am not sure why you decided to randomnly put +2 there.
for (int i = 0; i < n; ++i) -> You will be looping from 0 to n. You need to loop from 0 to n-1.
Edit: Or as #SirRaffleBuffle suggested, just do set.length. Total credits to him
Assuming your example is missing "BB" and "CC" because it includes "AA", it looks like what you want is just like the odometer of a car except that instead of ten digits, you want a choice of letters. It's not hard to model an odometer:
class Odo {
private final char [] chars;
private final int [] positions;
private boolean hasNext;
Oddo(String chars, int nPositions) {
this.chars = chars.toCharArray();
this.positions = new int [nPositions];
this.hasNext = true;
}
boolean hasNext() {
return hasNext;
}
String emitNext() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < positions.length; ++i) sb.append(chars[positions[i]]);
for (int i = 0; i < positions.length; ++i) {
if (++positions[i] < chars.length) {
hasNext = true;
return sb.toString();
}
positions[i] = 0;
}
hasNext = false;
return sb.toString();
}
}
Calling like so:
Odo odo = new Odo("AB", 3);
while (odo.hasNext()) {
System.out.println(odo.emitNext());
}
Produces
AAA
BAA
ABA
BBA
AAB
BAB
ABB
BBB
Related
I have the task of determining whether each value from 1, 2, 3... n is in an unordered int array. I'm not sure if this is the most efficient way to go about this, but I created an int[] called range that just has all the numbers from 1-n in order at range[i] (range[0]=1, range[1]=2, ect). Then I tried to use the containsAll method to check if my array of given numbers contains all of the numbers in the range array. However, when I test this it returns false. What's wrong with my code, and what would be a more efficient way to solve this problem?
public static boolean hasRange(int [] givenNums, int[] range) {
boolean result = true;
int n = range.length;
for (int i = 1; i <= n; i++) {
if (Arrays.asList(givenNums).containsAll(Arrays.asList(range)) == false) {
result = false;
}
}
return result;
}
(I'm pretty sure I'm supposed to do this manually rather than using the containsAll method, so if anyone knows how to solve it that way it would be especially helpful!)
Here's where this method is implicated for anyone who is curious:
public static void checkMatrix(int[][] intMatrix) {
File numberFile = new File("valid3x3") ;
intMatrix= readMatrix(numberFile);
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
int[] range = new int[nSquared];
int valCount = 0;
for (int i = 0; i<sideLength; i++) {
for (int j=0; j<sideLength; j++) {
values[valCount] = intMatrix[i][j];
valCount++;
}
}
for (int i=0; i<range.length; i++) {
range[i] = i+1;
}
Boolean valuesThere = hasRange(values, range);
valuesThere is false when printed.
First style:
if (condition == false) // Works, but at the end you have if (true == false) or such
if (!condition) // Better: not condition
// Do proper usage, if you have a parameter, do not read it in the method.
File numberFile = new File("valid3x3") ;
intMatrix = readMatrix(numberFile);
checkMatrix(intMatrix);
public static void checkMatrix(int[][] intMatrix) {
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
Then the problem. It is laudable to see that a List or even better a Set approach is the exact abstraction level: going into detail not sensible. Here however just that is wanted.
To know whether every element in a range [1, ..., n] is present.
You could walk through the given numbers,
and for every number look whether it new in the range, mark it as no longer new,
and if n new numbers are reached: return true.
int newRangeNumbers = 0;
boolean[] foundRangeNumbers = new boolean[n]; // Automatically false
Think of better names.
You say you have a one dimensional array right?
Good. Then I think you are thinking to complicated.
I try to explain you another way to check if all numbers in an array are in number order.
For instance you have the array with following values:
int[] array = {9,4,6,7,8,1,2,3,5,8};
First of all you can order the Array simpel with
Arrays.sort(array);
After you've done this you can loop through the array and compare with the index like (in a method):
for(int i = array[0];i < array.length; i++){
if(array[i] != i) return false;
One way to solve this is to first sort the unsorted int array like you said then run a binary search to look for all values from 1...n. Sorry I'm not familiar with Java so I wrote in pseudocode. Instead of a linear search which takes O(N), binary search runs in O(logN) so is much quicker. But precondition is the array you are searching through must be sorted.
//pseudocode
int range[N] = {1...n};
cnt = 0;
while(i<-inputStream)
int unsortedArray[cnt]=i
cnt++;
sort(unsortedArray);
for(i from 0 to N-1)
{
bool res = binarySearch(unsortedArray, range[i]);
if(!res)
return false;
}
return true;
What I comprehended from your description is that the array is not necessarily sorted (in order). So, we can try using linear search method.
public static void main(String[] args){
boolean result = true;
int[] range <- Contains all the numbers
int[] givenNums <- Contains the numbers to check
for(int i=0; i<givenNums.length; i++){
if(!has(range, givenNums[i])){
result = false;
break;
}
}
System.out.println(result==false?"All elements do not exist":"All elements exist");
}
private static boolean has(int[] range, int n){
//we do linear search here
for(int i:range){
if(i == n)
return true;
}
return false;
}
This code displays whether all the elements in array givenNums exist in the array range.
Arrays.asList(givenNums).
This does not do what you think. It returns a List<int[]> with a single element, it does not box the values in givenNums to Integer and return a List<Integer>. This explains why your approach does not work.
Using Java 8 streams, assuming you don't want to permanently sort givens. Eliminate the copyOf() if you don't care:
int[] sorted = Arrays.copyOf(givens,givens.length);
Arrays.sort(sorted);
boolean result = Arrays.stream(range).allMatch(t -> Arrays.binarySearch(sorted, t) >= 0);
public static boolean hasRange(int [] givenNums, int[] range) {
Set result = new HashSet();
for (int givenNum : givenNums) {
result.add(givenNum);
}
for (int num : range) {
result.add(num);
}
return result.size() == givenNums.length;
}
The problem with your code is that the function hasRange takes two primitive int array and when you pass primitive int array to Arrays.asList it will return a List containing a single element of type int[]. In this containsAll will not check actual elements rather it will compare primitive array object references.
Solution is either you create an Integer[] and then use Arrays.asList or if that's not possible then convert the int[] to Integer[].
public static boolean hasRange(Integer[] givenNums, Integer[] range) {
return Arrays.asList(givenNums).containsAll(Arrays.asList(range));
}
Check here for sample code and output.
If you are using ApacheCommonsLang library you can directly convert int[] to Integer[].
Integer[] newRangeArray = ArrayUtils.toObject(range);
A mathematical approach: if you know the max value (or search the max value) check the sum. Because the sum for the numbers 1,2,3,...,n is always equal to n*(n+1)/2. So if the sum is equal to that expression all values are in your array and if not some values are missing. Example
public class NewClass12 {
static int [] arr = {1,5,2,3,4,7,9,8};
public static void main(String [] args){
System.out.println(containsAllValues(arr, highestValue(arr)));
}
public static boolean containsAllValues(int[] arr, int n){
int sum = 0;
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == n*(n+1)/2);
}
public static int highestValue(int[]arr){
int highest = arr[0];
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
return highest;
}
}
according to this your method could look like this
public static boolen hasRange (int [] arr){
int highest = arr[0];
int sum = 0;
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == highest *(highest +1)/2);
}
Suppose we have an alphabet "abcdefghiklimnop". How can I recursively generate permutations with repetition of this alphabet in groups of FIVE in an efficient way?
I have been struggling with this a few days now. Any feedback would be helpful.
Essentially this is the same as: Generating all permutations of a given string
However, I just want the permutations in lengths of FIVE of the entire string. And I have not been able to figure this out.
SO for all substrings of length 5 of "abcdefghiklimnop", find the permutations of the substring. For example, if the substring was abcdef, I would want all of the permutations of that, or if the substring was defli, I would want all of the permutations of that substring. The code below gives me all permutations of a string but I would like to use to find all permutations of all substrings of size 5 of a string.
public static void permutation(String str) {
permutation("", str);
}
private static void permutation(String prefix, String str) {
int n = str.length();
if (n == 0) System.out.println(prefix);
else {
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n));
}
}
In order to pick five characters from a string recursively, follow a simple algorithm:
Your method should get a portion filled in so far, and the first position in the five-character permutation that needs a character
If the first position that needs a character is above five, you are done; print the combination that you have so far, and return
Otherwise, put each character into the current position in the permutation, and make a recursive call
This is a lot shorter in Java:
private static void permutation(char[] perm, int pos, String str) {
if (pos == perm.length) {
System.out.println(new String(perm));
} else {
for (int i = 0 ; i < str.length() ; i++) {
perm[pos] = str.charAt(i);
permutation(perm, pos+1, str);
}
}
}
The caller controls the desired length of permutation by changing the number of elements in perm:
char[] perm = new char[5];
permutation(perm, 0, "abcdefghiklimnop");
Demo.
All permutations of five characters will be contained in the set of the first five characters of every permutation. For example, if you want all two character permutations of a four character string 'abcd' you can obtain them from all permutations:
'abcd', 'abdc', 'acbd','acdb' ... 'dcba'
So instead of printing them in your method you can store them to a list after checking to see if that permutation is already stored. The list can either be passed in to the function or a static field, depending on your specification.
class StringPermutationOfKLength
{
// The main recursive method
// to print all possible
// strings of length k
static void printAllKLengthRec(char[] set,String prefix,
int n, int k)
{
// Base case: k is 0,
// print prefix
if (k == 0)
{
System.out.println(prefix);
return;
}
// One by one add all characters
// from set and recursively
// call for k equals to k-1
for (int i = 0; i < n; i++)
{
// Next character of input added
String newPrefix = prefix + set[i];
// k is decreased, because
// we have added a new character
printAllKLengthRec(set, newPrefix,
n, k - 1);
}
}
// Driver Code
public static void main(String[] args)
{
System.out.println("First Test");
char[] set1 = {'a', 'b','c', 'd'};
int k = 2;
printAllKLengthRec(set1, "", set1.length, k);
System.out.println("\nSecond Test");
char[] set2 = {'a', 'b', 'c', 'd'};
k = 1;
printAllKLengthRec(set2, "", set2.length, k);
}
This is can be easily done using bit manipulation.
private void getPermutation(String str, int length)
{
if(str==null)
return;
Set<String> StrList = new HashSet<String>();
StringBuilder strB= new StringBuilder();
for(int i = 0;i < (1 << str.length()); ++i)
{
strB.setLength(0); //clear the StringBuilder
if(getNumberOfOnes(i)==length){
for(int j = 0;j < str.length() ;++j){
if((i & (1 << j))>0){ // to check whether jth bit is set (is 1 or not)
strB.append(str.charAt(j));
}
}
StrList.add(strB.toString());
}
}
System.out.println(Arrays.toString(StrList.toArray()));
}
private int getNumberOfOnes (int n) // to count how many numbers of 1 in binary representation of n
{
int count=0;
while( n>0 )
{
n = n&(n-1);
count++;
}
return count;
}
I want to exhaustively test a String matching algorithm, named myAlgo(Char[] a, Char[] b)
The exhaustive test includes a no. of different char letters, alplhabet " l ", in an "n" long array. The test then computes all combinations, while comparing it with all combinations of another array with similar properties (Like truth tables),e.g.
I have not been able to either compute something that would generate every combination of the array of size n and alphabet l, niether have I been able to make code that is able to combine the computation into iterative testcases (test all the combinations of the two arrays compared), though with code that would be able to generate the combinations, making a nested for-loop should do the required testing.
My goal is to break my algorithm by making it compute something it should not compute.
Test(char[] l, int n)
l = [a;b] //a case could be
n = 2 //a case could be
myAlgo([a;a],[a;a]); //loops over my algorithm in the following way
myAlgo([a;b],[a;a]);
myAlgo([b;a],[a;a]);
myAlgo([b;b],[a;a]);
myAlgo([a;a],[a;b]);
myAlgo([a;b],[a;b]);
myAlgo([b;a],[a;b]);
myAlgo([b;b],[a;b]);
myAlgo([a;a],[b;a]);
myAlgo([a;b],[b;a]);
...
myAlgo([b;b],[b;b]);
My own solution (only works for a finite set of "l") and also starts printing wierd outputs on later iterations.
public class Test {
//aux function to format chars
public static String concatChar(char [] c){
String s = "";
for(char cc : c){
s += cc;
}
return s;
}
public static void main(String[] args) {
String ss1 = "AA"; //TestCases, n = 2
String ss2 = "AA";
char[] test1 = ss1.toCharArray();
char[] test2 = ss2.toCharArray();
Fordi fordi = new Fordi(); //my algorithm
TestGenerator tGen = new TestGenerator(); //my testGenerator
for(int i=0; i<Math.pow(4.0, 2.0);i++){ //to test all different cases
for(int j=0; j<Math.pow(4.0, 2.0);j++){
int k = fordi.calculate(test1, test2); //my algorithm
String mys1 = concatChar(test1); //to print result
String mys2 = concatChar(test2); //to print result
System.out.println(mys1 + " - " + mys2);
System.out.println(k);
test2 = tGen.countArray(test2); //"flip" one number
}
test2 = ss1.toCharArray();
test1 = tGen.countArray(test1); //"flip"
}
}
}
My arrayflipper code:
public char[] countArray(char[] a){
int i=0;
while(i<a.length){
switch (a[i]){
case 'A':
a[i]='B';
clearBottom(a,i);
return a;
case 'B':
a[i]='C';
clearBottom(a,i);
return a;
case 'C':
a[i]='D';
clearBottom(a,i);
return a;
case 'D':
i++;
break;
default:
System.out.println("Something went terribly wrong!");
}
}
return a;
}
public char[] clearBottom(char [] a, int i){
while(i >0){
i--;
a[i] = 'A';
}
return a;
}
As I understand it, your goal is to create all n-character long strings (stored individually as elements in an array) consisting of letters in the L letter alphabet?
One way to accomplish this is to order your letters (A=0, B=1, C=2, etc). Then you can, from a starting string of AAA...AAA (n-characters long) just keep adding 1. Essentially you implement an addition algorithm. Adding 1 would turn an A=0 into a B=1. For example, n=3 and L=3:
start: AAA (0,0,0).
Adding 1 becomes AAB (0,0,1)
Adding 1 again become AAC (0, 0, 2)
Adding 1 again (since we are out of letters, now we carry a bit over) ABA (0, 1, 0).
You can boil the process down to looking for the right-most number that is not maxed out and add 1 to it (then all digits to the right of that digit go back to zero). So in the string ABCCC, the B digit is the right-most not maxed out digit, it goes up by 1 and becomes a C, then all the maxed out digits to the right go back to 0 (A) leaving ACAAA as the next string.
Your algorithm just repeatedly adds 1 until all the elements in the string are maxed out.
Instead of using a switch statement, I recommend putting every character you want to test (A, B, C, D) into an array, and then using the XOR operation to calculate the index of each character from the iteration number in a manner similar to the following:
char[] l = new char[]{'A','B','C','D'};
int n = 2;
char[] test1 = new char[n];
char[] test2 = new char[n];
int max = (int)Math.pow(l.length, n);
for (int i = 0; i < max; i++) {
for (int k = 0; k < n; k++) {
test2[k] = l[(i % (int)Math.pow(l.length, k + 1)) / (int)Math.pow(l.length, k)];
}
for (int j = 0; j < max; j++) {
for (int k = 0; k < n; k++) {
test1[k] = l[(j % (int)Math.pow(l.length, k + 1)) / (int)Math.pow(l.length, k)];
}
int k = fordi.calculate(test1, test2);
System.out.println(new String(test1) + "-" + new String(test2));
System.out.println(k);
}
}
You can add more characters to l as well as increase n and it should still work. Of course, this can be further optimized, but you should get the idea. Hope this answer helps!
I have some strings.
1
2
3
How do I combine them into all their unique combinations?
123
132
213
231
312
321
Here is the code I have, but I would like to work without the Random class because I understand that this is not the best way to do it.
import java.util.Random;
public class Solution
{
public static void main(String[] args)
{
String[] names = new String[]{"string1", "string2", "string3"};
for (int i = 0; i < 9; i++) {
Random rand = new Random();
int rand1 = rand.nextInt(3);
System.out.println(names[rand.nextInt(3)] +
names[rand1] +
names[rand.nextInt(3)]);
}
}
}
You can loop over the array by creating another nested loop for each repetition.
for (String word1 : words) {
for (String word2 : words) {
for (String word3 : words) {
System.out.println(word1 + word2 + word3);
}
}
}
Here is how to avoid having the same word in one combination.
for (String word1 : words) {
for (String word2 : words) {
if ( !word1.equals(word2)) {
for (String word3 : words) {
if ( !word3.equals(word2) && !word3.equals(word1)) {
System.out.println(word1 + word2 + word3);
}
}
}
}
}
Here is a class version that is capable of multiple lengths, using backtracking.
import java.util.ArrayList;
import java.util.List;
public class PrintAllCombinations {
public void printAllCombinations() {
for (String combination : allCombinations(new String[] { "A", "B", "C" })) {
System.out.println(combination);
}
}
private List<String> allCombinations(final String[] values) {
return allCombinationsRecursive(values, 0, values.length - 1);
}
private List<String> allCombinationsRecursive(String[] values, final int i, final int n) {
List<String> result = new ArrayList<String>();
if (i == n) {
StringBuilder combinedString = new StringBuilder();
for (String value : values) {
combinedString.append(value);
}
result.add(combinedString.toString());
}
for (int j = i; j <= n; j++) {
values = swap(values, i, j);
result.addAll(allCombinationsRecursive(values, i + 1, n));
values = swap(values, i, j); // backtrack
}
return result;
}
private String[] swap(final String[] values, final int i, final int j) {
String tmp = values[i];
values[i] = values[j];
values[j] = tmp;
return values;
}
}
Please note that using the random method, it is never guaranteed that all combinations are being get. Therefore, it should always loop over all values.
You could use the Google Guava library to get all string permutations.
Collection<List<String>> permutations = Collections2.permutations(Lists.newArrayList("string1", "string2", "string3"));
for (List<String> permutation : permutations) {
String permutationString = Joiner.on("").join(permutation);
System.out.println(permutationString);
}
Output:
string1string2string3
string1string3string2
string3string1string2
string3string2string1
string2string3string1
string2string1string3
Firstly, there is nothing random in the result you are after - and Random.nextInt() will not give you unique permutations, or necessarily all permutations.
For N elements, there are N! (N-factorial) unique sequences - which I believe is what you are after. Therefore your three elements give six unique sequences (3! = 3 * 2 * 1).
This is because you have a choice of three elements for the first position (N), then a choice of the two remaining elements for the second position (N-1), leaving one unchosen element for the last position (N-2).
So, this means that you should be able to iterate over all permutations of the sequence; and the following code should do this for a sequence of 3 elements:
// Select element for first position in sequence...
for (int i = 0 ; i < 3 ; ++i)
{
// Select element for second position in sequence...
for (int j = 0 ; j < 3 ; ++j)
{
// step over indices already used - which means we
// must test the boundary condition again...
if (j >= i) ++j;
if (j >= 3) continue;
// Select element for third position in sequence...
// (there is only one choice!)
for (int k = 0 ; k < 3 ; ++k)
{
// step over indices already used, recheck boundary
// condition...
if (k >= i) ++k;
if (k >= j) ++k;
if (k >= 3) continue;
// Finally, i,j,k should be the next unique permutation...
doSomethingWith (i, j, k);
}
}
}
Now, big caveat that I have just written this OTH, so no guarentees. However, hopefully you can see what you need to do. Of course, this could and should be generalised to support arbitary set sizes, in which case you could populate an int[] with the indices for the sequence.
However, I guess that if you look around there will be some better algorithms for generating permutations of a sequence.
There are some similar questions on the site that have been of some help, but I can't quite nail down this problem, so I hope this is not repetitive.
This is a homework assignment where you have a set array of characters [A, B, C], and must use recursion to get all permutations (with repetition). The code I have sort of does this:
char[] c = {'A', 'B' , 'C'};
public void printAll(char[] c, int n, int k) {
if (k == n) {
System.out.print(c);
return;
}
else {
for (int j = 0; j<n; j++) {
for (int m = 0; m<n; m++) {
System.out.print(c[k]);
System.out.print(c[j]);
System.out.print(c[m] + "\r\n");
}
}
}
printAll(c, n, k+1);
}
However, the parameter n should define the length of the output, so while this function prints out all permutations of length 3, it cannot do them of length 2. I have tried everything I can think of, and have pored over Google search results, and I am aggravated with myself for not being able to solve what seems to be a rather simple problem.
If I understand correctly, you are given a set of characters c and the desired length n.
Technically, there's no such thing as a permutation with repetition. I assume you want all strings of length n with letters from c.
You can do it this way:
to generate all strings of length N with letters from C
-generate all strings of length N with letters from C
that start with the empty string.
to generate all strings of length N with letters from C
that start with a string S
-if the length of S is N
-print S
-else for each c in C
-generate all strings of length N with letters from C that start with S+c
In code:
printAll(char[] c, int n, String start){
if(start.length >= n){
System.out.println(start)
}else{
for(char x in c){ // not a valid syntax in Java
printAll(c, n, start+x);
}
}
}
I use this java realization of permutations with repetitions. A~(n,m): n = length of array, m = k. m can be greater or lesser then n.
public class Permutations {
static void permute(Object[] a, int k, PermuteCallback callback) {
int n = a.length;
int[] indexes = new int[k];
int total = (int) Math.pow(n, k);
Object[] snapshot = new Object[k];
while (total-- > 0) {
for (int i = 0; i < k; i++){
snapshot[i] = a[indexes[i]];
}
callback.handle(snapshot);
for (int i = 0; i < k; i++) {
if (indexes[i] >= n - 1) {
indexes[i] = 0;
} else {
indexes[i]++;
break;
}
}
}
}
public static interface PermuteCallback{
public void handle(Object[] snapshot);
};
public static void main(String[] args) {
Object[] chars = { 'a', 'b', 'c', 'd' };
PermuteCallback callback = new PermuteCallback() {
#Override
public void handle(Object[] snapshot) {
for(int i = 0; i < snapshot.length; i ++){
System.out.print(snapshot[i]);
}
System.out.println();
}
};
permute(chars, 8, callback);
}
}
Example output is
aaaaaaaa
baaaaaaa
caaaaaaa
daaaaaaa
abaaaaaa
bbaaaaaa
...
bcdddddd
ccdddddd
dcdddddd
addddddd
bddddddd
cddddddd
dddddddd
I just had an idea. What if you added a hidden character (H for hidden) [A, B, C, H], then did all the fixed length permutations of it (you said you know how to do that). Then when you read it off, you stop at the hidden character, e.g. [B,A,H,C] would become (B,A).
Hmm, the downside is that you would have to track which ones you created though [B,H,A,C] is the same as [B,H,C,A]
Here is c# version to generate the permutations of given string with repetitions:
(essential idea is - number of permutations of string of length 'n' with repetitions is n^n).
string[] GetPermutationsWithRepetition(string s)
{
s.ThrowIfNullOrWhiteSpace("s");
List<string> permutations = new List<string>();
this.GetPermutationsWithRepetitionRecursive(s, "",
permutations);
return permutations.ToArray();
}
void GetPermutationsWithRepetitionRecursive(string s, string permutation, List<string> permutations)
{
if(permutation.Length == s.Length)
{
permutations.Add(permutation);
return;
}
for(int i =0;i<s.Length;i++)
{
this.GetPermutationsWithRepetitionRecursive(s, permutation + s[i], permutations);
}
}
Below are the corresponding unit tests:
[TestMethod]
public void PermutationsWithRepetitionTests()
{
string s = "";
int[] output = { 1, 4, 27, 256, 3125 };
for(int i = 1; i<=5;i++)
{
s += i;
var p = this.GetPermutationsWithRepetition(s);
Assert.AreEqual(output[i - 1], p.Length);
}
}