Time Limit Exceeded in C++ Online Judge - c++

I just sent the solution to a problem COJ written in C ++. The problem is this link: http://coj.uci.cu/24h/problem.xhtml?pid=1839
This is my solution:
#include<iostream>
using namespace std;
unsigned int t, n;
int main(){
cin >> t;
while(t > 0 && cin >> n){
cout<< ( n * 8 ) + 42 << endl;
t--;
}
return 0;
}
To this the judge online of COJ says: "Time Limit Exceeded". Can someone explain why?

Your could try to get rid of std::endl because it is slow. Instead, you use '\n'. The code is below:
#include<iostream>
using namespace std;
unsigned int t, n;
int main(){
cin >> t;
while(t > 0 && cin >> n){
cout<< ( n * 8 ) + 42 << '\n';
t--;
}
cout.flush();
return 0;
}
Or you could try printf() to fasten your I/O.
This algorithm grows linearly, it should not be a limit factor. I believe I/O is the limiting factor. If you could find a algorithm that is log N, please tell me.
Someone vote it down because they believe doing I/O with standard out(stdout) is fast. However, std::endl flush after every iteration, which makes it slow.
Another idea is to use recursion, and you hope the judge system has good optimization on tail recursion(it is possible.). It may get a little faster, too.
On your own computer, you could even try to profile it to find the limiting factor, and if it is I/O, try the way above.
If it is still not fast enough, get rid of object-oriented design, use C and write direct to stdout instead use printf.
Good luck!

Related

Strange Behavior in C++ Input/Output When Parsing Large Integer Input

I have the following piece of code:
#include <iostream>
using namespace std;
int main() {
// Number of inputs
int N;
scanf("%d", &N);
// Takes in input and simply outputs the step it's on
for (int i = 0; i < N; i++) {
int Temp;
scanf("%d", &Temp);
printf("%d ", i);
}
}
When taking in a large amount of integer input, C++ stops at a certain point in printing output, seemingly waiting for more input to come.
Given an input of 2049 1's, the program stops after printing 2048 integers (0 up to 2047), and does not print the final 2048 (the 2049th integer). 2048 looks suspicious, being a power of 2.
It seems to be the case that the larger the input values, the quicker the program decides to stop, and in this case after what looks like a random number of steps. For example, I gave it 991 integers (up to the ten thousands), and the program stopped outputting after iteration 724.
Note that I copied and pasted the numbers as a whole block, rather than typing and entering them one by one, but I doubt this plays a role. I also tried cin and cout, but they did not help.
Could someone please explain the reasons behind this phenomenon?
I have found the answer to my question. The reason behind the failure is indeed due to copying and pasting large chunks of input, as many have suggested, and I thank everyone for their help. There were no incorrect characters, though, and cause of this problem is instead the 4096 character limit posed by canonical mode.
In canonical mode, the terminal lets the user navigate the input, using arrow keys, backspace, etc. It sends the text to the processor only when there is a newline or the buffer is full. The size of this buffer being 4096 characters, it becomes clear why the code fails to parse more input than that, i.e. 2049 "1 "s is 4098 characters. One can switch to noncanonical mode, which allows larger input at the expense of not being able to navigate it, using stty -icanon. Entering stty icanon takes it back to canonical mode.
Practically speaking, entering the input with newlines separating the numbers seems like the easiest fix.
This source was quite helpful to me: http://blog.chaitanya.im/4096-limit.
This post on unix stack exchange is similar to my problem: https://unix.stackexchange.com/questions/131105/how-to-read-over-4k-input-without-new-lines-on-a-terminal.
My first thought was that you're reaching some sort of barrier on the input side...
The limit for the length of a command line is not [typically] imposed by the shell, but by the operating system.
Bash Command Line and Input Limit - SO
However, this is probably not the case.
First, focus on your data, make sure your data is what you think it is (no unexpected characters) and then try to debug your reads, make sure the values are making it into memory like you intend.
Try separating out your read and write into two loops, this might help your debugging a little easier depending on your skill level, but again, making sure something funky isn't going on with your reads. Suspicion is high with the reads on this one...
Here's a couple of cracks at it below... haven't tested. Hope this helps!
#include <iostream>
int main() {
int N;
std::cin >> N;
// Read N integers, storing to array
int* numbers = new int[N];
for (int i = 0; i < N; i++) {
std::cin >> numbers[i];
}
// Print
for (int i = 0; i < N; i++) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
// Free the dynamically allocated memory
delete[] numbers;
return 0;
}
Okay... maybe a little more optimized...
#include <iostream>
int main() {
int N;
std::cin >> N;
// fixed-size on the stack
int numbers[N];
// cin.tie(nullptr) and ios::sync_with_stdio(false) might improve perf.
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
// Read N integers, storing to array
for (int i = 0; i < N; i++) {
std::cin >> numbers[i];
}
// Print
for (int i = 0; i < N; i++) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
return 0;
}

Google KickStart Round B Bus Routes Problem wrong answer?

I was practicing with google kickstart's round B bus route problem. I actually looked at their analysis and implemented their alternative answer.
I'll also paste the problem prompt below my code.
https://codingcompetitions.withgoogle.com/kickstart/round/000000000019ffc8/00000000002d83bf
And my solution passes the first test set but gets a wrong answer on the second test set. I have no idea what the second test set is, only that it's very big. I'm pretty confused as my solution follows the analysis of the problem, and is actually an implementation of the alternate provided solution to a T. I also have no idea how to figure out which test case could be giving a wrong answer, there seems to be so many possibilities!
I have no idea how to even debug such a vague answer. Maybe there are some edge cases I'm not considering?
#include <iostream> // includes cin to read from stdin and cout to write to stdout
#include <bits/stdc++.h>
using namespace std;
int main() {
int t, n, d;
cin >> t; // read t. cin knows that t is an int, so it reads it as such.
for (int i = 1; i <= t; ++i) {
cin >> n >> d; // read n and then m.
stack <int> bus;
for(int j=0; j<n; j++){
int x;
cin >> x;
bus.push(x);
}
while(!bus.empty()){
int b = bus.top();
bus.pop();
d = d - d%b;
}
cout << "Case #" << i << ": " << d << endl;
}
return 0;
}
****Here's a shortened version of the Problem Prompt ****
Problem
Bucket is planning to make a very long journey across the countryside by bus. Her journey consists of N bus routes, numbered from 1 to N in the order she must take them. The buses themselves are very fast, but do not run often. The i-th bus route only runs every Xi days.
More specifically, she can only take the i-th bus on day Xi, 2Xi, 3Xi and so on. Since the buses are very fast, she can take multiple buses on the same day.
Bucket must finish her journey by day D, but she would like to start the journey as late as possible. What is the latest day she could take the first bus, and still finish her journey by day D?
It is guaranteed that it is possible for Bucket to finish her journey by day D.
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with a line containing the two integers N and D. Then, another line follows containing N integers, the i-th one is Xi.
Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the latest day she could take the first bus, and still finish her journey by day D.
Limits
Time limit: 10 seconds per test set.
Memory limit: 1GB.
my guess is using int is not sufficient as D can be up to 10^12 in test set 2
Edited: I verified my guess. You will be able to solve the problem by fixing this bug. And I believe the use of long long is common for coding contests, i.e. take note of the input/output constraints every time.
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main ()
{
int t;
long long int x,i,j,n,d;
cin >> t;
for ( i = 0; i < t; i++)
{
cin >> n >> d;
stack < long long int >route;
for (j = 0; j < n; j++)
{
cin >> x;
route.push (x);
}
while (!route.empty ())
{
long long int c = route.top ();
route.pop ();
d = d - d % c;
}
cout << "Case #" << i+1 << ": " << d << endl;
}
return 0;
}

more efficient cpp code

I'm trying to solve a problem from the site open.kattis.com https://open.kattis.com/problems/different
the problem is you take in two non-negative integers from 0 to 10^15 and you calculate the difference. I wrote this and it calculates it correctly, but it is not fast enough, how can I make it faster?
#include <iostream>
#include <stdio.h>
using namespace std;
int main() {
long long int a, b;
while(a != 0){
cin >> a >> b;
if (a > b) { cout << a-b << endl;}
else{ cout << b-a << endl;}
}
return 0;
}
The real performance hit, if ran many many times would come from the 'endl' actually, because while it adds a '\n' at the end, it also flushes the stream. Any other micro optimization is quite meaningless at best, I'm sure the compiler is smart enough to put a fast enough code in it's place.
EDIT: Could also add std::ios::sync_with_stdio(false); if you are REALLY desperate for potential performance increase. This prevents the synchronization between C style streams. See: sync
Rather than doing a comparison to see which is bigger, which takes more time, you could just forget about which is bigger and calculate the difference anyway: cout << a-b << ends; If b is larger than a then yes you will end up with a negative result. In which case, multiply it by -1. I work mainly in C but I think in C++, it would look something like this: first store the result of the calculation in a variable 'x' long long int x = a-b, then if (x < 0) { x *= -1 ;}. This should work if my code is correct; I'm not sure if it will be much faster but it's definitely worth a try.
EDIT: Or, like #user64322 said, you could do the same as above, but rather than multiplying by -1, just take the absolute value, which is the same, but quicker.
In addition to the others' suggestions, an obvious thing you can do is use argv to take command line arguments at startup (e.g. ./PrintDiffQuick 10 5 would print 5) instead of blocking execution while waiting for user input.
#include <cinttypes>
#include <iostream>
int main(int argc, const char **argv)
{
std::ios::sync_with_stdio(false);
std::cout << std::imaxabs(std::strtoimax(argv[1], nullptr, 10) -
std::strtoimax(argv[2], nullptr, 10)) << '\n';
return 0;
}

Buffered input versus standard input

I was trying to read a long list of numbers (Around 10^7) from input file. Through some searching I found that reading the contents using buffer gives more performance when compared to reading the number one by one.
My second program is performing better than the first program. I am using a cin stream object in the first program and stringstream object in the second program. What is the difference between these two in terms of I/O performance?
#include <iostream>
using namespace std;
int main()
{
int n,k;
cin >> n >> k;
int count = 0;
while ( n-- > 0 )
{
int num;
cin >> num;
if( num % k == 0 )
count++;
}
cout << count << endl;
return 0;
}
This program is taking a longer time when compared to the following code using buffered input.
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
cin.seekg(0, cin.end);
int length = cin.tellg();
cin.seekg(0, cin.beg);
char *buffer = new char[length];
cin.read(buffer,length);
stringstream ss(buffer);
int n,k;
ss >> n >> k;
int result = 0;
while( n-- )
{
int num;
ss >> num;
if( num % k == 0 )
result++;
}
cout << result << endl;
return 0;
}
The second one will require ~twice the file's size in memory, otherwise, since it reads the entire file in one call, it will likely read data into memory as fast as the underlying storage can feed it, and then process it as fast as the CPU can do so.
It'd be good to avoid the memory cost, and in that respect, your first program is better. On my system, using an input called test.txt that looks like:
10000000 2
13
13
< 10000000-2 more "13"s. >
and your first program called a, and your second called b. I get:
% time ./a <test.txt
0
./a < test.txt 1.70s user 0.01s system 99% cpu 1.709 total
% time ./b <test.txt
0
./b < test.txt 0.76s user 0.04s system 100% cpu 0.806 total
cin is not buffered by default, to keep "synchronized" with stdio. See this excellent answer for a good explanation. To make it buffered, I added cin.sync_with_stdio(false) to the top of your first program, and called the result c, which runs perhaps slightly faster:
% time ./c <test.txt
0
./c < test.txt 0.72s user 0.01s system 100% cpu 0.722 total
(Note: the times waffle around a bit, and I only ran a few tests, but c seems to be at least as fast as b.)
Your second program runs quickly because while not buffered, we can just issue one read call. The first program must issue a read call for each cin >>, whereas the third program can buffer (issue a read call every now and then).
Note that adding this line means you can't read from stdin using the C FILE * by that name, or call any library methods that would do so. In practice, this is likely to not be an issue.

Getting multiple lines of input in C++

The first line contains an integer n (1 ≤ n ≤ 100). Each of the following n lines contains one word. All the words consist of lowercase Latin letters and possess the lengths of from 1 to 100 characters.
(Source: http://codeforces.com/problemset/problem/71/A)
How would you get input from the user given n? I tried using a while loop but it doesn't work:
#include <iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int i;
while (i<=n) {
cin>>i ;
i++;
}
}
You probably meant to have something like:
#include <iostream>
int main() {
int n;
cin>>n;
int theInputNumbers[n];
for(int i = 0; i<n; ++i) {
cin >> theInputNumbers[i];
}
}
Your loop is really quite far off of what you need. What you wrote is extremely wrong such that I cannot provide advice other than to learn the basics of loops, variables, and input. The assistance you need is beyond the scope of a simple question/answer, you should consider buying a book and working through it cover to cover. Consider reading Programming Principles and Practice Using C++
Here is a working example of something approximating your question's requirements. I leave file input and output as an exercise up to you. I also make use of C++11's front and back std::string members. You would have to access via array index in older versions.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main(){
int totalWords;
cin >> totalWords;
stringstream finalOutput;
for (int i = 0; i < totalWords; ++i){
string word;
cin >> word;
if (word.length() > 10){
finalOutput << word.front() << (word.length() - 2) << word.back();
}else{
finalOutput << word;
}
finalOutput << endl;
}
cout << endl << "_____________" << endl << "Output:" << endl;
cout << finalOutput.str() << endl;
}
With that said, let me give you some advice:
Name your variables meaningfully. "int i" in a for loop like I have above is a common idiom, the "i" stands for index. But typically you want to avoid using i for anything else. Instead of n, call it totalWords or something similar.
Also, ensure all variables are initialized before accessing them. When you first enter your while loop i has no defined value. This means it could contain anything, and, indeed, your program could do anything as it is undefined behavior.
And as an aside: Why are you reading into an integer i in your example? Why are you then incrementing it? What is the purpose of that? If you read in input from the user, they could type 0, then you increment by 1 setting it to 1... The next iteration maybe they'll type -1 and you'll increment it by 1 and set it to 0... Then they could type in 10001451 and you increment by 1 and set it to 10001452... Do you see the problem with the logic here?
It seems like you are trying to use i as a counter for the total number of iterations. If you are doing this, do not also read input into i from the user. That completely undermines the purpose. Use a separate variable as in my example.