Permutations of a league schedule - java

Creating league scheduling software and have a math question that I need a little help wrapping my head around.
Say you have 4 teams(for simplicity) and you check every possible permutation of 1,2,3,4. This permutation is only called the first week which gives you 24 possible permutations.
1,2,3,4 is a permutation and say Week 1 1X4 is a game 2X3 is a game.
Week Two's combination of game is set via round robin so 4,1,2,3 is up next; 4X3 1X2 are the game.
My question is that if week two's combination of games does not work (because of constraints) but instead an order of 3,4,1,2 would work would this ever be checked by performing the permutation on week 1? i.e. week 1 was 1,2,3,4 week 2 was 3,4,1,2
Or would I need to permute week 1 then permute week 2 and so on and so on to actually get every possible schedule. My gut is telling me that I do actually need to permute every week in order to actually get every possible permutation of the schedule.
EDIT:
I'm asking if there were four weeks would my permutations calculator be 24*24*24*24 not just 24.

To answer your question directly, just checking all permutations for week 1 will not necessarily result in all possible permutations being checked. Test with some simple samples and you'll see that fairly quickly
It looks to me as if you need a standard Backtracking algorithm. These are designed for exactly these types of problems with constraints.
The general form would be something like
function permutation
if all current matches satisfy constraints
if any weeks remaining to be allocated
for each possible match for next week
call permutation with that match added
else
accept this solution
The assumption is that there are enough constraints that few permutations will be legal. However if many permutations are legal then the process of accepting the solutions will need to take this into account in how they are processed.

As far as I am concerned this solution may help you.
First you take an input that is week from user.After that you compute permutation of week.
And Finally, multiply with power of week.
public class Schedule {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter week");
int x = scan.nextInt();
int y = (int) Math.pow(permutation(x), x);
System.out.println(y);
}
public static int permutation(int week) {
int y;
if (week == 1) {
return 1;
} else {
y = week * permutation(week - 1);
}
return y;
}
}

Related

Java exam prep - Recursion task [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
This is my task:
Use recursion to find 13th member of an array where every member is multiplication of last two members minus the second member. First two members are 3 and 3.
This is what I came up with:
public class Zadatak2 {
int array[] = {3,3,0,0,0,0,0,0,0,0,0,0,0};
public Zadatak2(){
find13(2);
}
public int find13(int index){
if (index == 13){
System.out.println("Member 13: " + array[index-1]);
return 0;
}
else{
array[index] = array[index-1] * array[index-2] - array[1];
System.out.println(index + " : " + array[index]);
return find13(index + 1);
}
}
}
Console output where I see index in array : value :
2 : 6
3 : 15
4 : 87
5 : 1302
6 : 113271
7 : 147478839
8 : 1947758222
9 : 465247871
10 : 818773103
11 : -459621106
12 : 383828239
Member 13: 383828239
But I am pretty sure I made a mistake or there is a better solution. Any help is appreciated.
As Kevin W. said in a comment, in the future, "if you want someone to review your code... use the codereview stackexchange". However, here are a few suggestions.
Firstly, as something to keep in mind, the problem you have is a lot like calculating the fibonacci sequence, and there are probably plenty of examples of using recursion to calculate members of that sequence.
Secondly, the way you built your recursive function makes it limited to being used only to find the 13th number in the sequence. You begin at the start of the sequence and work your way up to the 13th number, and what you are doing is basically an iterative solution to the problem with minor tweaks to make it work via recursion.
A better approach would be to generalize your function so that you can pass the sequence member number as a parameter, and the function will calculate it via recursion. The way to do this is to start at your target member number and through recursion, get the members required to make that member. This allows the function to be used to calculate any number in the sequence, not just the 13th number. It also has the added benefit that your code can be both shrunk and do more.
This is the code:
// index is the member number; it is 1 based e.g. index of 1 gives the first number in the sequence
int find(int index)
{
if (index == 1 || index == 2)
return 3;
return (find(index - 1) * find(index - 2)) - find(2);
}
When solving problems with recursion, the method generally used is to start with the problem you want to solve and break it down (as shown in my code above), rather than start with subproblems to find the larger problem (as your code shows).
When applying recursion to a sequence, write out the mathematical definition of the sequence first, and that is what must be returned from the recursive function. For example, in your problem, the definition is
a[n] = (a[n-1] * a[n-2]) - a[2]
Now take a look at the solution I wrote. What I am returning is precisely this sequence definition, just in terms of the recursive function. The base case at the beginning of the function is simply the initial member(s) required to calculate the rest of the sequence. I encourage you to work the algorithm through on paper and play with it to see exactly what is happening.
As a final note, this algorithm is horrendous in terms of run time. There are three recursive calls per call to find(), which means that finding the 13th member is on the order of 3^13, which is exponential. Exponential algorithms are terrible algorithms, and should always be avoided.
If the recursion is examined closely you can see that in order to calculate a[n], the code calculates a[n-1] and a[n-2]. But in order to calculate a[n-1], a[n-2] and a[n-3] are both calculated, meaning that a[n-2] is calculated TWICE. This observation is very important because we only went down one level of recursion. There are a total of about 3^13 member calculations occurring when all there should be are 13 (for the 13 members). All of that time performing the same calculations millions of times is a horrendous waste and is what makes exponential algorithms so awful.
So what if we stored each of the members that the function calculates? This technique is called dynamic programming, and is where answers to subproblems are stored on the way to solving a larger problem so calculations are not performed multiple times. The solution implementing dynamic programming is:
// a variable that persists across function calls such as an instance field
int[] array = new int[20]; // just giving some extra memory in case you want to calculate other members
array[0] = -1; //invalid member of the sequence since it is 1-based
array[1] = 3;
array[2] = 3;
//set the rest of the numbers to values letting you know they have not been set/found/calculated yet
for (int i = 3; i < 20; i++)
{
array[i] = -1;
}
// index is the member number; it is 1 based e.g. index of 1 gives the first number in the sequence
int find(int index)
{
if (array[index] != -1) //if already calculated that member, just return it
return array[index];
//store the answer
array[index] = (find(index - 1) * find(index - 2)) - find(2);
return array[index];
}
With this code, you can call find() for any number and it will calculate it for you, instead of just the 13th number.
Lastly, and most importantly, as Kevin W. pointed out in a comment, the presence of a negative number as a member means that you are getting numbers too big for ints. Luka Milosevic says that the 13th member is actually a number x10^90, which is too big for a long even. Doubles can work as long as you don't need more than 20 or so digits of precision, but because of at least 90 digits in the answer, doubles are not accurate enough. Fortunately Java has a class called BigInteger, which can store as large of numbers as you want, regardless of size. In order to obtain your answer, you probably have to use them, unless you want to do the math manually. The documentation for BigInteger is here.
As this is a task you were assigned to do I would like to give you a hint only. In our case a recursive function would call itself with a lower argument and finally end with some defined values.
In our case the lower values f(1) and f(2) are already defined as 3.
So f(n) = f(n-1) * f(n-2) - f(2) where f(1) = 3 and f(2) = 3.
(If I understood the task right)
Now your job is to do the coding and find f(13).
Does it help?

Arrangements of sets of k positions in a n-competitors race

this is a copy of my post on mathexchange.com.
Let E(n) be the set of all possible ending arrangements of a race of n competitors.
Obviously, because it's a race, each one of the n competitors wants to win.
Hence, the order of the arrangements does matter.
Let us also say that if two competitors end with the same result of time, they win the same spot.
For example, E(3) contains the following sets of arrangements:
{(1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,2), (2,1,1), (2,1,2),(2,1,3), (2,2,1), (2,3,1), (3,1,2), (3,2,1)}.
Needless to say, for example, that the arrangement (1,3,3) is invalid, because the two competitors that supposedly ended in the third place, actually ended in the second place. So the above arrangement "transfers" to (1,2,2).
Define k to be the number of distinct positions of the competitors in a subset of E(n).
We have for example:
(1,1,1) -------> k = 1
(1,2,1) -------> k = 2
(1,2,3,2) -------> k = 3
(1,2,1,5,4,4,3) -------> k = 5
Finally, let M(n,k) be the number of subsets of E(n) in which the competitors ended in exactly k distinct positions.
We get, for example,M(3,3) = M(3,2) = 6 and M(3,1) = 1.
-------------------------------------------------------------------------------------------
Thus far is the question
It's a problem I came up with solely by myself. After some time of thought I came up with the following recursive formula for |E(n)|:
(Don't continue reading if you want to derive a formula yourself!)
|E(n)| = sum from l=1 to n of C(n,l)*|E(n-l)| where |E(0)| = 1
And the code in Java for this function, using the BigInteger class:
public static BigInteger E (int n)
{
if (!Ens[n].equals(BigInteger.ZERO))
return Ens[n];
else
{
BigInteger ends=BigInteger.ZERO;
for (int l=1;l<=n;l++)
ends=ends.add(factorials[n].divide(factorials[l].multiply(factorials[n-l])).multiply(E(n-l)));
Ens[n]=ends;
return ends;
}
}
The factorials array is an array of precalculated factorials for faster binomial coefficients calculations.
The Ens array is an array of the memoized/cached E(n) values which really quickens the calculating, due to the need of repeatedly calculating certain E(n) values.
The logic behind this recurrence relation is that l symbolizes how many "first" spots we have. For each l, the binomial coefficient C(n,l) symbolizes in how many ways we can pick l first-placers out of the n competitors. Once we have chosen them, we to need to figure out in how many ways we can arrange the n-l competitors we have left, which is just |E(n-l)|.
I get the following:
|E(3)| = 13
|E(5)| = 541
|E(10)| = 102247563
|E(100)| mod 1 000 000 007 = 619182829 -------> 20 ms.
And |E(1000)| mod 1 000 000 007 = 581423957 -------> 39 sec.
I figured out that |E(n)| can also be visualized as the number of sets to which the following applies:
For every i = 1, 2, 3 ... n, every i-tuple subset of the original set has GCD (greatest common divisor) of all of its elements equal to 1.
But I'm not 100% sure about this because I was not able to compute this approach for large n.
However, even with precalculating factorials and memoizing the E(n)'s, the calculating times for higher n's grow very fast.
Is anyone capable of verifying the above formula and values?
Can anyone derive a better, faster formula? Perhaps with generating functions?
As for M(n,k).. I'm totally clueless. I absolutely have no idea how to calculate it, and therefore I couldn't post any meaningful data points.
Perhaps it's P(n,k) = n!/(n-k)!.
Can anyone figure out a formula for M(n,k)?
I have no idea which function is harder to compute, either E(n) or M(n,k), but helping me with either of them will be very much appreciable.
I want the solutions to be generic as well as work efficiently even for large n's. Exhaustive search is not what I'm looking for, unfortunately.
What I am looking for is solutions based purely on combinatorial approach and efficient formulas.
I hope I was clear enough with the wording and what I ask for throughout my post. By the way, I can program using Java. I also know Mathematica pretty decently :) .
Thanks a lot in advance,
Matan.
E(n) are the Fubini numbers. M(n, k) = S(n, k) * k!, where S(n, k) is a Stirling number of the second kind, because S(n, k) is the number of different placing partitions, and k! is the number of ways to rank them.

Generating Random Numbers from 1-100

int getnum50()
{
Random rand = new Random();
return (1+rand.nextInt(50));
}
You are given a predefined function named getnum50() which returns an
integer which is one random number from 1-50.
You can call this function as many times as you want but beware
that this function is quite resource intensive.
You cannot use any other random generator. You can NOT change the
definition of getnum50().
Print numbers 1-100 in random order. (Not 100 random numbers)
Note:
i. Every number should be printed exactly once.
ii. There should be no pattern in the numbers listing. List should be
completely random i.e., all numbers have equal probability
appearing at any place.
iii. You may call getnum50() any number of time to get random number
from 1 to 50 but try to make the code optimised.
iv. You cannot use any other random generator function except
getnum50().
I wrote some code which was showing correct output.
import java.util.Random;
public class RandomInteger{
int number[]=new int[100];//To store numbers in random order
public RandomInteger(){
int n[]=new int[100];//array to store which random numbers are generated
int off[]={-1,0};//offset to add
System.out.println("Length of array number100 is:"+number.length);
System.out.println("Generating random numbers in the range 1-100:");
for(int n1=0;n1<number.length;n1++){
int rnd=off[(getnum50()-1)/50]+(getnum50()*2);
if(n[rnd-1] == 0){
n[rnd-1]=1;//to indicate which random number is generated
number[n1]=rnd;
System.out.println(number[n1]+" ");
}
}
}
//end of constructor
int getnum50(){
Random rand = new Random();
return (1+rand.nextInt(50));
}
public static void main(String args[]){
RandomInteger m= new RandomInteger();
}
//end of main()
}
//end of class
While it was accepted in that round, in the next round the interviewer tells me that getnum50() is a costly method and even in best case scenario I have to call it twice for every number generated. i.e. 200 times for 1-100. In worst case scenario it would be infinity and tens of thousand in average case. He asks me to optimize the code so as to significantly improve the average case.
I could not answer.So please give me proper answer for the question? How will I optimize my above code??
One stupid optimization would be be to just realize that since your randomized source is limited to 1-50, you might as well set TWO array positions, e.g.
rand = getnum50();
n[rand] = 1;
n[rand+50] = 1;
Now the array will be slightly "less" random, because every index n is going simply be 1/2 of whatever's at n+50, but at least you've cut ~half the build array construction time.
I think they want you to produce a shuffle algorithm.
In this, you start with an array of exactly 100 numbers ( 1 through 100 in order ), and then on each iteration you shuffle the numbers.
Do it enough times, and the original array is completely random.
The 50 is a red herring. Use two calls to random50, mod 10. Now you have two digits: tens and ones place. This gives you a random100() function.
The real killer is the generate-and-check approach. Instead, put the numbers 1-100 into an arraylist, and use your random100 to REMOVE a random index. Now your worst case scenario has 2n calls to random50. There's a few problems left to solve - overruns - but that's the approach I'd look at.
Your problem us that if you are toward the end of the list you will have to generate lots of random numbers to get a number in the couple of spots left. You could reduce a couple of ways one the fits into your current answer fairly will is as follows:
while(n[rnd-1] == 1)
{
rnd++;
rnd=end%101;
}
n[rnd-1]=1;//to indicate which random number is generated
number[n1]=rnd;
System.out.println(number[n1]+" ");
However if you assume that the getnum50 is more expensive than anything you can write you could reduce the number of getnum50 that you call while filling in the second half of the list. Each time you find a number you could reduce your search space by one so (using non primitives):
while(myArrayList.size()>1)
{
int rnd=0;
if(myArrayList.size()>50);
rnd=((getnum50()-1)/50)+((getnum50()*2)%myArrayList.size())+1;
else
rnd=getnum50()%myArrayList.size()+1;
System.out.println(rnd);
myArrayList.remove(rnd);
}
System.out.println(myArrayList.get(rnd);
myArrayList.remove(rnd);
In this example your best, average and worst are 149 getnum50 calls;
The reason you are calling the method getnum50() twice is because of this line:
int rnd = off[(getnum50()-1)/50] + (getnum50()*2);
which seems self-explanatory. And the reason your worst case scenario is so bad is because of this block:
if(n[rnd - 1] == 0){
n[rnd - 1] = 1; //to indicate which random number is generated
number[n1] = rnd;
System.out.println(number[n1] + " ");
}
Depending on how bad your luck is, it could take a very long time to get each value. So, best case, you make your two getnum50() calls, which WILL happen the first time, but as you fill up your array, it becomes increasingly less likely. For 100 numbers, the last number will have a 1% chance of success on the first time, and every time it fails, you make another two calls to getnum50().
Sorry, this doesn't answer HOW to improve your efficiency, but it does explain why the efficiency concerns. Hope it helps.

java random number generator - lottery

My code will seem amateurish as I am a software engineering student in 2nd year.
I created a lottery number generator and have noticed peculiar but consistent results. My program attempts to match the previous lottery numbers for the Euro Millions draw. I track the number of attempts it takes and i also track the number of times I match 3, 4, 5 and 6 numbers.
The attempts range between 1 million and 422 million. i.e. I would run the program 10 times and I would achieve a range, I would also track the length of time each run takes.
I account for a number of things like preventing a random number from being used more than once and this check is done against a HashMap of the possible lottery numbers. If I find the random number within the hashmap I add the number to an arraylist and then remove the number from the hashmap.
My questions surrounds the results.
In all attempts to match the lottery numbers my chance of getting 3 numbers was 3.13% on average. For 4 numbers it dropped to 0.28%, 5 numbers 0.00012% and 6 numbers 0.00022%.
Understandably The chance of winning as the number of lottery numbers increase is going to decrease however whether I had 1 million or 100 million attempts the ratio was the same or extremely close.
If you are interested my smallest number of attempts was 1,088,157, it took approximately 6 seconds or 6612ms.
Largest number of attempts was 422,036,905 and it took 26mins or 1589867ms.
Since I am using the Java Random library I am merely looking for some clarity on this. Or should I simply put it down to probability?
My code is an unnecessary 225 lines, if you would like to see a particular part or prefer to see the whole thing then please request this. Here is a sample below of the random number generation for the first 5 numbers.
//stores all possible lottery numbers
public static HashMap<Integer,Integer> randRange = new HashMap<Integer,Integer>();
//stores bonus ball numbers
public static HashMap<Integer,Integer> boRange = new HashMap<Integer,Integer>();
//stores lottery number output
public static ArrayList<Integer> lotNum = new ArrayList<Integer>();
//stores bonus ball output
public static ArrayList<Integer> boNum = new ArrayList<Integer>();
public static void randomInt(){
Random rand = new Random();
//generate a random number
int RandInt = rand.nextInt(51);
int boInt = rand.nextInt(12);
//loop used to get unique random number
int count=0;
while(count!=5){
//check if random number exists
if(randRange.get(RandInt)!=null)
{
//finalise random number
RandInt=randRange.get(RandInt);
//add to ArrayList
lotNum.add(RandInt);
//remove number
//ensures next random number is unique
randRange.remove(RandInt);
count++;
}
else
{
//get a new random number
//and start process again
RandInt = rand.nextInt(51);
}
}
}
EDIT:
First of all sorry I couldn't upvote as I have less than 15 reputation. All answers were helpful including comments.
Thanks to the suggestions by all members I improved my program and discovered unsurprisingly a fault in my code. #digitaljoel you were correct in the probability of matching 5 and 6 numbers. I set up the calculation incorrectly, e.g. for the numbers 11,20 30,35,45,2,3 for the euromillions draw to match 3 was 0.7%, 4 was .05%, 5 was .00273% and 6 was .000076%.
Thanks to #maybewecouldstealavan I changed my shuffling method to simply populate an ArrayList and shuffle the list, get the first five numbers and do the same for the bonus balls. The benefit was in the number of checks per second increasing from 150 - 200 thousand checks per second to 250-700 thousand checks per second.
Thanks to #trutheality as in some cases if i checked 1000 or 1,000,000 matches the variation was similar or minute.
#LeviX Appreciate again the calculation for the possible combinations. I used this within the program and found that it took more than the total number of combinations to win the lottery. Most likely I am producing duplicate random numbers. From this i will probably create all possible combinations and randomly select each combination until the program finds a match.
In all attempts to match the lottery numbers my chance of getting 3 numbers was 3.13% on average. For 4 numbers it dropped to 0.28%, 5 numbers 0.00012% and 6 numbers 0.00022%.
Understandably The chance of winning as the number of lottery numbers increase is going to decrease however whether I had 1 million or 100 million attempts the ratio was the same or extremely close.
That is actually not surprising at all. What you end up doing here is estimating the probability of guessing 3,4,5, or 6 numbers correctly. Having more samples will only make the variations in your estimates smaller, but even with "as little" as 1 million samples, your estimate is expected to be close to the exact probability (which you could calculate by doing some math).
Do you mean that you expect the proportion of times that you win to be more "random"? If that's what you're getting at, then #truthreality is quite correct. For further reading you might look at the law of large numbers and the central limit theorem.
If you're asking if your method of shuffling is correct, it is though it is inefficient. You're generating more random numbers than necessary, since you're just checking for dupes when they occur, and you're not creating a new random number after you pick a ball, so you're requiring a minimum of one HashMap.get(int) per pick.
I might use one of the following methods instead:
1) Create an ArrayList containing all the ball values. For each drawing, use Collections.shuffle(yourArrList, rand) to shuffle a clone of it them, then just use the first 5 balls from the list.
2) Again, create an Array or ArrayList of ball values. Then implement a portion of the shuffle operation yourself: Choose from smaller and smaller subsets of the possibilities and swap in the element that no longer fits into the place of the element that was just chosen. The advantage is that you don't need to shuffle the entire array. Here's my quick and dirty implementation:
public static int[] choose(int[] array, int count, Random rand) {
int[] ar = array.clone();
int[] out = new int[count];
int max = ar.length;
for (int i = 0; i<count; i++) {
int r = rand.nextInt(max);
//max is decremented,
//the selected value is copied out then overwritten
//by the last value, which would no longer be accessible
max--;
out[i]=ar[r];
ar[r]=ar[max];
}
return out;
}
There's probably room for improvement, especially if order doesn't matter.
From my understanding there are two different parts to the Euro Millions. The 5 balls and then the 2 bonus balls. You can check the math of your program by figuring out the exact probabilities of winning. I'm sure you can google it, but it's easy to calculate.
Probability of getting 5 balls out of 50 (order doesn't matter)
P(A) = 50!/5!(50-5)! = 2,118,760
Probability of getting 2 balls out of 11 (order doesn't matter)
P(B) 11!/2!(11-2)! = 55
The two events are independent so multiply them together.
P(A) * P(B) = P(A&B)
2,118,760 * 55 = 116,531,800
Therefore the chances of winning the lottery is:
1 in 116,531,800

How to calculate Lucas Numbers in Java

I am a starting programmer and need to program an application in java which ask for a number and then prints the first n number of Lucas Numbers. for example when 7 is put in, it outputs: 2, 1, 3, 4, 7, 11, 18.
Just to be clear, lucas numbers are defined as:
2 if n = 0
1 if n = 1
L(n-1) + L(n-2) if n>1
I am really not sure howver how to programm this in java. Because I cannot translate this into java code. I've been thinking for a while now but still can't figure it out. Also when i would have the code for calculating the Nth lucas number, i would now how to output all the first Lucan Numbers up until the Nth number. Can some of you guys help me gte on the right way or give me tips? Thanks a lot!
The definition you have for the Lucas number is recursive, i.e., to calculate the Nth lucas number, you already need to know the N-1th and the N-2nd.
A naive way to do this would be
public int lucas(int N) {
if( N == 0 ) return 2;
if( N == 1 ) return 1;
return lucas(N-1) + lucas(N-2);
}
However, you only have to print the numbers, don't you? Then it's quite easy, actually.
int L2 = 2;
int L1 = 1;
for( int i = 2; i <= N; i++ ) {
int L = L1 + L2;
print(L); //or whatever output function you have
L2 = L1;
L1 = L;
}
The idea is to keep the last two numbers, which you need to compute the next two numbers, always at hand.
PS: These Lucas numbers are just like the Fibonacci numbers with different starting values, so any algorithm for the Fibonacci numbers will do. If you're really good at math, you can even try to find a closed formula for the Lucas numbers, but it's definitely beyond high school math (search tag would be "linear difference equation with constant coefficients").
If you're not sure how to do the whole thing, break the problem down into smaller pieces until you can start.
Try taking each case, one at a time. Implement the '2 if n=0' case, test that it works. The calculation is trivial, but you will have to write the code that calls your implementation, too. The trivial case helps you check that the code around it works properly.
Then implement the next one, check it still works, implement the final one. It'll become clearer as you go.
Just in case someone is looking for a formula and happens on this page then maybe this will help. In Windows take the following line and replace each N with the desired integer, copy the modified line and paste it into Windows' calculator:
(5#/2+0.5)yN+(-(5#/2+0.5))y(-N)=
For example if you want to find the Lucus number for 7 you would paste this line into Windows' calculator:
(5#/2+0.5)y7+(-(5#/2+0.5))y(-7)=
And the result will be 29.

Categories

Resources