Categories
Best Practices Programming Tutorial

Best Practices Part 2: Speed Up Testing and Uploading

Best Practices for STEM Loyola Programming Challenges

Contents:

This tutorial assumes that you have already read Part 1: “Understand the Basics”.

Overview

Time is critical during a programming contest. Few seconds can be the difference between being the first or second. One of the time consuming parts during a programming challenge is repeatedly testing your code against the provided test cases. This tutorial will describe few tricks that you can use to test and upload your solution fast.

…a professional is someone who can do his best work when he doesn’t feel like it

Alistair Cooke

Filename Convention

The contest platform can help you populate most of the fields when you submit your solution. This happens when you name the file of your source code using the short code given for a particular problem.

The short code of problems is available in the title row where the color of a problem and its points are displayed. Usually, the short codes are A, B, C, D, and E.

If you are solving Problem A in C++, then naming your source code as A.cpp will automatically cause the website to select the problem and the your programming language after you browse for the source file. Few seconds saved there.

Redirect Standard Input/Output for Testing

When you write a solution to a problem, you will need to test it several times for correctness. This is a tedious task, especially when the test data is huge. Fortunately, feeding data to your program for testing can and should be automated.

The first method does not involve modifying your source code and it involves the use of a Terminal or PowerShell.

During an ongoing challenge, if you visit the Problem Set section, you can download the sample test cases. Click on the “zip with all samples” to download all sample test cases. After extracting, each sample test case will have its input and output file (e.g. 1.in and 1.out for test cases #1). Copy and paste the test cases into the same folder that has your program.

Open a Terminal (In Linux/MAC) or PowerShell (in Windows) and navigate to the folder containing your program using a change directory command (cd). In Windows, suppose your program is in “C:\Users\STEM\Documents\My Programs”, then you will type:

cd "C:\Users\STEM\Documents\My Programs"

In Linux/MAC, if your program is in “/home/stem/Documents/Programs”, then you will type:

cd /home/stem/Documents/Programs

At this point, if you list the contents of your directory (using ls command), you should be able to see your compiled program and the test cases.

By default, when you execute your program, the standard input is mapped to the keyboard. You will have to manually type in the test case data to check your program. However, you can map the standard input to the test case you want to test your program with. Suppose you are in Windows, and your program is called “A.exe”, and you want to run it using the data in “1.in”, you can type the following in the PowerShell.

cat 1.in | .\A.exe

Or you can also use the following command.

Get-Content 1.in | .\A.exe

Your program (A.exe) will be executed using the data in “1.in”. Results will be displayed in the PowerShell. Then, you can compare the results of your program with the sample test case one results in “1.out”. If you want to save the results of your program in a file (like “my-results.txt”), then you can add ” > my-results.txt” to either of the above commands.

cat 1.in | .\A.exe > my-results.txt

Adding ” > my-results.txt” redirects the standard output from being the PowerShell (screen) to the “my-results.txt” file.

Similarly, if you are using Linux/MAC, you can execute the above commands like:

cat 1.in | ./A > my-results.txt

You can omit the ” > my-results.txt” if you want the results to be displayed in the Terminal.

Redefine Standard Input/Output for Testing

This is another method of mapping the standard input/output to a file. This method involves modifying your source code but it is more convenient if you are using an IDE like CodeBlocks (Our recommended IDE for C/C++). We will demonstrate this method using C++.

This method uses the C function freopen found in the cstdio (or stdio.h) header. Hence, you need to include this header like:

#include<cstdio>

Then, at the top of your main() function, add the following line to use test data from “1.in” file.

freopen("1.in", "r", stdin);

When you compile and run your program (F9 in CodeBlocks), there will be no entering data manually as that will automatically be fetched from “1.in”. You are welcome!

At this point, the results of your program will be displayed on the screen. If you want to save them into a file, you can redefine the standard output to that file (say my-results.txt) using:

freopen("my-results.txt", "w", stdout);

A complete program that adds two numbers (taken from “1.in”) and displays results to the screen can be written as follows.

#include<iostream>
#include<cstdio>

using  namespace std;

int main(){
    freopen("1.in", "r", stdin);
    //freopen("my-results.txt", "w", stdout);

    int A, B;
    cin >> A >> B;

    cout << A + B << endl;

    return 0;
}
Code language: PHP (php)

You can comment out line 8 to have the results saved into “my-results.txt”.

Important Note: Remember to remove (or comment out) the lines that redefine the standard input/output (lines 7 and 8 in the above source code) before uploading your solution to the contest platform.

Using Java, the above can be written as follows:

import java.util.*;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.File;
import java.io.PrintStream;

public class A {
    public static void main( final String[] args) {
        try {
            System.setIn(new FileInputStream(new File("C:\\Users\\stem\\Documents\\My Programs\\1.in")));
            //System.setOut(new PrintStream(new File("C:\\Users\\stem\\Documents\\My Programs\\my-results.txt")));
        } catch (FileNotFoundException e) {
            System.out.print(e.getMessage());
        }        

        Scanner input = new Scanner(System.in);

        int A = input.nextInt();
        int B = input.nextInt();
        
        System.out.println(A + B);
    }
}
Code language: JavaScript (javascript)

Important Note: Remember to remove (or comment out) the lines that redefine the standard input/output (lines 11 and 12 in the above source code) before uploading your solution to the contest platform.

Stay tuned for Part 3 of this series and all the best tackling the next challenge!

Categories
Best Practices Programming Tutorial

Best Practices Part 1: Understand the Basics

Best Practices for STEM Loyola Programming Challenges

Contents:

Overview

This is a multi-part tutorial on participating in the STEM Loyola Programming Challenges. The objective of this series of tutorials is to equip you with the necessary tools to become competitive as you participate in future challenges.

Give me six hours to chop down a tree and I will spend the first four sharpening the axe

Abraham Lincoln

This series will highlight the tools that you will need such as programming languages, data structures, algorithms, and other principles/tricks. In this part, we will provide an overview of the automatic challenges grader and a good method of approaching solving the problems.

Understand the Automatic Challenges Grader

Since all programming challenges are automatically graded, it matters to understand the system. The grader works by accepting the source code you upload (e.g. file.cpp, file.java, file.c), compile the source code, execute the program, supply it with inputs, and observe if the program produces the correct output.

Suppose a problem requires you to input two positive integers less than a million and compute the sum of the two numbers. One of the correct ways to solve this problem is shown in the C++ source code below.

#include <iostream>
<iostream>using namespace std;

int main(){
    int A, B;
    cin >> A >> B;

    cout << A + B << endl;

    return 0;
}</iostream>Code language: PHP (php)

Note the following from the above source code:

  1. When inputting the two number into the program, we did not have to request the compiler to input the two numbers like cout << Enter the two numbers: ";
    This is because the compiler will automatically know to supply the two numbers and more importantly, anything you display on the standard output will be treated as your answer (resulting in the grader marking your program output as wrong).
  2. Similarly, when outputting the sum of the two numbers, we only displayed the sum without additional words like cout << "Sum is: " which will cause the grader to mark your answer as wrong. Because if the two numbers are 5 and 6, their sum is “11” and not “Sum is: 11
  3. The program ends with return 0;. Your program should run only once and return zero at the end. Ending your program with return main(); will result in time-limit error.
  4. Since the problem states that the two numbers are positive and less than a million, we chose int because we are sure a million can fit in the int data type. If the two numbers were bigger (say 5 billion), then we would have to select a bigger data type like long long int. Refer to our Programming and Data Structures in C++ guideline for an in-depth treatise of data structure.

Think of Problem’s Special Cases

Your submitted solution will be tested against five or more different test cases. Different test cases are used to ensure that your program has covered different special cases.

For instance, suppose the problem is to input two numbers and find the quotient when the first number is divided by the second. A basic solution can look like the source code below.

#include<iostream>

using namespace std;

int main(){
    float A, B;
    cin >> A >> B;

    cout << A / B << endl;

    return 0;
}
Code language: PHP (php)

However, the above program will crash when the second number is zero. This is due to the fact that in Mathematics, dividing a number by zero is undefined. What will happen exactly during your program’s execution depends on the compiler that was used, some compilers have protection against such cases and will produce inf as the answer. Some compilers will just result in run-time error and your program crashing.

To become a better programmer is to always think of such special cases that may crash your program and write your code defensively. A better solution for the above problem is as follows.

#include<iostream>
#include<cmath>

using namespace std;

int main(){
    const float INFINITESIMAL = 0.000001;
    float A, B;

    cin >> A >> B;

    if( abs(B) < INFINITESIMAL ){
        cout << "Cannot divide by zero!" << endl;
    } else {
        cout << A / B << endl;
    }

    return 0;
}Code language: PHP (php)

Note the following from the above solution:

  1. Since the numbers are assumed to be decimal numbers, line 12 does not check if the second number is zero using if( B == 0 ) because that works reliably with whole numbers (e.g. int, long, short, etc.) and not with decimal numbers (e.g. float and double). To check if a decimal number is zero, you select your precision (the smallest number that anything less than that will be assumed to be practically zero). Then compare if the magnitude of your number is less than that.
  2. In line 13, during an actual challenge, only write “Cannot divide by zero!” if the problem has requested you to do so.

Can I Do Better?

After crafting your solution, you should always ask yourself, “can I do better?

With the data structures that you have thought of using, can you do better? Is there a better data structure that you can use to make implementing the solution easier, faster, or use less memory? Do you really need to store all those numbers? Can you do better?

With the algorithm you have selected, is there a better one? Do you need to do something else (e.g. reverse the list, sort the list, find the binary representation of a number, etc.) before applying my algorithm? Can you do better?

You will be amazed by how much you can improve your solutions if you keep asking yourself this question and put in the effort to improve your solutions.

Part 2 “Speed Up Testing and Uploading” is now available.