GCD of numbers confusion - c++

I was looking for simple code for calculating gcd of 2 numbers and came across this code which works
ll gcd(ll a, ll b){
return b ? gcd(b,a%b):a;
}
I was trying to make this code work
ll gcd(ll a, ll b){
return a ? gcd(a%b,b):b;
}
No matter what I do, I am not able to get the second code block to work. My reason is simple, no matter how I start, I should be able to get GCD. Can someone please help me understand where I am going wrong?

If you want to swap a and b, you must do two things:
Replacing every a with a b and every b with an a
Changing the order of the arguments passed to each recursive call to gcd.
You have done it partially. What you need to do is:
return a ? gcd(b%a, a):b;
What you have generates infinite recursion. For example, if you call gcd (12, 8) with your modified function, this is what you get at each iteration:
a = 12, b = 8
a = 4, b = 8
a = 4, b = 8
a = 4, b = 8
...

Related

Assign the work for 2 people so that the time is minimum

Question:
There are N works that needs to be assigned for 2 people. Person A can finish work i in a[i] time, person B can finish work i in b[i] time.
Each work can only be assigned to 1 person. After the works are assigned, each person will do their works seperately.
The overall time will be the larger of the total time taken by the 2 people.
Find a way to assign the work so that the Overall Time is minimum.
Example:
N = 6
a[] = 10 100 30 50 50 80
b[] = 100 30 40 40 60 90
Answer: 130
Explaination:
Person A do work 1, 3, 6 -> total time: 120
Person B do work 2, 4, 5 -> total time: 130
Overall time: 130
Constrants:
N <= 100
a[i], b[i] <= 30.000
My take
I tried solving it with dynamic-programming, more specifically: DP[i][p][c]
With i is the number of works done so far, p is total time of person A so far, c is total time of person B so far. For each i, we can try to give the work to either person A or B, then save the best answer in DP[i][p][c] so we dont have to recalculate it.
But p and c can get up to 3.000.000, so I tried to shrink it to DP[i][max(p,c)]
The code below gives the right answer for the example case, and some other case I generated:
int n, firstCost[105], secondCost[105];
int dp[105][300005];
int solve(int i, int p, int c){
if(i > n) return max(p, c);
int &res = dp[i][max(p, c)];
if(res != -1) return res;
res = INT_MAX;
int tmp1 = solve(i+1, p + firstCost[i], c);
int tmp2 = solve(i+1, p, c + secondCost[i]);
res = min(tmp1, tmp2);
return res;
}
int main(){
// input...
cout << solve(1, 0, 0);
}
But when I submited it, it gives the wrong anwer to this case:
20
4034 18449 10427 4752 8197 7698 17402 16164 12306 5249 19076 18560 16584 18969 3548 11260 6752 18052 14684 18113
19685 10028 938 10379 11583 10383 7175 4557 850 5704 14156 18587 2869 16300 15393 14874 18859 9232 6057 3562
My output was 77759 but the answer is suppose to be 80477.
I don't know what I did wrong, is there anyway to imrpove my solution?
P/S:
Here's the original problem, the page is in Vietnamese, you can create an account and submit there
The trick that you're missing is the idea of an optimal fringe.
You are trying to shrink it to max(p,c), but it may well be that you need to send the first half the jobs to person A, and that initially looks like a terrible set of choices. You are right that you could get the right answer with DP[i][p][c], but that quickly gets to be too much data.
But suppose that p0 <= p1 and c0 <= c1. Then there is absolutely no way that looking at a path through (p1, c1) can ever lead to a better answer than (p0, c0). And therefore we can drop (p1, c1) immediately.
I won't give you code, but I'll show you a bit of how this starts with your example.
4034 18449 10427 4752 8197 7698 17402 16164 12306 5249 19076 18560 16584 18969 3548 11260 6752 18052 14684 18113
19685 10028 938 10379 11583 10383 7175 4557 850 5704 14156 18587 2869 16300 15393 14874 18859 9232 6057 3562
At first we start off with DP = [[0,0]].
After we assign the first element, you get [[0,19685], [4034,0]].
After we assign the second we get, [[0,29713], [4034,10028], [18449,19685], [22483,0]]. We can drop [18449,19685] because it isn't as good as [4034,10028], so we get to [[0,29713], [4034,10028], [22483,0]].
The third element gives [[0,30651], [4034,10966], [10427,29713], [14461,10028], [22483,938], [32910,0]] and then we can drop [10427,29713] as being worse than [4034,10966]. And now we are at [[0,30651], [4034,10966], [14461,10028], [22483,938], [32910,0]].
And so on.
As an additional optimization I'd first sort the indexes by c[i]/p[i] and produce a greedy solution where we assign all of the beginning indexes to A and all of the end to B. From the existence of that greedy solution, we never need to look at any solution with p or c worse than that known solution. After we get half-way through the jobs, this should become a useful filter.

getting wrong answer while changing log value to integer in c++

My task is to calculate log(a*(x^x))+1 to the base b and take its integer part.
int temp = log(a)/log(b) + (x*log(x))/log(b) +1 ; // this gave me 25 for a= 2, b= 2, x=8
When I changed it to:
floor(log(a)/log(b) + (x*log(x))/log(b))+1
It worked fine.
What is the difference between both expressions?

Fibonacci sequence multiplying

I tried to make the fibonacci sequence with the following code:
def fibonacci(n): # write Fibonacci series up to n
"""Print a Fibonacci series up to n."""
a = 0
b = 1
the_list = []
while n > len(the_list):
the_list.append(a)
#By saying a = b and b = a+b we define the
#fibonacci sequence, since this is how the
#fibonacci sequence works.
a = b
b = a+b
print the_list
# Now call the function we just defined:
fibonacci(10)
As far as I know this code should do it but instead of giving me the fibonacci sequence its giving the following output:
[0, 1, 2, 4, 8, 16, 32, 64, 128, 256]
So my fibonacci sequence is multiplying instead of working correcly. I have no idea why because i thought
a = b
b = a+b
should do the trick, if i look at my while loop the statements for this loop are also correct, so I just dont get it why i dont get the right output.
So if someone could explain me why this code is not working it would be highly appriciated
Your code is creating an exponential sequence because of a logic flaw. Based on your code:
Start:
a = 0
b = 1
1st iteration:
a = b = 1
b = a + 1 = 1 + 1 = 2
2nd iteration:
a = b = 2
b = a + 2 = 2 + 2 = 4
As you can see the fact that you set a before performing the b calculation causes your issue.
Instead you need would something like (to prove the point):
tmp = a
a = b
b = tmp + a
A little extra math would eliminate the need for the extra variable:
b += a
a = b - a
But the easiest (and most pythonic) way would be:
a, b = b, a + b

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);

Advice for POUR1 on SPOJ?

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.