For example I may have a frequent itemset of characters {A, B, C, G}. I need to generate all possible antecendents of association rules. In this case: ABC, ABG, ACG, AB, AC, AG, BC, BG, CG, A, B, C, G. I have no idea where to start on doing this. Hours of research has taught me about the terminology and concept, but nothing has explained how to do this particular step. This is what I have so far for the method. The itemsets are all kept in the form of Strings, and stored together as an ArrayList. I have already made a working Apriori algorithm for the generation of frequent itemsets.
public static ArrayList<String> associationRules(ArrayList<String> data, ArrayList<String> freqItemsets, int minConf){
ArrayList<String> generatedRules = new ArrayList<String>();
for(int i = 0; i < freqItemsets.size(); i++) {
String currentItemset = freqItemsets.get(i);
if(currentItemset.length() < 2) {
continue;
}
}
return null; // temporary return statement to avoid compile error
}
While code, feedback, and advice on this and later steps would of course be a huge help, all I really need is an English explanation of how to do this one step (as opposed to pseudocode or another working method using different data types). Everything else seems manageable.
Assuming you nailed the definition of what you actually need (all subsets that are sorted as the original list), you can do this by thinking about it as that and using those properties:
sorted like in your list
finite
dividable
All you need to do is go through your character list multiple times and each time decide per chraracter, whether to include it this time or drop it. If you go through and capture all possibilities, then you are done. To do this you should find a solid way to count through the possible result strings.
an iterative solution
Think about possible bit-states. You have n characters and assign each character a bit (in your case 4). Then each possible bit-state defines a legal permutation of a subset, e.g. for {A, B, C, G}:
1001 would be AG
As we know, all possible states of a bit set are 'countable', or in other words, you can just count through them by counting from the least state to the highest by adding 1.
Make a loop counting from 1 to 2^n - 1 (where n is the number of chars you have) and then build your String by adding (in correct sequence) all characters for which you have a 1 as their representing bit and leave out the characters with a 0. Then you 'count' through all possible legal permutations.
Such an implementation highly depends on the programmer and their style, but for me it would look about like this:
public static List<String> associationRules(List<String> elements) {
List<String> result = new ArrayList<>();
long limit = 1 << elements.size(); // thanks to saka1029 for this correction. My code was n^2 not 2^n.
// count from 1 to n^2 - 1
for (long i = 1; i < limit; ++i) {
StringBuilder seq = new StringBuilder();
// for each position (character) decide, whether to include it based on the state of the bit.
for (int pos = 0; pos < elements.size(); ++pos) {
boolean include = ((i >> pos) % 2) == 1; // this line will give you true, if the in 'i' the bit at 'pos' (from behind) is 1, and false otherwise.
if (include) {
seq.append(elements.get(pos));
}
}
// add to the final result the newly generated String.
result.add(seq.toString());
}
return result;
}
and the result looks like this:
[A, B, AB, C, AC, BC, ABC, G, AG, BG, ABG, CG, ACG, BCG, ABCG]
This is an iterative (non-recursive) solution, but there is also a recursive one that may (or may not) be easier to implement still.
a recursive solution
A recursive solution could just simply work by creating a method that takes as arguments the a set of sorted characters and a boolean state (included or not included) and returns a list of all possible sorted subpermutations.
You would then call this with a public method that passes the characters and 0 as position and either true or false as initial state (the other comes later).
The method then works with divide and conquer. You include the character at the defined position (based on whether or not the include flag is set) and call the own method again with a cloned character (sub)set that does not include the first character.
Let's assume for the moment, that you start by not including the first character of each sequence (but later include it).
If you pass to such a method the character set {A, B, C, G} then the method would (start) to operate like this:
A: recurse on {B, C, G}
B: recurse on {C, G}
C: recurse on {G}
G: set is empty,
G: Add to the result all Strings with 'G' prefixed and without.
G: return {"G", ""}
C: Add to the result all Strings with 'C' prefixed and without.
C: {"CG", "C", "G", ""}
...
This way, you will collect all sorted subset permutations recursively. Depending on whether the empty String is allowed, you can remove that at the end, or not add it at all.
I implemented it like this, but there are other correct ways:
public static List<String> associationRules2(List<String> elements) {
List<String> result = new ArrayList<>();
String thisElement = elements.get(0);
// build the subset list (leaving out the first element
List<String> remaining = new ArrayList<>();
boolean first = true;
for (String s : elements) {
if (first) {
first = false;
} else {
remaining.add(s);
}
}
// if the subset is not empty, we recurse.
if (! remaining.isEmpty()) {
List<String> subPermutations = associationRules2(remaining);
// add all permutations without thisElement.
result.addAll(subPermutations);
// add all permutations *with* thisElement.
for (String s : subPermutations) {
result.add(thisElement + s);
}
}
// finally add thisElement on it's own.
result.add(thisElement);
return result;
}
Result: [G, CG, C, BG, BCG, BC, B, AG, ACG, AC, ABG, ABCG, ABC, AB, A]
Related
public class TestPossibleNumbers {
public static void main(String[] args) {
int input[] = { 1, 2, 3 };
// int input[] = {10,11,12,13};
possibleNumbers(input, 0);
}
public static void possibleNumbers(int[] x, int index) {
if (index == x.length) {
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + " ");
}
System.out.println();
}
for (int i = index; i < x.length; i++) {
int temp = x[index];
x[index] = x[i];
x[i] = temp;
possibleNumbers(x, index + 1);
temp = x[index];
x[index] = x[i];
x[i] = temp;
}
}}
Can anyone help me to understand the code inside for loop?
This program run perfectly. But, I am unable to figure out how it is working
You are recursively calling the method again at:
possibleNumbers(x, index + 1);
Thus the method runs the method again, with index + 1 passed. It checks if
if(index == x.length)
If the statement is correct it prints the numbers.
It then enters the 2nd for loop again(if the if statement was incorrect it will still enter it). And calls the recurring method again. It will keep entering 2nd for loop but when "index" will be equal to or greater than "i.length" no iterations of the for loop will run because you specified for loop to run only when:
i<i.length
When 2 for loop does not do any iterations the method will stop recurring. So in your case when index is equal to 3 no iterations of 2nd for loop will run.
Try running debug step by step to see what is happening more in depth.
The Program prints permutation of numbers not combination.
Permutation - Order matters
Combination - Order doesnt matter and more of choosing k elements out of n
for example
int a= {a,b};
permutation = {ab,ba}
whereas combination ={{},{a},{b},{a,b}}
To understand how the program works
go through the following link will
https://www.geeksforgeeks.org/write-a-c-program-to-print-all-permutations-of-a-given-string/
Don't get confused on recursion inside for loop.
if (index == x.length) is the terminating condition for recursion.
Inside the for loop before and after calling the recursive call possibleNumberselements are swapped.
Before swap helps to generate all possible outcomes and after swap elements will swap to previous position so that all other permutation will be generated from the for loop. It may sounds confusing please go through the link.
I'll provide an alternative explanation that I feel is more intuitive.
Consider the case of only 1 number in the list: [a]. This is pretty trivial: there's a single combination [a].
Now consider the case of 2 numbers in the list: [a, b]. In this case you can take each of the elements in turn and then look at all combinations of the remaining element using the previous method and then add the element back.
Now consider the case of 3 numbers in the list: [a, b, c]. In this case you can take each of the elements in turn and then look at all combinations of the other 2 elements using the previous method and then add the element back.
And so on for 3, 4, 5... elements.
So, in general, consider the case of n numbers in the list: [a1, a2, ... an]. In this case take each of the elements in turn and then look at all combinations of the other n-1 elements using the exact same method and then add the element back.
Converting to pseudo code:
getCombos(values)
for each value
for each combo in getCombos(values with value removed)
add value + combo to results
return results
The only thing to add is the base case which is necessary for all recursive implementations. One possibility is the case of a single item. However there's an even simpler one: if there are no values then the result is a single empty list.
So converting that to Java, using sets to make clear that the elements need to be unique (to avoid duplicate results), using streams and making it generic so it'll work for any type:
Stream<List<C>> combos(Set<C> values) {
if (values.isEmpty())
return Stream.of(new ArrayList<>());
else
return values.stream().flatMap(value ->
combos(values.stream()
.filter(v -> !v.equals(value))
.collect(toSet())).peek(r -> r.add(value)));
}
Your code is really just an alternate implementation of the same algorithm that swaps the element under consideration to the front of the array instead of creating a new collection.
I have to make a iterative solution to the Towers of Hanoi problem. I am trying to convert a tail recursive call to an iterative one. I am following an algorithm I found in my textbook to transform it. I followed this algorithm and even though my code is similar to the recursive variant my output doesn't match the designated form. Now from what the book tells me, having a recursive call with an iterative is strange, but valid.
public class DemoIterative
{
public static void TowersOfHanoi(int numberOfDisks,
String startPole, String tempPole, String endPole)
{
while (numberOfDisks > 0)
{
/** MUST GO 1, 3, 2, 1 */
TowersOfHanoi(numberOfDisks - 1, startPole, endPole, tempPole);
System.out.println(startPole + " -> " + endPole);
numberOfDisks = numberOfDisks - 1;
startPole = tempPole;
tempPole = startPole;
}
}
public static void main(String[] args)
{
DemoIterative demoIterative = new DemoIterative();
System.out.println("Enter amount of discs: ");
Scanner scanner = new Scanner(System.in);
int discs = scanner.nextInt();
demoIterative.TowersOfHanoi(discs, "A", "B", "C");
} // end of main
} // end DemoIterative
Now the output I am getting from this is:
A to C,
A to B,
C to B,
A to C,
B to B,
B to C,
B to C
I should be getting this (tested from recursive original):
A to C,
A to B,
C to B,
A to C,
B to A,
B to C,
A to C
This is the algorithm I am using:
While numberOfDisks is greater than 0, move disk from startPole to endPole, numberOfDisks--, exchange the contents of tempPole and startPole.
Now is this possible? If so, is there a problem with my algorithm or am I printing it wrong?
You have a problem with your algorithm. Most important for your own understanding of this, slap a print statement at the top of your routine and print out the arguments. Also insert one at the bottom of the loop to help track that execution.
To summarize, I don't think you understand the call tree you've created, and I think you should trace it to see. There are applications that will use such a tree, but I don't think that this what you want for this assignment.
There area couple of structural problems. For one, when you get to the bottom of the loop, you set startPole = tempPole, and follow that with a useless assignment back -- this wipes out the old startPole value; it does not exchange them.
Next, your loop + recursion structure is strange. First, you've used a while loop where the semantics clearly indicate a for -- you know how many times you'll iterate when you enter the loop. When you first call this with, say, 5 disks, the numberOfDisks (I'll call it N) = 5 iteration will loop 5 times. Each iteration recurs with N = 4, 3, 2, 1, respectively.
Now, the N=4 instance will do likewise: recurring with N=3, 2, 1. This gives you two instances at N=3. Continuing, you'll get three instances at N=2, and four at N=1, for a total of 11 calls to your function. Since only four of these involve moving a one-disk stack (for a tower of 5 disks, you need several more), I think you've incorrectly implemented whatever you had in mind.
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.
Given n users (u_1, u_2,..., u_n) and k groups (g_1, g_2, ..., g_k), create all possible combinations of all groups. basically, in the end, each combination is a Map<Integer,Integer>, where the first Integer is user ID, and the second Integer is group ID.For example, [(u_1,g_1), (u_2,g_1)....,(u_n, g_1)] is one possible combination.
There will be k^n combinations.
I searched and saw similar problems, but they do have some extra conditions that do not apply for my problem. In my case, there is no limit in each group, and there is no evenness or uniform distribution.
Can you suggest a quick way to do this in Java?
Thanks
My tries so far:
I tried to create a for loop for each possibility for each user, but I face the problem that I cannot define the number of for loops.
So I switched to recursion, but stuck at creating parameters for inside calls to the functions. Still working on it though.
Please, also note that this is not "n choose k". "n choose k" is when all users are identical, but here users are obviously not identical.
OK. I created a solution for this. Basically, it's a dynamic programming problem. Assume you have created a List of Maps (combinations) for j users and k locations. TO create for j+1 users and k locations, need 2 loop: for each Map, for each i=1 to k, Map.put(user_j+1, k)). Is is both recursive and iterative. Recursive because you need to pass the old maps to the new iterations. That's it.
The traditional solution to these kinds of problems is using recursion: If there are n = 0 users the only grouping possible is the empty group. Otherwise, take out the first user and generate the solution for the other n-1 users. Using the solution for the subproblem, generate the final solutions by assigning the first user to each of the k possible groups.
In code:
import java.util.*;
class Grouping {
public static void main(String[] args) {
List<?> groups = grouping(Arrays.asList(1,2,3), Arrays.asList(4,5,6,7));
System.out.println(groups.size());
System.out.println(groups);
}
static List<Map<Integer,Integer>> grouping(List<Integer> users, List<Integer> groups) {
if (users.isEmpty()) {
Map<Integer,Integer> empty = Collections.emptyMap();
return Collections.singletonList(empty);
} else {
Integer user = users.get(0);
List<Map<Integer,Integer>> subs = grouping(users.subList(1,users.size()), groups);
List<Map<Integer,Integer>> solutions = new ArrayList<>();
for (Integer group: groups) {
for (Map<Integer,Integer> sub : subs) {
Map<Integer,Integer> m = new HashMap<>(sub);
m.put(user, group);
solutions.add(m);
}
}
return solutions;
}
}
}
Ok, here is simple idea.
Lets first assume that each user_id is in {0, ... n-1}, and group_id is in {0, ... k-1}, we can map this numbers back to real ids later.
Now, what you basically want to do is to iterate thru all n-digit numbers in Base k numeral system, i.e. where each digit 0 <= base < k.
So, you start with number is 0000...00 (n-zeroes) and you end with kkkk....kk (n digits of nominal k). For each such number the position indicates user_id and digit value is this user's group_id.
So, the main workhorse you need to implement is the class Combination representing such n-digits sequence(try ArrayList or simple int[] array), with increment() operation implemented correctly (I imagine recursion is the best way to do this implementation). May be you could also have method isMaxReached() to check if all digits are of value k.
Then you would have a single loop :
Combination combination = new Combination(); // initialized with n -zeroes
while (!combination.isMaxReached()) {
combination.increment();
}
Please let me know if you would need more details on implementation.
Hope that helps.
It looks like we have the following:
n different numbers (users)
k sets (groups)
Objective is:
Find all the k-tuples with k sets S_k, such that for all i,j in 1..k the pairwise intersection of S_i and S_j is empty and the union S_1 .. S_k is the set 1..n
If this is what you want, then I would attack this recursively:
If n is 0, then the result is 1 k-tuple of empty sets.
If n is 1, then the results are k tuples, where for all elements S_j with j = 1..k it is the empty set except for the j-th element that is set {1}.
If n is m, then compute the list of tuples for m-1. Then replicate the list k times, and let the i-th set be the union of the i-th set and {n}. (Note that this is just a more general form of the previous rule for n=1).
Example:
n = 3, k = 2
n = 2, k = 2
n = 1, k = 2
n = 0, k= 2
result: [({},{})]
result: [({1},{}), ({},{1})]
result: [({1,2},{}), ({2},{1}), // j=1, union 1st with {2}
({1},{2}), ({},{1,2})] // j=2, union 2nd with {2}
result: [
({1,2,3},{}), ({2,3},{1}), ({1,3},{2}), ({3},{1,2}), // j=1, union 1st with {3}
({1,2},{3}), ({2},{1,3}), ({1},{2,3}), ({},{1,2,3}) // j=2, union 2nd with {3}
]
So u want maps like k1,n1, k1,nN .. kN,nN..
You will need 2 loops
Start by looping the groups . In each group, loop over all the users... and in the second loop , put(group,user) in a hashmap...
Code using the above algorithm.
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);
}
}