Добавление задачи в систему SPOJ. Примеры программ судей (Judges)
Программа судья (Judge) для задачи состоит из одного файла и может быть написана на любом языке поддерживаемым SPOJ. Большинство
программ судей в системе написаны на C\C++. Ниже будут приведены примеры, которые написаны на языке программирования Cи. Стандартный проект судьи
для запуска и проверки на локальной машине состоит из 3ёх файлов: spoj.c, spoj.h и judge.c. Первые два файла предоставлены
разработчиками системы и выглядят следующим образом:
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_u_info, /* additional info - psetter only */
*spoj_p_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);
}
}
Для отладки тестирующей программы на локальной машине рекомендуется слегка изменить функции
spoj_init() и spoj_finalize() для своих нужд. Доступные потоки данных:
*spoj_p_in - входные данные для задачи
*spoj_p_out - выходные данные для задачи (эталонные выходные данные)
*spoj_t_out - выходные данные сгенерированные тестируемой программой (то, что вывела программа пользователя)
*spoj_t_src - исходный код тестируемой программы (то, что прислал пользователь через форму)
*spoj_score - счет (количество баллов) пользователя
*spoj_p_info - дополнительная информация для автора задачи (рекомендую пользоваться этой возможностью. Вы можете проверить какие то промежуточные данные в течение соревнования. Вся информация из этого потока видна только автору задачи).
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.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.C (для задачи "Size Contest") #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;
}
Ненулевой код возврата из программы судьи интерпретируется системой SPOJ, как Wrong Answer.
<-- Часть 1. Структура и описание всех полей формы
Часть 3. Описание программы судьи высшего уровня (Master Judge) -->
|