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
Related
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];
}```
void evolve(board prv, board nxt){
int i, j;
int n;
printf("\rGeneration %d\n", generation++);
if (printLazy == 1){
lazyPrint(prv);
for (j=0; j < WIDTH; ++j) {
for (i = 0; i < HEIGHT; ++i) {
n = neighbors(prv, i, j);
if (prv[i][j] && (n == 3 || n == 2))
nxt[i][j] = true;
else if (!prv[i][j] && (n == 3))
nxt[i][j] = true;
else
nxt[i][j] = false;
}
}
}
** Some asked me to add the neighbors method so
static int neighbors (board b, int i, int j) {
int n = 0;
int i_left = max(0,i-1);
int i_right = min(HEIGHT, i+2);
int j_left = max(0,j-1);
int j_right = min(WIDTH, j+2);
int ii, jj;
for (ii = i_left; ii < i_right; ++ii) {
for (jj = j_left; jj < j_right; ++jj) {
n += b[ii][jj];
}
}
return n - b[i][j];
}
So I am working on optimizing this so that it will go faster and I'm stuck on how to optimize this more. Here's what I have so far
void evolve(board prv, board nxt) {
register int i, j;
int n;
bool next;
printf("\rGeneration %d\n", generation++);
if (printLazy == 1){
lazyPrint(prv);
}
for (j=0; j < WIDTH; ++j) {
for (i = 0; i < HEIGHT; ++i) {
n = neighbors(prv, i, j);
if (prv[i][j])
if (n == 2)
next = true;
else if (n == 3)
next = true;
else
next = false;
else
if(n == 3)
next = true;
else
next = false;
nxt[i][j] = next;
}
}
}
Is there a better way to do this or are there any resources or videos y'all recommend?
Thanks, any help is appreciated.
Some ideas Inline your function neighbors(). Or turn it into a macro. Tidy up the conditional. To unroll the inner loop replace every use of i with the literal values so your code looks like :
for (j =0;.......
n = fun(prev, 0 ,j);
If.....
n = fun(prev, 1, j);
if......
and so on.
If the value of HEIGHT was let's say 100, then you get a code explosion of 100 function calls and 100 compound conditionals. Even worse if you unroll the outer loop.
If n was limited to say 8 neighbors, use a lookup table
bool foo[2][8] = { [1][2] = true, [1][3] = true, [0][3] = true };
for (j=0; j < WIDTH; ++j) {
for (i = 0; i < HEIGHT; ++i) {
n = neighbors(prv, i, j);
nxt[i][j] = foo[prv[i][j]][n];
}
}
A common weakness is the neighbors(prv, i, j) function itself. One trick to to oversize the 2D array by 1 on all four sides and populate the edge with false so neighbors() can always check 8 neighbors as it is never used on the edge/corners.
Making sure the 2nd dimension is a power of 2 helps also - simplifies index calculation. So if the original array way 12*11, make the new array (1+12+1)*(1+11+1+4) or 14*16.
this program is build to know all the huiwen number from 1 to 256
like 11^2=121 so 11 is a huiwen.
actually I have a good one
but I am confuse about why this program doesn't work well.
#include<stdio.h>
int is_huiwen(int l)
{
//DON'T WORK?WHY?
int number[20]={0};
int i,j,k;
int f=l*l;
for(j=0;f;j++)
{
number[j]=f%10;
f/=10;
}
for(k=0;j-k>0;k++,j--)
{
if(number[j]!=number[k] )
{
return 0;
}
}
return 1;
/* this is ok
int y=0;
int t = l*l;
int x = t;
do
{
y=y*10+t%10;
t /= 10;
}
while(t);
if(x==y)
return 1;
else
return 0;
*/
}
int main()
{
int i;
int flag;
for(i=0;i<256;i++)
{
flag=is_huiwen(i);
if(flag)
{
printf("%d is huiwen",i);
}
else
{
printf("\n");
}
}
printf("end\n\n\n\n");
return 0;
}
end.
The error is the if( number[j] != number[k] )line as pointed out by BluePixy.
The correction is if( number[j-1] != number[k] )
I would to point out that the code has hidden the problem partly because of a smattering of one letter variable names and inconsistent naming.
Here is the code that I used to find the same solution
int is_huiwen_2(int L )
{
int ret = 1;
int j = 0;
int k = 0;
int t = L * L;
int number[8] = { 0 };
for( j = 0; t; j++)
{
number[j] = t % 10;
t /= 10;
}
for( k = 0; (j - k) > 0 && ret; k++, j-- )
{
if( number[j-1] != number[k] )
{
ret = 0;
}
}
return( ret );
}
int is_huiwen_1( int L )
{
int ret = 1;
int y = 0;
int t = L * L;
int x = t;
do
{
y = y * 10 + t % 10;
t /= 10;
}
while( t );
if( x != y )
{
ret = 0;
}
return( ret );
}
int main()
{
int i = 0;
int flag = 0;
for( i = 0; i < 256; i++)
{
flag = is_huiwen_1(i);
if(flag)
{
printf("1: %d is huiwen\n",i);
}
}
for( i = 0; i < 256; i++)
{
flag = is_huiwen_2(i);
if(flag)
{
printf("2: %d is huiwen\n",i);
}
}
printf("end\n");
return( 0 );
}
I don't know what all the variables do. The use of 'l' looks like a '1' in some editors.
Being a Code Refactoring monk or zealot, I did some modifications such as reducing the code to one consistent return condition, value and point of return.
While it might seem overly simple, having multiple declarations on one line hides trouble, such as int i not being used in the second function.
The use of int numbers[20] = { 0 }; was also misleading us as for the range of values here [20] was overkill, having an explanation of what the range of values "12321", "1234321" where could have meant easier debugging of this code. A simple comment of what the outcome should look like would have solved several problems.
// A Huiwen number looks like this "12321", "1589851"
While this might be a simple exercise it portends greater problems down the line if this was not a trivial exercise. Try not to make it hard on the next coder.
Document your algorithms, arithmetic and variables please.
The program triggers a break point on the free() function call.
Debugging the program returns this message:
HEAP[C_C.exe]: Heap block at 00498240 modified at 00498298 past requested size of 50
C_C.exe has triggered a breakpoint.
I don't understand why free() triggers the break point if all seems correct...
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
int* aloca_vetor(int control)
{
int *vetor;
vetor = (int *)malloc((control * sizeof(int)));
return vetor;
}
int main()
{
int *vetor;
int Input[2];
int testes;
int control;
int i, j, w = 0;
scanf("%d", &testes);
while (testes != 0)
{
scanf("%d%d", &Input[0], &Input[1]);
control = ((Input[1] - Input[0]) + 2);
vetor = aloca_vetor(control);
if (vetor == NULL)
{
printf("No memory!");
}
for (i = 2; i < control; i++)
{
vetor[i] = TRUE;
}
for (i = 2; i < control; i++)
{
if (vetor[i] == TRUE)
{
j = 0;
for (w = 0; j < (control - 1); w++)
{
j = i*i + w*i;
vetor[j] = FALSE;
}
}
}
for (i = 0; i < control; i++)
{
if (vetor[i] == TRUE)
{
printf("%d\n", i);
}
}
testes--;
free(vetor);
}
return 0;
}
I think that the problem arises in this loop
for (w = 0; j < (control - 1); w++)
{
j = i*i + w*i;
vetor[j] = FALSE;
}
It seems that the value calculated such a way as
j = i*i + w*i;
can be greater than control.
You could rewrite the loop like
for (w = 0; ( j = i*i + w*i ) < (control - 1); w++)
{
vetor[j] = FALSE;
}
Also in my opinion the loop
while (testes != 0)
{
//...
testes--;
free(vetor);
}
would be more readable if it would be rewritten the following way
while ( testes-- != 0 )
{
//...
free(vetor);
}
or
while ( testes-- )
{
//...
free(vetor);
}
Take into account that you wrote the program such a way that it seems nobody understands what it does.:) You should try to write programs more readable even if they are test programs.
j = i*i + w*i will become much larger than the last valid index for the array. Accesses beyond the borders of an array presents undefined behaviour.
One effect might be to overwrite memory used by the hep management, so the effect will only become visible when calling free.
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.