1 / 44
May 2006

1) To get the possibility to add problems into SPOJ system you need to get the problemsetter privelegies. You have to write the letter to one of administrators ( contact@spoj.com7).

2) If you already have the problemsetter privelegies, you can start from here: spoj.com/problems/my/98 . Be sure you logged-in in SPOJ system.

3) There you should press "Add problem button" ( spoj.com/problems/add/73).

4) Then you'll be able to see the window, in which you should write unick problem code using english letters (from 3 up to 8). And some initial settings. After you press "Create" button you'll be able to use all other problem settings.

5) The view of "Add / edit problem" window for the problem "Digits of PI", after filling all fields, are shown on the picture:

  • created

    May '06
  • last reply

    Oct '22
  • 43

    replies

  • 5.5k

    views

  • 27

    users

  • 17

    links

1) Problem Code - unick problem code, consists of capital English letters from 3 up to 8. Defined on the initial step of problem creation, after that you won't be able to change this code.
2) Problem Name - it speaks for itself.
3) Co-authored by - the group of people related to this problem. The group must exist (you can create group in right SPOJ menu using "Add group" command). You should use it if you want to grant access to your problems to other co-authors.
4) Source Code Limit - limit of source code of solutions sent by users, measured in bytes.
5) Resource - where do you get this problem?.
6) Assessment Type - Type of problem.
- Binary - "ACM-type" solution judgment ("accepted" or "wrong answer").
- Maximize Score - solution the better the higher score for this solution.
- Minimize Score - solution the better the lower score for this solution.
7) Checker - how the problem is judged Pyramid (PIII733) - automatically, Manual - manually.
8) Placement in main problem set - do you want to add the problem in main SPOJ problem set? If "yes" in which category.
9) Testable - does it possible to submit solutions to problem? Available for use in 3rd party contests - is it possible to use your problem in other contests?
10) Problem body - the problem description in HTML format.
11) Dynamic content - enables the form using (see No 12). As usual it doesn't necessary to enable it. I use it only once to manipulate the dataset sequences.
12) Master Judge for Multiple Datasets - high level judge. You can write your own. The current masterjudge available by link. You can use this judge for single Dataset. The source code of standard "Generic Masterjudge" will be available later in this FAQ.
Problem test sequence - problem test sequence (for example: #0 #1 #2). All this tests must exist (they defined lower on this page).
13) Available languages - list of available languages. M14) Include new languages - if this option enabled all new SPOJ languages will be automatically added to use for this problem.
Merge all languages in ranklist - if this option disabled, participant will appear in score table as many times as he change programming language. In other case he'll appear only once.
15) Modify - save changes. Preview - looks at problem preview. Continue editing after saving changes - apply changes and stay in this window.

1) In section Test Data Upload settle down adjustments and control panel for problem test data. For standard problem usually one test data set suffices (as well as on screenshot), but if you wish you can add more of them.
The table fields:
"Test" – name (index) of test for using in "Problem Test Sequence" field.
"Input" – input file and its size in bytes (you can download it by pressing on number).
"Output" – output and its size in bytes (you can download it by pressing on number).
"Judge" – current judge programm.
"Time Limit" – time limit for this test in seconds.

Set of the predetermined judges (Judge):
1. Ignore extra whitespaces - the standard judge for binary problems, i.e. problems of ACM-type Accepted or Wrong Answer. The generated by submitted program output file should be exactly the same as problem output on server within blanks.
2. Ignores FP rounding UP tp 10^-2 - the standard judge for binary problems, i.e. problems of ACM-type Accepted or Wrong Answer. This judge used for numerical problems. The generated by submitted program output file should be exactly the same as problem output with accuracy 0.01.
3. Ignores FP rounding UP tp 10^-4 - the standard judge for binary problems, i.e. problems of ACM-type Accepted or Wrong Answer. This judge used for numerical problems. The generated by submitted program output file should be exactly the same as problem output with accuracy 0.0001.
4. Score is source length – score for the solution equals to length of source code in the case of status “Accepted”.

If no one of predetermined judges donÂ’t suite the problem, youÂ’ll have to write your own judge in any of supported by SPOJ programming language. YouÂ’ll find some examples of judges below.

2) In section rejudge submission range it is possible to pass anew through judging process already sent solutions. It is necessary to use at significant changes of a principle of scoring system for problem or in case of mistakes in test data.

Problem judge consists of one file and can be written in any language supported by SPOJ. Here I put as example, how you can write it in C/C++. Standard project for SPOJ consists from 3 files: spoj.c, spoj.h and judge.c. First two files are given by SPOJ system developers and in general case looks like:

SPOJ.C

#include <spoj.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>


/* file handles */
FILE
        *spoj_p_in,             /* problem's input */
        *spoj_p_out,    /* problem's output */
        *spoj_t_out,    /* tested program's output */
        *spoj_t_src,    /* tested program's source */
        *spoj_score,    /* score for the program, for challenge problems */
        *spoj_p_info,   /* additional info - psetter only */
        *spoj_u_info;   /* additional info - psetter and solution's owner */


#define __WARN_IF_NULL(x) if (errno=0, (x)==NULL)\
        fprintf(stderr, "warning: \"" #x "\" -> %s\n", strerror(errno))


#define __BUF_SIZE 1024*1024

static char buffer[__BUF_SIZE+1];


static void spoj_finalize();

void spoj_init() {
        __WARN_IF_NULL(spoj_p_in = fdopen(SPOJ_P_IN_FD,"r"));
        __WARN_IF_NULL(spoj_p_out = fdopen(SPOJ_P_OUT_FD,"r"));
        __WARN_IF_NULL(spoj_t_out = fdopen(SPOJ_T_OUT_FD,"r"));
        __WARN_IF_NULL(spoj_t_src = fdopen(SPOJ_T_SRC_FD,"r"));
        __WARN_IF_NULL(spoj_score = fdopen(SPOJ_SCORE_FD,"w"));
        __WARN_IF_NULL(spoj_p_info = fdopen(SPOJ_P_INFO_FD,"w"));
        __WARN_IF_NULL(spoj_u_info = fdopen(SPOJ_U_INFO_FD,"w"));
        atexit(spoj_finalize);
}


static void spoj_finalize() {
        fclose(spoj_p_in);
        fclose(spoj_p_out);
        fclose(spoj_t_out);
        fclose(spoj_t_src);
        fclose(spoj_score);
        fclose(spoj_p_info);
        fclose(spoj_u_info);
}


unsigned spoj_file_length(FILE *file) {
        int fd = fileno(file);
        unsigned size = 0;
        unsigned temp;
        while ((temp = read(fd, buffer, __BUF_SIZE))>0)
                size+=temp;
        return size;
}


void __spoj_assert_fail(char *s, int r) {
        if (!r) {
                fprintf(spoj_p_info, "%s\n", s);
                exit(SPOJ_RV_NEGATIVE);
        }
}

For local debug, its useful to slightly change functions spoj_init() and spoj_finalize() for your own necessities. Standard availble streams:
*spoj_p_in - problem input data
*spoj_p_out - problem output data
*spoj_t_out - output generated by user program
*spoj_t_src - source code of tested solution
*spoj_score - score
*spoj_p_info - additional info availible to problemsetter (I recomend to use this possibility, you can check for errors or intermediate test data during contest. All stored information availible only to problemsetter).

SPOJ.H

#ifdef __cplusplus
extern "C"
{
#endif

#ifndef __SPOJ_H__
#define __SPOJ_H__


#include <stdio.h>


/* return values */
#define SPOJ_RV_POSITIVE        0
#define SPOJ_RV_NEGATIVE        1
#define SPOJ_RV_IE                      2


/* descriptor numbers */
#define SPOJ_P_IN_FD            0
#define SPOJ_P_OUT_FD           4
#define SPOJ_T_OUT_FD           3
#define SPOJ_T_SRC_FD           5
#define SPOJ_SCORE_FD           1
#define SPOJ_P_INFO_FD          6
#define SPOJ_U_INFO_FD          7


/* file handles */
extern FILE
        *spoj_p_in,             /* problem's input */
        *spoj_p_out,    /* problem's output */
        *spoj_t_out,    /* tested program's output */
        *spoj_t_src,    /* tested program's source */
        *spoj_score,    /* score for the program, for challenge problems */
        *spoj_p_info,   /* additional info - problemsetter only */
        *spoj_u_info;   /* additional info - psetter and solution's owner */


/* must be called before using other functions or variables */
void spoj_init();


/* spoj "files" are really pipes, this is the recommended way to tell size */
/* the file's data is unaccessible later, so use it only if it doesn't matter */
unsigned spoj_file_length(FILE*);


/* use spoj_assert()! */
/* usual assert() from assert.h will cause "judge's internal error" in the future! */
#define spoj_assert(x) __spoj_assert_fail(__FILE__ ":" __spoj_xstr(__LINE__) ": SPOJ assertion `" #x "' failed.", x)
#define __spoj_str(x) #x
#define __spoj_xstr(x) __spoj_str(x)
void __spoj_assert_fail(char*, int);


#endif
#ifdef __cplusplus
}
#endif

Judge example: Real judge for problem “Digits of PI” (not so accurate):

Judge.C

#include <cstdio>
#include <spoj.h>

#define LIMIT 1000000
#define mMin(a, b) (((a)<(b))?(a):(b))
char s[LIMIT], o[LIMIT];

int main()
{
	int i;
	spoj_init();
	int lo = fread (o, 1, LIMIT, spoj_t_out);
	int ls = fread (s, 1, LIMIT, spoj_p_out);
	while (lo>0 && o[lo-1]=='\n') lo--;
	while (ls>0 && s[ls-1]=='\n') ls--;
	spoj_assert(lo > 0);
	for (i = 0; i < mMin(lo, ls); i++)
		if (s[i]!=o[i])
			break;
	fprintf (spoj_score, "%d\n", i);
	return 0;
}

Judge example: Real judge for problem “Size Contest”:

Judge.C

#include "spoj.h"
#include <stdio.h>
#include <string.h>

int main()
{
	int a, b, i;
	int score;
	int c;
	spoj_init();
	
	/* Check for AC */

	fscanf(spoj_p_out, "%d", &a);
	fscanf(spoj_t_out, "%d", &b);
	if (b != a)
		return 1;
	
	score = 0;
	for (i = 0; i < 10003; i++)
	{
		c = fgetc(spoj_t_src);
		if (c > 32)
			score++;
	}

	fprintf (spoj_score, "%d\n", score);
	return 0;
}

Any nonzero return from judge interpreted by SPOJ, as Wrong Answer.

The possibility to edit master judge appeared comparatively recently. Now its possible to adjust problem more flexible, but in most cases, standard default Master Judge (1000. Generic masterjudge) will do. You can find code for this default master judge below:

1000. Generic masterjudge

#include <spoj.h>
#include <cstdio>
int main()
{
	spoj_init();
	int test, sig, mem, memMax=0, tc=0;
	double score, scoreAll=0, time, timeAll=0;
	char status[4];
    while (fscanf(spoj_p_in, "%d %3s %lf %d %lf %d\n", &test, status, &score, &sig, &time, &mem)==6)
{
	fprintf(spoj_p_info, "test %d - %s (score=%lf, sig=%d, time=%lf, mem=%d)\n", test, status, score, sig, time, mem);
	memMax >?= mem;
	scoreAll += score;
	timeAll += time;
	if (status[0]!='A')
	{
		fprintf(spoj_score, "%s 0 %d %lf %d\n", status, sig, timeAll, memMax);
		return 0;
	}
	tc++;
}
fprintf(spoj_score, "AC %lf 0 %lf %d\n", scoreAll/tc, timeAll, memMax);
}

The default judge works as follows:
- if at leats one test didn't give AC (it was WA, TLE, ..), the whole solution is ranked this way
- otherwise, the result is AC with score being the average score for all datasets, memory usage is the maximum of memory usages and the time is a sum of all times
Note that if a problem has only one dataset, it's fine - the result is just copied by this masterjudge.

It's nesessary to modify this judge if you want to make the scoring more complicated in some way. Some ideas:
- don't fail a solution which didn't pass some of the tests, but only adjust the score accordingly; AC for one dataset = one point for the final score
- include running times in the final score
- output some details about results for each dataset for the user (for example, he could be able to click on his "5 points" and see he had WA for test 3 and TLE for tests 6-10, when there are 10 tests total)

10 months later

How might I go about writing a judge for another language? I would like to do one in Python, though I suppose an example in any language but C/C++ would work.

It should be possible in most languages.
The important thing is to know how to read/write to a raw file descriptor (like opening such file with fdopen() in C).
"libspoj" library which hides this and allows to use spoj_p_in files etc. is really simple:
sphere.pl/~noix/spoj-devel/spoj.h16
sphere.pl/~noix/spoj-devel/spoj.c11

2 months later

I think my judge & masterjudge of problem MATH2 is OK.Why my own submissions always get "internal error" and PSINFO is "judge crashed!"?

I think it was some bug triggered by a combination of empty "output" files, multiple test cases and some output caching problems...
Could you please check if it's ok now?

5 months later
12 months later

There a judge who dont ignore whitespaces and EOL ?, a judge that just do a file compare between the user solution and the original one ?.. thanks

2 months later

I need some help. I don't understand source code at spoj.pl/files/judge/1000/8 ? As far as I understand, Master judge is used to calculate score, not to check particular test case, but spoj_p_in is input file for the problem. It is surely that I don't understand, but I can't figure out why it is sourced there. Can someone explain me, please?

Should I add checker for test cases in the section "test data upload" ? I will write my own checker, because there is no unique output for problem that I would like to set.

Also, code at spoj.pl/files/judge/3/7 seems, IMHO, a bit complicated. Can I read double just like

double val;
fscanf(spoj_t_out, "%lf", &val);

Thank you in advance.

The best regards,

3 months later
1 year later

Status:
AC - accepted
WA - wrong answer
CE - compilation error
RE - runtime error
TLE - time limit exceeded

What are the others?
(SIGSEGV, NZEC, SIGXFSZ, SIGABRT, SIGFPE)

Edit:
SIGSEGV - status="RE" && sig=11
SIGXFSZ - status="RE" && sig=25
SIGABRT - status="RE" && sig=6
SIGFPE - status="RE" && sig=8

For example: fprintf(spoj_score, "RE 0 6 0 0\n"); // SIGABRT

I still don't know NZEC and SIGKILL.

Edit2:
SIGKILL - status="RE" && sig=9
other SIG's: http://members.chello.pl/prosiak/sle_PL.pdf5

Just NZEC please.

NZEC: status=RE, signal=-1

In normal situation judge uses only AC/WA/SE. Some times (for special problems like judge=interpreter) it can use CE/RE/TLE/MLE. But I don't think it is a good idea to set signals by judge.

4 months later

Could You describe "Test data multiupload"?
Because it's a new option but wasn't neither added into tutorial for psetters nor here.
(updating tests section is also new but I think that it's obvious, how to use it; but You may also describe it if You want)

Test data multiupload is a beta functionality at the moment. It allows to import input and output for test cases - check the export feature to see the format. But please notice that importing supports only in/out data, as opposite to export feature.

1 month later
1 month later

And one more question.

I want to make a task with the masterjudge: "1001. Score is % of correctly solved sets".
So I chose this masterjudge, changed "assessment type" to "maximize score".
The task works corractly but all users which get AC get maximum points for the task even if they have 0/100 pts.
How to fix this?
I have to write my own judge also?