Mix multiple strings into all the possible combinations - java

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.

Related

Generate all possible combinations longer than the length of an array

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

Generating all permutations of a certain length

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;
}

Java - Finding all subsets of a String (powerset) recursively

So, I need to find all subsets of a given string recursively. What I have so far is:
static ArrayList<String> powerSet(String s){
ArrayList<String> ps = new ArrayList<String>();
ps.add(s);
for(int i=0; i<s.length(); i++){
String temp = s.replace(Character.toString(s.charAt(i)), "");
ArrayList<String> ps2 = powerSet(temp);
for(int j = 0; j < ps2.size(); j++){
ps.add(ps2.get(j));
}
}
return ps;
I think I know what the problem is now, but I dont know how to fix it. Currently, I find all the power sets of temp, which are "bcd", "acd", "abd", "abc", which will cause duplicates. Any ideas on how to fix this?
By powerset, I mean if the string is abc, it will return "", "a", "b", "c", "ab", "ac", "bc", "abc".
The number of subsets of a set with n elements is 2n. If we have, for example, the string "abc", we will have 2n = 23 = 8 subsets.
The number of states that can be represented by n bits is also 2n. We can show there is a correspondence between enumerating all possible states for n bits and all possible subsets for a set with n elements:
2 1 0 2 1 0
c b a bits
0 0 0 0
1 a 0 0 1
2 b 0 1 0
3 b a 0 1 1
4 c 1 0 0
5 c a 1 0 1
6 c b 1 1 0
7 c b a 1 1 1
If we consider line 5, for example, bits 2 and 0 are active. If we do abc.charAt(0) + abc.charAt(2) we get the subset ac.
To enumerate all possible states for n bits we start at 0, and sum one until we reach 2n - 1. In this solution we will start at 2n - 1 and decrement until 0, so we don't need another parameter just to keep the number of subsets, but the effect is the same:
static List<String> powerSet(String s) {
// the number of subsets is 2^n
long numSubsets = 1L << s.length();
return powerSet(s, numSubsets - 1);
}
static List<String> powerSet(String s, long active) {
if (active < 0) {
// Recursion base case
// All 2^n subsets were visited, stop here and return a new list
return new ArrayList<>();
}
StringBuilder subset = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
// For each bit
if (isSet(active, i)) {
// If the bit is set, add the correspondent char to this subset
subset.append(s.charAt(i));
}
}
// Make the recursive call, decrementing active to the next state,
// and get the returning list
List<String> subsets = powerSet(s, active - 1);
// Add this subset to the list of subsets
subsets.add(subset.toString());
return subsets;
}
static boolean isSet(long bits, int i) {
// return true if the ith bit is set
return (bits & (1L << i)) != 0;
}
Then you just need to call it:
System.out.println(powerSet("abc"));
And get all 8 subsets:
[, a, b, ab, c, ac, bc, abc]
There is a way to do this without using recursion, it relies on a simple correspondence between bit strings and subsets.
So, assume you have a three character string "abc", then, as you noted, the subsets would be "", "c", "b", "bc", "a", "ac", "ab", "abc"
If you make a table of the characters and write a 1 for every character that is in the subset and 0 for not in the subset, you can see a pattern:
a b c bits decimal
0 0 0 0
c 0 0 1 1
b 0 1 0 2
b c 0 1 1 3
a 1 0 0 4
a c 1 0 1 5
a b 1 1 0 6
a b c 1 1 1 7
For each length-n string of unique characters, you will have 2n subsets, and you can generate them all by simply making one for loop from i=0 to i=2n-1, and includes only those characters corresponding to the bits in i that are 1.
I wrote a Java example here and a C example here.
I find it helpful to think of the simple corner cases first when designing a recursive algorithm, i.e. the empty string and the string with one character. Then you usually split the problem and make the recursive call on the rest/ tail of the string. Somewhat like this:
static List<String> nuPowerSet(String s) {
if (s.length() == 0) { // trivial, subset of empty string is empty
return emptyList();
}
String head = s.substring(0, 1);
if (s.length() ==1) // the subset of a one character string is exactly that character
return asList(head);
String tail = s.substring(1);
ArrayList<String> ps = new ArrayList<String>();
ps.add(head); // one of the subsets is the current first character
List<String> tailSubsets = nuPowerSet(tail); // all the subsets of the remainder.
List<String> tailSubsetsWithCurrentHeadPrepended = tailSubsets
.stream()
.map(element -> head + element)
.collect(Collectors.toList());
ps.addAll(tailSubsets);
ps.addAll(tailSubsetsWithCurrentHeadPrepended);
return ps;
}
to eliminate duplicate, you just need to add all of them into a Set, this can be done easily with some sort of helper:
static ArrayList<String> powerSet(String s) {
return new ArrayList<>(_powerSet(s));
}
static HashSet<String> _powerSet(String s) {
HashSet<String> set = new HashSet<>();
set.add(s);
for(int i = 0; i < s.length(); i++) {
String tmp = s.substring(0, i) + s.substring(i+1, s.length());
set.addAll(_powerSet(tmp));
}
return set;
}
btw, your code has dealt with edge cases by nature. you don't need to worry about this.
You're right, you do have duplicates because you're creating temp multiple times (each time without another character) so when you're calling recursively there will be different subsets that will share the same characters and create the dup. For example, "abc" will create a temp with: ["ab", "ac", "bc"] and each one of them will call recursively with only one character so you'll get each one of "a", "b" and "c" twice.
One way to avoid it (with minimal changes) would be to use a Set instead of a list - which will omit all the dups:
static Set<String> powerSet(String s) {
Set<String> ps = new HashSet<>();
ps.add(s);
for (int i = 0; i < s.length(); i++) {
String temp = s.replace(Character.toString(s.charAt(i)), "");
Set<String> ps2 = powerSet(temp);
for (String x : ps2) {
ps.add(x);
}
}
return ps;
}
Now the output will be:
bc
a
ab
b
ac
abc
c
A different solution:
public static List<String> powerset(String s) {
List<String> ans = new LinkedList<>();
if (null == s) {
return ans;
}
return powerset(s, ans);
}
private static List<String> powerset(String s, List<String> ans) {
if ("".equals(s)) {
return ans;
}
String first = s.substring(0, 1);
String rest = s.substring(1);
ans.add(first);
List<String> pAns = new LinkedList<>(ans);
for (String partial : ans.subList(0, ans.size()-1)) {
pAns.add(partial + first);
}
return powerset(rest, pAns);
}
OUTPUT
[a, b, ab, c, ac, bc, abc]
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MainClass {
static List<List<char[]>> list = new ArrayList<List<char[]>>();
// static List<int[]> list1 = new ArrayList<int[]>();
public static void main(String[] args) {
List<char[]> list1 = new ArrayList<char[]>();
String string = "abcd";
char[] a = string.toCharArray();
generate(a, 0, 0, list1);
for (List<char[]> l : list) {
for (char[] b : l) {
for (char c : b) {
System.out.print(c + ",");
}
System.out.println();
}
}
}
public static void generate(char[] array, int offset, int index, List<char[]> list1) {
if (offset >= array.length)
return;
char[] newArray = Arrays.copyOfRange(array, offset, index);
list1.add(newArray);
if (index >= array.length) {
list.add(list1);
offset++;
index = offset;
generate(array, offset, index, new ArrayList<char[]>());
} else {
index++;
generate(array, offset, index, list1);
}
}
}

corresponding permutation number

I have a given word, for wich I need to find its number of permutation on its corresponding sorted word .
Say I have word BABA , its corresponding sorted word would be, AABB, if I start permuting this sorted word, would come to AABB as a second "word", regardless of letter repetition, then ABAB, ABBA , BABA .. so the permute number for word BABA is 5 .
The easy way would be start doing all possible combinations, and then compared with the initial word .
so far , ive done..
import java.util.Arrays;
public class Permutation {
int location =1;
public static char[] warray;
void printArray(char []a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
System.out.println("location " + location );
}
void permute(char []a,int k ) {
if(k==a.length) {
location++;
// Check if the permuted word is the one looking for.
if (Arrays.equals(a, warray))
{ System.out.println("final iteration k" + k);
printArray(a);
System.exit(0);}
}
else
for (int i = k; i < a.length; i++) {
char temp=a[k];
a[k]=a[i];
a[i]=temp;
permute(a,k+1);
}
}
public static void main(String[] args) {
if (args[0].length() > 25 ) {
System.out.println(" Word not in permited range " );
System.exit(0);
}
else {
Permutation p=new Permutation();
warray = new char[args[0].length()];
char [] wpermute = new char[args[0].length()];
for (int i = 0; i < args[0].length(); i++) {
warray[i] = new Character(args[0].charAt(i));
wpermute[i] = new Character(args[0].charAt(i));
}
Arrays.sort(wpermute);
System.out.print("sorted word : " );
for (int i = 0; i < wpermute.length; i++) {
System.out.print(wpermute[i]);
}
p.permute(wpermute,0);
}
}
But this could be very slow performance.
My second guess, would be , starting like a binary search startting with first letter of unsorted word, calculate possibble permutations to have this letter as the first letter on permutations, and then second letter..and so ... would that sound good ?
If you only have 2 letters and if the length of the word is N and the number of A's is n then the number of permutations is N choose n.
If you have N letters total and n_a, n_b, ..., n_z describe the number of each letter then the total number of permutations is
N!/(n_a! n_b! n_c! ... n_z!)
Check out Multinomials, scroll down to the bit on permutations.
Another word would be QUESTION , its sorted word is EINOQSTU .
for question , q is in position 1 , and in postion 5 in the new word, how many permutations need to do to put is in postion 1 = 20161 .
Now I take second letter in question, is U, which is in position 8 in sorted word , how many permutations need to do, is 24481
I think, I could calculate , not perform, the number permutations needed to put a letter in y position, to be in X position. and then , the sum of all , would be the permutations needed for the whold word.
Now, how to calculate those numbers, I know has to be with factorial plus something else ..is not ?
So I finally completed the code, and yes, needed to check the multinomials.
also got part of the idea from a related post here.
But here my code.
package WordPuzzle;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/** Rafael G. */
public class WordPuzzle {
static String sortWord (String[] wordinput){
char [] wsorted = new char[wordinput[0].length()];
wsorted = wordinput[0].toCharArray();
Arrays.sort(wsorted);
String aux="";
for (int i = 0; i < wsorted.length; i++) {
aux = aux + wsorted[i];
}
return aux;
}
static void calculatePerm(String wordtofind,String wordsorted)
{
int sum = 0;
int numberpermutations;
char nextchar;
int charlocremainder =0;
String lowerLetters;
String greaterLetters;
Map<Character, Integer> characterCounts = new HashMap<Character, Integer> ();
int count ;
char letter;
int factorial;
int [] factorials = new int [wordsorted.length()+1];
factorial =1;
numberpermutations = 1;
int nMinusI;
int nextcharcount;
// set a mapping of repeated letters and its number
// and store factorial calculation.
for (int i = 0; i < wordsorted.length(); i++) {
letter = wordsorted.charAt(i);
factorial = factorial * (i+1);
factorials[i+1]= factorial;
count = characterCounts.containsKey(letter) ? characterCounts.get(letter) + 1 : 1;
characterCounts.put(letter, count);
}
String trimWord = new String(wordsorted);
for (int i = 0; i < wordtofind.length() ; i++){
nMinusI = wordtofind.length()-(i+1);
nextchar = wordtofind.charAt(i);
charlocremainder = trimWord.indexOf(nextchar);
lowerLetters = trimWord.substring(0, charlocremainder);
// Calculate the denominator which is the number of repeated letters
// of the formula (N-i)! * (Na+Nb) /Na!Nb!..
nextcharcount = characterCounts.get(nextchar);
characterCounts.put(nextchar, nextcharcount-1);
int denomfact = factorials[nextcharcount];
if (lowerLetters.length() > 1){
char x = lowerLetters.charAt(0);
char y = x;
for (int k = 1 ; k < lowerLetters.length(); k++){
y = lowerLetters.charAt(k);
if (x != y) {
denomfact = denomfact * factorials[characterCounts.get(x)];
x = y;
}
}
denomfact = denomfact * factorials[characterCounts.get(y)];
}
numberpermutations = factorials[nMinusI] * lowerLetters.length() / denomfact;
sum = sum + numberpermutations;
greaterLetters= trimWord.substring(charlocremainder+1);
trimWord = lowerLetters.concat(greaterLetters);
}
System.out.println(" Rank of permutation " + (sum+1));
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
long startTime = System.nanoTime();
String wordsorted;
String wordentered;
if (args[0].length() > 25 ) {
System.out.println("Word not in permited range " );
System.exit(0);
}
else {
wordentered = args[0].toUpperCase();
wordsorted = sortWord(args).toUpperCase();
calculatePerm(wordentered,wordsorted);
}
long endTime = System.nanoTime();
System.out.println("Took "+(endTime - startTime)/1000000000.0 + " seconds");
System.out.println("Took "+(endTime - startTime)* 0.000001 + " milliseconds");
}
}

Permutation of an array, with repetition, in Java

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);
}
}

Categories

Resources