Polygon Guide
Introducere
Polygon este o platformă dezvoltată de Mike Mirzayanov, dezvoltatorul Codeforces și este unul dintre cele mai importante medii folosite în zilele noastre pentru dezvoltarea problemelor date la concursurile de programare competitivă din întreaga lume. Această platformă face acest proces mult mai puțin anevoios, iar de asemenea permite și o adaptare ușoară la cerințele altor interfațe de concurs (CMS / DomJudge etc.).
Pe lângă platformă în sine, există și biblioteca testlib.h care reprezintă resursa folosită cel mai frecvent de cei care lucrează în Polygon pentru crearea problemelor, bibliotecă care ușurează foarte mult procesul de generat date de intrare și generat teste, folosind interfața Polygon.
Crearea unei noi probleme
Pentru a crea o problemă nouă, din meniul principal, apăsăm new problem și o numim, folosind un nume cu litere mici și liniuțe între ele. De preferat ar fi ca numele problemelor să respecte un anumit model (concurs-an-problemă).
De exemplu dacă propuneți problema gigel la concursul din anul , o puteți numi (X-Y-gigel). O să vă fie mai ușor ulterior să le găsiți în arhiva problemelor voastre.
Apoi, puteți seta parametrii problemei, precum limitele de timp/memorie, precum și dacă citirea e de la tastatură sau din fișier. Aici am atașat un exemplu de setare pentru o problemă ce am dat-o la olimpiada locală în Piatra Neamț anul acesta.
Scrierea enunțului
Pentru a scrie cerința unei probleme, se va folosi LaTeX, un avantaj important al scrierii enunțurilor în Polygon este acela că aceștia oferă un ghid ușor accesibil pentru scrierea enunțurilor unei probleme. Trebuie remarcat faptul că există mici diferențe de formatare între Polygon, Overleaf și alte editoare de LaTeX, deci trebuie avut grijă atunci când convertiți un enunț dintr-un format în altul.
În contextul folosirii Polygon, sunt patru secțiuni relevante din punct de vedere al enunțului, acestea fiind Legend, Input Format, Output Format și Notes. Descrierile acestor formate sunt oarecum de la sine înțelese, acest format fiind unul similar cu cel prezent pe infoarena, cu excepția faptului că nu există secțiune separată de restricții pe Polygon.
Personal, recomand menționarea restricțiilor de variabile în secțiunea input format, iar pentru numerele mai mari sau egale cu , recomand folosirea notației științifice.
De exemplu, () e în regulă, dar nu (). Folosiți () în schimb. De asemenea, se recomandă punerea simbolului de dolar între paranteze, nu în afara lor.
Nu în ultimul rând, eventualele subtaskuri se pot pune fie la input format (format folosit la IOIT printre altele) sau la notes. Din experiența personală, e mult mai ușor pentru concurenți să le observe la input format, deoarece apar împreună cu celelalte restricții.
Generarea testelor
Biblioteca testlib.h face generarea testelor mult mai ușoară, deoarece putem folosi funcțiile acestei biblioteci cu mult mai mare ușurință comparat cu celelalte metode disponibile.
După ce se adaugă exemplul manual în secțiunea tests, putem să apelăm generatorul din secțiunea script, asemănător unor instrucțiuni din command line. Se va trece numele generatorului folosit, precum și parametrii necesari, în ordinea folosirii lor. Trebuie avut grijă ca parametrii trecuți să fie folosiți și in generatorul propriu-zis, care trebuie încărcat în secțiunea files. Mai jos am atașat și un exemplu de generator, care prezintă și anumite funcționalități ale generatorului.
Trebuie precizat faptul că testele pot fi încărcate și manual, în cazul în care vrem ca inputul să aibă anumite particularități. Totuși, se recomandă folosirea generatoarelor pentru o calitate mai mare a testelor obișnuite.
#include "testlib.h" // biblioteca necesara
#include <iostream>
#include <vector>
#include <map>
using namespace std;
int main(int argc, char* argv[])
{
registerGen(argc, argv, 1);
int n = atoi(argv[1]); // parametrii in ordinea folositi
cout << n << endl; // pentru a se sari la urmatoarea linie, se foloseste neaparat endl
vector<int> v;
for(int i = 1; i <= n; i++)
{
int x = rnd.next(1, 1000);
cout << x;
if(i != n) // trebuie avut grija la spatiile suplimentare de la final
cout << " ";
v.push_back(x);
}
cout << endl;
shuffle(v.begin(), v.end()); // amestecarea elementelor din vector
println(v); // afisarea unui intreg vector, punandu-se si endl
}
Checkere
Polygon pune la dispoziție o gamă largă de checkere utlizatorilor, acestea având și descrieri detaliate. De asemenea, se pot scrie și checkere manual, având grijă să se respecte diferite particularități ale tipului de soluție cerut. Ideea de bază este aceea de a se verifica dacă răspunsul dat de utilizator respectă toate restricțiile problemei și dacă este corect pentru testul dat.
#include "testlib.h"
#include<bits/stdc++.h>
using namespace std;
int n, len;
string s;
int main(int argc, char* argv[])
{
registerTestlibCmd(argc, argv);
n = inf.readInt();
len = ouf.readInt();
ouf.readEoln();
s = ouf.readLine();
if(len > 2 * n)
quitf(_wa, "The length is too big");
if(len != s.size())
quitf(_wa, "Wrong length");
if(s[0] == '0')
quitf(_wa, "The number has leading zeroes");
int rest = 0;
for(int i = 0; i < s.size(); ++i)
rest = (rest * 10 + (s[i] - '0')) % n;
if(rest != 0)
quitf(_wa, "The number is not a multiple of n");
quitf(_ok, "The number is good");
return 0;
}
Validatoare
Deși testlib.h nu dă erori în ceea ce privește generarea datelor, scrierea unui validator este o idee foarte bună deoarece se previn erori nedorite la generarea datelor și posibile bug-uri la scrierea parametrilor pentru generarea valorilor prezente în datele de intrare.
#include <bits/stdc++.h>
#include "testlib.h"
using namespace std;
int main(int argc, char* argv[]) {
registerValidation(argc, argv);
int n = inf.readInt(1, 1000000000, "n");
inf.readSpace();
int m = inf.readInt(1, 1000000000, "m");
inf.readSpace();
int q = inf.readInt(1, 3000000, "q");
inf.readSpace();
int x = inf.readInt(1, n, "x");
inf.readSpace();
int y = inf.readInt(1, m, "y");
inf.readEoln();
for(int i = 0; i < q; ++i)
{
int a = inf.readInt(1, n, "a");
inf.readSpace();
int b = inf.readInt(1, m, "b");
inf.readSpace();
int c = inf.readInt(1, n, "c");
inf.readSpace();
int d = inf.readInt(1, m, "d");
inf.readEoln();
}
inf.readEof();
}
Scrierea soluțiilor
Un mare avantaj la Polygon este acela că soluțiile pot fi etichetate în funcție de tipul lor, fiind prezente mai multe categorii în funcție de tipul soluției. Aceste tipuri sunt foarte utile pentru a putea afla informații relevante în momentul în care se rulează toate soluțiile folosind datele de test, putând astfel să aflăm ușor dacă o soluție nu se comportă conform așteptărilor, folosind secțiunea invocations. Nu în ultimul rând, trebuie generate doar datele de intrare, deoarece datele de ieșire sunt generate automat de platformă la încărcarea soluțiilor, după ce a fost selectat checkerul potrivit.
Crearea pachetelor
După obținerea unei invocări cu succes, putem merge la secțiunea packages și solicităm crearea unui package full, pentru a putea obține datele complete în ceea ce privește testele, soluțiile și alte date relevante. Kilonova permite încărcarea directă a datelor dacă folosim package-ul full pentru Linux, ceea ce ușurează foarte mult procesul de generare și încărcare a datelor.
Concluzii
Polygon este o resursă ușor de utilizat și acest ghid servește drept un punct de pornire pentru învățarea acestei platforme ce face configurarea de probleme mult mai ușoară, indiferent de platforma pe care acele probleme ajung.