I use two method to calculate the binomial coefficient.
one is
int fac(int n) {
if ( n < 2 ) return 1; // return 1 when n=0,1
int ret = 1;
for(int i=2; i <= n; ++i)
ret *= i; // calculate factorial
return ret;
}
int choose_fac(int n, int k) {
return fac(n)/fac(k)/fac(n-k);
}
The other one is:
int choose_dp(int n, int k) {
int C[n+1][k+1];
int i, j;
for (i = 0; i <= n; i++) {
for (j = 0; j <= min(i, k); j++) {
if (j == 0 || j == i) C[i][j] = 1;
else C[i][j] = C[i-1][j-1] + C[i-1][j];
}
}
return C[n][k];
}
So when i run on (15,5), the second one give the right answer while first one gives 4. I know that for choose_fac the int goes out of range when calculate 15!, but if this is the reason, why choose_dp doesn't return a wrong answer as they both use int to define the function?
Thanks a lot!
E.
The first one overflows an int.
When you call fac(15) to compute choose_fac(15, 5) the value that should be computed by the function, 1,307,674,368,000 greatly exceeds the range of int. The end result of the computation 15 choose 5 would be in the range for int because two relatively large factorials are divided, but an error in the intermediate result prevents this computation from completing successfully.
The second function, which uses dynamic programming, is free from this problem, because it does not compute factorials explicitly. This method of computing binomial coefficients is called Pascal's Triangle.
When you return fac(n)/fac(k)/fac(n-k); It is evaluated left to right. (((fac(n)) /fac(k))/fac(n-k)) First evaluation fac(n) gives an overflow error.
Related
How to count comparisons in selectionsort?
terms:
when the statements you perform to find the maximum value is 'true'
then count comparison.
The value to get the maximum value is held at the first element in the array, not at random.
I try with C
variable count position change - no work
new variable 'first' , first=sort[MAX] insert first for loop, - no work
#include <stdio.h>
int main() {
int sort[10000], i, n, MAX, temp, count;
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%d", &sort[i]);
}
for (MAX = 0; MAX < n; MAX++)
for (i = MAX + 1; i < n; i++) {
if (sort[MAX] > sort[i]) {
count++;
temp = sort[MAX];
sort[MAX] = sort[i];
sort[i] = temp;
}
}
printf("%d ", count);
return 0;
}
Sample Input
10
0 7 1 6 7 7 6 6 5 4
Sample Output
17
EDIT: new code:
#include <stdio.h>
#define SWAP(x, y, temp) ( (temp)=(x), (x)=(y), (y)=(temp) )
int count = 0;
void selection_sort(int list[], int n) {
int i, j, least, temp;
for (i = 0; i < n - 1; i++) {
least = i;
for (j = i + 1; j < n; j++) {
if (list[j] < list[least]) {
least = j;
count++;
}
}
SWAP(list[i], list[least], temp);
}
}
int main() {
int list[10000], i, n;
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%d", &list[i]);
};
selection_sort(list, n);
printf("%d", count);
}
how about this? why this code didn't move too?
You aren't counting the right thing, this code
if(sort[MAX]>sort[i])
{
count++;
temp=sort[MAX];
sort[MAX]=sort[i];
sort[i]=temp;
}
counts the times that two numbers are swapped. But you want to count comparisons so it should be this
count++;
if(sort[MAX]>sort[i]) // this is what we are counting
{
temp=sort[MAX];
sort[MAX]=sort[i];
sort[i]=temp;
}
Another problem is that you don't give count an initial value of zero
int sort[10000],i,n,MAX,temp,count;
should be
int sort[10000],i,n,MAX,temp,count = 0;
how to count comparison selectionsort?
Your definition of the term is oddly worded, but it seems to be intended to focus on the essential comparisons of the algorithm, as opposed to comparisons performed incidentally for other purposes, or inside library functions. That is, in the implementation you present (whose correctness I do not evaluate), you're to count each evaluation of sort[MAX]>first, but not MAX<n or i<n.
You appear to be using variable count for that purpose, but you are counting only comparisons that evaluate to true. My interpretation of the problem, based both on the wording presented and on my general expectations for such a problem, is that every evaluation of sort[MAX]>first should be counted, regardless of the result. That would be achieved by lifting the expression count++ out of the if block, but leaving it inside the inner enclosing for loop.
Of course, as #john observes, you do need to initialize count to 0 before beginning to sort. You might luck into getting that by accident, but the initial value of a local variables without an initializer is indeterminate (at least) until a value is assigned.
i try with c variable count position change - no work
new variable 'first' , first=sort[MAX] insert first for loop, - no work
Even with the misplacement of your increment to count, if your sort were in fact working then you would expect to see some counts for most inputs. That you don't is a good sign that your sort in fact does not work correctly. I would suggest outputting also the the sorted results so that you can debug the details of the sort algorithm.
You could abstract out the comparison into a function or macro that also increments a counter. The macro approach could be
#define GT(x,y,counter) (counter++, (x) > (y) ? 1 : 0)
...
if ( GT( sort[MAX], sort[i], count ) == 1 )
{
// perform swap
}
whereas the function approach would be
int gt( int x, int y, int *counter )
{
(*counter)++;
if ( x > y )
return 1;
return 0;
}
...
if ( gt( sort[MAX], sort[i], &count ) == 1 )
{
// perform swap
}
You are counting the number of swaps, not the number of comparisons.
Here is a corrected without a global variable and a few extra checks:
#include <stdio.h>
#define SWAP(x, y, temp) ((temp) = (x), (x) = (y), (y) = (temp))
int selection_sort(int list[], int n) {
int count = 0;
int i, j, least, temp;
for (i = 0; i < n - 1; i++) {
least = i;
for (j = i + 1; j < n; j++) {
count++;
if (list[j] < list[least]) {
least = j;
}
}
SWAP(list[i], list[least], temp);
}
return count;
}
int main() {
int list[10000], i, n, count;
if (scanf("%d", &n) != 1 || n > 10000)
return 1;
for (i = 0; i < n; i++) {
if (scanf("%d", &list[i]) != 1)
return 1;
}
count = selection_sort(list, n);
printf("%d\n", count);
return 0;
}
Not however that your algorithm will always perform the same number of comparisons for any set of n values: n * (n - 1) / 2 comparisons, and since you do not test of i != least, it will perform n - 1 swaps.
I'm trying to optimize my code to calculate the nth power of a matrix.
Before I would just call multiplySquare n times but that was way too slow. The problem is, it builds just fine but when I run it, I get a failure with exit value 1. I believe my algorithm is right so what's causing this?
[EDIT] Added recursion termination condition but still, I get the same error.
[EDIT AGAIN] I re-wrote the recursion part again and now it seems to work but only for certain inputs of n. I'll have to play around with it more. Any help would be appreciated.
void multiplySquare(long long A[2][2], long long B[2][2]){
long long result[2][2];
for (int i = 0; i < 2; i++){
for (int j = 0; j < 2; j++){
result[i][j] = 0;
for (int k = 0; k < 2; k++){
result[i][j] += A[i][k] * B[k][j];
}
}
}
for (int i=0; i<2; i++){
for (int j=0; j<2; j++){
A[i][j] = result[i][j];
}
}
}
void power(long long A[2][2], long long B[2][2], long long n){
if(n/2 != 0){
power(A, B, n/2);
}
if(n%2 != 0){
multiplySquare(A, B);
}
}
The algorithm to compute the N-th power of a number x efficiently is:
If N is zero, return 1.
If N is 1, return x.
Compute (N/2)-th power. y = x^(N/2)
If N is even, return y*y
If N is odd, return x*y*y
If you translate that logic to your case, you will need something along the lines of:
// Assuming that the result is returned in B.
void power(long long A[2][2], long long B[2][2], long long n)
{
if ( n == 0 )
{
makeIdentity(B);
return;
}
if ( n == 1 )
{
assign(A, B); // Make B same as A.
return;
}
power(A, B, n/2);
multiplySquare(B, B);
if(n % 2 != 0)
{
multiplySquare(B, A);
}
}
I'm trying to optimize my code to calculate the nth power of a matrix.
Since your goal is an optimization, it might be a good thing to consider that diagonal matrices have trivial n-th power, i.e. the n-th power on the elements of the main diagonal.
So, firstly you should diagonalise your matrix. One way to do it is to find the eigenvectors and eigenvalues of your initial matrix, A, and utilize the following relationship:
A = P D P-1
where P is a matrix containing the (column) eigenvectors of A, P-1
is its inverse and D is a diagonal matrix containing the eigenvalues.
Then: An = P Dn P-1
The above equation:
Takes A to a place where rising to the n-th power is trivial.
Calculates the n-th power.
Returns A back to the original place.
It seems your snippet is not what you aim at. I conjecture what you mean is something like this:
void power(long long A[2][2], long long B[2][2], long long n){
if (n == 1) {
multiplySquare(A, B);
}
else if(n % 2 == 0) {
power(A, B, n / 2);
multiplySquare(A, A);
}
else {
power(A, B, (n - 1) / 2);
multiplySquare(A, A);
multiplySquare(A, B);
}
I am trying to calculate the determinant of a square matrix using row operations.
I ran into this code but I do not really understand how it works.
What do subi and subj do? Does it use row operations?
What is the logic behind this code?
int c, subi, i, j, subj;
double submat[10][10],d=0;
if (n == 2) {
return((mat[0][0] * mat[1][1]) - (mat[1][0] * mat[0][1]));
}
else {
for (c = 0; c < n; c++) {
subi = 0;
for (int i = 1; i < n; i++) {
subj = 0;
for (j = 0; j < n; j++) {
if (j == c)
continue;
submat[subi][subj] = mat[i][j];
subj++;
}
subi++;
}
d = d + (pow(-1, c)*mat[0][c] * determinant(n - 1, submat));
}
}
return d;
The function, which looks like:
double determinant(int n, double mat[10][10]);
recursively goes through rows and calls itself on the submatrices for that row and the first column return a value for all by matrices. The recursion ends for 2 by 2 matrices.
This is a recursive function using Laplace expansion to calculate the determinant whose base case is a 2 by 2 matrix.
However, it does not seem to be a good program to me for:
what if the input is a 1 by 1 matrix
submat is limited by size of 10 by 10
submat is a waste of memory
When matrix is large, it is better to use LU decomposition.
So Im writing a function that is supposed to count up all the first N even numbers in an array where the user picks N. Which is fine, however if there are fewer than N even numbers in the array, then the function should just add them all which is the part I am having difficulty with.
function call:
cout << "The sum of the first " << userSum << " even numbers is: " <<
SumEvens(list, SIZE, userSum) << endl;
function definition:
int SumEvens(int arr[], const int size, int evensAdd)
{
int sum = 0;
for (int i = 0; i < size; i++){
if (arr[i] % 2 == 0 && arr[i] != 0){//if the number is even and not 0 then that number is added to the sum
evensAdd--;
sum += arr[i];
}
if(evensAdd == 0)//once evensAdd = 0(N as previously mentioned) then the function will return the sum
return sum;
}
}
So for example if I have an array: {1,2,3,4,5}
and ask for it to calculate the sum of the first 2 even numbers it would output 6
however if i ask for it to calculate say the first 3 or 4 or 5 even numbers it will output that the sum is 6
why would it subtract one?
If you finish the for loop before evensAdd reaches 0, you never reach the return sum statement and therefore not set the return value of the function. The value returned is then just a random number read from the stack. This is just a technical stuff, the correct approach should look like this:
int SumEvens(int arr[], const int size, int evensAdd)
{
int sum = 0;
for (int i = 0; i < size; i++)
{
if (arr[i] % 2 == 0 && arr[i] != 0)
{
evensAdd--;
sum += arr[i];
}
if (evensAdd == 0)
{
break;
}
}
return sum;
}
Using break will immediately jump to the end of the for loop and the return value will be set if in all cases.
EDIT: Check your compiler warnings, I'm pretty sure that every compiler gives a "Control may reach end of non-void function".
int SumEvens(int arr[], const int size, int evensAdd)
{
int sum = 0;
for (int i = 0; i < size && evensAdd > 0; i++)
{
if (arr[i] % 2 == 0 && arr[i] != 0)
{
evensAdd--;
sum += arr[i];
}
}
return sum;
}
This will work but like #πάντα ῥεῖ said using vectors would be a better idea.
You can just stop the loop with set condition, which is in this case better style than breaking.
Working example!
The program runs but it also spews out some other stuff and I am not too sure why. The very first output is correct but from there I am not sure what happens. Here is my code:
#include <iostream>
using namespace std;
const int MAX = 10;
int sum(int arrayNum[], int n)
{
int total = 0;
if (n <= 0)
return 0;
else
for(int i = 0; i < MAX; i ++)
{
if(arrayNum[i] % 2 != 0)
total += arrayNum[i];
}
cout << "Sum of odd integers in the array: " << total << endl;
return arrayNum[0] + sum(arrayNum+1,n-1);
}
int main()
{
int x[MAX] = {13,14,8,7,45,89,22,18,6,10};
sum(x,MAX);
system("pause");
return 0;
}
The term recursion means (in the simplest variation) solving a problem by reducing it to a simpler version of the same problem until becomes trivial. In your example...
To compute the num of the odd values in an array of n elements we have these cases:
the array is empty: the result is trivially 0
the first element is even: the result will be the sum of odd elements of the rest of the array
the first element is odd: the result will be this element added to the sum of odd elements of the rest of the array
In this problem the trivial case is computing the result for an empty array and the simpler version of the problem is working on a smaller array. It is important to understand that the simpler version must be "closer" to a trivial case for recursion to work.
Once the algorithm is clear translation to code is simple:
// Returns the sums of all odd numbers in
// the sequence of n elements pointed by p
int oddSum(int *p, int n) {
if (n == 0) {
// case 1
return 0;
} else if (p[0] % 2 == 0) {
// case 2
return oddSum(p + 1, n - 1);
} else {
// case 3
return p[0] + oddSum(p + 1, n - 1);
}
}
Recursion is a powerful tool to know and you should try to understand this example until it's 100% clear how it works. Try starting rewriting it from scratch (I'm not saying you should memorize it, just try rewriting it once you read and you think you understood the solution) and then try to solve small variations of this problem.
No amount of reading can compensate for writing code.
You are passing updated n to recursive function as argument but not using it inside.
change MAX to n in this statement
for(int i = 0; i < n; i ++)
so this doesnt really answer your question but it should help.
So, your code is not really recursive. If we run through your function
int total = 0; //Start a tally, good.
if (n <= 0)
return 0; //Check that we are not violating the array, good.
else
for(int i = 0; i < MAX; i ++)
{
if(arrayNum[i] % 2 != 0) //THIS PART IS WIERD
total += arrayNum[i];
}
And the reason it is wierd is because you are solving the problem right there. That for loop will run through the list and add all the odd numbers up anyway.
What you are doing by recursing could be to do this:
What is the sum of odd numbers in:
13,14,8,7,45,89,22,18,6,10
+
14,8,7,45,89,22,18,6
+
8,7,45,89,22,18
+
7,45,89,22 ... etc
And if so then you only need to change:
for(int i = 0; i < MAX; i ++)
to
for(int i = 0; i < n; i ++)
But otherwise you really need to rethink your approach to this problem.
It's not recursion if you use a loop.
It's also generally a good idea to separate computation and output.
int sum(int arrayNum[], int n)
{
if (n <= 0) // Base case: the sum of an empty array is 0.
return 0;
// Recursive case: If the first number is odd, add it to the sum of the rest of the array.
// Otherwise just return the sum of the rest of the array.
if(arrayNum[0] % 2 != 0)
return arrayNum[0] + sum(arrayNum + 1, n - 1);
else
return sum(arrayNum + 1, n - 1);
}
int main()
{
int x[MAX] = {13,14,8,7,45,89,22,18,6,10};
cout << sum(x,MAX);
}