I need to find combination of combination in JAVA.
I have for instance 6 students in class. Out of them, I need to create combination of 4 people in group, and for each group I can choose an intimate group of 2.
I have to make sure that there are no doubles (order does not matter).! and need to print the 4 people group.
However, this is the hard part:
So defining students with numbers:
If I print out 1234 as one of the combinations, I can't print out1256 as well, since 12 appears both in 1234 and in 1256.
How can I write it in Java?
EDITED
output of ([1,2,3,4,5],3,2) will be:
Combinations without repetition (n=5, r=3)
{1,2,3} {1,2,4} {1,2,5} {1,3,4} {1,3,5} {1,4,5} {2,3,4} {2,3,5} {2,4,5} {3,4,5}
deleting repeating groups of 2 elements, will leave me only:
{1,2,3} {1,4,5} (i deleted groups that have combinations of 12,13,23,45,14,15 since they already appear in the first two that I have found.
Ok, here's the simple emulation of the process you described. But I use binary numbers to present set, it makes manipulations easier. For example, number 19 is 10011 in binary form: it means students 0, 3 and 4 are selected (there're 1's in those positions).
A little helper first.
// return all subsets of 'set', having size 'subsetSize'
Set<Integer> allSubsets(int set, int subsetSize) {
Set<Integer> result = new HashSet<Integer>();
if (subsetSize == 0) {
result.add(0);
return result;
}
if (set == 0) {
return result;
}
// check if 1st element is present
if (set % 2 == 1) {
// use 1st element, one less element to collect
for (Integer i : allSubsets(set / 2, subsetSize - 1)) {
result.add(i * 2 + 1);
}
}
// not use 1st element
for (Integer i : allSubsets(set / 2, subsetSize)) {
result.add(i * 2);
}
return result;
}
And main program. Suggestions are welcome.
int N = 5;
int M = 3;
int Z = 2;
List<Integer> result = new ArrayList<Integer>();
// get all groups of M elements from 'wholeSet'
int wholeSet = (1 << N) - 1;
for (int s : allSubsets(wholeSet, M)) {
// Check all subsets of 'Z' elements from set 's'
boolean valid = true;
for (int t : allSubsets(s, Z)) {
// check if this Z-element subset already was used
for (int past : result) {
// check if 't' is subset of 'past' set
if ((past|t) == past) {
valid = false;
break;
}
}
if (!valid) {
break;
}
}
if (valid) {
// none of Z-element subsets of 's' were used before
result.add(s);
}
}
But it may require improvements (like memoization) for big inputs. But for now, since you don't say what kind of input you expect, I assume this is good enough.
Imagine you have a Student object with an equals comparing their Primarykey. In your example, student 1 will return 1, 2 will return 2 and so on.
Put them all in the set, this will ensure that there will be no double.
Iterate though the set by 4 then by 2 and will return you your desired result.
Related
Note: I deleted this post earlier because I found the following post but I'm not sure how to apply it to my problem.
I'm working on a transposition cipher decoder. I have already solved the problem of static columns (1,2,3,4 kept in order), but I'm not sure how to create an array of each possible permutation of a length(Given as a parameter), I understand the easiest way is some kind of recursive method, but whilst attempting this I keep getting lost in the endeavour. (I've been coding all day and am quite tired)
Example array would contain:
1,2,3,4,5,6
2,1,3,4,5,6
2,3,1,4,5,6
...
After being very confused for awhile, and trying a few different things, a friend of mine (Not a user here) gave me the following java solution:
public static void main(String[] args) {
Nibba nib = new Nibba();
List<Character> characterSet = new ArrayList<>();
characterSet.add('1');
characterSet.add('2');
characterSet.add('3');
characterSet.add('4');
characterSet.add('5');
characterSet.add('6');
List<String> perms = nib.generatePermutations(characterSet);
// filter only the permutations of length 6
perms = perms.stream().filter(p -> p.length() == characterSet
.size()).collect(Collectors.toList());
for (String s : perms) {
System.out.println(s);
}
System.out.println("Total permutations = " + perms.size());
}
private List<String> generatePermutations(List<Character> characterSet) {
List<String> permutations = new ArrayList<>();
for (int idx = 0; idx < characterSet.size(); idx++) {
char character = characterSet.get(idx);
// Initialise first "permutation"
if (idx == 0) {
permutations.add(String.valueOf(character));
continue;
}
ArrayList<String> oldPerms = new ArrayList<>(permutations);
for (String subPermutation : oldPerms) {
insertPermutations(permutations, subPermutation, character);
}
}
return permutations;
}
/**
* Insert permutations into the given list
*
* #param list the list
* #param str the string
* #param c the character to insert at each point in the string
*/
private void insertPermutations(List<String> list, String str, char c) {
for (int i = 0; i <= str.length(); i++) {
String newStr = str.substring(0, i) + c + str.substring(i);
list.add(newStr);
}
}
Recall that there are n! permutations of n items. The n! can be easily understood in the following way:
1. There are `n` options for choosing the first item.
2. There are `n-1` items remaining from which to choose the second item
...
n-1. There are `2` options left for the `n-1`-th item.
n. There is only 1 item left for the `n`-th position.
Thus there are (n) * (n-1) * (n-2) * ... (2) * (1) = n! total choices for how to order the items.
This directly reveals a method for enumerating the permutations using a mixed-radix numbering scheme. In this scheme, the most-significant digit will be base n, the next-most-significant digit will be base n-1..etc.
You use such a mixed-radix number to select a permutation in the following way:
Use the most significant digit to select an element from the array (note that the first digit ranges from [0, n-1], and there are n elements to select from, so you can use it as the index of the item to select.)
Remove the selected element from the array, record that it's the first element of the permuted array, and compact the remaining elements to the front of the array.
Use the second-most significant digit to select an element from the remaining items (note that the value of this digit ranges from [0, n-2], and there are n-1 digits remaining)
Remove the selected element recording it as the second element in the permuted array
Repeat until all items have been selected.
If we use an array to represent the mixed-radix number in little-endian digit order, then we would have the following:
int mixed_radix[n] = {0};
You increment this mixed-radix number in the following way:
//Increment the least-significant digit
mixed_radix[0]++;
//Ripple overflow toward the most-significant digit
for(i=0; i<n; i++) {
if(mixed_radix[i] > i) {
mixed_radix[i] = 0;
if(i < n-1)mixed_radix[i+1]++;
}
else {
break;
}
}
So we have a way to initialize the mixed-radix number to zero, and then increment it through every possible value, stopping once it wraps back around to zero. (or after n!-1 increments...)
All that said, there's a lovely numerical trick that can make this even simpler: You can unpack that ugly mixed-radix number from an integer in the following way:
We know that there are n! permutations of n items; for any integer val in the range [0, n!-1] the following provides a bijective mapping between the integer value and a mixed-radix number:
int working = val; //val in the range [0, n!-1]
for(j=0 j<n; j++) {
mixed_radix[j] = working % (j+1);
working /= (j+1);
}
So embedding this "unpacking" loop within an outer loop that runs val over the range 0 to n!-1 is a much denser method to enumerate the mixed-radix numbers (which enumerates the possible permutations). It also assigns an integer to each permutation, effectively naming them. :)
I am writing to ask if anyone knows how to go about this. I do not need the code, I would just like the logic behind doing this. So I have a set {A,B,C,D,E}. Now I want to find all combinations of and or OR operators amongst the values in the set.
Some examples below.
A and B and C and D and E
A and B and C and D or E
A and B and C or D and E
From what I know there is 2^n-1 possibilities in the case above. So in the specific example above we would have 8 combinations.
In addition to the Above the values in the set can have two possibilities. For simplicities sake lets say A can be True or False. Likewise B,C,D and E. So what we would potentially have is something like the following :
A=True and B=True and C=True and D=True and E=True
A=True and B=True and C=True and D=True and E=False
A=True and B=True and C=True and D=True or E=True
and so on. So taking this into account we would have 2^(2 * n-1) combinations. So in our specific example above again we would have 16 combinations for a set of 4.
Is there an algorithm that already does this? If not would anyone have some logic to implement this in Java
Thanks,
I think you're saying you want to enumerate (perhaps print) all the distinct expressions of the forms you have described, for some set size n. Since each one can be characterized by a set of flags (=True vs =False at positions 1 ... n, and And vs Or at positions 1 ... n - 1), you can represent each expression as an integer, with each flag corresponding to one (binary) bit. If n has a value for which you could hope to explicitly enumerate all the possibilities, such an integer will be well within the range of a Java long. For comfortably being able to enumerate all the possibilities, such an integer will be within the range of a Java int.
One way to proceed, therefore, would be to write a method to decode in-range integers into expressions according to their bit patterns. You can then iterate over all the appropriate integers (i.e. 0 ... (1 << (2 * n)) - 1), and decode each one into the corresponding expression.
If you have to get possible combination of five boolean values, you can do one thing -
Iterate a loop from zero to binary value "11111".
In each iteration you will get a unique combination of 0 and 1.
Convert 1 to true and 0 to false.
I hope below code will be helpful :
import java.util.ArrayList;
public class Test{
public static void main (String[] args)
{
ArrayList<boolean[]> result = new ArrayList<boolean[]>();
int max_num = Integer.parseInt("11111", 2);
for(int i=max_num; i>=0; i--)
{
String val = String.format("%5s", Integer.toBinaryString(i)).replace(' ', '0');
boolean[] arr = new boolean[5];
char[] charArray = val.toCharArray();
for(int j=0; j<charArray.length;j++)
{
if(charArray[j]=='1')
{
arr[j]=true;
}
else
{
arr[j]=false;
}
}
result.add(arr);
arr=null;
val=null;
}
for(int i=0;i<result.size();i++)
{
for(boolean b: result.get(i))
{
System.out.print(b+" ");
}
System.out.println();
}
}
}
To change the variable count :
Replace same count of 1 with "11111". e.g. if variable count is 6, it should be "111111"
Change "%5s" accordingly. e.g. if variable count is 6, it should be "%6s".
Initialize array "arr" with same count.
I'm looking for some advice on a Java assignment. What I'm asked to do is perform different operations on numbers that are stored in a linked list, with each digit in a separate node. The point is to write a program that can do arithmetic on numbers that are very very large.
The particular problem that I'm looking for help on is for writing a method that compares two numbers, similar to regular compareTo() method for ints. It should return -1 if this.num < num, +1 if this.num > num, and 0 if they are equal.
What's making this difficult for me is the fact that the assignment specifies that the linked lists should store the numbers in reverse order. For example, the linked list for the number 145 would look like:
5 => 4 => 1 => null
This makes it easier to add numbers together but it's making it a headache for me when trying to compare. Here's what I've come up with, the comments explain how it's supposed to work.
public int compareTo(LLNum list)
{ // Compares two numbers.
// If the two numbers are of a different length, clearly the shortest is the smallest.
// If the two numbers are of equal length, call traverseToCompare to do the comparison.
if (this.len > list.len)
{
compareResult = 1;
}
else if (this.len < list.len)
{
compareResult = -1;
}
else if (this.len == list.len)
{
traverseToCompare(this.head, list.head);
}
return compareResult;
}
public void traverseToCompare(ListNode node1, ListNode node2)
{ // In the case that both numbers are of the same length, recursively traverse the list.
// compare each digit individually while unwinding the stack.
// Once two digits are found to be different, break out of the unwinding (Note: I could not find a way of breaking out)
// Since the dominant digit is at the tail end, this ensures the least number of comparisons.
if (node1 == null || node2 == null)
{ // Base case. Handles the case where both numbers are identical.
compareResult = 0;
return;
}
traverseToCompare(node1.getNext(), node2.getNext());
if (node1.getItem() > node2.getItem())
{
compareResult = 1;
}
if (node1.getItem() < node2.getItem())
{
compareResult = -1;
}
return;
}
The numbers being in reverse order is what pulled me towards recursion. I thought I would recursively traverse the list and then compare each digit on the way out, and somehow break out of the recursion at the first digits that are not the same. I realize this is not a usual way to use recursion but I wasn't sure how else to do it. Is there a way I could break without just throwing an exception? I think that might be a little too sloppy. Or any suggestions on how to do this without recursion?
Please don't just give me some code to copy and paste. I'm just looking to be pointed in the right direction. Thanks!
If I had to do this I would first check the lengths of both lists (like you did). If they're equal, a better way to do the comparison would be to create an iterator for each list. You can then increment the iterators at the same time and compare the values at that position in the linked lists. Doing it this way, you can simply stop comparing the lists once you have determined that one contains a larger number than the other.
In traverseToCompare you will need to take care of some cases.
It will be better and clean if you do not use the recursion.
Following can be a solution
boolean areSame = true;
boolean digitDiffer = false;
int compareResult = 0;
int length = node1.length
for(int i=0; i<length; i++)
{
if(!digitDiffer && ((node1.getItem() == node2.getItem()))
{
continue
}
else
{
digitDiffer = true;
if(node1.getItem() >= node2.getItem())
{
compareResult = 1
}
else
{
compareResult = -1;
}
}
}
return compareResult;
The best way to do it is to traverse the list for each number and construct the number and then compare the 2 numbers.
The way to construct a number from the list would be
int i = 0
int f = 1
Do while GetNext() <> Null
i = i + GetCurrentItem() * f
f = f * 10
End Do
For eg. if the number is 145, then the list would have 5->4->1
So running the above code
i = 0
f = 1
i = i + 5*1 = 5
f = f * 10 = 10
i = i + 4*10 = 45
f = f * 10 = 100
i = i + 1*100 = 145
f = f * 10 = 1000
So it comes out with i = 145.
It would have been much easier to do using plain String; as you could store data of any length. But anyway the requirement is for LinkedList :
Now as the data is stored in revers order; this means you can't decide response of compareTo method until you go through the complete list, as most significant data is stored at last position.
5 --> 4 --> 1 == 145
1 --> 4 --> 5 == 541
So read through the whole least; then you can store the value in a String and then decide compareTo method result.
traverseToCompare method is called for same length items. So you can write your own algorithm to compare two numbers stored in String.
Edit
If String is not allowed
Then will suggest you to do the same thing manually; iterate through the whole list compare the last node, if last node is same then compare the previous node and so on...
How can I write a function that takes an array of integers and returns true if there exists a pair of numbers whose product is even?
What are the properties of even integers? And of course, how do you write this function in Java? Also, maybe a short explanation of how you went about formulating an algorithm for the actual implementation. This is from the book however I am only trying to learn the explanation.
A pair of integers will always produce an even product if at least 1 of them is even. It can't produce an even product if both are odd. Therefore, you just need to check if there is at least 1 even number in the array.
This is a mathematical concept and known fact that, any even number multiplied by any other number is an even number. And so, all you have to do is return true if any one number in the array is an even number.
As others have pointed out, just having one even number is enough.
You only have to iterate until you find an even number, or the end of the array in which case there is no even number in it.
public static boolean hasEvenNumber(int[] vals) {
int i = 0;
while(i < vals.length) {
if(vals[i] % 2 == 0) {
return true;
}
i++;
}
return false;
}
Algorithm is quite simple .
You need a single even number should present in the array of integers .
Because multiple of even number with odd/even number results in a even number . So you can return true if there is an even number .
In java ,
public static int has_even_pair(int [ ] values,int n) //method definition to find sum
{
int i;
for(i=0; i< n; i++)
{
if (values[i] % 2 == 0 )
{
return 1;
}
}
return 0 ;
}
I have sets of three numbers, and I'd like to compare numbers in a set to another set. Namely, that each number in the first set is less than at least one number in the other set. The caveat is that the next numbers in the first set must be less than a different number in the second set (i.e., {6,1,6} would work against {8,8,2}, but {6,2,6} against {8,8,2} wouldn't). I have a working method, but it's brute force and ugly.
If we have setA and setB, and each of those have elements a, b, and c:
if(setB.a < setA.a)
if(setB.b < setA.b)
if(setB.c < setA.c)
return true;
else if(setB.b < setA.c)
if(setB.c < setA.b
return true;
and so on...
EDIT: I just realized you said these sets are hardcoded at 3 values. This is a super general algorithm for sets of any size.
For a 3-value set, you can do the same dumping and sorting of set elements, and then do:
if(setB.a < setA.a)
if(setB.b < setA.b)
if(setB.c < setA.c)
return true;
return false;
======================================================
A general algorithm:
This is the most efficient way I can immediately think of to do this.
pseudocode (more pythonic than java, sorry-- hopefully the comments explain):
list l1 = set1.items() //get the items out
list l2 = set2.items()
l1 = sort(l1)
l2 = sort(l2) //sort the lists
int set2idx1 = l1[0].find_closest_greater_than_value(l2) //binary search or something
if set2idx1 exists:
l2 = l2[set2idx1+1:] //in python this means l2 is reassigned to a subarray of l2 starting at set2idx1+1 going to the end of l2
else:
return false
for(int i=1; i<l1.len; i++)
int set2idxi = l1[i].find_closest_greater_than_value(l2) //binary search or something
if set2idxi exists:
l2 = l2[set2idxi+1:]
else
return false
return true
comment if anything doesn't make sense
EDIT EDIT:
explanation of the general algorithm for any interested parties:
dump the set elements into arrays
sort those arrays
iterate through the first array, seeing if there is a value in the 2nd array that is greater than the current value. If so, get the index of that value and lop off everything before and including that index and reassign the 2nd array variable to what remains.
if there ever is no such value (either because it doesn't exist or you've run out of values to test, return false). Otherwise, at the end, return true.
The idea here is that since the arrays are sorted, you know that any element that is greater than the matched element in the 2nd array will be greater than the element you're testing against in the 1st array. So you can just chop off the lower values, and since you don't want to use the same value, you can chop off the one you found, too. If you ever return false you know it's because either there were no greater values, either because the numbers in array1 were all greater than the numbers in array2, or because there weren't enough numbers in array2 greater than the numbers in array1.
What about the following pseudocode?
Condition(A : Set, B : Set) : Bool =
Let a := max(A), b := min(B) In
// Namely, that each number in the first set is less than at least one number in the other set
If a <= b Then
// the next numbers in the first set must be less than a different number in the second set
Condition(without(A, a), without(B, b))
Else
False
EndIf
Where without(A, a) means the set A minus the set {a}
It seems that a List would do better than a Set since your example includes duplicate elements. Simply:
1) Sort the two lists.
2) Trim off the first few elements from the second list until the sizes of the first and second list are equal.
3) Directly compare list1[i] with list2[i] for each i.
Code:
import java.util.*;
class Main {
public static void main (String[] args) {
List<Integer> list1 = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<Integer>();
list1.add(3); list1.add(7); list1.add(7);
list2.add(8); list2.add(8); list2.add(2); list2.add(1); list2.add(5);
//algorithm:
Collections.sort(list1);
Collections.sort(list2);
List<Integer> list3 = list2.subList(list2.size() - list1.size(), list2.size());
System.out.println(list1.size() + " " + list3.size());
boolean pass = true;
for(int i = 0; pass && i < list1.size(); i++)
if(list1.get(i) >= list3.get(i))
pass = false;
System.out.println(pass);
}
}