thanks in advance for taking a look at this.
I'm getting a Windows error message when I try to run this program I wrote in C in Code::Blocks. The funny thing is it compiles fine, and if I lower the upper bound of what I'm testing the program runs fine as well.
Details:
When I try to run the program, first I get a Windows popup that says "X.exe has stopped working. Windows is checking for a solution to the problem". Shortly this changes to "X.exe has stopped working. A problem caused the program to stop working correctly. Windows will close the program and notify you if a solution is available. (Close program)" I click the close program button, and then I see the command prompt that says "Process returned 255 <0xFF> execution time 3.940 s Press any key to continue".
I have Windows 8.
I'm using the GNU GCC compiler.
If I change "upto" to 100000, the program works fine.
Here's the code:
/************************************************
* Finds the starting integer under 1000000 that
* produces the longest Collatz sequence, and the
* length of said sequence.
*************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <limits.h>
#define upto 1000000
int main()
{
long i;
long long j;
long long max = LONG_LONG_MAX;
long length = 0;
long number = 0;
long penull = 0;
long len[upto];
for (i = 0; i < upto; i++) (len[i] = 0);
// counts length of Collatz sequence for starting integers from 1 to 999999
for (i = 1; i < upto; i++)
{
j = i;
while (j != 1)
{
assert (j <= (max - 1)/3);
if (j%2 == 0) (j = j/2);
else (j = 3*j + 1);
len[i]++;
if (j < i)
{
len[i] = len[i] + len[j];
j = 1;
}
}
// stores length of the longest sequence and the starting integer producing it
if (len[i] > length)
{
length = len[i];
number = i;
}
// stores a duplicate length for later comparison
else if (len[i] == length) (penull = len[i]);
}
if (length == penull) (printf("There are at least two!"));
else printf("%ld produces a Collatz sequence of length %ld", number, length + 1);
return 0;
}
Move the array len outside the main function. The size of the stack is sometimes limited, and local variables are stored on the stack. By moving it outside, you make it a global variable.
Related
I wrote the code for a problem in codeforces and even though I believe I was doing it in the best time complexity it was exceeding the time limit on the 7th test case. After some testing, it seemed to me that the major amount of time was being taken by printf, which seemed odd since using printf some 3 * 10^5 times shouldn't be such a big deal. So I searched a lot and found this: https://codeforces.com/blog/entry/105687#comment-940911
Now I made the conclusion that using this line at the top of my code will make printf faster:
#define __USE_MINGW_ANSI_STDIO 0
So I ran my code with the above included and voila what was exceeding the time limit of 1s earlier now with the inclusion of just one line of code got accepted in merely 62 ms.
I didn't understand most of the other stuff that was talked about in the link like MinGW implementations and all.
So my question is, firstly why does it work this way? Secondly, can I/should I keep using the above line of code in all my programs on codeforces from now on?
P.S. I also found this blog: https://codeforces.com/blog/entry/47180
It was too confusing for me to grasp for the time being but maybe someone else can understand it and shed some light on the matter.
Also, here is the codeforces problem: https://codeforces.com/contest/1774/problem/C
Here is my solution:
https://codeforces.com/contest/1774/submission/185781891
I don't know the entire input as codeforces doesn't share it and it'd be very very big. But I know that the value inputted to the tests variable is 3, the values inputted to n[0], n[1], n[2] are 100000, 100000, 100000
Here is my code:
#define __USE_MINGW_ANSI_STDIO 0
#include <stdio.h>
#include <stdlib.h>
// #include <math.h>
// #include <string.h>
// #define lint long long int
// Function Declarations
int main(void)
{
int tests;
scanf("%i", &tests);
int **answers = malloc(tests * sizeof(int*));
int *n = malloc(sizeof(int) * tests);
for (int i = 0; i < tests; i++)
{
scanf("%i", &n[i]);
char *enviro = malloc((n[i]) * sizeof(int));
answers[i] = malloc((n[i] - 1) * sizeof(int));
int consec = 1; // No. of same consecutive elements at the very
// end.
scanf("%s", enviro);
answers[i][0] = 1; // Case where x = 2;
for (int x = 3; x < n[i] + 1; x++)
{
// comparing corresponding to current x vs previous x
if (enviro[x - 2] == enviro[x - 3])
{
consec++;
}
else
{
consec = 1;
}
answers[i][x - 2] = x - consec;
}
// Free loop variables
free(enviro);
}
/* if (tests == 3)
{
printf("n[%i] = %i\n", i, n[i]);
} */
for (int i = 0; i < tests; i++)
{
for (int j = 0; j < n[i] - 1; j++)
{
printf("%i ", answers[i][j]);
}
printf("\n");
free(answers[i]);
}
// Free variables
free(answers);
return 0;
}
EDIT: So I tried the following code for the same problem on codeforces (https://codeforces.com/contest/1774/submission/185788962) just to see the execution time:
// #define __USE_MINGW_ANSI_STDIO 0
#include <stdio.h>
#include <math.h>
int main(void)
{
int n = pow(10, 5);
for (int i = 0; i < n; i++)
{
printf("*");
}
}
Without the #define __USE_MINGW_ANSI_STDIO 0 it gave an e.t. of 374ms. With it, it gave e.t. of 15ms.
It seems like MinGW defined their own printf() functions, __mingw_printf(). This is done to fix format specifiers' problems on some old Windows operating systems, as seen in their wikis. The macro __USE_MINGW_ANSI_STDIO is set to 0 if you don't want to use MinGW's implementation, and 1 if you do.
It also seems like MinGW's implementation is slower, so not using it will make your code faster.
This question already has an answer here:
Trouble implementing isalpha
(1 answer)
Closed 2 years ago.
Addmitedly and obviously I am new to this coding thing. I'm enjoying working it out but I feel stuck on this problem. Any guidance would be appreciated!
I am attempting to count all of the letters of a particular text from the user, but my counter (i) comes out as 1 when I run the program regardless of input. Below is my code.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
string a = get_string("Text: \n"); // Get input
for (int i = 0, n = strlen(a); i < 1; i++) //Set counter for number of letters
{
if isalpha(a[i]). // Count only if character is a letter
{i++;}
printf("%i\n", i); // print counter
}
}
Again, any guidance (in as simple of terms as possible!) is appreciated as I've been trying to figure this out for two days.
So i've edited your code a bit to where it would make sense and I'll try to explain why I changed some stuff. I'm a bit rusty with c/c++ so I'd appreciate if anyone can point out what I'm wrong with.
so here's a snippet of code that would count the number of letters.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
char a[] = "test";
int n = strlen(a);
int i = 0;
for (i = 0; i < n; i++) //Set counter for number of letters
{
}
printf("%i\n", i); // print counter
}
So with your code a couple things.
(1) for (int i = 0, n = strlen(a); i < 1; i++)
A for loop looks like this
for(where you start your loop at ; where you stop; count up or down)
so with your code I did this:
for (i = 0; i < n; i++) //Set counter for number of letters
where we start i with 0, we go till i hits n and we count up
now you can do this if it makes more sense:
for (i = 0; i < n; i++) //Set counter for number of letters
{
i++;
}
but they'll both do the same thing (I think) since we are iterating i, but I do think this is better due to readability.
(2) printf("%i\n", i); // print counter
As you probably know this prints out the number of letters and you had this in your for loop and that's fine when you're doing something like a countdown. So if we put it in the for loop it would look like this:
for (i = 0; i < n; i++) //Set counter for number of letters
{
printf("%i\n", i); // print counter
}
where it would print out 0 1 2 3 (Remember arrays always start at 0), so by keeping it outside of the for loop, you just have a counter for how many times 'i' was iterated in the for loop, so you get 4.
in your for loop, the i < 1 part means you will loop while i is smaller than 1, it is initialised to 0 on the first loop, so it runs (and counts to 1), and then at the end of the loop, i increments to 1, and therefore the loop will not run again. You need to put i < n instead of i < 1. and you also need to change the counter to j (or another variable), as mentioned in the comments.
Well, I wrote a little Program that should generate random values, but no value should be in the output file twice.
On Linux it's running perfectly, but on Windows it just runs infinity long on the 32768th value.
That means, that cmd is open but nothing really happens from that point.
I already did debug it 30 times by now but it never had any problem (it was hell do debug it)
I wrote it new, recompiled it, even changed values under it was running through the debugger
Here is the Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
int intlen(int[]);
int main(int argc, char *argv[]) {
FILE *fp;
int percent = 0;
int Ergebnis = 0, length = 0, lenNow = 0;
bool proof = true;
srand(time(NULL));
fp = fopen("ranGen.txt", "w");
length = atoi(argv[1]);
int Lookup[length];
for (int x = 0; x < length; x++){
Lookup[x] = 0;
}
for (int i = 0; i < length; i++) {
do {
proof = true;
Ergebnis = rand() % (2147483646 - 1 + 1) + 1;
for (int j = 0; j < length && Lookup[j] != 0 && proof != false; j++) {
if (Ergebnis == Lookup[j]) {
proof = false;
}
}
}while(proof == false);
Lookup[lenNow] = Ergebnis;
lenNow++;
fprintf(fp,"%i ",Ergebnis);
}
return 0;
}
posted everything, but the output because I don't really know where the problem is and I think you will need the most of it reproduce my problem.
if you compiled it, run it through cmd with something like 50000, so that it is higher than 32768.
(like this: example.exe 50000)
Expected was, that it will create a File named RanGen.txt with 200000 random values (200000 was my test value)
But the output was 32767 Values in the text Document and then the program just did nothing more.
Solution: used rand() % 214748346; instead of rand() % (214748346 - 1 + 1) + 1;
Looks like rand() is only 16 bits in that library. Make it 32 bits by calling it twice:
int rand32() {
return rand() ^ (rand() << 16);
}
Also, consider eliminating the inner duplicate-search loop by using Bob Floyd's algorithm: https://blog.acolyer.org/2018/01/30/a-sample-of-brilliance/
I have a simple test program in C to scramble an array of values on the heap. Sidenote: I know the random logic here has a flaw that will not allow the "displaced" value to exceed RAND_MAX, but that is not the point of this post.
The point is that when I run the code with N = 10000, every once in a while it will crash with very little information (screenshots posted below). I'm using MinGW compiler. I can't seem to reproduce the crash for lower or higher N values (1000 or 100000 for example).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int N = 10000;
int main() {
int i, rand1, rand2, temp, *values;
/* allocate values on heap and initialize */
values = malloc(N * sizeof(int));
for (i = 0; i < N; i++) {
values[i] = i + 1;
}
/* scramble */
srand(time(NULL));
for (i = 0; i < N/10; i++) {
rand1 = (int)(N*((double)rand()/(double)RAND_MAX));
rand2 = (int)(N*((double)rand()/(double)RAND_MAX));
temp = values[rand1];
values[rand1] = values[rand2];
values[rand2] = temp;
}
int displaced = 0;
for (i = 0; i < N; i++) {
if (values[i] != (i+1)) {
displaced++;
}
}
printf("%d numbers out of order\n", displaced);
free(values);
return 0;
}
it may be because rand() generates a random number from 0 to RAND_MAX inclusive so (int)(N*((double)rand()/(double)RAND_MAX)) can be N, which exceeds the array boundary. however, i don't see why that would vary with array size (it does explain why it only crashes sometimes, though).
try /(1+(double)RAND_MAX) (note that addition is to the double, to avoid overflow, depending on the value of RAND_MAX) (although i'm not convinced that will always work, depending on the types involved. it would be safer to test for N and try again).
also, learn to use a tool from Is there a good Valgrind substitute for Windows? - they make this kind of thing easy to fix (they tell you exactly what went wrong when you run your program).
I'm writing a program in C to do a simple dynamic programming algorithm where you return the minimum number of coins needed to add up to a certain amount. Here's my code:
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
/*
This function returns the minimum number of stamps required for a given value.
It assumes that the given array contains the available stamp sizes, and that it
always contains 1, so a solution is always possible
*/
int min_number_of_stamps(const int* array, size_t array_size, int request) {
/* Construct a table with dimensions (array_size+1)*(request+1) */
int numRows = array_size + 1;
int numCols = request + 1;
int **DPtable;
DPtable = malloc(numRows*sizeof(int));
int i;
for (i = 0; i < numRows; i++) {
DPtable[i] = malloc(numCols*sizeof(int));
}
printf("%d",DPtable[4][0]);
int r, c, useIt, loseIt;
for (r = 0; r < numRows; r++) {
for (c = 0; c < numCols; c++) {
printf("%d,%d\n", r, c);
if (c==0) {
printf("1\n");
//if the amount of change is 0, 0 coins are needed
DPtable[r][c] = 0;
}
else if ((r==0) || c < array[r-1]) {
printf("2\n");
//if there are no coins or if the change needed is less than
//the smallest coin available, then 'infinity' coins are needed
DPtable[r][c] = INT_MAX;
}
else {
printf("3\n");
useIt = DPtable[r][c-array[r-1]] + 1;
loseIt = DPtable[r-1][c];
if (useIt <= loseIt) {
//if 'use it' requires fewer coins than 'lose it,' then
//'use it' coins are needed.
DPtable[r][c] = useIt;
}
else {
//if 'lose it' requires fewer coins, 'lose it' coins are needed
DPtable[r][c] = loseIt;
}
}
}
}
return DPtable[numRows][numCols];
}
int main() {
const int array[] = {1,5,10,25};
const int* stamps = &array[0];
printf("%d", min_number_of_stamps(stamps, 4, 44));
}
I'm getting a segfault when my inner for loop gets to the case where r=4 and c=0. I left my debugging print statements in because I'm lazy, but you can see where I got stuck. If I access the same place in the array outside of my for loops, there's no problem. But in the for loop, I get a `Segmentation fault: 11' message after it outputs "4,0" for the array element and "1" for the if case it's in. Can anyone see what I'm missing?
Learn to enable warnings & debugging for your compiler, i.e. gcc -g -Wall on Linux.
Learn to use a debugger, i.e. gdb -tui on Linux.
Consider using valgrind
EDIT
Many tutorials (in several languages, e.g. English, French, ....) for GCC, GDB, and ValGrind are easily found on the Web.
You're allocating dpTable incorrectly. It should be
DPtable = malloc(numRows*sizeof(int*));
See if that fixes the problem.
return DPtable[numRows][numCols];
thats out of bounds isn't it?