Java - Listing combinations - java

I'm writing a program to list all possible combinations of letters A,B,C, and D. I have successfully written a program to list all possible permutations.
However, how would I rewrite the program to work and produce all combinations (i.e.: ABCD = DCBA and AB = BA, so as long as one is there, the other need not be listed).
So far, the code for my current program is:
import java.util.ArrayList;
public class Perms {
public static void main(String[] args) {
ArrayList<Character> characters = new ArrayList<Character>();
characters.add('A');
characters.add('B');
characters.add('C');
characters.add('D');
int count = 0;
for (int i = 0; i < characters.size(); i++) {
for (int j = 0; j < characters.size(); j++) {
for (int k = 0; k < characters.size(); k++) {
for (int d = 0; d < characters.size(); d++) {
count++;
System.out.println(count + ": " + characters.get(i) + characters.get(j) + characters.get(k) + characters.get(d));
}
}
}
}
}
}

Your second case is equivalent to the list of binary values of 4 digits. Let's assume that A is rightmost digit and D is leftmost. Then there are 16 combinations in total:
DCBA
0000
0001
0010
0011
0100
...
1110
1111
Each combination is decoded like follows:
DCBA
1010 = DB
since there are ones in B and D positions.
You have various of ways to generate and or decode binary numbers in Java.
For example, with bitwise operations:
public static void main(String[] args) {
// starting from 1 since 0000 is not needed
for(int i=1; i<16; ++i) {
// bitwise operation & detects 1 in given position,
// positions are determined by sa called "masks"
// mask has 1 in position you wish to extract
// masks are 0001=1, 0010=2, 0100=4 and 1000=8
if( (i & 1) > 0 ) System.out.print("A");
if( (i & 2) > 0 ) System.out.print("B");
if( (i & 4) > 0 ) System.out.print("C");
if( (i & 8) > 0 ) System.out.print("D");
System.out.println("");
}
}

Here is my code for your problem :)
I'm so sorry that my answer looks ugly because I just a new comer at Java.
import java.util.Vector;
public class StackOverFlow {
static int n ;
static Vector<String> set;
static int[] d ;
public static void recursion(int t){
if(t==n){
PRINT();
return;
}
d[t]=1;
recursion(t+1);
d[t]=0;
recursion(t+1);
}
public static void PRINT(){
System.out.println("ANSWER");
for(int i=0;i<n;i++)
if(d[i]==1) System.out.println(set.elementAt(i));
}
public static void main(String[] args) {
n = 4;
set = new Vector<String>(4);
d = new int[6];
set.add("a");
set.add("b");
set.add("c");
set.add("d");
recursion(0);
}
}

// Returns all combinations of a List of Characters (as Strings)
// THIS METHOD MODIFIES ITS ARGUMENT! Make sure to copy defensively if necessary
List<String> charCombinations(List<Character> chars)
{
if(chars.isEmpty())
{
List<String> result = new ArrayList<String>();
result.add("");
return result;
}
else
{
Character c = chars.remove(0);
List<String> result = charCombinations(chars);
int size = result.size();
for(int i = 0; i < size; i++)
result.add(c + result.get(i));
return result;
}
}
I used List for the argument, because Set doesn't have a method to pop a single item out from the set.

Take a look at Peter Lawrey's recursive solution, which handles combinations of a list containing repeated values.

Related

JAVA code for the possible number of combinations of a 6-digit code between ranges of two integers

Conditions of the 6-digit code:
None of the digits are 0
Each digit of the combination is different
The 6-digit number is divisible by each one of the digits
Input:
Two integers, L and H
L is the limit on the smallest number on the range
H is the limit on the largest number on the range
Output:
C, which defines the number of possible combinations where L<=c<=H
I thought I could use arrays as the condition check, then realized I couldn't use it to find the number of possible combinations. Tried using loops, but couldn't figure it out, all I got for the pseudocode is the input, then a condition if L is less or equal to H. Then I sort of ran to a brick wall.
Here's the code.
''''''''
public static void main(String[] args) {
Scanner FF = new Scanner(System.in);
List<Integer> result = new ArrayList<>();
int l = FF.nextInt();
int h = FF.nextInt();
for (int i = l; i <= h; i++) {
result.add(i);
}
for (int i=l; i<=h; i++){
if (result.get(i) == result.get(i)){
result.remove(i);
}
int temp = result.get(i);
while (result.get(i)>0){
int k = result.get(i)%10;
if (temp % k != 0){
result.remove(i);
}
}
if (String.valueOf(result.get(i)).contains("0")){
result.remove(i);
}
}
System.out.println(result);
}
}
You can create a stream of integers, here 111111 to 1000000 and then filter out everything what doesnot meet your conditions.
public class SixDigitCode {
public static void main(String[] args) {
IntStream.iterate(111111, i -> i < 1000000, i -> i + 1)
.filter(containsZero.negate())
.filter(digitDifferent)
.filter(divideByDigits)
.forEach(System.out::println);
}
static IntPredicate containsZero = i -> Integer.toString(i).contains("0");
static IntPredicate digitDifferent = i -> Integer.toString(i).chars().boxed().collect(Collectors.toSet()).size() == 6;
static IntPredicate divideByDigits = i -> Integer.toString(i).chars().boxed()
.filter( x -> i%Character.getNumericValue(x) ==0)
.count() ==6;
}
There are multiple ways to solve this problem.
Let's start with an easy, but inefficient one:
boolean isOk(int number){
String numberStr = Integer.toString(number);
if(numberStr.contains("0"))
return false;
for(int i = 0; i < numberStr.length(); i++){
for(int j = i + 1; j < numberStr.length(); j++){
if(numberStr.charAt(i) == numberStr.charAt(j))
return false;
}
}
return true;
}
...
int count = 0;
for(int i = L; i <= H; i++){
if(isOk(i))
count ++;
}
Note: this code is by no means optimal, but I think it is a straight forward easy to understand solution.
However, I cannot test it right now, so it may contain minor issues.

Algorithm to create all permutations and lengths

I am looking to create an algorithm preferably in Java. I would like to go through following char array and create every possible permutations and lengths out of it.
For example, loop and print the following:
a
aa
aaaa
aaaaa
.... keep going ....
aaaaaaaaaaaaaaaaa ....
ab
aba
abaa .............
Till I hit all possible lengths and permutations from my array.
private void method(){
char[] data = "abcdefghiABCDEFGHI0123456789".toCharArray();
// loop and print each time
}
I think it would be silly to come up with 10s of for loops for this. I am guessing some form of recursion would help here but can't get my head around to even start with. Could I get some help with this please? Even if pointing me to a start or a blog or something. Been Googling and looking around and many permutations examples exists but keeps to fixed max length. None seems to have examples on multiple length + permutations. Please advice. Thanks.
Another way to do it is this:
public class HelloWorld{
public static String[] method(char[] arr, int length) {
if(length == arr.length - 1) {
String[] strArr = new String[arr.length];
for(int i = 0; i < arr.length; i ++) {
strArr[i] = String.valueOf(arr[i]);
}
return strArr;
}
String[] before = method(arr, length + 1);
String[] newArr = new String[arr.length * before.length];
for(int i = 0; i < arr.length; i ++) {
for(int j = 0; j < before.length; j ++) {
if(i == 0)
System.out.println(before[j]);
newArr[i * before.length + j] = (arr[i] + before[j]);
}
}
return newArr;
}
public static void main(String []args){
String[] all = method("abcde".toCharArray(), 0);
for(int i = 0; i < all.length; i ++) {
System.out.println(all[i]);
}
}
}
However be careful you'll probably run out of memory or the program will take a looooong time to compile/run if it does at all. You are trying to print 3.437313508041091e+40 strings, that's 3 followed by 40 zeroes.
Here's the solution also in javascript because it starts running but it needs 4 seconds to get to 4 character permutations, for it to reach 5 character permutations it will need about 28 times that time, for 6 characters it's 4 * 28 * 28 and so on.
const method = (arr, length) => {
if(length === arr.length - 1)
return arr;
const hm = [];
const before = method(arr, length + 1);
for(let i = 0; i < arr.length; i ++) {
for(let j = 0; j < before.length; j ++) {
if(i === 0)
console.log(before[j]);
hm.push(arr[i] + before[j]);
}
}
return hm;
};
method('abcdefghiABCDEFGHI0123456789'.split(''), 0).forEach(a => console.log(a));
private void method(){
char[] data = "abcdefghiABCDEFGHI0123456789".toCharArray();
// loop and print each time
}
With your given input there are 3.43731350804×10E40 combinations. (Spelled result in words is eighteen quadrillion fourteen trillion three hundred ninety-eight billion five hundred nine million four hundred eighty-one thousand nine hundred eighty-four. ) If I remember it correctly the maths is some how
1 + x + x^2 + x^3 + x^4 + ... + x^n = (1 - x^n+1) / (1 - x)
in your case
28 + 28^2 + 28^3 + .... 28^28
cause you will have
28 combinations for strings with length one
28*28 combinations for strings with length two
28*28*28 combinations for strings with length three
...
28^28 combinations for strings with length 28
It will take a while to print them all.
One way I can think of is to use the Generex library, a Java library for generating String that match a given regular expression.
Generex github. Look at their page for more info.
Generex maven repo. Download the jar or add dependency.
Using generex is straight forward if you are somehow familiar with regex.
Example using only the first 5 chars which will have 3905 possible combinations
public static void main(String[] args) {
Generex generex = new Generex("[a-e]{1,5}");
System.out.println(generex.getAllMatchedStrings().size());
Iterator iterator = generex.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
Meaning of [a-e]{1,5} any combination of the chars a,b,c,d,e wit a min length of 1 and max length of 5
output
a
aa
aaa
aaaa
aaaaa
aaaab
aaaac
aaaad
aaaae
aaab
aaaba
aaabb
aaabc
aaabd
aaabe
aaac
....
eeee
eeeea
eeeeb
eeeec
eeeed
eeeee
You can have a for loop that starts from 1 and ends at array.length and in each iteration call a function that prints all the permutations for that length.
public void printPermutations(char[] array, int length) {
/*
* Create all permutations with length = length and print them
*/
}
public void method() {
char data = "abcdefghiABCDEFGHI0123456789".toCharArray();
for(int i = 1; i <= data.length; i ++) {
printPermutations(data, i);
}
}
I think the following recursion could solve your problem:
public static void main(String[] args) {
final String[] data = {"a", "b", "c"};
sampleWithReplacement(data, "", 1, 5);
}
private static void sampleWithReplacement(
final String[] letters,
final String prefix,
final int currentLength,
final int maxLength
) {
if (currentLength <= maxLength) {
for (String letter : letters) {
final String newPrefix = prefix + letter;
System.out.println(newPrefix);
sampleWithReplacement(letters, newPrefix, currentLength + 1, maxLength);
}
}
}
where data specifies your possible characters to sample from.
Is this what you're talking about?
public class PrintPermutations
{
public static String stream = "";
public static void printPermutations (char[] set, int count, int length)
{
if (count < length)
for (int i = 0; i < set.length; ++i)
{
stream += set[i];
System.out.println (stream);
printPermutations (set, count + 1, length);
stream = stream.substring (0, stream.length() - 1);
}
}
public static void main (String[] args)
{
char[] set = "abcdefghiABCDEFGHI0123456789".toCharArray();
printPermutations (set, 0, set.length);
}
}
Test it using a smaller string first.
On an input string 28 characters long this method is never going to end, but for smaller inputs it will generate all permutations up to length n, where n is the number of characters. It first prints all permutations of length 1, then all of length 2 etc, which is different from your example, but hopefully order doesn't matter.
static void permutations(char[] arr)
{
int[] idx = new int[arr.length];
char[] perm = new char[arr.length];
Arrays.fill(perm, arr[0]);
for (int i = 1; i < arr.length; i++)
{
while (true)
{
System.out.println(new String(perm, 0, i));
int k = i - 1;
for (; k >= 0; k--)
{
idx[k] += 1;
if (idx[k] < arr.length)
{
perm[k] = arr[idx[k]];
break;
}
idx[k] = 0;
perm[k] = arr[idx[k]];
}
if (k < 0)
break;
}
}
}
Test:
permutations("abc".toCharArray());
Output:
a
b
c
aa
ab
ac
ba
bb
bc
ca
cb
cc

Specific element permutation within an array of characters in JAVA?

How can I list all uppercase/lowercase permutations for any letter specified in a character array?
So, say I have an array of characters like so: ['h','e','l','l','o']
and I wanted print out possible combinations for say the letter 'l' so it would print out [hello,heLlo,heLLo,helLo].
This is what I have so far(the only problem is that I can print the permutations however I'm not able to print them inside the actual word. so my code prints [ll,lL,Ll,LL] instead of the example above.
my code:
import java.util.ArrayList;
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
//Sample Word
String word = "Tomorrow-Today";
//Sample Letters for permutation
String rule_char_set = "tw";
ArrayList<Character> test1 = lettersFound(word, rule_char_set);
printPermutations(test1);
}
public static void printPermutations(ArrayList<Character> arrayList) {
char[] chars = new char[arrayList.size()];
int charIterator = 0;
for(int i=0; i<arrayList.size(); i++){
chars[i] = arrayList.get(i);
}
for (int i = 0, n = (int) Math.pow(2, chars.length); i < n; i++) {
char[] permutation = new char[chars.length];
for (int j =0; j < chars.length; j++) {
permutation[j] = (isBitSet(i, j)) ? Character.toUpperCase(chars[j]) : chars[j];
}
System.out.println(permutation);
}
}
public static boolean isBitSet(int n, int offset) {
return (n >> offset & 1) != 0;
}
public static ArrayList<Character> lettersFound(String word, String rule_char_set) {
//Convert the two parameter strings to two character arrays
char[] wordArray = word.toLowerCase().toCharArray();
char[] rule_char_setArray = rule_char_set.toLowerCase().toCharArray();
//ArrayList to hold found characters;
ArrayList<Character> found = new ArrayList<Character>();
//Increments the found ArrayList that stores the existent values.
int foundCounter = 0;
for (int i = 0; i < rule_char_setArray.length; i++) {
for (int k = 0; k < wordArray.length; k++) {
if (rule_char_setArray[i] == wordArray[k]) {
found.add(foundCounter, rule_char_setArray[i]);
foundCounter++;
}
}
}
//Convert to a HashSet to get rid of duplicates
HashSet<Character> uniqueSet = new HashSet<>(found);
//Convert back to an ArrayList(to be returned) after filtration of duplicates.
ArrayList<Character> filtered = new ArrayList<>(uniqueSet);
return filtered;
}
}
You need to make few changes in your program. Your logic is perfect that you need to find first the characters to be changed in the given word. After finding them, find powerset of characters to print all the permutation but this will only print permuatation of the characters of rule-char-set which are present in the given word.
Few changes you need to make is that first find all the indexes of word which contains characters of rule-char-set. Then find all subsets of indexes stored in an ArrayList and then for each element of each of the subsets, make the character present on that index to uppercase letter which will give you all permutation you require.
Consider an example that word = "Hello" and rule-char-set="hl" Then here first you need to find all indexes of h and l in the String word.
So here indexes are 0,2,3. Store it in ArrayList and then find its powerset.Then for each subset ,make the character present on that index to the uppercase letter.
Word[] = {'h','e','l','l','o'}
indexes = 0 , 1 , 2 , 3 , 4
index[]= { 0 , 2 ,3} //Store the indexes of characters which are to be changed
BITSET | SUBSET | word
000 | - | hello
001 | {3} | helLo
010 | {2} | heLlo
011 | {2,3} | heLLo
100 | {0} | Hello
101 | {0,3} | HelLo
110 | {0,2} | HeLlo
111 | {0,2,3} | HeLLo
Code :
import java.util.ArrayList;
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
//Sample Word
String word = "Tomorrow-Today";
//Sample Letters for permutation
String rule_char_set = "tw";
ArrayList<Integer> test1 = lettersFound(word, rule_char_set); //To store the indexes of the characters
printPermutations(word,test1);
}
public static void printPermutations(String word,ArrayList<Integer> arrayList) {
char word_array[]=word.toLowerCase().toCharArray();
int length=word_array.length;
int index[]=new int[arrayList.size()];
for(int i=0; i<arrayList.size(); i++){
index[i] = arrayList.get(i);
}
for (int i = 0, n = (int) Math.pow(2, index.length); i < n; i++) {
char[] permutation = new char[length];
System.arraycopy(word_array,0,permutation,0,length);
//First copy the original array and change
//only those character whose indexes are present in subset
for (int j =0; j < index.length; j++) {
permutation[index[j]] = (isBitSet(i, j)) ? Character.toUpperCase(permutation[index[j]]) : permutation[index[j]];
}
System.out.println(permutation);
}
}
public static boolean isBitSet(int n, int offset) {
return (n >> offset & 1) != 0;
}
public static ArrayList<Integer> lettersFound(String word, String rule_char_set) {
//Convert the two parameter strings to two character arrays
char[] wordArray = word.toLowerCase().toCharArray();
char[] rule_char_setArray = rule_char_set.toLowerCase().toCharArray();
//ArrayList to hold found characters;
ArrayList<Integer> found = new ArrayList<Integer>();
//Increments the found ArrayList that stores the existent values.
int foundCounter = 0;
for (int i = 0; i < rule_char_setArray.length; i++) {
for (int k = 0; k < wordArray.length; k++) {
if (rule_char_setArray[i] == wordArray[k]) {
found.add(foundCounter, k); //Store the index of the character that matches
foundCounter++;
}
}
}
return found;
}
}
Output :
tomorrow-today
Tomorrow-today
tomorrow-Today
Tomorrow-Today
tomorroW-today
TomorroW-today
tomorroW-Today
TomorroW-Today
Sanket Makani answer is perfect.
I may offer a more objective approach of this problem.
As an input you have a string to modify, and characters, which should be replaced with the modified case ( upper or lower ).
As an output you will have all permutated strings.
I would create a structure which contains index, and possible values to change with:
class Change {
int index;
char values[];
}
We will need to make all possible combinations, so lets include field which will tell which character is currently used in to our structure, and add some methods:
class Change {
int index;
char values[];
int cur;
void reset() {cur=0;}
boolen isMax(){return cur==values.length-1;}
void next(){cur++;}
char getValue(){ return values[cur]; }
}
We will have a list or array of these classes then, which we will put in to a separate class
class Combination {
Change changes[];
void reset() { for (Change c: changes) c.reset();}
boolean next() {
for ( int i=0; i<changes.length; i++)
if ( changes[i].isMax())
changes[i].reset(); // next change will be taken in cycle, with "next()"
else {changes[i].next(); return true;}
return false; // all changes are max
}
}
So when you initialize your "Combination" class by your input data, you may use it in cycle then.
Combination c = new Combination();
.... // initialization here
c.reset();
do {
... // update and print your string
} while ( c.next() );
The initialization of "Combination" and using of values for updating the input string I leave after you :)
For the permutation case, I think recursion is the best fit in terms of readability, taking into account that maybe is not best in terms of performance.
My approach would be this:
public static void main(String[] args) {
generateCombinations("hello", "l", "");
}
public static void generateCombinations(String text, String changingLetters, String current) {
if (0 == text.length()) {
System.out.println(current);
return;
}
String currentLetter = text.substring(0, 1);
if (changingLetters.contains(currentLetter)) {
generateCombinations(text.substring(1), changingLetters, current + currentLetter.toUpperCase());
}
generateCombinations(text.substring(1), changingLetters, current + currentLetter);
}
The output for the main execution will be:
heLLo
heLlo
helLo
hello

Getting a list of binary numbers composing a number

In Java, having a number like 0b1010, I would like to get a list of numbers "composing" this one: 0b1000 and 0b0010 in this example: one number for each bit set.
I'm not sure about the best solution to get it. Do you have any clue ?
Use a BitSet!
long x = 0b101011;
BitSet bs = BitSet.valueOf(new long[]{x});
for (int i = bs.nextSetBit(0); i >=0 ; i = bs.nextSetBit(i+1)) {
System.out.println(1 << i);
}
Output:
1
2
8
32
If you really want them printed out as binary strings, here's a little hack on the above method:
long x = 0b101011;
char[] cs = new char[bs.length()];
Arrays.fill(cs, '0');
BitSet bs = BitSet.valueOf(new long[]{x});
for (int i = bs.nextSetBit(0); i >=0 ; i = bs.nextSetBit(i+1)) {
cs[bs.length()-i-1] = '1';
System.out.println(new String(cs)); // or whatever you want to do with this String
cs[bs.length()-i-1] = '0';
}
Output:
000001
000010
001000
100000
Scan through the bits one by one using an AND operation. This will tell you if a bit at one position is set or not. (https://en.wikipedia.org/wiki/Bitwise_operation#AND). Once you have determined that some ith-Bit is set, make up a string and print it. PSEUDOCODE:
public static void PrintAllSubbitstrings(int number)
{
for(int i=0; i < 32; i++) //32 bits maximum for an int
{
if( number & (1 << i) != 0) //the i'th bit is set.
{
//Make up a bitstring with (i-1) zeroes to the right, then one 1 on the left
String bitString = "1";
for(int j=0; j < (i-1); j++) bitString += "0";
System.out.println(bitString);
}
}
}
Here is a little test that works for me
public static void main(String[] args) {
int num = 0b1010;
int testNum = 0b1;
while(testNum < num) {
if((testNum & num) >0) {
System.out.println(testNum + " Passes");
}
testNum *= 2;
}
}

creating k -itemsets from 2-itemsets

I have written the following code to generate k-elements itemsets from 2-element sets. The two elements sets are passed to candidateItemsetGen as clist1 and clist2.
public static void candidateItemsetGen(ArrayList<Integer> clist1, ArrayList<Integer> clist2)
{
for(int i = 0; i < clist1.size(); i++)
{
for(int j = i+1; j < clist2.size(); j++)
{
for(int k = 0; k < clist1.size()-2; k++)
{
int r = clist1.get(k).compareTo(clist2.get(k));
if(r == 0 && clist1.get(k)-1 == clist2.get(k)-1)
{
** candidateItemset.add(clist1.get(i), clist1.get(clist1.size()-1), clist2.get(clist2.size()-1));
}
}
}
}
// return candidateItemset;
}
The condition to create k-itemsets is that clist1(i) == clist2(i), where i = 1,...,k-2 and clist1(k-2) != clist2(k-2). But there is error in the code where i have put **. How can i fix this? The logic is that this function generates candidateItemsets which will be used again as an input to generate other candidate Itemsets.
The add method in ArrayList takes a maximum of two arguments and you are passing in three. If you wish to add all three items, call add(Integer i) three times.
Also, if you want to return candidateItemsets from the function you must declare an ArrayList<Integer> return value and create the list:
public static ArrayList<Integer> candidateItemsetGen(ArrayList<Integer> clist1, ArrayList<Integer> clist2) {
ArrayList<Integer> candidateItemset = new ArrayList<Integer>();
for (int i = 0; i < clist1.size(); i++) {
for (int j = i + 1; j < clist2.size(); j++) {
for (int k = 0; k < clist1.size() - 2; k++) {
int r = clist1.get(k).compareTo(clist2.get(k));
if(r == 0 && clist1.get(k) - 1 == clist2.get(k) - 1) {
candidateItemset.add(clist1.get(i));
candidateItemset.add(clist1.get(clist1.size() - 1));
candidateItemset.add(clist2.get(clist2.size() - 1));
}
}
}
}
return candidateItemset;
}
If you want to add all three as a group of related values, store them together in a separate data structure and add that to candidateItemset (of correct type).
You could optimize that code further if you consider that each list of itemsets are sorted according to the lexical order.
For example, let's say that
clist1 = AB, AD, AF, AG, BC, FG
clist2 = BD, FE, FG, FH, FI
With your code, you will compare AB with all the itemsets of clist2.
But you could optimize that, by stoping right after BD because B is larger than A in AB according to the lexical order. Therefore, no itemsets after BD in Clist2 will match with AB.
If you want to see the code of an optimized implementation of Apriori, you can check my open source data mining library named SPMF

Categories