I'm trying to solve the famous "water jug puzzle" (like in the movie Die Hard with a Vengeance).
I solve easily the puzzle with supports of 2 jugs in C#.
But now I would like to achieve the same with N number of jugs (2, 3, 4, 5, ...). It completely changes the way the algorithm works.
My current solution works on the following principle :
Fill the m litre jug and empty it into n liter jug.
Whenever the m liter jug becomes empty fill it.
Whenever the n liter jug becomes full empty it.
Repeat steps 1,2,3 till either n liter jug or the m liter jug contains d litres of water.
Then, I repeat the operation by reversing the order of the jugs and I take the fastest solution between the two.
This system works great with 2 jugs but cannot work with more jugs.
Reminder of the rules: You have N jugs of water, each with a specific capacity. It is possible to fill a jug completely from a faucet, empty a jug completely into a sink, and transfer the contents of one jug to another (subject to available capacity of target and current fill of source).
The goal is to get ONE jug with a given amount of water (the goal) and find the fastest way to do it.
For example: Two jugs of 3 and 5 liters represented as an array of int [3, 5]. The goal is to have a jug with 4 (represented by an int). The function takes these two elements as parameters and displays the fastest path (if there is one).
The way to get there is (in 6 steps in this case):
(0,5)
(3,2)
(0,2)
(2,0)
(2,5)
(3,4)
As explained before, I solved this simple version with 2 jugs easily.
But how to do it with N jugs? Has anyone ever done something similar? Or have an idea?
The only precise operations are
FILL: Completely fill any jug from an infinite water supply.
EMPTY: Completely empty the contents of any jug.
POUR: Pour the contents of jug A into jug B until jug B is full or jug A is empty.
These operations perform, respectively:
amount[A] = capacity[A];
amount[A] = 0;
temp = min(available(B), amount[A]); amount[B] += temp; amount[A] -= temp;
With this special convenience function:
available(i) => capacity[i] - amount[i]
Perform a breadth first search from among these relatively few available operations until the desired amount of water exists in one of the jugs.
There are N choices of indices for operation 1 and 2 (FILL or EMPTY), and there are (N * N-1) choices for operation 3 (POUR), in other words choose a random A and a random B that is not equal to A.
Optimization Note
A useful optimization is to prevent enqueuing search states that have already been deemed reachable with fewer steps. A state here is at first glance represented by the values in the amount array, but can also be represented by the number of jugs of each unique capacity and amount, because the jugs themselves are not unique except for their capacity and current amount.
Related
This is an interview Question that I encountered recently .
You have G guests (numbered from 1 to G) in a party.Each Guest has a preference list of length G which represents his preferences to talk with others.
For example if the preference list of guest 1 is N Y N N Y (assuming 5 guests), then Guest 1 is interested to talk to either 2 or 5 but not others.
Assume that
a) Each guest can talk to only one other guest
b) If a is interested in talking to b , then b is also interested in talking to a
Given a matrix of guests and their preferences , Give maximum No of pairs that can be kept engaged.
Let G = 5;
The Preference matrix be
N Y N N N
Y N Y Y Y
N Y N N N
N Y N N N
N Y N N N
As We can observe everyone is interested in talking to Guest 2 but he can talk only to one other person and so the answer is 1 pair.
My Approach:
I thought of it as a Maximum matching Problem in graph theory but unable to implement it
in the short time frame.(I am not good in Graph Algo Implementation)
Is this solved only using graphs or is there some better , faster approach?
Is there any Greedy Approach ?
We can use recursion and some memoization. Please find a way to recognize a graph with K nodes and all relationships (we'll see below why we need this). During recursion we should record already solved cases (K, R) where K is the number of guests and R is the list of relationships of these K guests.
For the problem (N, R) we would number guests as 1, 2, ..., N, then scan through list of relationships to get a list with no repetition (a hash table may help checking for duplicates)
1 & 2, 1 & 4, 2 & 3, etc.
We need to find maximum of non-colliding pairs (for example, 1 & 2 collides with 2 & 3). We can use the following recursive algorithm:
A) if 1 & 2 is taken, then remove all pairs with 1 or 2, and do recursion on the rest.
RA will be the list of remaining relationships without 1 and 2. And we have recursion of ((N-2), RA)
B) if 1 & 2 are skipped, do recursion with the rest.
RB will be the list of remaining relationships without the link (1 & 2). And we have recursion of (N, RB) - still N because 1 or 2 may still remain in the full set.
C) Check what route render a bigger number of pairs.
We need memoization to store results of (K, R) because there may be clusters of guests like (1, 3, 5, ...) and (2, 4, 6, ...) where guests are friends of each other just inside the clusters.
If we use naive recursion, we'll solve the same problems many times. But the clusters mean that their solutions are symmetrical. Therefore we need to recognize the graphs by the combination of number of guests and their relationships (renumbering guests produces the same graph).
The recursion will split into two principal stages:
Simplification:
Remove guests without friends.
Divide graph into non-connected areas.
Further, for every area the next stage will be fulfilled:
Cutting
Order the guests up according to number of their friends.
Take the first untried connection into the found pairs list.
Repeat the whole process starting from simplification with the received diminished area until all connections are recursively tried or the number of pairs in the currently build set is equal to [Area power /2].
We could also improve the speed if we'll first try the connections that divide the area into two non-connected areas of even power.
I am trying to put a water jug problem into a heuristic function but I am finding some problems.
There are 2 jugs, one that can hold 5(x) and other that can hold 3(y) gallons of water. The goal is (y,x)=(0,4).
I can't figure out how to put it into a heuristic function and also I have a doubt about the number of states. If I admit the actions (fill one from the faucet, empty one to the drain, and pour from one to the other until either the receiving jug is full or the pouring jug is empty), there are 15 possible states, but if I consider all the possibilities regarding the number of gallons, there are 24 possibilities. Is that correct?
(0,0)
(3,0)(0,5)
(0,3)(3,5)(3,2)
(3,3) (0,2)
(1,5) (2,0)
(1,0) (2,5)
(0,1) (3,4)
(0,4)
I think that the Heuristic function for this problem can be defined as:
h(x,y) = (x * 5) + (y * 3)
but I also found this answer for a question (Heuristic function for Water Jug)
and now I am confused. Can anyone explain it to me please?
max(estimate_from_parent - action_cost, estimate_from_this_node)
Number of states and reachability:
You are correct about the theoretical number of states (assuming buckets can only have an integer number of gallons - otherwise it's infinite). Because there are 6 possible numbers of gallons that bucket X can contain and for 4 that bucket Y can contain, the total number of states is 6*4=24.
Technically, (3,1) is also reachable, after you find the solution, so there are 16 possible states.
Heuristic Function:
In terms of the heuristic function, you might want to take a second and think about your goal. You want to have four gallons in bucket x. So the closer you are to having four gallons in bucket x, the closer you are to your goal, and the lower the value of your heuristic function should be (since it's an estimated cost). The lowest value of your heuristic function, then, should occur when there are four gallons in bucket x. The heuristic function you proposed here, h(x,y) = (x * 5) + (y * 3), is lowest at (0,0). Since this is not your goal node, this isn't likely to be a good heuristic function.
In thinking of a heuristic function, it's often useful to find a constraint that makes your problem harder and then relax it. This facilitates coming up with a heuristic that is admissible and consistent, because your heuristic will basically be a best case estimate. For this problem, a pretty big constraint is that there are only certain amounts of water that you can add to bucket x (i.e. the amount in bucket y, or the amount that it would take to fill bucket x). We could relax this constraint, and basically end up with h(x,y) = |X-4| (the heuristic function discussed in the linked post, adapted to your problem). This is definitely admissible and consistent, as it is effectively the amount that it would cost to get to the goal from that node in one step if taking such a step were possible. If you are at the goal node, it will be equal to 0. Note that the way your costs are calculated is critical to making this a useful heuristic.
Does that clear up your confusion?
Given two state A and B,find out that is it possible to reach B from A moving optimally.
where each state says the current position of disks in respective pegs. Here the number of pegs are 3.
example
For N=3 disks and 3 pegs, the task is to move all the disk from peg 1 to 2 using peg 3
peg(disk number)
state A - 1(4), 2(3,2,1), 3(blank)
explanation- peg one has disk no 4, peg 2 has disk no. 3,2,1 and peg 3 has disk no. 3
state B - 1(2,1), 2(blank), 3(4,3)
For the above case the answer is true, its possible to move.
My current approach
For given N(no of disk),generate all the set put it in map, with generation time. For a given states compare the generation time and answer.
Problem
For larger N=10^4 or more, its not feasible to generate all the set bcz total number of set is 2^N. I hope that a linear or logarithmic solution exist here.
This question is for a program I am trying to write which involves connecting chains of physical parts together. I believe I have distilled it down into the simplest form of the question. I would also appreciate if someone knows any additional words that describe this problem, as about 30 min of searching for related questions hasn't even turned up a name for this problem.
You have N vectors. If you choose one value from each vector and do not allow any repeats, you will have one permutation of the type I am trying to find. What is a pseudo-code algorithm to find all of them without brute forcing?
Example:
You have the vectors
v1=[1 2] v2=[1 2 3] v3=[1 2 3 4]
(Edit note: The nesting of the vectors is unintentional and cannot be leveraged in the algorithm.)
You pick values from each of the vectors and don't allow repeats.
Value 1 is from v1 ---> 2
Value 2 is from v2 ---> 1
Value 3 is from v3 ---> 4
Resulting permutation is [2 1 4].
This is one allowable permutation. Here is an example of a permutation that is not allowed because it repeats.
Value 1 is from v1 ---> 2
Value 2 is from v2 ---> 1
Value 3 is from v3 ---> 2
Resulting permutation is [2 1 2], which is invalid due to repeats.
What is an algorithm to find all valid permutations?
Bonus points if you can calculate how many permutations there are before calculating them.
I'll be sure to post back if I can come up with an answer before anyone else can.
The example you give has nested vectors, meaning that the entries in v_i are a subset of those in v_{i+1}. If this is indeed the general case for your application, then the number of solutions is simply:
n_1 * (n_2 - 1) * ... * (n_k - (k-1))
where n_i is the length of v_i and there are k nested vectors.
As far as algorithms are concerned, if you want to generate all possible solutions, then I cannot see a better way than to choose from each successive vector after eliminating already selected entries.
If you aren't nested, a good way to visualize this problem is as a Marriage Problem in the following sense. Make k vertices corresponding to the given k vectors
v_1 v_2 ... v_k
and another m vertices corresponding to the distinct entries of the combined vectors
a_1 a_2 ... a_m
Then connect a_i to v_j if and only if a_i appears in v_j. The goal is to find a maximum matching between the vs and the as that touches all of the v's. That is, choose k edges so that each v_i is an endpoint of exactly one edge.
Any of the standard algorithms, e.g. using augmented paths, will work to find one solution or generate them all.
I think you can solve this problem incrementally. Let s1, s2, s3,..,sk be the solutions involving v1, v2, .., vn. Now with vn+1 for every current solution si and element j (j in vn+1), see if j is already in si, if not then add it to your new collection (corresponding to n+1).
Initialize S={ {j} for j in v1 }
For n=2..m:
newS = {}
for j in vn
for s in S
if j not in s add sU{j} to newS
S = newS
return S
I will compete in the OBI (Brazilian Olympiad of Informatics, in English) and I am trying a few exercises from the last years. But I can't find a solution for this exercise (I translated it, so there may be a few errors):
Chocolate Competition
Carlos and Paula just got a bag of chocolate balls. As they would eat
everything too quickly, they made a competition:
They will eat alternately, one after the other (Paula always starts).
Each time, they can only eat from 1 to M balls, M decided by Paula's mother, so they don't choke.
If one ate K balls in his/her turn, the next can't eat K balls.
Whoever can't play according the rules above loses.
In the example below with M = 5 and 20 balls, Carlos has won:
Who plays How many ate Balls left
20
Paula 5 15
Carlos 4 11
Paula 3 8
Carlos 4 4
Paula 2 2
Carlos 1 1
Note that in the end, Carlos couldn't eat 2 balls to win, because Paula ate 2 in her last turn. But Paula couldn't eat the last ball, because Carlos ate 1 in his last turn, so Paula can't play and loses.
Both are very smart and play optimally. If there is a sequence of turns that ensures him/her the victory independent of the other's turns, he/she will play these sequences.
Task:
Your task is to find out who will win the competition if both play optimally.
Input:
The input contains only a single test group, which should be read from the standard input (usually the keyboard).
The input has 2 integers N (2 ≤ N ≤ 1000000) and M (2 ≤ M ≤ 1000), being N the number of balls and M the number allowed per turn.
Output:
Your program should print, in the standard output, one line containing the name of the winner.
Examples:
Input: Output:
5 3 Paula
20 5 Carlos
5 6 Paula
I've been trying to solve the problem, but I have no idea how.
A solution in C can be found here: http://olimpiada.ic.unicamp.br/passadas/OBI2009/res_fase2_prog/programacao_n2/solucoes/chocolate.c.txt But I can't understand the algorithm. Someone posted a question about this problem in another site, but nobody replied.
Could you explain me the algorithm?
Here are the expected outputs of the program: http://olimpiada.ic.unicamp.br/passadas/OBI2009/res_fase2_prog/programacao_n2/gabaritos/chocolate.zip
Let's say we have a boolean function FirstPlayerWin (FPW) that takes two arguments: number of chocolates left (c) and the last move (l) i.e. the number of chocolates taken on the previous round, which is 0 at the first move. The routine returns true if and only if the first player to play at this situation is guaranteed a win.
The base case is that FPW(0, l) = false for any l != 1
Otherwise, to calculate FPW(c, l), FPW(c, l) is true if for any x <= M, x <= c, x != l, FPW(c - x, x) is false. Otherwise it is false. This is where dynamic programming kicks, because now the calculation of FPW is reduced to calculating FPW for smaller values of c.
However, storing the entries for this formulation would require N * M table entries, where as the solution you pointed to uses only 2N table entries.
The reason for this is that if FPW(c, 0) is true (first player wins if any move is available at chocolate count c) but FPW(c, x) is false for x > 0, FPW(c, y) for and y != x must be true. This is because if denying the move x makes the player lose, i.e. the player would win only by playing x, then the move x is available when y is banned instead. Therefore it is enough to store for any count 'c' at most one forbidden move that causes the player to lose there. So you can refactor the dynamic programming problem so that instead of storing the full 2-dimensional array FPW(c, x) you have two arrays, one stores the values FPW(c, 0) and the other stores the single forbidden moves that cause the first player to lose instead of winning, if any.
How you get to the exact text of the quoted C program is left as an exercise to the reader.
I think this is yet another thinly disguised exercise in dynamic programming. The state of the game is described by two quantities: the number of balls remaining, and the number of balls eaten in the previous move. When the number of balls remaining is <= M, the game is either won (if the number remaining is not equal to the number eaten in the previous move) or lost (if it is - you can't eat all the balls, and your opponent can eat the balls that you leave).
If you have worked out the win/lose situation for all numbers of balls up to H, and all possible numbers of balls eaten by the previous player and written this down in a table, then you can work out the answers for all numbers of balls up to H+1. A player with H+1 balls and k balls eaten in the previous move will consider all possibilities - eat i balls for i = 1 to M except for the illegal value of k, leaving a position with H+1-i balls and a previous move of i. They can use the table giving the win-lose situation for up to H balls left to try and find a legal k that gives them a win. If they can find such a value, the H+1/k position is a win. If not, it is a loss, so they can extend the table to cover up to H+1 balls, and so on.
I haven't worked through all the uncommented example code, but it looks like it could be doing something like this - using a dynamic programming like recursion to build a table.