COINS - SPOJ TLE in File reading Method - c

Solving the question by Memoization without the help of Maps, I got a TLE due to the method of reading the file, which shouldn't have been the case according to me. What could be the possible reason?
Here is the code that gives AC - http://ideone.com/OX1XlD
In the above code, for scanning n, if the while(scanf("%lld",&n)!=EOF) is replaced by
scanf("%lld",&n)
while(n!=EOF){ do something
scanf("%lld",&n);
}
the same gives a TLE. I can't figure out why.

I did not check your code in the link, but from the code in the question, in case of while(scanf("%lld",&n)!=EOF), you're checking the return value of scanf() itself.
OTOH, by saying
scanf("%lld",&n)
while(n!=EOF){
you're checking the value of n, which, is a completely different case and in case of scanf() failure, is undefined behaviour, if n is not initialized earlier.
The correct and preferred method,Thanks to Mr. Weather Vane will be to check against the number of items in scanf(), like
if (1 != scanf("%lld",&n))
or,
while ( 1 == scanf("%lld",&n)) //as in this case
EOF is a corner case and is usually rare.

In response to a recent comment by OP I suggest he tries this.
#include <stdio.h>
int main(void) {
long long int n;
char instr[20];
while (1 == scanf("%lld", &n)) {
printf ("The entry was %lld\n", n);
}
printf("End of file\n");
return 0;
}
The SPOJ will test your code by feeding it input from a file. Let's say inp.txt has
1
2
3
4
You then run your code with something like (in the case of Windows console)
coins <inp.txt
and this gives me the output
The entry was 1
The entry was 2
The entry was 3
The entry was 4
End of file
If this works, and your program still exceeds the time limit, you must look at your solution algorithm, since SPOJ gives no clues as to why you have a TLE.
Of course, your submitted solution must not print those cues since the output will fail the test.

Related

How do I generate random numbers but not repeating and within a certain range based on user input?

Currently, I am experimenting some codes regarding/about random numbers. The problem is, when I run the program, input any number (ex. 12), I, sometimes get the correct and sometimes wrong answer. The correct answer must be any non repeating random numbers based on user input. (ex. input 5, output must be 1. seats[12]=1, 2. seats[19]=1,..., 5. seats[47]=1). I do not know what to do and yeah help me coders!
Here's the code:
#include<stdio.h>
#include<conio.h>
#include<time.h>
main()
{
int x,y,chc1A,seats[50]={};
printf("Enter a number: ");
scanf("%d",&chc1A);
srand(NULL);
for(x=0;x<chc1A;x++)
{
if(seats[rand()%50]==0)
seats[rand()%50]=1;
else
x--;
}
for(x=0,y=1;x<50;x++)
if(seats[x]==1)
{
printf("%d. seats[%d] = %d\n",y,x,seats[x]);
y++;
}
getch();
}
I do not really know what's wrong please enlighten me.
I run and coded this on Dev C++
What I want to do is: generate random numbers between 0-49 and putting it in an array seats[50]. (ex 38 then put 1 in array seats[38]). Btw this code represents passengers sitting on a bus with 50 seats. So the "1" means that the seat is occupied.
This part may cause problem.
for(x=0;x<chc1A;x++)
{
if(seats[rand()%50]==0)
seats[rand()%50]=1;
else
x--;
}
I think by
if(seats[rand()%50]==0)
seats[rand()%50]=1;
you meant to generate a random number, use that as index to seats and if seats[random_no] is 0, set seats[random_no] to 1.
But the random number in the if statement and the one in its body are different numbers.
You could use
int index = rand()%50;
if(seats[index]==0)
seats[index]=1;
Consider changing the signature of your main() function. See What are the valid signatures for C's main() function?
conio.h is not part of the standard, try to avoid its usage. Same goes for getch() as it's from conio.h.
srand() expects an unsigned int as argument and NULL is not of that type. See here.
Include stdlib.h to use srand().
And checking the return value of scanf() is a good idea. You can see if it failed or not.

Shortest difference between elements of an array

I am new to online judges. I solved a problem getting correct output on my PC but online judge is directly saying wrong answer.
Here is the problem https://www.codechef.com/problems/HORSES
This question deals with only shortest difference between elements of array.
My solution may not be efficient but it is correct.
Please help me
Chef is very fond of horses. He enjoys watching them race. As expected, he has a stable full of horses. He, along with his friends, goes to his stable during the weekends to watch a few of these horses race. Chef wants his friends to enjoy the race and so he wants the race to be close. This can happen only if the horses are comparable on their skill i.e. the difference in their skills is less.
There are N horses in the stable. The skill of the horse i is represented by an integer S[i]. The Chef needs to pick 2 horses for the race such that the difference in their skills is minimum. This way, he would be able to host a very interesting race. Your task is to help him do this and report the minimum difference that is possible between 2 horses in the race.
Input:
First line of the input file contains a single integer T, the number of test cases.
Every test case starts with a line containing the integer N.
The next line contains N space separated integers where the i-th integer is S[i].
You can read the problem here https://www.codechef.com/problems/HORSES
#include<stdio.h>
#include<limits.h>
int main(){
int t,n,i,u,v;
int min=INT_MAX;
scanf("%d",&t);
while(t>0){
scanf("%d",&n);
int *s=malloc(sizeof(int)*n);
for(i=0;i<n;i++){
scanf("%d",&s[i]);
}
for(i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
if(min>abs(s[i]-s[j]))
min=abs(s[i]-s[j]);
}
}
printf("%d\n",min);
t--;
}
}
I solved a problem getting correct output on my PC but online judge is directly saying wrong answer.
Insufficient testing. Code is correct when t ==1, yet not for t > 1.
Code needs to reset the minimum for each test case.
// int min=INT_MAX;
scanf("%d",&t);
while(t>0){
int min = INT_MAX; // add
Other short-comings exists too, yet the above is key.
Robust code would:
Check the return value of scanf()
Check that malloc() succeeded and then later free it.
Address potential; overflow in abs(s[i]-s[j])
Also
Consider delaying variable declaration to the block that needs it. Had OP done this, the above problem would not have occurred.
Format code more uniformly and use {} even with single line blocks with for, if, ....
Efficiency
Sort the array first (qsort()) and then walk the array noting difference between elements. O(n*lg(n))

Why am I getting this huge numbers in C?

I'm trying to teach myself C using Kernighan's book and I'm supposed to make a graph that indicates how many letters there are in each word. I haven't got to the "plotting" part as I'm getting really weird and enormous numbers at the output. Right now I'm just trying to have the value of the first and second elements of the array "arreglo" printed.
The code is the following:
#include <stdio.h>
#define ARRAY_SIZE 100
/*#define AUX 0
#define AUX2 0*/
main()
{
int s,j,noletra,i,arreglo[ARRAY_SIZE],otros, nopalabra, c;
int a;
nopalabra=1;
while((c=getchar())!=EOF)
{
if(c==' '||c=='\t'||c=='\n')
++nopalabra;
else
++arreglo[nopalabra];
}
printf("%d",arreglo[1],arreglo[2]);
}
The reason I'm trying to know the value in the second element in the array is that the first element has the correct value. The code is supposed to add 1 to the array index which is the number of words each time a space, tab or \n is typed and to add 1 to the array element whenever something different than the previously mentioned characters is typed (Letters). Right now it´s supposed to print correctly the number of the letters of two words, the first element is correctly printed but the second is a huge number, the output is:
alan amaury
^Z
4 8257542
--------------------------------
Process exited after 7.773 seconds with return value 9
Press any key to continue . . .
The output is supposed to be 4 7. I'm using a compiler in windows so EOF should be Ctrl+Z
Any help that I could get from you will be appreciated :)
At least these problems.
int arreglo[ARRAY_SIZE]; is not initialized before its elements are incremented. This is the mostly likely cause of "Why am I getting this huge numbers" #ikegami
// int arreglo[ARRAY_SIZE];
// replace with
int arreglo[ARRAY_SIZE] = { 0 };
Code can access out of array bounds as nopalabra is not confined to 0 to 99.
#define ARRAY_SIZE 100
int arreglo[ARRAY_SIZE];
++arreglo[nopalabra]; // No access protection
printf("%d",arreglo[1],arreglo[2]); only prints arreglo[1]
Logic flow is incorrect to "make a graph that indicates how many letters there are in each word."
main() return type not coded.
Some pseudo-code as an alternative
int main(void) {
set all arreglo[] to 0
int nopalabra = 0;
part_of_word = false; // Keep track of word state
loop forever {
get a character into c
if c is a separator or EOF
if (part_of_word) {
arreglo[nopalabra]++;
part_of_word = false;
nopalabra = 0;
if (c == EOF) break loop
} else {
nopalabra++;
part_of_word = true;
}
}
print out results
}
First, try the solution answered before, changing the printf() call.
If there is still a problem try:
printf("%d %d \n",arreglo[1],arreglo[2]);
Just before the while loop, to see if the "arreglo" array is initialize to 0's or just random values.
On the side:
Your call to printf() has more parameters than covered by the format string.
So you should clean up your code to something similar to
printf("%d %d\n", arreglo[1], arreglo[2]);
Concerning the strange output:
A way of getting surprising values is using non-initialised variables.
In your case the lack of initialisation affects the array arreglo.
Make sure to initialise it, so that all counting starts on a meaningful value.
Another way of getting seemingly very high values is printing several numbers next to each other, without separating white space in between.
So the " " and the "\n" in the format string I proposed are quite relevant.
the question is: "Why am I getting this huge numbers in C?"
the answer is: you have not assigned anything to arreglo array, and since you have not initialized it, you got some random values that have been there in memory. Trust me on this, I have run your code in debugger, which I also highly recommend a a standard practice while lerning to program.
Also, this is a common mistake where the format specifier is not written:
printf("%d",arreglo[1],arreglo[2]);
See if using printf("%d","%d",arreglo[1],arreglo[2]) solves your problem.
By the way, K&R book is very old, and written at the time where there have been no other C books. There are better ways to learn C.

C -- Double type data: Number slightly larger than allowed is able to slip through the conditions

I'm new to C language, it is required for my degree to complete one course on C programming. Hope the title makes sense... I had a hard time trying to convey what I meant. I'll elaborate here.
The problem I am facing right now is double type data being able to slip through the program undetected when it should have been rejected. This happens when a number very very close to the boundaries I set is provided.
In this assignment, in order to get an HD, my code has to have identical output to the lecturer's. The solutions are able to detect any number larger than the boundaries, no matter how close.
Basically, the program will ask the user to provide a GPA which is from 0 to 4.
I tried the following inputs:
4.01 rejected
4.001 rejected
...
4.000001 rejected
But at 4.0000001, it is accepted. This should not happen at all. I am baffled.
Here's my code:
double GPA=-1; /*Flags are being initialised*/
int GPAflag=1;
while(GPAflag){
char str[50];
char *ptr;
int isnum=1,n=0,i,point=0;
printf("Enter GPA>");
fflush(stdin);
gets(str);
n = strlen(str);
if(n==0){ /*string length is 0? There was no input, thus invalid*/
printf("Invalid GPA. ");
isnum=0;
}else{
for(i=0;i<n;i++) /*Validates numerical inputs, if not numerical, prompts user with error*/
if(!(str[i]>='0' && str[i]<='9')){
if(str[i]!='.'){
printf("Invalid GPA. ");
isnum=0;
break;
}else{
point++;
}
}
}
if(isnum){ /*If the input is a number, it may still be invalid*/
GPA=strtod(str, &ptr); /*The string is converted to a double*/
if(GPA>=0&&GPA<=4&&point<=1) /*If GPA is between 0 and 4, and the above is also satisfied (point=1), then the flag is 0 and thus a valid input*/
GPAflag=0;
else
printf("Invalid GPA. "); /*If not, it is still invalid*/
}
}
I personally don't think this will be a problem but I would really like to know why it happens, and if possible, a way to fix it.
I can simply make a FOR loop:
IF leading number is 4 and there's a '.'
-> Reject
But this seems like hard coding to me, I think it's rather a workaround than an actual solution.
Or I can change the IF statement from "<=4" to "<4.0000000000000000000000...1". Which in my opinion should lose marks... (if I was the marker I will take marks off for that)
Also, I am totally aware that the function "gets" is primitive and causes many problems (overflow... etc.). I have tried using fgets but it's a pain to implement... replacing the '\n' with '\0' blah blah... we haven't even learnt gets, let alone fgets. Is there a better way to implement fgets? Maybe have a function to replace the '\n'? I've tried that and it refused to work.
Any help and tips are greatly appreciated!
OP's true code was using float GPA=-1; and so GPA=strtod("4.0000001", &ptr); resulted in a GPA value of exactly 4.0 due to the greater limited precision of float versus a double.
By using double GPA;, as in the posted code, GPA=strtod("4.0000001", ... and GPA=strtod("4.000000001", ... will return a value just greater than 4. Even GPA=strtod("4.00000000000001", ... is likely to return a value a bit larger than 4.
At some point the limited precision of double will render GPA=strtod("4.0 many digits 001", ... as 4.0. A typical solution to limit the number of digits to something like 15 or less.
(Could taunt the user if more that 15 digits are used.)
The problem is solved, and looking back, it was due to a mistake:
In the structure, I have declared GPA as a float. I later changed it in my functions but missed out the most important part. As a result, the GPA was still stored as a float. Hope this conclusion is correct.
The limitations of the datatype causes round-off errors when an incredibly "close to allowed" value is provided.
Lesson learnt: When changing something, always make sure everything is consistent.
I appreciate all the help! Thanks a lot!

codechef :wrong answer error in smallfactorial

#include<stdio.h>
int fact(int k)
{
int j,f=1;
for(j=1;j<=k;j++)
f*=j;
return f;
}
int main()
{
int t,i,n[100],s[100],j;
scanf("%d",&t);
for(i=0;i<t;i++)
{
scanf("%d",&n[i]);
}
for(j=0;j<t;j++)
{
s[j]=fact(n[j]);
printf("%d \n",s[j]);
}
return 0;
}
You are asked to calculate factorials of some small positive integers.
Input
An integer t, 1<=t<=100, denoting the number of testcases, followed by t lines, each containing a single integer n, 1<=n<=100.
Output
For each integer n given at input, display a line with the value of n!
Example
Sample input:
4
1
2
5
3
Sample output:
1
2
120
6
Your code will give correct results for the given test cases but that doesn't prove that your code works. It is wrong is because of integer overflow. Try to calculate 100! by your program and you'll see what's the problem.
My answer lacked details. I'll update this to add details for an answer to the question as it stands now.
C has limitations over the the maximum and minimum size that can be stored in a variable. For doing arbitrary precision arithmetic it is usually advisable to use a bignum library as PHIFounder has suggested.
In the present case however, the use of external libraries is not possible. In this case arrays can be used to store integers exceeding the maximum value of the integers possible. OP has already found this possibility and used it. Her implementation, however, can use many optimizations.
Initially the use of large arrays like that can be reduced. Instead of using an array of 100 variables a single variable can be used to store the test cases. The use of large array and reading in test cases can give optimization only if you are using buffers to read in from stdin otherwise it won't be any better than calling scanf for reading the test cases by adding a scanf in the for loop for going over individual test cases.
It's your choice to either use buffering to get speed improvement or making a single integer instead of an array of 100 integers. In both the cases there will be improvements over the current solution linked to, on codechef, by the OP. For buffering you can refer to this question. If you see the timing results on codechef the result of buffering might not be visible because the number of operations in the rest of the logic is high.
Now second thing about the use of array[200]. The blog tutorial on codechef uses an array of 200 elements for demonstrating the logic. It is a naive approach as the tutorial itself points out. Storing a single digit at each array location is a huge waste of memory. That approach also leads to much more operations leading to a slower solution. An integer can at least store 5 digits (-32768 to 32767) and can generally store more. You can store the intermediate results in a long long int used as your temp and use all 5 digits. That simplification itself would lead to the use of only arr[40] instead of arr[200]. The code would need some additional changes to take care of forward carry and would become a little more complex but both speed and memory improvements would be visible.
You can refer to this for seeing my solutions or you can see this specific solution. I was able to take the use down to 26 elements only and it might be possible to take it further down.
I'll suggest you to put up your code on codereview for getting your code reviewed. There are many more issues that would be best reviewed there.
Here, your array index should start with 0 not 1 , I mean j and ishould be initialized to 0 in for loop.
Besides, try to use a debugger , that will assist you in finding bugs.
And if my guess is right you use turbo C, if yes then my recommendation is that you start using MinGW or Cygwin and try to compile on CLI, anyway just a recommendation.
There may be one more problem may be which is why codechef is not accepting your code you have defined function to accept the integer and then you are passing the array , may be this code will work for you:
#include<stdio.h>
int fact(int a[],int n)// here in function prototype I have defined it to take array as argument where n is array size.
{
int j=0,f=1,k;
for (k=a[j];k>0;k--)
f*=k;
return f;
}
int main()
{
int t,i,n[100],s[100],j;
setbuf(stdout,NULL);
printf("enter the test cases\n");
scanf("%d",&t); //given t test cases
for(i=0;i<t;i++)
{
scanf("%d",&n[i]); //value of the test cases whose factorial is to be calculated
}
for(j=0;j<t;j++)
{
s[j]=fact(&n[j],t);// and here I have passed it as required
printf("\n %d",s[j]); //output
}
return 0;
}
NOTE:- After the last edit by OP this implementation has some limitations , it can't calculate factorials for larger numbers say for 100 , again the edit has taken the question on a different track and this answer is fit only for small factorials
above program works only for small numbers that means upto 7!,after that that code not gives the correct results because 8! value is 40320
In c language SIGNED INTEGER range is -32768 to +32767
but the >8 factorial values is beyond that value so integer cant store those values
so above code can not give the right results
for getting correct values we declare the s[100] as LONG INT,But it is also work
only for some range

Resources