Shaydiesin's blog

By Shaydiesin, history, 3 years ago, In English

Where to begin?

It has been a common misconception amongst Competitive Programming(hereafter CP) beginners, that Python is a slower language than C++ and they must learn C++ for CP. Some of the rumours I've come across were Python submissions giving TLE but the same algorithm implemented in C++ cleared the test cases. I intend to write this blog to clear these misconceptions and give a beginner-friendly guide for CP using Python. Before diving further it would be helpful if you are fairly aware of Python syntax.

First of all, whether python is a slower language? Yes, it is definitely a slower language as compared to C++. Usually on CP platforms python submissions are given x5 more time to execute than C++. But many beginners don't know this fact and assume that using C++ will give them an upper hand.

The $$$10^8$$$ thumb rule

Before jumping in to code any question one needs to think of the logic for it. Every question is given a particular time limit within which your code needs to complete execution and your algorithm needs to be efficient to do so. The thumb rule says that for a question with a 1-sec time limit, your algorithm must perform at most a $$$10^8$$$ number of operations. If the time complexity goes beyond this you will certainly get TLE.

Taking Input

The first step in your code is to take the input. The function input() returns the input as a string and at times you will need to convert it into a corresponding integer or float. Sometimes you are given arrays as spaced integers.

N = input()                             # returns a string
N = int(input())                        # returns a single integer
                                     
# if the input is given as some spaced integers
A = input().split()                     # returns an array of strings
A = [int(i) for i in input().split()]   # returns an array of integers
C,D = [int(i) for i in input().split()] # returns two integer variables C & D 

Fast Input/Output

When the size of test cases gets larger the normal input/output methods will give TLE irrespective of the fact that your algorithm is correct. This is because the print() statement takes significant time to actually execute.

import sys                        #importing libraries
from time import perf_counter     #importing perf_counter for finding the execution time

t1 = perf_counter()

for i in range(10):   
	print(i)
t2 = perf_counter()               #using print() to print the output


t3 = perf_counter()

for i in range(10):   
	sys.stdout.write(str(i)+"\n")
t4 = perf_counter()               #using sys.stdout.write(str(i)+"\n") to print the output

print("Exec time: print():",t2-t1)
print("Exec time: sys.write:",t4-t3)         #printing the respective execution time

You can clearly see that with sys.stdout.write() the execution time is significantly better.

Now for faster input, I prefer using the following snippet.

ONLINE_JUDGE = __debug__
if ONLINE_JUDGE:
    import io,os
    input = io.BytesIO(os.read(0,os.fstat(0).st_size)).readline

If you want to understand what exactly the code is read the section below else you can skip it..

Fast I/O

Now while taking the input when input = io.BytesIO(os.read(0,os.fstat(0).st_size)).readline integers won't be affected but while reading strings, they will be read as byte strings instead of normal ones.

input = io.BytesIO(os.read(0,os.fstat(0).st_size)).readline
string = input()
print(string)

If the input string is Shaydiesin it will be printed as b'Shaydiesin\r\n'. Here you won't be able to access individual characters of the string and you will need to decode it. For this use string.decode("utf-8") to get the normal string.
Even after that you might want to remove the last two elements of the string "\r\n" use string = string[:len(string)-2] for that.

Example of a question where you need to use Fast I/O

1670B - Dorms War

TLE : 157394407
Accepted : 157396661

You might wonder when to use Fast I/O and when not to? The best way out is to always use Fast I/O but I've tried to limit test and found that it is required when the number of test cases is of the order $$$10^5$$$.

Other important things.

Some ways of writing code in Python are faster than the others in this section I will be mentioning a few preferable ways of writing.

  • List comprehension is faster than for loop.

    Performing an operation on an entire list is faster done using list comprehension.

For Loop:

N = 5000
A = [0]*N

for i in range(N):
    A[i]+=1

List Comprehension:

A = [0]*N

A = [i+1 for i in A]

  • Effectively making a multidimensional array.

    In order to initialize a 1-D array in python one can simply write A = [0]*6.
    When we print A we get.
    [0, 0, 0, 0, 0, 0]
    Now when we try the same thing in more than one dimension A = [[0]*6]*2
    [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]
    But if we change any element of the 2-D array A A[0][0] = 4
    [[4, 0, 0, 0, 0, 0], [4, 0, 0, 0, 0, 0]]
    You will see that both the arrays are changed even though we just changed the first element of the first array. This is because when we create a list using shallow listing all the elements point to the same object. Essentially the elements of the outer array are pointing towards the same list.
    Instead use list comprehension
A=[[0 for i in range(6)] for j in range(2)]       
A[0][0]=4    

[[4, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]] 
  • Vote: I like it
  • 0
  • Vote: I do not like it

| Write comment?
»
3 years ago, # |
Rev. 2   Vote: I like it +3 Vote: I do not like it

So you say that python being slower than cpp is a misconception, but use "1e8 thumb rule" for python, while for c++ you can go with 1e9

  • »
    »
    3 years ago, # ^ |
      Vote: I like it +6 Vote: I do not like it

    In my experience it's more like 1e7 for python. If you push for 1e8 it might pass sometimes but it wouldn't be surprising if it didn't.

»
3 years ago, # |
  Vote: I like it +10 Vote: I do not like it

About IO in Python. The main thing making IO slow in Python is that input() calls sys.stdout.flush(). C++ has a very similar problem, and the fix in C++ is to add cin.tie(0) to your code. For Python the fix is to add something like

def input():
  return sys.stdin.readline().rstrip('\n')

or if you are fine with the return value of input() having a newline character at the end, you can just use

input = sys.stdin.readline

Using this ^, you should have no problem with IO being slow in Python.

»
3 years ago, # |
Rev. 2   Vote: I like it -17 Vote: I do not like it

Now here is a counterexample for The 10**8 thumb rule

python