Advice for POUR1 on SPOJ? - c++

I need help with this problem POUR1. I think
it can be solved with bruteforce approach, but I read that it is a graph problem (BFS). I solved problems like ABCPATH, LABYR1, PT07Y, PT07Z, BITMAP, ...
But I don't know how to approach POUR1 in BFS manner.
Can someone give me some advice?
Problem statement:
Given two vessels, one of which can accommodate a litres of water and the other - b litres of water, determine the number of steps required to obtain exactly c litres of water in one of the vessels.
At the beginning both vessels are empty. The following operations are counted as 'steps':
emptying a vessel,
filling a vessel,
pouring water from one vessel to the other, without spilling, until one of the vessels is either full or empty.
Input:
An integer t, 1<=t<=100, denoting the number of testcases, followed by t sets of input data, each consisting of three positive integers a, b, c, not larger than 40000, given in separate lines.
Output:
For each set of input data, output the minimum number of steps required to obtain c litres, or -1 if this is impossible.
Example:
Sample input:
2
5
2
3
2
3
4
Sample output:
2
-1

This question has a simpler solution. No need for BFS. Ad-hoc would do good.
method 1 - fill A, empty it into B. whenever A becomes empty fill it back, whenever B becomes full empty it. (all the above-mentioned actions count as individual moves). Continue this process until you arrive at the required amount of water in any one of the vessels. Get the number of moves here. (say C1).
method 2 - fill B, empty it into A. whenever B becomes empty fill it back, whenever A becomes full empty it. Continue this until you arrive at the required amount. Get the number of moves say C2).
The answer is min(C1,C2).
Source code in C++:
#include < cstdio >
#include < algorithm >
using namespace std;
int pour(int A, int B, int C) {
int move = 1, a = A, b = 0, tfr;
while (a != C && b != C) {
tfr = min(a, B - b);
b += tfr;
a -= tfr;
move++;
if (a == C || b == C)
break;
if (a == 0) {
a = A;
move++;
}
if (b == B) {
b = 0;
move++;
}
}
return move;
}
/** Reason for calculating GCD of a,b is to check whether an integral solution of
* equation of form ax + by = c exist or not, to dig deeper read Diophantine Equations
*/
int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
int main() {
int t, a, b, c;
scanf("%d", & t);
while (t--) {
scanf("%d%d%d", & a, & b, & c);
if (c > a && c > b)
printf("-1\n");
else if (c % gcd(a, b) != 0)
printf("-1\n");
else if (c == a || c == b)
printf("1\n");
else
printf("%d\n", min(pour(a, b, c), pour(b, a, c)));
}
return 0;
}

Consider the set of all a priori possibles states (eg [3, 7] meaning Vessel1 contains 3 litters and vessel2 contains 7 litters). You have a directed graph whose vertices are those states and whose edges are the possible moves. The question is to find a path in the graph joining the state [0, 0] to either a state of type [c, ?] or a state of type [?, c]. Such a path is typically searched by a BFS.

Related

Bool A, B and C truth combination

I need to combine 3 bools to test for the entire truth table (8 combinations) in c++.
I have 2 special cases that need to be attended to, they are a, b and c are all true, and a, b are true but c is false.
The rest don't need to be catered for specifically (they will work automatically together without case-specific instructions)
is there a way to only test for these two cases, and then the individual cases but still allow the individuals to work together?
Such as,
if(a && b && c)
and if(a && b && !c)
then if a, if b, if c respectively
I think it uses if else, but I'm having no luck, the way I have it now performs some operations twice as "a" is true in a b c, a b !c and also in a.
I hope this is clear enough, my first time posting here so apologies if it is not.
Your two special cases can be handled something like:
if (a && b)
if (c)
all_true();
else
ab_true_c_false();
Another possibility would be to combine the three arithmetically, then use the result as an index:
typedef void (*action)();
// handlers for the individual cases:
void all_false() { std::cout << "all_false"; }
void a_true() { std::cout << "a true"; }
// ...
// table of handlers. The order of handlers in the array is critical.
static const action actions[] = {
all_false, a_true, b_true, ab_true,
c_true, ac_true, bc_true, abc_true };
// Create index into array
int x = a | (b << 1) | (c << 2);
// invoke correct handler:
actions[x]();

Move number away from n in C++

I am looking for a simple way to increment/decrement a number away from n, without using if statements, or creating a function. Here is an example:
Increment x from 9 to 10, n is 6
Decrement x from 3 to 2, n is 6
An obvious way to do this is with if statements, but that seems like too much code in my opinion. Here is a function that I could imagine using:
x += 1 * GetSign(6, 9) //GetSign(A, B) returns 1 or -1 depending on what would
Be necessary to move farther away from 6. The made up function above would look something like:
int GetSign(A, B)
{
if( A < B) return -1;
else return 1;
}
You can use the ternary operator:
int A = 6;
int B = 9;
x += (A < B) ? (-1) : (1);

Simple way to check a large number of similar conditions?

I am working on a game, and I am finding myself very often checking that certain quantities are in the bounds of the indexes accepted by the vector that represents my world:
if(a >= 0 && a < 16 && b >= 0 && b < 16 && c >= 0 && c < 16 &&
d >= 0 && d < 16 && e >= 0 && e < 16)
{
//do things with vector[a][b][c][d][e]
}
I often have to check even more conditions than this. Is there a way that I can make these checks more concise and/or easier to read?
Alternatively, is there a way that I can avoid doing the checks entirely? The vector is 16x16x16x16x16; can I make it so that if I were to give it a 16 as an index, it would do nothing rather than segfault?
You could write a variadic check function:
bool check(int a) {
return 0 <= a && a < 16;
}
template<typename... Args>
bool check(int a, Args... args) {
return check(a) && check(args...);
}
You can use it like check(a, b, c, d, e, ...). It also has the advantage of being able to take any number of conditions.
Here's a demo
Here's a compact and efficient way to do the check. It assumes two's complement arithmetic.
bool IsInBounds(int a, int b, int c, int d, int e)
{
// Make sure only bits 0-3 are set (i.e. all values are 0-15)
return ((a | b | c | d | e) & ~0xf) == 0;
}
This works by noting that all values outside the 0-15 range all have a bit set that isn't one of the four least significant ones, and all values inside the range don't.
Of course it's only worth using this sort of optimization if the gains in efficiency outweigh the loss of code readability.
The point of functions is reusability. If you find yourself writing certain long expressions or groups of statements repeatedly, it might be time to refactor it out.
In this case, I would write a simple function to do the bounds checking:
bool isInBounds(int a, int b, int c, int d, int e)
{
return a >= 0 && a < 16 &&
b >= 0 && b < 16 &&
c >= 0 && c < 16 &&
d >= 0 && d < 16 &&
e >= 0 && e < 16;
}
Then use it instead of your long condition:
if (isInBounds(a, b, c, d, e))
{
// do things with array[a][b][c][d][e]
}
You can store your variables as elements in a std::vector rather than separate variabes like this:
bool test(const std::vector<int>& values)
{
for(auto v: values)
if(v < 0 || v >= 16)
return false;
return true;
}
Alternatively if you are using C++11 or later you can use std::all_of:
if(std::all_of(std::begin(values), std::end(values),
[](int i){ return i >= 0 && i < 16; }))
{
// do stuff with values
}
In that case you may also be able to use a std::array.
You could combine the 5 integers making up your index into one std::array or your own class.
using Index5 = std::array<int, 5>;
Then you can write a function like:
bool contains(Index5 bounds, Index5 point) {
for (Index5::size_type d = 0; d != bounds.size(); ++d) {
if ((unsigned)point[d] > bounds[d]) // using the trick mentioned in comments
return false;
}
return true;
}
Then use it like this:
auto bounds = Index5{16, 16, 16, 16, 16};
auto point = Index5{a, b, c, d, e};
if (contains(bounds, point)) {
// do things with point
}
Generally, I would suggest using something like Index5 instead of managing five integers.
If the quantities a, b, c, d, and e are something that occur
together quite frequently and all need to stay within the bounds
of your "world" (e.g. they represent the "state" of something in that world)
then it might make sense to define a class whose primary purpose is
to hold one "state" consisting of those five quantities.
Then make sure that if any code ever tries to store values in an object
of that class that are not within the bounds, something reasonable
(not a segfault) happens instead,
and no out-of-bounds values are ever stored there.
That way, an object of that class is safe to pass to any function that
requires a, b, c, d, and e to be within bounds,
and there is no need for any such function to do bounds-checking
on those five values.

How does that recursive function work?

Might be a very basic question but I just got stuck with it. I am trying to run the following recursive function:
//If a is 0 then return b, if b is 0 then return a,
//otherwise return myRec(a/2, 2*b) + myRec(2*a, b/2)
but it just gets stuck in infinite loop. Can anybody help me to run that code and explain how exactly that function works? I built various recursive functions with no problems but this one just drilled a hole in my head.
Thanks.
Here is what I tried to do:
#include<iostream>
int myRec(int a, int b){
if (a==0){
return b;
}
if (b==0){
return a;
}
else return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
int main()
{
if (46 == myRec(100, 100)) {
std::cout << "It works!";
}
}
Well, let us mentally trace it a bit:
Starting with a, b (a >= 2 and b >= 2)
myRec(a/2, 2*b) + something
something + myRec(2*a', b'/2)
Substituting for a/2 for a' and 2*b for b', we get myRec(2*(a/2), (b*2)/2), which is exactly where we started.
Therefore we will never get anywhere.
(Note that I have left out some rounding here, but you should easily see that with this kind of rounding you will only round down a to the nearest even number, at which point it will be forever alternating between that number and half that number)
I think you are missing on some case logic. I last program in C ages ago so correct my syntax if wrong. Assuming numbers less than 1 will be converted to zero automatically...
#include<iostream>
int myRec(int a, int b){
// Recurse only if both a and b are not zero
if (a!=0 && b!=0) {
return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
// Otherwise check for any zero for a or b.
else {
if (a==0){
return b;
}
if (b==0){
return a;
}
}
}
UPDATE:
I have almost forgot how C works on return...
int myRec(int a, int b){
if (a==0){
return b;
}
if (b==0){
return a;
}
return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
VBA equivalent with some changes for displaying variable states
Private Function myRec(a As Integer, b As Integer, s As String) As Integer
Debug.Print s & vbTab & a & vbTab & b
If a = 0 Then
myRec = b
End If
If b = 0 Then
myRec = a
End If
If a <> 0 And b <> 0 Then
myRec = myRec(a / 2, 2 * b, s & "L") + myRec(2 * a, b / 2, s & "R")
End If
End Function
Sub test()
Debug.Print myRec(100, 100, "T")
End Sub
Running the test in Excel gives this (a fraction of it as it overstacks Excel):
T: Top | L: Left branch in myRec | R: Right branch in myRec
The root cause will be the sum of the return which triggers more recursive calls.
Repeating of the original values of a and b on each branch from level 2 of the recursive tree...
So MyRec(2,2) = MyRec(1,4) + MyRec(4,1)
And MyRec(1,4) = MyRec(.5,8) + MyRec(2,2)
So MyRec(2,2) = MyRec(.5,8) + MyRec(2,2) + MyRec(4,1)
Oops.
(The .5's will actually be zeroes. But it doesn't matter. The point is that the function won't terminate for a large range of possible inputs.)
Expanding on gha.st's answer, consider the function's return value as a sum of expressions without having to worry about any code.
Firstly, we start with myRec(a,b). Let's just express that as (a,b) to make this easier to read.
As I go down each line, each expression is equivalent, disregarding the cases where a=0 or b=0.
(a,b) =
(a/2, 2b) + (2a, b/2) =
(a/4, 4b) + (a, b) + (a, b) + (4a, b/4)
Now, we see that at a non-terminating point in the expression, calculating (a,b) requires first calculating (a,b).
Recursion on a problem like this works because the arguments typically tend toward a 'base case' at which the recursion stops. A great example is sorting a list; you can recursively sort halves of the list until a list given as input has <= 2 elements, which is trivial without recursion. This is called mergesort.
However, your myRec function does not have a base case, since for non-zero a or b, the same arguments must be passed into the function at some point. That's like trying to sort a list, in which half of the list has as many elements as the entire list.
Try replacing the recursion call with:
return myRec(a/2, b/3) + myRec(a/3, b/2);

Cannot understand comma expression

#include <iostream>
using namespace std;
int main()
{
int a, b, c, max;
cout<<"a="; cin>>a;
cout<<"b="; cin>>b;
cout<<"c="; cin>>c;
a>b?(max=a, a=b, b=max):a;
b>c?(max=b, b=c, c=max):a;
a>b?(max=a, a=b, b=max):a;
cout<<a<<" "<<b<<" "<<c;
}
This is a code where you can input 3 random numbers and it will put them in order. I don't understand this part, however:
a>b?(max=a, a=b, b=max):a;
b>c?(max=b, b=c, c=max):a;
a>b?(max=a, a=b, b=max):a;
How does it work, and why?
Let's say a = 6, b = 54, and c = 12.
a>b?(max=a, a=b, b=max):a; <-- sets max to 6, then a to 54, then 54=max. then compares 6 to 54 which is false and writes a (6) as the first number?
b>c?(max=b, b=c, c=max):a; <-- sets max to 54, b=12, 12=max. then compares 54 to 12 which is true in our case and writes c=12 as the second number?
a>b?(max=a, a=b, b=max):a; <-- sets max to 6, a=54, 54=max. then compares 6 to 54 which is false and writes 6 again, wtf?
The program itself works correctly. I just don't understand how the algorithm works.
This:
cond ? A : B
is roughly equivalent to this:
if (cond) {
A;
} else {
B;
}
This:
(X, Y, Z)
is roughly equivalent to this:
X;
Y;
Z;
i.e. each expression is evaluated completely, in turn.
Using these two rules, you should be able to trace the execution of your code. However, that code is grotesque, and should never have been written like that. So my recommendation is to just ignore it, and write the algorithm properly.
All the code's doing is abusing the comma operator's ability to do multiple things in one to swap values in one statement.
The first line finds the max of the first two numbers. The second finds the max of that and the third, so that it's now found the largest of the three. The third line sorts the other two in order afterwards.
It's about the same as this:
if (a > b)
swap (a, b); //b is max(a,b)
if (b > c)
swap (b, c); //c is max(max(a,b),c), which is largest
if (a > b)
swap (a, b); //b is max (a, b), so numbers are in order smallest to largest
a>b?(max=a, a=b, b=max):a
The final ":a" really doesn't do anything, it could just as easily have been ":0". It is essentially the statement that is to be carried out if the "a>b" is false. but since the a isn't assigned to anything, it doesn't do anything. so in this case
if(a > b){
max = a;
a = b;
b = max;
}
It uses the max variable to swap a and b; The SAME algorithm is used for the following two lines. So essentially
if a > b then swap them
now if b (which could hold a) > c then swap them
now if a (which could hold the older b) > b(which could hold the oldest c) then swap
Well, essentially I this is what happens.
a>b?(max=a, a=b, b=max):a;
the first section is just a normal comparison in the fashion of a tertiary if statement, so basically it checks if a>b, then ? is just equal to the first brackets set, so if its true, it evaluates the first section otherwise then the code after : is just like else and that is is evaluated.. The (max=a, a=b, b=max) basically evaluates each item in turn, so first max is set to a, then a = b and finally b = max; Same for the other two lines.
You can read more here: http://www.cplusplus.com/doc/tutorial/operators/
Hope this helped.