Recursive algorithm for Budgeted Itinerary - java

I'm trying to solve a recursive problem. However, failing to come up with a working solution. When working with recursive problems I usually start by making an iterative one then converting it, but in this case, I was not able to do so...
The input is a list of n items given by their unit prices from least to most expensive, and a budget value; all positive integers.
method(int unitPriceList[], int budget )
Unit Price List = [ 3 , 7 , 9 ]. Budget = 18
The output prints all possible saturated itineraries as a list of item quantities, one list per line, each followed by its total price on the same line. The term saturated means that it is within budget, but it will fail to be within budget if we add any more item to it.
Quantities = [ 0 , 0 , 2 ]. Total Price = 18.
Quantities = [ 1 , 2 , 0 ]. Total Price = 17.
Quantities = [ 0 , 1 , 1 ]. Total Price = 16.
...
The number of saturated itineraries = …
I would be really appreciative if you could point me in the right direction to solve this problem.

This would be a case of the "all combinations of coins" problem. Find a solution for that. To convert to your case, add a unit coin (Price == 1). Now, reject any solution that has as many unit coins as your cheapest price (3 in this case).
Restating, you're looking for a count of the ways you can make 18 cents with coin denominations of (1, 3, 7, 9) -- but you can't use more than two 1-cent coins. That would require trading in those coins for a higher denomination.
Does that get you moving?

Related

How to change probability of random numbers

First of all, I did a search on this topic but I could not found anything similar to what I'm trying to accomplished, so this could be a duplicate question.
I would like to have a function that returns a number (1 or 2) with a probability of 0.8% for the number one and 0.2% for the number two.
How can I do it?
Generate a random number between 0 and 1. If the number is between 0 and 0.8, return 1. else, return 2:
return rnd.nextFloat() < 0.8 ? 1 : 2;
You just make intervals, and if your random number fits in the interval, you have a hit. In this most simple example, you make intervals 1-4 and 5. So you fetch random number from 1 to 5. if it's a 1-4 (80% probability) you act as it's 1, and if it's 5 (20% probability) you act as it's 2.
For example, make an array of 100 numbers. 20 numbers with number two, and 80 numbers with number one.
Use the Random class to generate a number between 0 and 100. Then you use that number to get the result from the array.
This is just an example, you can use another values in the array.

Dynamic Programing to generate combinations

I had a technical phone interview and I was doing well until i was asked this question. I was totally lost i had very little idea on how to solve such a problem.
You are given the following inputs: Total Score, Number of Players, Scores by each player. Sample Input would be
10 4 3 5 5 7
Where
10 = Total Score
4 = 4 players
3 = Score by player 1
5 = Score by player 2
5 = Score by player 3
7 = Score by player 4
You are to print out any combination that equals the total score. For instance we know player 4 and player 1 can have combine score of total score 10. So output for the above answer would be
1 4
1 = INDEX of player 1 4 = INDEX of player 4. Yes i know index of player 1 is technically 0 but they said print it out as such. If no combination matched you can print out none or anything you like . That didn't matter.
MY ATTEMPT
Well rather than being silent i first told interviewer i can use brute force approach to solve this. He said of course but we need better run time.
So i started thinking we could find all the possible combinations that could lead the total dollar and use MEMOIZATION to store the previously stored values. I was not able to think of a way of generating all combos and so i got stuck there.
Update
He also mentioned the maximum score i can give you is 1000. I am not even sure why this matters?
I would appreciate if someone can stir me in right direction or even provide pseudo/working java sample of how to solve such a problem. I think this is a generic problem and i really wanna understand how to solve this problem
This is the subset sum problem, and assuming your scores are relatively small integers, it can be solved in pseudo-polynomial time using DP:
D(i,0) = 1
D(0,x) = 0 x > 0
D(i,x) = D(i-1, x) + D(i-1, x-arr[i])
The above recursion formulas will generate the matrix of size total_score X num_players. The number of possible combination is denoted in the bottom right entry of the matrix.
The idea is to mimic an exhaustive search, for each person you can either add it or not add it, and invoke the recurse to a smaller problem.
Pseudo code for DP solution:
Input:
let W be the total score
let arr be the array of players scores
let n be the size of arr
Pseudo Code:
declare 2d array D of size W+1 X n+1
//initialization of "borders":
for each i from 0 to n+1:
D[i][0] = 1
for each x from 1 to W+1
D[0][x] = 0
//the DP:
for each i from 1 to n+1:
for each x from 1 to W+1:
if arr[i] < x:
D[i][x] = D[i-1][x]
else:
D[i][x] = D[i-1][x] + D[i-1][x-arr[i]]
//by here you have the matrix D filled up
//the wanted value is D[n][W]
return D[n][W]

Is the 0/1 knapsack algorithm a suitable candidate here?

I have three categories of input , each with a impact range.
Cat 1 : 20 - 16
Cat 2 : 15 - 5
Cat 3 : 4 -1
I have a file with say N randomly generated categories.
I am trying to take a sum of impact for all the 100 entries through a logic that looks something like this :
// calculate sum of impacts
getSum(){
Generate a random class with seed as current system execution time
for(as many entries in file){
switch(category)
case 1 : i = random input between 20 - 16
case 2 : i = random input between 15 - 5
case 3 : i = random input between 4 - 1
some default case here
sum = sum + i
}
return sum
}
.
.
// loop until you get a desired sum
while(true){
if(Call to getSum() returns value within a desired range){
display some statistics;
break;
}
}
However , i see that the program generally runs infinitely , as the random generation and subsequent summation is giving result beyond the desired range. So , to get things in range , I have to manually tune the max-min ranges for each execution.
Can someone suggest an algorithm that will automatically vary the max min ranges for each category , by learning the trend of obtained sum as the program is running , so as to quickly give a solution ?
Edit : i have just read about the 0/1 knapsack algorithm.. and it seems promising , but unsure if that is the algorithm for this case. Any help would be great.
A couple band-aids:
1) use a long int instead of a regular int t give you a longer range.
2) use an unsigned long, since all of your relevant numbers are positive (then be careful of underflow errors when you subtract.
A couple possible strategies:
1) (This contradicts your question, but it is how things are usually done.) Determine the static maximum for each category, and design to it, using long unsigned int if that is large enough, or some larger data structure as necessary.
2) (This is exactly what you are asking.) Use, and build if necessary, a data structure which expands when an overflow occurs.
Solution for strategy 2:
I will get back to you on this. :)

Generate N random numbers in given ranges that sum up to a given sum

first time here at Stackoverflow. I hope someone can help me with my search of an algorithm.
I need to generate N random numbers in given Ranges that sum up to a given sum!
For example: Generatare 3 Numbers that sum up to 11.
Ranges:
Value between 1 and 3.
Value between 5 and 8.
value between 3 and 7.
The Generated numbers for this examle could be: 2, 5, 4.
I already searched alot and couldnt find the solution i need.
It is possible to generate like N Numbers of a constant sum unsing modulo like this:
generate random numbers of which the sum is constant
But i couldnt get that done with ranges.
Or by generating N random values, sum them up and then divide the constant sum by the random sum and afterwards multiplying each random number with that quotient as proposed here.
Main Problem, why i cant adopt those solution is that every of my random values has different ranges and i need the values to be uniformly distributed withing the ranges (no frequency occurances at min/max for example, which happens if i cut off the values which are less/greater than min/max).
I also thought of an soultion, taking a random number (in that Example, Value 1,2 or 3), generate the value within the range (either between min/max or min and the rest of the sum, depending on which is smaller), substracting that number of my given sum, and keep that going until everything is distributed. But that would be horrible inefficiant. I could really use a way where the runtime of the algorithm is fixed.
I'm trying to get that running in Java. But that Info is not that importend, except if someone already has a solution ready. All i need is a description or and idea of an algorithm.
First, note that the problem is equivalent to:
Generate k numbers that sums to a number y, such that x_1, ..., x_k -
each has a limit.
The second can be achieved by simply reducing the lower bound from the number - so in your example, it is equivalent to:
Generate 3 numbers such that x1 <= 2; x2 <= 3; x3 <= 4; x1+x2+x3 = 2
Note that the 2nd problem can be solved in various ways, one of them is:
Generate a list with h_i repeats per element - where h_i is the limit for element i - shuffle the list, and pick the first elements.
In your example, the list is:[x1,x1,x2,x2,x2,x3,x3,x3,x3] - shuffle it and choose first two elements.
(*) Note that shuffling the list can be done using fisher-yates algorithm. (you can abort the algorithm in the middle after you passed the desired limit).
Add up the minimum values. In this case 1 + 5 + 3 = 9
11 - 9 = 2, so you have to distribute 2 between the three numbers (eg: +2,+0,+0 or +0,+1,+1).
I leave the rest for you, it's relatively easy to create a uniform distribution after this transformation.
This problem is equivalent to randomly distributing an excess of 2 over the minimum of 9 on 3 positions.
So you start with the minima (1/5/3) and then cycle 2 times, generating a (pseudo-)random value of [0-2] (3 positions) and increment the indexed value.
e.g.
Start 1/5/3
1st random=1 ... increment index 1 ... 1/6/3
2nd random=0 ... increment index 0 ... 2/6/3
2+6+3=11
Edit
Reading this a second time, I understand, this is exactly what #KarolyHorvath mentioned.

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

Categories

Resources