Program for permutation and combination yields an unexpected output - java

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.

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

Adding two character arrays and storing the result as characters in another char array in Java

I want to add two character arrays and store the result as characters in another character array.
The addition involves addition of two english letters from the two arrays as operands.
The addition will wrap around z back to a .
eg.
Input:Array1 and Array 2 and output is Array 3
Array 1 :abcdeyz
Array 2 :aaaaaaa
Array 3 :bcdefza
Below is a part of my code which is not working.
Kindly suggest any changes
int c = 0;
char array3[] = new char[count] ;
for(int a=0;a<array1.length;a++)
{
for(int b=0;b<array2.length;b++)
{
int temp = (array1[a] + array2[b]) % 26 ;
array3[c] = (char) temp ;
c++ ;
}
}
Hint - value of 'a' is not 0
The issue is in the line -
int temp = (array1[a] + array2[b]) % 26 ;
Here is the modified code (assuming all characters are lower case)-
int c = 0;
char array3[] = new char[count] ;
for(int a=0;a<array1.length;a++)
{
for(int b=0;b<array2.length;b++)
{
int temp = ( (array1[a]-'a') + (array2[b]-'a')) % 26 ;
array3[c] = (char) (temp+'a') ;
c++ ;
}
}
Using the modulo of 26 is a good way of handling a-z to 1-26 conversion. This way your program can be agnostic about the actual ASCII character numbers.
Some other concerns:
Case Insensitivity. I would recommend converting your letters to lowercase before processing them.
Handling of exceptional cases. What if your arrays are different lengths? Or what if they have a character that isn't a
letter?
The below code is one way to handle these things.
public static int letterToInt(char letter) {
char letterToConvert = Character.toLowerCase(letter);
int codeForA = (int)'a';
int numberOfLetter = ((int)letterToConvert) - codeForA + 1;
if(numberOfLetter < 1 || numberOfLetter > 26) {
throw new IllegalArgumentException(
"The character argument can only be a-z or A-Z, but was '" + letter + "'");
}
return numberOfLetter;
}
public static char intToLetter(int number) {
if(number < 1 || number > 26) {
throw new IllegalArgumentException(
"The number can only be 1-26, but was " + number);
}
int codeForA = (int)'a';
return (char)(codeForA + number - 1);
}
public static char addLetters(char letter1, char letter2) {
int numberFromAddedLetters =
letterToInt(letter1) + letterToInt(letter2);
int modulo = numberFromAddedLetters % 26;
return intToLetter(modulo == 0 ? 26 : modulo);
}
public static char[] addLetterArrays(char[] array1, char[] array2) {
char[] longerArray;
char[] shorterArray;
if(array1.length >= array2.length) {
longerArray = array1;
shorterArray = array2;
} else {
longerArray = array2;
shorterArray = array1;
}
char[] addedLetters = new char[longerArray.length];
for(int index = 0; index < longerArray.length; index++) {
if(index < shorterArray.length) {
addedLetters[index] = addLetters(longerArray[index], shorterArray[index]);
} else {
addedLetters[index] = longerArray[index];
}
}
return addedLetters;
}
// Test it out
public static void main(String[] args) {
char[] letters1 = "abcdeyz".toCharArray();
char[] letters2 = "aaaaaaa".toCharArray();
// Prints [b, c, d, e, f, z, a]
System.out.println(Arrays.toString(addLetterArrays(letters1, letters2)));
}
This is a fixed and working example on how to do this:
public static void main(String[] args) {
char[] array1 = new char[] {'a', 'b', 'c', 'd', 'e', 'y', 'z'};
char[] array2 = new char[] {'a', 'a', 'a', 'a', 'a', 'a', 'a'};
char[] array3 = new char[array1.length];
for (int i = 0; i < array1.length; i++) {
array3[i] = toChar((toInt(array1[i]) + toInt(array2[i]) + 1) % 26);
}
System.out.println(Arrays.toString(array3));
}
private static int toInt(char chr) {
return chr - 'a';
}
private static char toChar(int value) {
return (char)(value + 'a');
}
There are some thinks to notice here (except the - 'a' part, the other answers mentioned that already):
you only need one loop for this task. If you use 2 nested loops, then you'll add each letter of array1 with every letter of array2. And you'll a larger array3. And since the result doesn't match the desired result ... :)
the + 1 in toInt(array2[i]) + 1 is necessary, because char - 'a' is "zero-based". Therefore 'a' + 'b' would result in 'b' and not 'c', because you'll calculate 0 + 1 (which will be 'b' if you "convert" it back to char by adding 'a') (I hope this is understandable expressed :D)
it is necessary that array2 has at least the same length as 'array1'. It is almost like padding in cryptography. (I've omitted the padding part to keep this code short)
Write this:
int temp = (((array1[a] - 'a') + (array2[b] - 'a')) % 26) + 'a';
what this does is convert both characters into their respective place in the alphabet, perform addition modulo the number of characters in the alphabet for the wraparound effect, and convert back to the correct ascii value.
Note that your code was having trouble because you were acting as though the alphabet's ascii values were their respective places in the alphabet itself, which is incorrect.

Array How would you add a digit to the same location as its value?

The input comes as a String "543210".
The code extracts each character using the charAt method and place them one after the other in a specific array location that corresponds to the value of the number.
charAt(0) = 5 means that 5 should go intoarrayLocation 5.
It doesnt seem to work. I even tried with arrayLists.
public class HugeInteger {
private String digits;
int[] arrayToStoreTheDigits = new int[6];
public HugeInteger(String digits) {
this.digits = digits;
add();
}
public void add() {
for (int i = 0; i < 5; i++) {
arrayToStoreTheDigits[digits.charAt(i)] = digits.charAt(i);
System.out.println(digits.charAt(i));
}
}
public String toString() {
return "" + arrayToStoreTheDigits + "/ " + digits.charAt(2);
}
}
package Exercise8_17_HugeIntegers;
public class HugeIntegertester {
// static HugeInteger huge;
public static void main(String[] args) {
HugeInteger huge = new HugeInteger("543210");
System.out.println(huge.toString());
}
}
Your question is unclear, but I suspect the problem is here:
arrayToStoreTheDigits[digits.charAt(i)] = digits.charAt(i);
If digits.charAt(i) is '5' that has an integer value of 53, as that's the UTF-16 code unit for the character '5'. If you're trying to extract its value when viewed as a digit, you need to use Character.digit. Alternatively you could just subtract '0' if you really only care about 0-9, and are confident there will be no other characters.
So you could write your code like this:
char c = digits.charAt(i);
arrayToStoreTheDigits[c - '0'] = c;
Note that due to this initialization:
int[] arrayToStoreTheDigits = new int[6];
... your code will fail if it ever sees a value of '6' or greater.
Additionally, if you want to use all the characters in digits, your loop should be:
for (int i = 0; i < digits.length(); i++)
Overall this is a very odd thing to want to do - because the only values valid for array element 1 (for example) will be '1' (if the digit is present) or 0 (the default, if it's not). In particular, this loses all information about the position in which the digits occurred. If the class is meant to be similar to BigInteger, you should be writing something much more like this:
arrayToStoreTheDigits = new int[digits.length()];
for (int i = 0; i < arrayToStoreTheDigits.length; i++)
{
// TODO: Digit validation
arrayToStoreTheDigits[i] = digits.charAt(i) - '0';
}
So that after passing in "543210" you'd have an array of { 5, 4, 3, 2, 1, 0 }. That's now useful information.
Problem exists with your loop :
for (int i = 0; i < 5; i++) { // condition shoule be i < 6
// arrayToStoreTheDigits[digits.charAt(i)] = digits.charAt(i); // convert String to integer
// shoule be
arrayToStoreTheDigits[Integer.parseInt(digits.charAt(i))] = Integer.parseInt(digits.charAt(i));
System.out.println(digits.charAt(i));
}

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