Optimization of algorithm while - c

here are 2 codes that give the same result :
Code 1
#include <stdio.h>
int main(int argc, char **argv)
{
int res, nbMax = 0, i;
unsigned long j;
for (i = 1; i <= 1000000; i++) {
j = i;
int nb = 1;
while (j != 1) {
nb++;
if (j % 2 == 0) {
j = j / 2;
} else {
j = 3 * j + 1;
}
}
if (nb > nbMax) { // <-
nbMax = nb;
res = i;
}
}
printf("longest: %d (%d)\n", res, nbMax);
return 0;
}
Code 2:
#include <stdio.h>
int main(int argc, char **argv)
{
int res, nbMax = 0, i;
unsigned long j;
for (i = 1; i <= 1000000; i++) {
j = i;
int nb = 1;
while (j != 1) {
nb++;
if (nb > nbMax) { // <-
nbMax = nb;
res = i;
}
if (j % 2 == 0) {
j = j / 2;
} else {
j = 3 * j + 1;
}
}
}
printf("longest: %d (%d)\n", res, nbMax);
return 0;
}
the diference is the commented bloc (if). the first time is outside the 2nd while loop, and in the second inside.
the first algorithm should be faster than the second because that scope is executed more times in the 2nd algorithm.
however i get 1second time execution in the first one, and 0.9 in the second...
how can be the 2nd algoirthm faster than the 1st ??
EDIT. I work on MinGW(4.7.1) Windows 8.1 intel i7-4500

I cannot reproduce it here, but it depends on the platform and compiler you are working with. Based on the Optimization Algorithms used in the compiler, some parts of your code may change. If something does not affect your code, may be get out of the loop or even be omitted from the code during optimization phase while compiling. You can check the compiler optimization techniques in Loop Optimization for some insight.

Related

The Damerau-Levenshtein distance in C

I'm working on a spell checker and I need to optimize the Damerau-Levenshtein distance. For example... when 2 words have a distance greater than 3 (or a limit), I need to break the function. This will reduce the execution time. i was thinking veryfy when the min is greater than 3, but through the proccess, sometimes the min is greater, because Damerau-Levenshtein distance works on a table of min values. I think to add a condition like i == j, but when a word is longer than the other it fail. The code is version from Internet.
#include <stdio.h>
#include "levenshtein.h"
#include <stdlib.h>
#include <string.h>
int min_(int a, int b){
return (a<b)?a:b;
}
int dist_dlevenshtein(char* p_string1, char* p_string2, int umbral)
{
int l_string_length1 = strlen(p_string1);
int l_string_length2 = strlen(p_string2);
int d[l_string_length1+1][l_string_length2+1];
int i;
int j;
int l_cost;
for (i = 0;i <= l_string_length1;i++)
{
d[i][0] = i;
}
for(j = 0; j<= l_string_length2; j++)
{
d[0][j] = j;
}
for (i = 1;i <= l_string_length1;i++)
{
for(j = 1; j<= l_string_length2; j++)
{
if( p_string1[i-1] == p_string2[j-1] )
{
l_cost = 0;
}
else
{
l_cost = 1;
}
d[i][j] = min_(
d[i-1][j] + 1, // delete
min_(d[i][j-1] + 1, // insert
d[i-1][j-1] + l_cost) // substitution
);
if( (i > 1) &&
(j > 1) &&
(p_string1[i-1] == p_string2[j-2]) &&
(p_string1[i-2] == p_string2[j-1])
)
{
d[i][j] = min_(d[i][j],d[i-2][j-2] + l_cost); // transposition
}
}
}
return d[l_string_length1][l_string_length2];
}```

How to efficienty count from 0000 to 9999 in a digit display?

I've n display that count from 0 to 9. I'd like to make an efficient code for a micro in C language. What I've wrote is:
dis_value[0]++;
if (dis_value[0] > 9) {
dis_value[0] = 0;
dis_value[1]++;
}
if (dis_value[1] > 9) {
dis_value[0] = 0;
dis_value[1] = 0;
dis_value[2]++;
}
if (dis_value[2] > 9) {
dis_value[0] = 0;
dis_value[1] = 0;
dis_value[2] = 0;
dis_value[3]++;
}
if (dis_value[3] > 9) {
dis_value[0] = 0;
dis_value[1] = 0;
dis_value[2] = 0;
dis_value[3] = 0;
}
Where from 0 to 3 are display module number.
Is that the best way?
Or maybe is better a single counter of 16bit that is split into 4 different part?
You can nest the digit reset or increment
dis_value[0]++;
if (dis_value[0] > 9) {
dis_value[0] = 0;
dis_value[1]++;
if (dis_value[1] > 9) {
dis_value[1] = 0;
dis_value[2]++;
if (dis_value[2] > 9) {
dis_value[2] = 0;
dis_value[3]++;
if (dis_value[3] > 9) {
dis_value[3] = 0;
}
}
}
}
By doing above you are not unnecessarily executing all the ifs.
char *inc(char *buff, unsigned *i)
{
unsigned tmp = ++(*i);
buff[0] = tmp % 10;
tmp /= 10;
buff[1] = tmp % 10;
tmp /= 10;
buff[2] = tmp % 10;
tmp /= 10;
buff[3] = tmp % 10;
return buff;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void delay(int number_of_seconds)
{
int milli_seconds = 1000 * number_of_seconds;
clock_t start_time = clock();
while (clock() < start_time + milli_seconds);
}
int main(int argc, const char *argv[])
{
int arr[4] = {0};
for(int i=0; i < 4; i++)
{
for(int j = 0; j<9; j++)
{
arr[i]++;
delay(1000);
printf("%i%i%i%i\n",arr[3], arr[2], arr[1], arr[0]);
}
}
printf("\n");
return 0;
}
I spotted you want to keep the code with minimal dependencise on a microcontroller.
If you are willing to treat the dis_value buffer as an integer, with one byte per digit, say little-endian, which can be held in a register, which should also be faster, then you can combine the sequence:
if (dis_value[N] > 9) {
dis_value[N] = 0;
dis_value[N+1]++;
It becomes (with #kiran 's nesting)
if ((dis_value&(0xf<<(N*8)))==(10<<(N*8)))
{
dis_value+=(0x100-10)<<(N*8);
if ...
}
Where I am presuming the compiler will resolve the constant expressions.
It would also be good to reverse the addition and the if in order to improve conditional pipeline evaluation, if your controller has a pipeline, but that means writing assembler code.
The following pseudocode should give the idea. The next condition is evaluated using the value before the addition, so the two operations can be performed in parallel. If you were actually encoding this to a circuit, this is an obvious optimisation:
bool do0 = ((dis_value&(0xf<<(0*8)))==(9<<(0*8)))
dis_value++;
if (do0)
{
bool do1 = ((dis_value&(0xf<<(1*8)))==(9<<(1*8)));
dis_value += (0x100-10)<<(0*8);
if (do1)
{
do2 = ((dis_value&(0xf<<(2*8)))==(9<<(2*8)));
dis_value += (0x100-10)<<(1*8);
if (do2) ...
}
}
The next question to ask is how can you minimally update a segmented display for an increment!
simulate math addition would suffice, checking from the lowest digit to the highest.
#include <stdio.h>
void incr(int dis_value[], int n) {
++dis_value[0];
for (int i=0; i+1<n; ++i) {
if (dis_value[i] < 10) break;
dis_value[i+1] += dis_value[i] / 10;
dis_value[i] %= 10;
}
dis_value[n-1] %= 10;
}
void echo(int dis_value[], int n) {
for (int i=n-1; i>=0; --i) printf("%d", dis_value[i]);
printf("\n");
}
int main() {
int dis_value[] = {0, 0, 0, 0};
for (int i=0; i<10000; ++i) {
incr(dis_value, 4);
echo(dis_value, 4);
}
return 0;
}

simulation algorithm implementation in C/C++

Let a row of 8000 lamps. Initially, only the one located to the left is lit.
Then, every second, the following operation is performed: each lamp changes state (on or off) if the one on its left was lit a second before. The leftmost lamp stays on all the time. This operation is instantaneous.
The process stops when the lamp at the right end lights for the first time.
How many lights are on?
My following implementation of the problem is false, can you help me?
#include <cstdio>
int t[8001][2];
int main()
{
t[1][0] = 1;
t[1][1] = 1;
int cpt1 = 0, ip = 0;
while (t[8000][0] != 1 && t[8000][1] != 1)
{
ip++;
for (int j=2;j<8001;j++)
{
if(t[j-1][!(ip&1)])
t[j][(ip & 1)] = !t[j][!(ip & 1)];
}
}
for(int j = 1;j < 8001; j++)
cpt1 += t[j][1];
printf("cpt=%d\n", cpt1);
}
Code is missing an update when the left does not change.
Code simplified (zero based offset, use of bool) and corrected below
#include<stdbool.h>
#include<stdio.h>
#define N 8000
bool t[N][2];
int main(void) {
t[0][0] = true;
t[0][1] = true;
int ip = 0;
while (t[N - 1][0] == 0 && t[N - 1][1] == 0) {
ip = !ip;
for (int j = 1; j < N; j++) {
if (t[j - 1][!ip]) {
t[j][ip] = !t[j][!ip];
} else {
t[j][ip] = t[j][!ip]; // add
}
}
}
int cpt1 = 0;
for (int j = 0; j < N; j++) {
cpt1 += t[j][1];
}
printf("N=%d cpt=%d\n", N, cpt1);
return 0;
}
Output
N=8000 cpt=2048
the following proposed code:
cleanly compiles
uses C header files rather than C++ header files
performs the desired operation, but not the fastest possible algorithm
is liberally commented
And now the proposed code:
#include <stdio.h>
int t1[8000]; // initially all zeros
int t2[8000];
int main( void )
{
// setup initial conditions
int numLitLights = 0;
t1[0] = 1;
// while stop condition not true
while ( t1[7999] != 1 )
{
// make one pass through lamps
// update values
for (int j=0; j<7999; j++)
{
if( t1[j] )
{
t2[j+1] = ( t1[j+1] )? 0 : 1;
}
}
// update original
for( int j=0; j< 8000; j++ )
{
t1[j] = t2[j];
}
}
// count lit lamps
for(int j = 0; j < 8000; j++)
{
if( t1[j] )
{
numLitLights++;
}
}
// output number of lit lamps
printf( "number of lit lamps: %d\n", numLitLights );
} // end function: main
The result (number of lamps lit) is
1024

Access Violation in C program involving pointer variable?

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

Program Bugs with large sequences (C) [closed]

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.

Resources