Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to code the Waterman algorithm in C.
Now when the length of the sequence exceeds 35 the program just lags.
I have no idea where to start looking, tried but got nothing worked out.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Max Function Prototype.
int maxfunction(int, int);
// Prototype of the random Sequences generator Function.
void gen_random(char *, const int);
int main(int argc, char *argv[]) {
// Looping variable and Sequences.
int i = 0, j = 0, k = 0;
char *X, *Y;
int length1, length2;
// Time Variables.
time_t beginning_time, end_time;
// Getting lengths of sequences
printf("Please provide the length of the first Sequence\n");
scanf("%d", &length1);
printf("Please provide the length of the second Sequence\n");
scanf("%d", &length2);
X = (char*)malloc(sizeof(char) * length1);
Y = (char*)malloc(sizeof(char) * length2);
int m = length1 + 1;
int n = length2 + 1;
int L[m][n];
int backtracking[m + n];
gen_random(X, length1);
gen_random(Y, length2);
printf("First Sequence\n");
for (i = 0; i < length1; i++) {
printf("%c\n", X[i]);
}
printf("\nSecond Sequence\n");
for (i = 0; i < length2; i++) {
printf("%c\n", Y[i]);
}
// Time calculation beginning.
beginning_time = clock();
// Main Part--Core of the algorithm.
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0) {
L[i][j] = 0;
} else
if (X[i-1] == Y[j-1]) {
L[i][j] = L[i-1][j-1] + 1;
backtracking[i] = L[i-1][j-1];
} else {
L[i][j] = maxfunction(L[i-1][j], L[i][j-1]);
backtracking[i] = maxfunction(L[i-1][j], L[i][j-1]);
}
}
}
// End time calculation.
end_time = clock();
for (i = 0; i < m; i++) {
printf(" ( ");
for (j = 0; j < n; j++) {
printf("%d ", L[i][j]);
}
printf(")\n");
}
// Printing out the result of backtracking.
printf("\n");
for (k = 0; k < m; k++) {
printf("%d\n", backtracking[k]);
}
printf("Consumed time: %lf", (double)(end_time - beginning_time));
return 0;
}
// Max Function.
int maxfunction(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
// Random Sequence Generator Function.
void gen_random(char *s, const int len) {
int i = 0;
static const char alphanum[] = "ACGT";
for (i = 0; i < len; ++i) {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[len] = 0;
}
Since you null terminate the sequence in gen_random with s[len] = 0;, you should allocate 1 more byte for each sequence:
X = malloc(sizeof(*X) * (length1 + 1));
Y = malloc(sizeof(*Y) * (length2 + 1));
But since you define variable length arrays for other variables, you might as well define these as:
char X[length1 + 1], Y[length2 + 1];
Yet something else is causing a crash on my laptop: your nested loops iterate from i = 0 to i <= m, and j = 0 to j <= n. That's one step too many, you index out of bounds into L.
Here is a corrected version:
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
The resulting code executes very quickly, its complexity is O(m*n) in both time and space, but m and n are reasonably small at 35. It runs in less than 50ms for 1000 x 1000.
Whether it implements Smith-Waterman's algorithm correctly is another question.
Related
How do I make my code more efficient (in time) pertaining to a competitive coding question (source: codechef starters 73 div 4):
(Problem) Chef has an array A of length N. Chef wants to append a non-negative integer X to the array A such that the bitwise OR of the entire array becomes = Y .
Determine the minimum possible value of X. If no possible value of X exists, output -1.
Input Format
The first line contains a single integer T — the number of test cases. Then the test cases follow.
The first line of each test case contains two integers N and Y — the size of the array A and final bitwise OR of the array A.
The second line of each test case contains N space-separated integers A_1, A_2, ..., A_N denoting the array A.
Please don't judge me for my choice of language .
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int* binary_number(int n) // returns pointer to a array of length 20(based on given constrains) representing binary
{
int* ptc;
ptc = (int*) malloc(20*sizeof(int));
for(int i = 0; i < 20; i++)
{
if((n / (int) pow(2,19-i)) > 0){*(ptc + i) = 1;}
else {*(ptc + i) = 0;}
n = n % (int) pow(2,19-i) ;
}
return ptc;
}
int or_value(int* ptc, int n) // Takes in pointers containing 1 or zero and gives the logical OR
{
for(int k = 0; k < n; n++)
{
if(*ptc == *(ptc + 20*k)){continue;} // pointers are 20 units apart
else{return 1;break;}
}
return *ptc;
}
int main(void) {
int t; scanf("%d", &t);
for (int i = 0; i < t; i++)
{
int n, y;
scanf("%d %d", &n, &y);
int a[n];
for(int j = 0; j < n ; j++)
{
scanf("%d", &a[j]);
}
int b[20*n];
for (int j = 0; j < n; j++)
{
for (int k = 0; k < 20; k++)
{
b[20*j + k] = *(binary_number(a[n])+k);
}
}
int c = 0;
int p = 0;
for (int j = 0; j < 20; j++)
{
if ((*(binary_number(y) + j) == 1) && (or_value((&b[0] + j),n) == 0)){c = c + pow(2,19 - j);}
else if ((*(binary_number(y) + j) == 0) && (or_value((&b[0] + j),n) == 1)){p = 1; break;}
}
if (p==1){printf("-1");}
else {printf("%d\n", c);}
}
return 0;
}
Sample Input
2
2
5
Sample Output
0 1 1
0 1 1 2 1 2
I already knew how to transfer an integer to its binary and count how many 1 in its binary.
But my code only can input one integer each time. I want it to input many numbers, like the sample input and sample output. To make question more easy to understand, so I drew a picture. Thank you!!
Thanks all of you!! But I need some time to understand those code and my English is pretty basic, so I couldn't reply you guys soon. But I will understand and reply you as soon as possible!!thank you :D
#include <stdio.h>
int main()
{
int n,cnt=0,m;
scanf("%d",&n);
while(n>0){
m=n%2;
if(m==1){
cnt++;
}
n/=2;
}
printf("%d",cnt);
return 0;
}
In practice, the process can be simplified and accelerated by noticing that if we know the result for i < 2^p, then, for all values in [2^p, 2^(p+1)-1], we have
count(j) = 1 + count(j-2^p)
This method is useful here as we have to provide the result for all values less or equal to n.
Moreover, in order to avoid performing the same calculation at different times, we first calculate the maximum n value, and perform the calculation for this maximum value.
#include <stdio.h>
int main() {
int t;
int check = scanf("%d", &t);
if (check != 1) return 1;
int nn[t];
for (int i = 0; i < t; ++i) {
int check = scanf("%d", &nn[i]);
if (check != 1) return 1;
}
int nmax = 0;
for (int i = 0; i < t; ++i) {
if (nn[i] > nmax) nmax = nn[i];
}
int count[nmax+1];
count[0] = 0;
count[1] = 1;
int pow2 = 1;
do {
pow2 *= 2;
for (int j = pow2; (j < 2*pow2) && (j <= nmax); j++) {
count[j] = 1 + count[j-pow2];
}
} while (pow2 <= nmax+1);
for (int i = 0; i < t; ++i) {
for (int j = 0; j <= nn[i]; ++j) {
printf ("%d ", count[j]);
}
printf ("\n");
}
return 0;
}
Let the number of measured values be t. Now if you want to take t number of integers as input, you have to run a loop t times and perform necessary tasks (like taking value of n, calculating cnt etc) inside that loop. Check the following code snippet:
int main()
{
int n,cnt=0,m;
int numberOfMeasuredValues;
scanf("%d", &numberOfMeasuredValues);
while(numberOfMeasuredValues > 0){
cnt = 0;
scanf("%d",&n);
// perform necessary calculations
printf("%d\n",cnt);
numberOfMeasuredValues--;
}
return 0;
}
In the code numberOfMeasuredValues is the t I've used in the explanation.
You can pre-allocate number of cases and work on them with outer and inner loops. I've added the code with comments below.
#include <stdio.h>
int main(void)
{
int cases; // Number of cases
scanf("%d", &cases);
int* nums = malloc(cases * sizeof *nums); // Allocate enough space.
/* Take the inputs. */
for (int i = 0; i < cases; i++)
{
scanf("%d", (nums + i));
}
int cnt = 0; // Counter for number of 1s.
// Outer loop for going through cases.
for (int i = 0; i < cases; i++)
{
// Inner loop for couting towards inputted number.
for (int j = 0; j < *(nums + i) + 1; j++)
{
/*
* You can Implement this part by yourself if you wish.
*/
for (int k = 0; k < 32; k++)
{
if ((j >> (31 - k)) & 0x01) cnt++; // Increment counter if digit is 1.
}
printf("%d ", cnt);
cnt = 0;
}
printf("\n");
}
return 0;
}
Here's the following code to your problem
#include<iostream>
using namespace std;
int main()
{
int tcs;
cin >> tcs;
while (tcs--) {
int n;
cin >> n;
for (int i = 0 ; i <= n ; i++) {
cout << __builtin_popcount(i) << " ";
}
cout << "\n";
}
return 0;
}
Task description -> Whole task description is here
I have done part with sorting and got stuck.
How can I combine these arrays in one of already sorted pairs?
printf("\nHeight of boys in descending order\n");
for (i = (LENGTH1 - 1); i >= 0; i--)
{
printf("%d ", heightBoys[i]);
}
for (i = 0; i < LENGTH2; i++)
{
for (j = 0; j < (LENGTH2 - j - 1); j++)
{
if (heightGirls[j] > heightGirls[j+1])
{
temp = heightGirls[j];
heightGirls[j] = heightGirls[j+1];
heightGirls[j+1] = temp;
}
}
}
printf("\nHeight of girls in descending order\n");
for (j = (LENGTH2 - 1); j >= 0; j--)
{
printf("%d ", heightGirls[j]);
}
You have a sort [for the girls], but it is broken. Change:
for (j = 0; j < (LENGTH2 - j - 1); j++)
Into:
for (j = 0; j < (LENGTH2 - i - 1); j++)
To avoid [needless] replication of code, put the sorting code into a separate function.
Sort both arrays.
Take the minimum of the lengths of the two arrays (e.g. minlen).
I'm not sure what you mean [exactly] by "pairing", but the simplest is to print the pairing
Then, just loop on:
for (i = 0; i < minlen; ++i)
printf("Girl:%d Boy:%d\n",heightGirls[i],heightBoys[i]);
If you needed something more complex, you might need an array of structs like:
struct pair {
int boyheight;
int girlheight;
};
This array would need to be at least minlen in length. You could fill it in by adapting the final print loop.
But, if you're just printing, here is some sample code:
#include <stdio.h>
void
print_single(const int *height,int len,const char *sex)
{
printf("\nHeight of %s in descending order\n",sex);
for (int i = (len - 1); i >= 0; i--)
printf(" %d", height[i]);
printf("\n");
}
void
sort_height(int *height,int len)
{
for (int i = 0; i < len; i++) {
for (int j = 0; j < (len - i - 1); j++) {
if (height[j] > height[j + 1]) {
int temp = height[j];
height[j] = height[j + 1];
height[j + 1] = temp;
}
}
}
}
int
main(void)
{
int heightBoys[] = { 5, 8, 7, 9, 6 };
int heightGirls[] = { 3, 1, 2 };
int LENGTH1 = sizeof(heightBoys) / sizeof(heightBoys[0]);
int LENGTH2 = sizeof(heightGirls) / sizeof(heightGirls[0]);
sort_height(heightBoys,LENGTH1);
print_single(heightBoys,LENGTH1,"boys");
sort_height(heightGirls,LENGTH2);
print_single(heightGirls,LENGTH2,"girls");
int minlen = LENGTH1;
if (minlen > LENGTH2)
minlen = LENGTH2;
printf("\n");
printf("Pairing:\n");
for (int i = 0; i < minlen; ++i)
printf("Girl:%d Boy:%d\n",heightGirls[i],heightBoys[i]);
return 0;
}
UPDATE:
Let's say that we input heights and number of them by ourselves. If we have extra heights of boys or girls, how can we output these extra heights apart from the rest?
Two additional for loops appended to the bottom should do the trick. In order for this to work, the iteration variable of the final for loop in the previous example must be defined outside the loop. In other words, notice the definition and usage of ipair below.
If you are creating an array the type of struct that I suggested, these loops can fill it in. The array size would then need to be max(LENGTH1,LENGTH2).
And, in unpaired loops (e.g. for boy 8, the girl value in the struct could be set to 0 or -1 to indicate that the boy is unpaired)
#include <stdio.h>
void
print_single(const int *height,int len,const char *sex)
{
printf("\nHeight of %s in descending order\n",sex);
for (int i = (len - 1); i >= 0; i--)
printf(" %d", height[i]);
printf("\n");
}
void
sort_height(int *height,int len)
{
for (int i = 0; i < len; i++) {
for (int j = 0; j < (len - i - 1); j++) {
if (height[j] > height[j + 1]) {
int temp = height[j];
height[j] = height[j + 1];
height[j + 1] = temp;
}
}
}
}
int
main(void)
{
int heightBoys[] = { 5, 8, 7, 9, 6 };
int heightGirls[] = { 3, 1, 2 };
int LENGTH1 = sizeof(heightBoys) / sizeof(heightBoys[0]);
int LENGTH2 = sizeof(heightGirls) / sizeof(heightGirls[0]);
sort_height(heightBoys,LENGTH1);
print_single(heightBoys,LENGTH1,"boys");
sort_height(heightGirls,LENGTH2);
print_single(heightGirls,LENGTH2,"girls");
int minlen = LENGTH1;
if (minlen > LENGTH2)
minlen = LENGTH2;
int ipair = 0;
printf("\n");
printf("Pairing:\n");
for (; ipair < minlen; ++ipair)
printf("Girl:%d Boy:%d\n",heightGirls[ipair],heightBoys[ipair]);
if (ipair < LENGTH1) {
printf("\n");
printf("Unpaired Boys:\n");
for (int i = ipair; i < LENGTH1; ++i)
printf("Boy:%d\n",heightBoys[i]);
}
if (ipair < LENGTH2) {
printf("\n");
printf("Unpaired Girls:\n");
for (int i = ipair; i < LENGTH2; ++i)
printf("Girl:%d\n",heightGirls[i]);
}
return 0;
}
I tackled the problem by first figuring out the length of two given numbers and aligning the one with less digits (if one exists) into a new array so that the ones, tens, hundreds etc. align with the bigger number's ones, tens, hundreds, etc.
Then I wanted to save the sum of each two aligned elements (with a mod of 10) into a new array while checking if the sum of digits is greater than 10 - just the basic sum stuff. Now the problem occurs with adding two elements into the aplusb integer and I've tried fixing it with writing
int aplusb = (lengthA[max-i]-'0') +(temp[max-i]-'0');
but it doesn't work. I'm stuck and I don't know what to do. Please help.
The whole code:
#include <stdio.h>
#include <math.h>
int main(){
char a[10000];
char b[10000];
scanf("%s %s", &a, &b);
char sum[10000];
int lengthA = 0;
int lengthB = 0;
int i = 0;
while(a[i]){
i++;
} lengthA = i;
i = 0;
while(b[i]){
i++;
} lengthB = i;
char temp[10000];
int aplusb;
int carry = 0;
int max = lengthA;
int difference = abs(lengthA - lengthB);
if(lengthA>lengthB){
for(i=0; i<lengthA; i++){
temp[i+difference]=b[i];
}
for(i=0; i<=max; i++){
aplusb = lengthA[max-i]+temp[max-i]; //<-- this is the problematic line
if(carry = 1) aplusb++;
if(aplusb>9){
carry = 1;
aplusb%=10;
}
sum[i]=aplusb;
}
}
for(i=0; i<=max; i++){
printf("%c", sum[i]);
}
/*
if(lengthB>lengthA){
max = lengthB;
for(i=0; i<lengthB; i++){
temp[i+difference]=a[i];
}
}*/
return 0;
}
Doing operations and storing on very large numbers is very akin to doing operations and storing polynomials, i.e. with x = 10. a0 + a1.10 + a2.10^2 ... + an.10^n.
There are many polynomial libraries on the Internet, where you could find inspiration. All operations on your very large numbers can be expressed in terms of polynomials. This means that by using base 2^8, or even base 2^63, instead of base 10 to internally store your large numbers you would greatly improve performance.
You must also normalize your coefficients after operations to keep them positive. Operations may result in a negative coefficient, That can easily be fixed, as it is very similar to borrowing after a subtraction, this means coefficients must be larger than your base by 1bit.
To convert back to base 10, you'd need to solve r (your result) for v (your value), such as r(10)=v(2^63). This has only one solution, if you enforce the positive coefficients rule.
[note] After thinking about it some more: the rule on positive coefficients may only be necessary for printing, after all.
Example: adding. no memory error checking
int addPolys(signed char** result, int na, const signed char* a, int nb, const signed char* b)
{
int i, nr, nmin, carry, *r;
nr = max(na, nb) + 1;
nmin = min(na, nb);
r = malloc(sizeof(signed char) * (na + nb + 1));
if (nb < na)
{
nr = nb;
}
for (i = 0; i < nmin; ++i)
{
r[i] = a[i] + b[i];
}
for (; i < na; ++i)
{
r[i] = a[i];
}
for (; i < nb; ++i)
{
r[i] = b[i];
}
r[nr - 1] = 0;
// carry - should really be a proc of its own, unoptimized
carry = 0;
for (i = 0; i < nr; ++i)
{
r[i] += carry;
if (r[i] > 10)
{
carry = r[i] / 10;
r[i] %= 10;
}
else if (r[i] < 0)
{
carry = (r[i] / 10) - 1;
r[i] -= (carry * 10);
}
else
carry = 0;
}
// 'remove' leading zeroes
for (i = nr - 1; i > 0; --i)
{
if (r[i] != 0) break;
}
++i;
*result = r;
if (i != nr)
{
*result = realloc(i * sizeof(signed char));
}
return i; // return number of digits (0 being 1 digit long)
}
That code is working now for any two positive numbers with up to ten thousand digits:
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(){
char chara[10000];
char charb[10000];
scanf("%s %s", &chara, &charb);
int lengthA = strlen(chara);
int lengthB = strlen(charb);
int max = lengthA;
if(lengthB>lengthA) max=lengthB;
int dif = abs(lengthA - lengthB);
//ustvari int tabele
int a[max];
int b[max];
int sum[max+1];
// nastavi nule
int i;
for(i=0; i<max; i++){
a[i] = 0;
b[i] = 0;
sum[i] = 0;
} sum[max] = 0;
//prekopiraj stevila iz char v int tabele &obrni vrstni red
for(i=0; i<lengthA; i++){
a[i] = chara[lengthA-i-1]-'0';
}
for(i=0; i<lengthB; i++){
b[i] = charb[lengthB-i-1]-'0';
}
int vsota;
int prenos = 0;
for(i=0; i<max; i++){
vsota = a[i]+b[i] + prenos;
if(vsota>=10) prenos = 1;
else if (vsota<10) prenos = 0;
sum[i]=vsota%10;
}
if(prenos==1){
sum[max] = 1;
for(i = max; i>=0; i--){
printf("%d", sum[i]);
}
} else {
for(i = max-1; i>=0; i--){
printf("%d", sum[i]);
}
}
return 0;
}
I was trying to solve Project Euler question 16 using c. I did not use bignnum libraries. The question asks 2^1000. I decided to store every digit of that number in an array.
For Example: 45 means arr[0]=4, arr[1]=5;
The problem is definitely i the function int multi.
#include<stdio.h>
#include<conio.h>
int multi(int *base, int k);// does the multiplication of array term by 2
void switcher();//switches every term when the fore mostvalue is >10
int finder();// finds the array address of last value
int arr[1000];
int summer();//sums all values of the array
int main()
{
arr[1000] = { 0 };
arr[0] = 1;
int i, j, sum, k, p;
for (i = 0; i < 1000; i++)
{
j = 0;
k = finder();
p = multi(arr + k, j);
}
sum = summer();
printf("sum of digits of 2^1000 is %d", sum);
_getch();
}
int multi(int *base, int k)
{
int p;
if (base == arr)
{
*base = *base - 1;
*base = *base + k;
if (*base > 10)
{
*base = *base - 10;
switcher();
}
return 0;
}
*base = *base * 2;
*base = *base + k;
if (*base > 10)
{
*base = *base - 10;
p = multi(base - 1, 1);
}
else
{
p = multi(base - 1, 0);
}
}
void switcher()
{
int j;
for (j = 0;; j++)
{
if (arr[j] == 0)
{
break;
}
}
j--;
for (; j > 0; j--)
{
arr[j + 1] = arr[j];
}
arr[0] = 1;
}
int finder()
{
int j;
for (j = 0;; j++)
{
if (arr[j] == 0)
{
break;
}
}
return --j;
}
int summer()
{
int summ, i;
summ = 0;
for (i = 0; i<1000; i++)
{
summ = summ + arr[i];
if (arr[i] == 0)
break;
}
return summ;
}
It compiles but during runtime it shows Access Write Violation, base was ......
Please explain this error and how to resolve it ?
Array is of 100 Bytes but you are looping for 1000. Also in function Finder() , you do not have a limit on variable j so your array size is going beyond 100 bytes.
Also use memset to assign array variables to 0.
As said in the comments, 2^1000 has 302 decimal digits.
You're going far outside your array.
But your code is very complicated because you store the digits with the most significant one first.
Since you're only interested in the digits and not the order in which they would be written, you can store the number "in reverse", with the least significant digit first.
This makes the code much simpler, as you can loop "forwards" and no longer need to shuffle array elements around.
Using -1 as "end of number" marker, it might look like this:
void twice(int* digits)
{
int i = 0;
int carry = 0;
while (digits[i] >= 0)
{
digits[i] *= 2;
digits[i] += carry;
if (digits[i] >= 10)
{
carry = 1;
digits[i] -= 10;
}
else
{
carry = 0;
}
i++;
}
if (carry)
{
digits[i] = 1;
digits[i+1] = -1;
}
}
int main()
{
int digits[302] = {1, -1}; /* Start with 1 */
twice(digits); /* digits is now { 2, -1 } */
return 0;
}