Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
139 views

An Introduction To Competitive Coding

The document provides an overview of competitive coding competitions. It discusses how competitive coding challenges programmers to design efficient algorithms to solve problems within time limits. It then surveys several major competitive coding competitions like Code Jam, CodeForces, HackerRank, TopCoder, and ICPC. It explains their formats, time limits, difficulty levels, and goals of assessing or improving programming skills. The document serves as an introduction to the world of competitive programming.

Uploaded by

theGreenGhost
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
139 views

An Introduction To Competitive Coding

The document provides an overview of competitive coding competitions. It discusses how competitive coding challenges programmers to design efficient algorithms to solve problems within time limits. It then surveys several major competitive coding competitions like Code Jam, CodeForces, HackerRank, TopCoder, and ICPC. It explains their formats, time limits, difficulty levels, and goals of assessing or improving programming skills. The document serves as an introduction to the world of competitive programming.

Uploaded by

theGreenGhost
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 8

An Introduction to Competitive Coding

By Hari Sethuraman
Part 1: A Brief Overview
Computers are a major part of everyone’s life. From the time one was used by Alan Turing to break the Enigma code, and
save more than 20 million lives, to simply texting your friend through your phone, computers have been used for several
important events are basically everywhere.
Ever since Charles Babbage created the first mechanical computer, they have only gotten much smaller, more powerful,
and more power efficient. It‘s easy to forget take for granted how much far computers have progressed over the past 100
years. We now have smartphones that are millions of times faster than the computers of the last century, and can be held
in a pocket rather than in an entire room.
However, over the past decade or two, we have been reaching approaching the limits of what the hardware of computers
can do. The transistors in our CPUs can only be so small, before until they no longer are transistors aren’t transistors.
Moore’s law stated that the number of transistors in a computer’s CPU would double every 2 years, as the price of the
computers would half. But this law is no longer valid relevant, as we are reaching the chemical limits of the components
in our CPUs.
This is where the efficiency of algorithms become the key to solving the problem. This is where algorithm design
becomes the key to any further progression.
In case you don’t know, an algorithm, is simply a program that takes in an input, follows a set of sequential instructions,
and gives an output. While it may seem quite simple and straight forward, it’s important to realize that every task by the
computer, including something as simple as adding two single digit numbers is an algorithm. It’s also important to
remember that an efficient algorithm will not only be able to complete its task much faster, but also with a much lower
impact on the computer’s resources like memory without hogging your computer’s resources. And considering that we are
reaching the physical limits of computers, increasing the efficiency of algorithms is the way to accommodate our
increasing reliance on them.

Competitive Coding
Competitive Coding (or programming) is one of the best ways to get a hands-on experience of designing your own
algorithms that can solve real problems. It pushes you to critically think in a limited time to write a piece of code that not
only works perfectly, but also efficiently. This book will introduce you to the world of competitive programming, by
providing a background to this sport, explaining some of the most useful algorithms, and giving a comprehensive analysis
of question from past real competitions and problem sets.
This part of the book will explain the different formats of Competitive Coding, the way to approach a problem, and a brief
history of the sport.

A Brief History
Competitive programming is relatively new sport, originating in 1970 with ACM’s ICPC (International Collegiate
Programming Contest), where students invited other students globally to participate in a friendly coding competition.
While the sport did grow gradually over the years, it really started to pick up popularity in the 2000’s with the rise of the
internet. This saw the creation of several new competitions, and websites solely for hosting them such as CodeForces and
HackerRank. During this time, several large companies had joined the trend, and began hosting their own competitions. In
2003, Google decided to host their first programming contest: the ‘Code Jam’, which is currently one of the largest and
most prestigious coding competitions in the world. Facebook also created their competition: the ‘Facebook Hacker Cup’,
which also serves as a way to find employees.
No matter where you live, if you have a computer and internet, you can begin your journey in competitive coding.

Scope of this Book


This book will explain key algorithms and data structures and teach some important concepts such as runtime. However,
the book will not be going into detail for the proofs of some of the concepts, in order to preserve its simplicity. The book
will also go over ten problems from past competitions from various competitions such as Google’s kick start, CodeForces,
and CodeChef. While these are real problems, they won’t contain any extremely difficult concepts. The book will use
Python-3 as it is the most popular language at the time of release of this book. However no language specific features
(such as Generics or Pointers) will be present, meaning you should be able to understand the code irrespective of whether
you know how to code in Python or not. GitHub links will be present in the glossary for every code snippet (code will be
in Python 3).

Prerequisites
While it is possible to start off competitive coding with any amount of knowledge, to begin comfortably, there are 2 main
pre-requisites you should preferably have to understand all concepts in this book:
Coding: While you don’t need to be an avid programmer, the basics of coding is important in order to get your ideas
from your brain and onto the computer screen. Knowing what variables, operators, loops, functions, and conditions are is
important. Additionally, knowing basic data structures such as arrays/lists or hash tables/dictionaries can be helpful, but
are not completely necessary. In part 2 of the book when analyzing the past competitions, code is used for which you do
need the knowledge of the afore mentioned in order to comprehend it.
Math: This is the most important pre-requisite to competitive programming, and coding in general, especially when trying
to calculate the efficiency of your algorithm. Majority of problem sets in competitions are based off of discrete math
concepts such as graph theory and combinatorics. However those concepts aren’t needed for this book. You’ll only need a
solid understanding of algebra and other basic High-School math concepts.

Competition Format
There are two formats of Competitions: Short-term, and Long-term.
Short-term competitions tend to last between one to five hours, and focus on problems encapsulating number theory,
graph theory, combinatorics, and other math related topics. Some notable short-term competitions include the Code Jam
by Google, all the CodeForces rounds, TopCoder, and most notably, the ICPC.
Long-term competitions can last anywhere between a few days to a few months, and focus on the afore mentioned terms,
but often, also include machine learning competitions (which is beyond the scope of this book). Some notable long-term
competitions include the HackerRank week of code, the ICFP Programming contest, and Google’s code-in. And for those
interested in Machine learning: some competitions include Kaggle, and the Google AI challenge.

A Survey of Competitions
Kick Start: This competition is hosted by Google. However, unlike the more competitive Code Jam, Kick Start is aimed
for high school students, and those new to competitive coding. It consists of several three-hour long competitions and is
held online, regularly through the year. The problems are often based on algorithms and are developed by Google
engineers, ‘to give a taste of the technical skills needed for a career’ as quoted. Additionally, winners and avid participants
may be asked for an interview for an employment at google.
CodeForces rounds: Being the most varied in terms of skill levels, the questions in certain CodeForces rounds can be
easy enough for a person who doesn’t know coding to come up with a solution, while others are heavily dependent on
discrete math concepts such as graph and number theory. The general timing for these rounds are between 1.5 – 2.5 hours.
Several educational contests also occur two to three times a month, which last between 2.5 to 3 hours, and have a goal of
educating their participants rather than being a competition. This site is one of the best places for beginners, due to its
large collection of problem sets and vast community.
HackerRank: Despite being most popular for their work in enterprise, HackerRank is a site that several students,
especially ones in universities. However, rather than just offering the standard competitions, HackerRank offers large
projects, and other workshops that aim to improve programming skills to get a job at the company you want. They also
offer long-term competitions, in the form of the ‘Week of Code’, which is a 7-day competition, with 1 challenge per day.
TopCoder: Like HackerRank, TopCoder too heavily focuses on enterprise. However, it does several single-rounded
matches that last 1.5 hours. However the main event for competitive programming hosted by TopCoder is the TopCoder
Open, which is one of the best recognized competitions. The competition is split into three different phases: Coding phase,
Challenge phase, system testing phase, which together last for about 100 minutes.
ICPC: This competition is like the Olympics of competitive programming i.e. the competition you want to be in. The
competition is aimed for university students, and compete in teams of 3, representing their country. There are 2 rounds for
this competition: regionals, finals, both of which are short-term and select only the best of the best competitive
programmers. The regional competition lasts for 5 hours, where participants are given eight problems. The World Finals
also lasts for five hours, but participants are given twelve problems to solve. All solutions must be submitted in C, C++,
Java, Ada, Python, or Kotlin. While you may not be able to participate in this competition as a beginner, winning in the
ICPC should be one of your goals.
Code Jam: Code jam is the main contest hosted by Google, and is aimed for the more experienced competitive
programmers. This competition like the ICPC, is one that you should aim to win, especially the world finals, as it is one of
the best recognized and most competitive contests. There are four rounds in this contest, where the first three are online
elimination rounds lasting for 27 hours per round. The final round is the World finals and occurs in various locations and
will only have the best twenty-five participants.
ICFP: While not as well recognized as the ICPC, ICFP is an annually held contest that focuses on the long-term style
questions, with rounds lasting 72 hours, with ‘lightning division’ rounds lasting for 24 hours. One of the contest’s goal is
to show the capabilities of the favorite languages and tools used by the contestant. The cash prizes of the competition are
modest, but winners to earn a ‘bragging right’ to tell their programming language of choice is the one ‘of choice for
discriminating hackers’, though it should be noted that in reality, that your programming language of choice won’t matter
irrespective of the task, and what matters is your comfort with that language.
Code-in: This competition is very different from the ones previously listed. It is a long-term competition that lasts for 50
days, where you contribute to open source platforms such as TensorFlow, Wikimedia, and several others, by solving bugs,
or using them in order to create applications, or creating documentation. This is a great place to get started with
competitions because it is less fierce and time constrained than others. However, the concepts required for this and other
similar types of competitions is out of the scope of this book.
Part 2: Foundations
In this portion of the book, we’ll go over notions that will allow you to assess how fast your program runs. We’ll also
study several algorithms and data structures, and a programming technique called recursion which can greatly help in
solving many problems. Some of these concepts will require some math, but the math itself isn’t too complex. However,
in this chapter, a good understanding of functions and other computer logic statements (loops, if conditions…) is
necessary, especially for the algorithms and recursion section. These prerequisites are basics and should be known by
most programmers. However, if you haven’t learnt about them, it should only take a matter of a few hours to get a good
grasp of them by using websites such as Khan Academy, Coursera, or a YouTube series. [1]
As stated previously, the proofs for the validity and performance of the algorithms and other notions won’t be discussed
as they require knowledge on more advanced math concepts and will be abstracted. However, if you are interested in
learning the fine details, ‘Introduction to Algorithms’ by Thomas Cormen is a great source to widen your knowledge.
Now, let’s begin!

The Big O
Let’s say you just finished writing a book after several months of hard work. You want to see your completed book in its
physical glory rather than on a screen. So, you’ve got to print it. You have access to two printers: one in a printing store,
and one in your house. The printing store is thirty minutes away. However, the printer there is very fast and can print ten
pages per minute. The printer at your house is much slower and prints at a rate of four pages per minute. However, you
don’t need to travel anywhere to get to it. If your book is n pages long, which printer should you use, to get your book
printed as quick as possible? Ignore any other factors that will affect the time taken to print (file transfer time, road
congestion…)
To get an answer to this, let’s start off by creating two functions: T1 and T2, that represent the time taken for the printer at
the store and at your house to print the book respectively. The input to these function will be n (the number of pages), and
the output will be the number of minutes it will take to print the n pages.
1 1
T2 is pretty straight forward: T 2( n)= n. The ‘ ’ comes from the fact that the printer at your house prints four pages per
4 4
minute. Therefore, it takes fifteen seconds, or a quarter of a minute to print one page.
1
In the case of T1, we can write out the function as T 1( n)= n+30. The ‘+30’ comes from the fact that we need to travel
10
30 minutes in order to get to the printing store.
Now that we’ve got the two functions, let’s compare them. To do this, we can plot the two as a graph (Figure 2.01). The
x-axis represents n and the y-axis represents the time taken to print in minutes.
From the graph, we can observe that if n is lesser than
200, it would take less time to print the books at home.
However, if n is greater than 200, it would take less time
to print the books at the printing store. Therefore, the
answer to the question ‘Which printer should you use?’
depends on the number of pages in your book.
The idea that the time taken to accomplish one task in
different ways can take different amounts of time is key
in competitive coding.
The ‘Runtime’ of a program is essentially how quickly
it will convert the input to the output in relation to the
size of the input. It is a function that describes an
algorithm. It takes in the size of the input n and gives
out a value describing how fast the algorithm will run. Knowing how to create a Runtime function for your program
during a competition is a very useful skill.
Runtime rarely is measured in units of time. Why? Because of variance. Every computer will take varying amounts of
time to run the exact same algorithm or program. This is because some computers are much slower or faster than others as
a result of differing CPUs or memory. Therefore, there it isn’t fair to measure the runtime of algorithms in units of time. A
fast and efficient algorithm running on a slow computer may take longer to complete than a slow and inefficient algorithm
on a faster computer.
So instead of time, we measure the algorithm based on the number of steps. Well, kind of.
When representing the runtime of an algorithm (more specifically the worst-case runtime), we use Big-O notation. In
essence, the Big-O removes all constants and lower order terms. It can be thought of as a function that takes in a function
for the input. We represent it similar to how we write functions in math: O( ). A function of the input size n goes in
between.

For example, suppose there’s a program of which the runtime T (n) (for n-sized input) was found out to be 3 n2 +2 n+1
(we’ll go into more detail on how to approximate runtimes of programs later in this part). Since the raw number of steps
are too dependent on individual implementation, we will use Big-O notation. In the case of this runtime function, each
term has a constant coefficient. Additionally, there are two lower order terms: 2 n and 1. These need to be removed or
suppressed. Therefore, the runtime of this program in Big-O notation would be O(n 2).

You might be wondering why we do this, as a lot of precision in our runtime is lost by using this notation. Why don’t we
just create a function that represents the runtimes in the actual number of steps taken? There are a few reasons.
Measuring the runtime of an algorithm in the raw number of steps prevents the speed of the computer from playing a
factor. However the number of steps is highly dependent on the individual implementation of an algorithm or program.
For instance, some people may prefer to use many variables and functions when writing an algorithm so that their
program is cleaner, while some people may use the bare minimum number of variables needed. Declaring each variable is
an additional step when the algorithm/program is executed. Therefore, we need to account for these very minor lines of
code as well.
Additionally, we come to the question of what is considered a step and how many steps a line of code may take. Are
adding two numbers and multiplying two numbers the same number of steps? Is performing an action in a separate
function faster or slower than just performing it? Does an action in one language use the same number of steps as in
another language? The answers to these questions aren’t clear.
Finally, lower order terms don’t really contribute much to the runtime as n (the input size) gets larger. For example, if the
runtime equaled n3 +n . Even if the input size n were a relatively small value at 1000 (note that real-life problems often
deal with numbers in the millions or billions), the runtime would be 10003 +1000which equals1,000,001,000. As seen,
the second term in the runtime equation contributes very little to the sum, and as n gets even larger, the significance of this
term will only reduce. Therefore, we remove these terms from the runtime when applying the big-O notation.
A mistake often made, is when the size of the input can be represented by two or more variables. If the runtime of an
arbitrary algorithm is 2 , in big-O notation, the
3 n +5 m
runtime would be written as O(n 2+ m), as n and m are

independent of each other. Therefore, if the input size is


represented by two or more variables, be sure to include
both in the big-O notation.
In terms of dealing with exponential runtimes, the base of
the exponents – even if it is a constant – shouldn’t be
suppressed. If the runtime of an algorithm is T (n)=5n or
T (n)=2n, the runtime in big-O would be O(5n ) and O(2n ) respectively. In terms of logarithms, we need to suppress the
base when representing the runtime in big-O.
Figure 2.02 represents some common non-linear runtimes of algorithms, where the x-axis is n (n > 0), and the y-axis is the
runtime in big-O.
Now that you’ve got the general gist of Big-O notation and why you might want to use it, let’s go over a formal definition
and what the Big-O really means.

For a runtime function t (n) to be O(f (n)) , there must exist two independent constants c and n0 such that c × f (n)>t( n)
for all n> n0.

To start off understanding what that statement means, let’s understand what the big-O actually represents. In addition to
representing the runtime, the big-O can be thought of as a class or order of algorithms. All the algorithms in a certain
class/order of big-O, will have a worstcase
Part 3: Winning

You might also like