\( \newcommand{\Z}{\mathbb{Z}} \newcommand{\val}{\textnormal{val}} \)

Let's look again at a typical (now quite easy) programming problem.

Problem : Primes. In this little problem example, you are asked to write a program that can determine whether a given integer is a prime number. Remember: a prime number is a natural number $p \geq 2$ that has only trivial divisors, namely 1 and itself. There is no need to implement sophisticated algorithms like the Rabin-Miller test. Input numbers will be quite small.

Input: several lines, the $i$-th line containing a single integer $n_i$ with $-1,000,000 \leq n_i \leq 1,000,000$.

Output: one output line per input line, the $i$th output line being "$n_i$ is prime" "$n_i$ is not prime", depending on whether the $n_i$ was prime or not.

Sample Input
11 
21
31
41
51
61
71
Sample Output
11 is prime
21 is not prime
31 is prime 
41 is prime
51 is not prime
61 is prime 
71 is prime                                         

For each such problem please create a directory on your computer. Create a sub-directory testcases.

Exercise In the sub-directory testcases, create two files: sample.in and sample.ans. Copy the above test input into sample.in and the test output into sample.out.

Exercise Create two more files: edge-cases.in and edge-cases.ans. Fill them with what you think are edge cases that you would like to test.

Writing your program

Now comes the most important part: implementing your solution. For this problem, this is not too hard to do. You can see my code here:

def isPrime(n):
    i = 2
    while (i*i <= n):
        if n % i == 0:
            return False 
        i = i+1
    return True


while True:
    try: 
        line = input()
    except EOFError:
        break
    
    n = int(line)
    if isPrime(n):
        print (n, "is prime")
    else:
        print (n, "is not prime")
 

Have a look at how we read from standard input (the console) in python. We have to use try/except to handle the end of the input.

Testing your program

Suppose you have written a program primes.py. You can now test it by hand by running it on the terminal:

python primes.py
5
5 is prime
91
91 is not prime

The blue text is, for clarity, the output of the program; the black test is what the user (i.e., you or I) entered. In the long run, we don't want to enter the test input by hand. Fortunately, there is the <-operator on the console:

python primes.py < testcases/sample.in                        
11 is prime
21 is not prime
31 is prime
41 is prime
51 is not prime
61 is prime
71 is prime

The operator < opens the file testcases/sample.in and feeds its content as standard input to the program python primes.py. The output is still printed on the console. We now want to compare the output of our program to the "correct" output in testcases/sample.ans. This can be done with the shell command diff:

python primes.py < testcases/sample.in > output.txt

The operator > re-directs the standard output into the file output.txt; if the latter does not exist yet, it will be created. Now we can use diff to check whether the two files output.txt and testcases/sample.ans differ:

diff -b output.txt testcases/sample.ans

The command diff produces no output. This is good: it means that it has not found any differences between the two files.

We can go one step further and do away with the temporary output file output.txt. Instead, we use the shell pipe operator | to direct the output of our program into the standard input of diff:

python primes.py < testcases/sample.in | diff -b testcases/sample.ans -                        

Automated Testing

This still becomes very tiresome if we have for example ten different test files. For this, I wrote a shell script that facilitates automated testing. For this to work, your test input / test output files must match in name, i.e., be named like file-XYZ.in and file.XYZ.ans.

icpc-run-python

Download it and try to get it to run. If you use C or C++ instead of python, the compiler will produce an executable. In this cases, use the bash script

icpc-run

instead.


icpc-run-python primes.py testcases/*.in                        
running program primes.py
testcases/edge-cases.in
	 Failure
testcases/sample.in
	 Success

As you can see, my program failed at testcases-edge.cases.in, and in fact, my implementation above is not completely correct.