Looping through all combinations - java

I'm trying to program a multiple players game in Java.
I need to create a list of all combinations and to store these in an array.
If 2 players are logged in as the game start, the combinations are:
p1,p2 and p2, p1 (positions are important)
while if 3 players logged in to the game, the combinations are:
p1,p2,p3 ; p1,p3,p2 ; p2,p1,p3 ; p2,p3,p1 ; p3,p1,p2 and p3,p2,p1
In fact, I need a redundant array:
if 3 players are logged in, I need in advance the combinations of 3 AND the combinations of each possible pairs
p1,p2,p3 ; p1,p3,p2 ; p2,p1,p3 ; p2,p3,p1 ; p3,p1,p2 and p3,p2,p1
and
p1,p2 and p2, p1
and
p1,p3 and p3, p1
and
p2,p3 and p3, p2
)
Many players (EDITED: up to 8 players) may be logged in simultaneously to the same round of the game. (EDITED: there are up to 32 groups, but this is not important, because groups are independent)
Is there a quick, short and a simple way to create this combinations array for n players?
A recursive solution is foreseen and acceptable.
Many thanks
P.S.
My ongoing idea is to split the group into 2, a selected pair and the rest of the players.
The sekected pairs are selected using 2 FOR loops and the rest with a third.
If there are 2 players, no 'rest". If there are 3 players, the 2 FORs will select the positions of the pair and the rest will get the rest.
then, the rest are ordered using the same split procedure.
May this way get real? how? Will it be efficient?
Thanks again.

The number of permutations of size n is n!, which grows exponentially.
For example, the number of all permutations of 20 elements is 2432902008176640000(~2.43290201 × 10^18), quite big number.
Like you correctly guessed, there is a recursive algorithm for generating all permutations, but it is quite ineffecient in both time and space for reasons listed above.
However, if your task is generating a random permutation, an efficient algorithm does exist: Fisher–Yates shuffle. It requires O(n) time(assuming you can generate a random integer in O(1)), and O(1) of additional memory.

You know the number of entries in each array. For the array with all players, it's 256! That's possibilities for the first entry in the array, 255 for the next, and so forth. 256! is a larger enough number that my calculator can't handle it. Even for 170 players, the size of the array would be 1.3e241. Even on a 64 bit computer, you only have 1.8e19 addressable bytes. This basically means you need to rethink your approach.

Related

About how to divide a list relatively evenly

I have a list. I need to divide it into 4 groups, and the sum of each group is relatively average. The list can be sorted or not.
Give an example: list(1,1,4,2,2,3,5,6) -> Divide into (1,1,4), (2,2,3), (5), (6).
Thanks in advance here, I know this requires some algorithmic ability.
You have three things to play with here.
a set of numbers, no of segments and the average of each segment.
If two of these are set, the third is automatically set.
In your case, your set of numbers is pre-defined and the no of segments is predefined - hence the average is also pre-defined.
You need to find this average and then run through the numbers. If the segments are required to be contiguous as in your example, this is the only way to do this.
If the elements in the segment can be non contiguous, then there are a lot more possibilities and your chances of getting to an even distribution is also better. You can keep a track of the four segments and add to whatever segment seems to be furthest away from it's target average. This is a greedy way to do this.
Keep in mind that your array could be horribly skewed.
Say the average is 6 and your array looks like
{ 24 , 0 , 0 , 0 , 0 ,0 , 0 , 0}
The ONLY distribution possible here would be
{24} ,{ 0 } , {0 , 0 ,0 },{0 , 0 ,0 }
Perhaps find the average of each group like so: (1+1+4+2+2+3+5+6)/4=6 and keep track of the total sum of each group. If it is in a certain [allowable] range, say 1 or 2, then proceed to the next list.

Searching for the amount of integers in multiple ArrayLists

I have been thinking about this, but i havent been able to come up with a solution.
I have 9 ArrayLists, which can have Integers from 1 to 10.
What i want to do is:
Find 2 Numbers(from 1 to 10), that occur in exactly 2 of these ArrayLists( Must be the same Array. For Example, the number 2 and 3 both appear only in List1 and List)4. Preferably also know in which ArrayLists these numbers occured.
Thanks for any help in advance
One method:
First: Create a Map<Integer, BitSet>. Call it m.
Next: Iterate through the 9 ArrayLists that you have. For each number n that you encounter in array #a:
m.putIfAbsent(n, new BitSet(9)); // Make there the number has a BitSet to start
m.get(n).set(a); // Set the bit indicating number n is in array a
After that, you just need to look for two BitSets in your Map having cardinality() == 2 and are BitSet.equals() equal to each other.

Partition array into K subsets of same sum value

trying to figure out following problem:
Given a set S of N positive integers the task is to divide them into K subsets such that the sum of the elements values in every of the K subsets is equal.
I want to do this with a set of values not more than 10 integers, with values not bigger than 10 , and less than 5 subsets.
All integers need to be distributed, and only perfect solutions (meaning all subsets are equal, no approximations) are accepted.
I want to solve it recursively using backtracking. Most ressources I found online were using other approaches I did not understand, using bitmasks or something, or only being for two subsets rather than K subsets.
My first idea was to
Sort the set by ascending order, check all base cases (e.g. an even distribution is not possible), calculate the average value all subsets have to have so that all subsets are equal.
Going through each subset, filling each (starting with the biggest values first) until that average value (meaning theyre full) is achieved.
If the average value for a subset can't be met (undistributed values are too big etc.), go back and try another combination for the previous subset.
Keep going back if dead ends are encountered.
stop if all dead ends have been encountered or a perfect solution was found.
Unfortunately I am really struggling with this, especially with implementing the backtrack and retrying new combinations.
Any help is appreciated!
the given set: S with N elements has 2^N subsets. (well explained here: https://www.mathsisfun.com/activity/subsets.html ) A partition is is a grouping of the set's elements into non-empty subsets, in such a way that every element is included in one and only one of the subsets. The total number of partitions of an n-element set is the Bell number Bn.
A solution for this problem can be implemented as follows:
1) create all possible partitions of the set S, called P(S).
2) loop over P(S) and filter out if the sum of the elements values in every subsets do not match.

Matching Algorithm (Java)

I am writing an algorithm to match students with different groups. Each group has a limited number of spots. Each student provides their top 5 choices of groups. The students are then placed into groups in a predetermined order (older students and students with perfect attendance are given higher priority). There is no requirement for groups to be filled entirely, but they cannot be filled passed capacity.
I've looked into similar marriage problems such as the Gale-Shapely stable marriage algorithm, but the problem I am having is that there far fewer groups than students and each group can accept multiple students.
What is the best way to implement such an algorithm to find a solution that has been optimized entirely such that there is no better arrangement of students in groups? In terms of algorithm complexity, I'm placing roughly 600 students into 10-20 groups.
NB The close votes are terribly misplaced. Algorithm choice and design to solve an ambiguous problem is absolutely part of programming.
I think you'll get farther with Minimum Weight Bipartite Matching than Stable Marriage (also called the Hungarian method or algorithm or Maximum Weight Matching, which can give you a min weight matching just by negating the weights).
You are out to match positions with students. So the two node types in the bipartite graph are these.
The simplest statement of the algorithm requires a complete weighed bipartite graph with equal numbers of nodes in each set. You can think of this as a square matrix. The weights are the elements. The rows are students. The columns are positions.
The algorithm will pick a single element from each row/column such that the sum is minimized.
#nava's proposal is basically a greedy version of MWBM that's not optimal. The true Hungarian algorithm will give you an optimal answer.
To handle the fact that you have fewer positions than students is easy. To the "real" positions add as many "dummy" positions as needed. Connect all these to all the students with super high-weight edges. The algorithm will only pick them after all the real positions are matched.
The trick is to pick the edge weights. Let's call the ordinal where a student would be considered for a position O_i for the i'th student. Then let R_ip be the ranking that the same student places on the p'th position. Finally, W_ip is the weight of the edge connecting the i'th student to the p'th position. You'll want something like:
W_ip = A * R_ip + B * O_i
You get to pick A and B to specify the relative importance of the students' preferences and the order they're ranked. It sounds like order is quite important. So in that case you want B to be big enough to completely override students' rankings.
A = 1, B = N^2, where N is the number of students.
Once you get an implementation working, it's actually fun to tweak the parameters to see how many students get what preference, etc. You might want to tweak the parameters a bit to give up a little on the order.
At the time I was working on this (late 90's), the only open source MWBM I could find was an ancient FORTRAN lib. It was O(N^3). It handled 1,000 students (selecting core academic program courses) in a few seconds. I spent a lot of time coding a fancy O(N^2 log N) version that turned out to be about 3x slower for N=1000. It only started "winning" at about 5,000.
These days there are probably better options.
I would modify the Knapsack problem (Knapsack problem, wikipedia) to work with K numbers of groups (knapsacks) instead of just one. You can assign "value" to the preferences they have and the number of spots would be the maximum "weight" of the Knapsack. With this, you can backtrack to check what is the optimal solution of the problem.
I am not sure how efficient you need the problem to be, but I think this will work.
the most mathematically perfect
is very opinion based.
simplicity (almost) always wins. here
Here is a pseudocode:
students <-- sorted by attendance
for i=0 to n in students:
groups <-- sorted by ith student's preference
for j=0 to m in groups:
if group j has space then add student i to group j; studentAssigned=true; break;
if studentAssigned=false;
add i to unallocated
for i=0 to k in unallocated
allocate i to a random group that is not filled
For each group:
create an ordered set and add all the students (you must design the heuristic which will order the students inside the set, which could be attendance level multiplied by 1 if the group is within their choice, 0 otherwise).
Fill the group with the first nth students
But there are some details that you didn't explain. For example, what happen if there are students that couldn't enter any of their 5 choices because they got full with other students with higher priority?

Java permutations of offsets

Had a question regarding generating a list of 10-digit phone numbers on a PhonePad, given a set of possible moves and a starting number.
The PhonePad:
1 2 3
4 5 6
7 8 9
* 0 #
Possible moves:
The same number of moves a Queen in chess can make (so north, south, east, west, north-east, north-west, south-east, south-west... n-spaces per each orientation)
Starting number: 5
So far I have implemented the PhonePad as a 2-dimensional char array, implemented the possible moves a Queen can make in a HashMap (using offsets of x and y), and I can make the Queen move one square using one of the possible moves.
My next step is to figure out an algorithm that would give me all 10-digit permutations (phone numbers), using the possible moves in my HasMap. Repetition of a number is allowed. * and # are not allowed in the list of phone numbers returned.
I would imagine starting out with
- 5555555555, 5555555551, 5555555552... and so on up to 0,
- 5555555515, 5555555155, 5555551555.. 5155555555.. and with the numbers 2 upto 0
- 5555555151, 5555551515, 5555515155.. 5151555555.. and with numbers 2 upto 0
... and so on for a two digit combination
Any suggestions on a systematic approach generating 10-digit combinations? Even a pseudocode algorithm is appreciated! Let me know if further clarification is required.
Thanks in advance! :)
In more detail, the simplest approach would be a recursive method, roughly like:
It accepts a prefix string initially empty, a current digit (initially '5'), and a number of digits to generate (initially 10).
If the number of digits is 1, it will simply output the prefix concatenated with the current digit.
If the number of digits is greater than 1, then it will make a list of all possible next digits and call itself recursively with (prefix + (current digit), next digit, (number of digits)-1 ) as the arguments.
Other approaches, and refinements to this one, are possible of course. The "output" action could be writing to a file, adding to a field in the current class or object, or adding to a local variable collection (List or Set) that will be returned as a result. In that last case, the (ndigits>1) logic would have to combine results from multiple recursive calls to get a single return value.

Categories