Code Docs

ARBITRE Docs

Prefix and Suffix

Found at “Runtime” tab on an Exercise

Untitled

Prefix and suffix are code bits that will be appended respectively before and after a student’s code when running tests.

The student’s file is stored as is, and the prefix and suffix are only added at runtime for testing.

One principle of Arbitre is that students don't need to worry about ensuring their work will be read correctly by the correction service. Instead, teachers write a prefix and suffix to condition the test's input and output. This ensures that a student's correct submission will always result in passing the exercise.

Getting consistent test results

<aside> 🏎️ TL;DR : use print(..., **end=""**)

</aside>

In Python, the print() function adds a newline character (\\n) at the end of the output.

This can lead to errors when comparing the expected output to the student’s output, even though the student passed the exercise.

Example

<aside> 📖 Exercise : Hello World

Write a function hello_world() that returns the string Hello, World!

</aside>

Test

<aside> ⚠️ Note : Outputs are always strings. Here, the expected output should be typed as Hello, World!, and not "Hello, World!"

</aside>

Submitted code

def hello_world():
    return "Hello, World!"

Result with incorrect suffix

Suffix : print(hello_world())

The code that will be evaluated is :

# Prefix (none)

# Student code
def hello_world():
    return "Hello, World!"

# Suffix
print(hello_world())

Untitled

Here, the test fails because the actual output is Hello, World!\\n.

The trailing \\n is not visible because the browser escapes it.

Result with correct suffix

Suffix : print(hello_world(), end="")

Untitled


Multi-argument functions

<aside> 💡 Arbitre tests work on an Input → Output basis. The input is strictly one string. The following section demonstrates how to write tests for functions that require more than one argument.

</aside>

<aside> 🏎️ TL;DR

With your_function being relevant to the exercise

</aside>

The exercise

Let’s type the following exercise into Arbitre, step by step, using Python.

Example exercise

Example exercise

Creating the exercise

Create a course called “Python 101”.

Create a session called “Powering and addition chains”.

Create an exercise called “Binary Powering”.

In the description field, type :

Write the recursive function `bin_pow(x,n)`, such as :

$$x^0=1, x^1=x$$ and for $$n>=2:$$

$$x^n=(x^{\\lfloor n/2 \\rfloor})^2 $$ for $$n$$ even, $$x^n=x*(x^{\\lfloor n/2 \\rfloor})^2$$ for $$n$$ odd.

Note this description takes advantage of both Markdown and KaTeX.

Result :

Untitled

The following code is a solution to the exercise :

# binary powering, returns x^n
def bin_pow(x,n):
    if n==0:
				return 1
    tmp=bin_pow(x,n//2)
    tmp=tmp*tmp
    if n%2==0:
				return tmp
    return tmp*x

Why is a prefix/suffix needed ?

The issue here is that Arbitre tests work on an Input → Output basis. The input is strictly one string.

The function bin_pow takes 2 arguments, x and n : we need to find a way to pass these 2 arguments into one string.

A solution is to provide the two inputs as a single string where the values are separated by a comma :

Input = x,n

We will then split this string into two variables and call bin_pow.

Note : This can all be done in the suffix, after the student’s code : for the sake of simplicity, there will be no prefix here.

Writing the tests

The goal of the exercise is to write a function that raises x to the power of n.

Let’s write a small series of tests, to test that :

Following the principle where values are comma-separated, the tests can be written like this :

Untitled

Writing the suffix

The suffix has to :

Step-by-step solution :

# Get input
stdin = input()

# Split the string at the comma
split_string = stdin.split(",")

# Get each variables (they still are strings)
x_string = split_string[0]
n_string = split_string[1]

# Cast the variables to integers
x = int(x_string)
n = int(n_string)

# Run bin_pow
result = bin_pow(x,n)

# Print the result
print(result, end="")

One-liner solution :

print(bin_pow(*[int(arg) for arg in input().split(",")]), end="")

Note : the * operator unpacks list elements into function arguments. Read more

<aside> 💡 Both solutions work the same. The first one is more explicit, the second one is faster to write.

</aside>

Untitled

It works !

After sending this file, we get this result :

Untitled