Permutation of an array, with repetition, in Java - 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);
}
}

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

Program for permutation and combination yields an unexpected output

After thinking for quite a long time on how to make a Java program that outputs all the possible combinations from a given input array, I finally thought of doing so by combining recursion and iteration.
My code takes input a char array {a,b,c} and should give an output of all possible array of length 3.
My code is-
public class Brute {
char[] val = new char[] { 'a', 'b', 'c' };
void work(char arr[], int i) {
for (int j = 0; j <= 2; j++) {
if (i <= 2) {
arr[i] = val[j];
}
while (i <= 2) {
i = i + 1;
if (i <= 2) {
work(arr, i);
System.out.println(new String(arr));
}
}
}
}
public static void main(String args[]) {
Brute b = new Brute();
char arr[] = new char[] { 'p', 'q', 'r' };
b.work(arr, 0);
}
}
The output is:
aaa
aaa
aaa
I can't understand why it gives me this output instead of all combinations.
The problem is that instead of reinitializing the value of i to 0 the value of i is always retained as 3 and the incremented value of i(which is 3) is passed to further recursive calls.

Java: Testing algorithms: all possible combinations

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!

Mix multiple strings into all the possible combinations

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.

Categories

Resources