Skip to content

Commit

Permalink
Support output variable and format
Browse files Browse the repository at this point in the history
Resolve #24
Resolve #25
  • Loading branch information
fushar committed Mar 29, 2015
1 parent e61e102 commit 8e1f530
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 21 deletions.
14 changes: 7 additions & 7 deletions docs/api_ref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ The following methods can be called inside the overridden method **BaseProblem::

If not specified, the default slug is "problem".

.. _api-ref-input-variables:
.. _api-ref-io-variables:

Input variables
---------------
Input/output variables
----------------------

There are three types of variables that are supported:

Expand All @@ -30,12 +30,12 @@ Vector
Matrix
std::vector<std::vector<\ **T**\ >>, where T is a scalar type as defined above. Note that you cannot use 2D arrays (\ **T**\ [][]).

.. _api-ref-input-segments:
.. _api-ref-io-segments:

Input segments
--------------
Input/output segments
---------------------

The following macros can be called inside the overridden method **BaseProblem::InputFormat()**.
The following macros can be called inside the overridden method **BaseProblem::InputFormat()** or **BaseProblem::OutputFormat()**.

.. py:function:: EMPTY_LINE()
Expand Down
54 changes: 42 additions & 12 deletions docs/basic_concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ This component consists of configuration of several aspects of the problem. To d

The complete reference of configurable aspects of a problem can be found here: :ref:`Problem configuration API reference <api-ref-problem-configuration>`.

Input variables
---------------
Input/output variables
----------------------

This component is a collection of variables which compose test cases inputs. They can be usually found in the input format section in the problem statement. For this problem, we have three input variables: **N**, **K**, and **A**. The input variables are defined as protected member variables.
**Input variables** are a collection of variables which compose test cases inputs. They can be usually found in the input format section in the problem statement. For this problem, we have three input variables: **N**, **K**, and **A**. The input variables are defined as protected member variables.

In this problem, we have two scalars (**N**, **K**) and one vector (**A**) as the input variables. We define them as follows:

Expand All @@ -101,12 +101,22 @@ In this problem, we have two scalars (**N**, **K**) and one vector (**A**) as th
int K;
vector<int> A;

The complete reference of input variables can be found here: :ref:`Input variables API reference <api-ref-input-variables>`.
Similarly, **output variables** are a collection of variables which compose test cases inputs. Most of the cases, this is just a single variable and does not have a particular name in the problem statement. Let's just call it result.

Input format
------------
.. sourcecode:: cpp

int N;
int K;
vector<int> A;

This component specifies how the input variables should be printed in test case input files. To define this component, override the method **void BaseProblem::InputFormat()**. The format is specified in terms of consecutive input **segment**\ s. Basically an input segment arranges the layout of several input variables.
int result;

The complete reference of input/output variables can be found here: :ref:`Input/output variables API reference <api-ref-io-variables>`.

Input/output format
-------------------

**Input format** specifies how the input variables should be printed in test case input files. To define this component, override the method **void BaseProblem::InputFormat()**. The format is specified in terms of consecutive input **segment**\ s. Basically an input segment arranges the layout of several input variables.

A test case input file for this problem consists of a single containing **N** and **K**, followed by a single line containing space-separated elements of **A**. We can define that format as follows:

Expand All @@ -117,12 +127,20 @@ A test case input file for this problem consists of a single containing **N** an
LINE(A % SIZE(N));
}

The complete reference of input segments can be found here: :ref:`Input segments API reference <api-ref-input-segments>`.
Similarly, **output format** specifies how the input variables should be printed in test case input files. To define this component, override the method **void BaseProblem::OutputFormat()**.

.. sourcecode:: cpp

void OutputFormat() {
LINE(result);
}

The complete reference of input/output segments can be found here: :ref:`Input/output segments API reference <api-ref-io-segments>`.

Constraints
-----------

This components specifies the constraints of the problem; i.e., the conditions that must be satisfied by the input
This components specifies the constraints of the problem; i.e., the conditions that must be satisfied by the input/output
variables. Two types of problems are supported: the ones without subtasks, and the ones with subtasks.

**For problems without subtasks**\ : Override the method **void BaseProblem::Constraints()**.
Expand Down Expand Up @@ -174,7 +192,7 @@ where **eachElementBetween()** is a private helper method, defined as follows:

As of this version, there is currently no easy way to test a predicate for each element of a vector. The workaround is to write a helper method ourselves, like what we did above.

The complete reference of input segments can be found here: :ref:`Constraints API reference <api-ref-constraints>`.
The complete reference of constraints can be found here: :ref:`Constraints API reference <api-ref-constraints>`.

We have now completed writing a problem specification class. In summary, our class should look like this:

Expand All @@ -186,6 +204,8 @@ We have now completed writing a problem specification class. In summary, our cla
int K;
vector<int> A;

int result;

void Config() {
setSlug("k-product");
}
Expand All @@ -195,6 +215,10 @@ We have now completed writing a problem specification class. In summary, our cla
LINE(A % SIZE(N));
}

void OutputFormat() {
LINE(result);
}

void Subtask1() {
CONS(N == 1);
CONS(1 <= K && K <= 100);
Expand Down Expand Up @@ -342,6 +366,8 @@ Note that for vector input variables, don't forget to clear them before assignin
int K;
vector<int> A;

int result;

void Config() {
setSlug("k-product");
}
Expand All @@ -351,6 +377,10 @@ Note that for vector input variables, don't forget to clear them before assignin
LINE(A % SIZE(N));
}

void OutputFormat() {
LINE(result);
}

void Subtask1() {
CONS(N == 1);
CONS(1 <= K && K <= 100);
Expand Down Expand Up @@ -487,8 +517,8 @@ the input-output file pair will be stored in the specified base directory (by de

Generation can fail due to several reasons:

Invalid input format
In this case, no test cases will be generated. For example: using scalar variable for a grid segment.
Invalid input/output format
For example: using scalar variable for a grid segment.

Invalid input variable states
For example: a grid segment requires that the size is 2 x 3, but after applying the test case definition, the matrix consists of 3 x 4 elements.
Expand Down
4 changes: 4 additions & 0 deletions include/tcframe/generator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ class BaseGenerator : protected TProblem, protected TestCasesCollector {
Failure("Standard error: " + string(istreambuf_iterator<char>(*result.errorStream), istreambuf_iterator<char>()), 1)
});
}

TProblem::beginParsingFormat(result.outputStream);
TProblem::OutputFormat();
TProblem::endParsingFormat();
}
};

Expand Down
2 changes: 1 addition & 1 deletion include/tcframe/os.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class UnixOperatingSystem : public OperatingSystem {
ExecutionResult result;
int exitStatus = system((command + " < " + inputFilename + " > " + outputFilename + " 2> " + errorFilename).c_str());
result.exitCode = WEXITSTATUS(exitStatus);
result.outputStream = openForReading(outputFilename);
result.outputStream = openForReading(outputName);
result.errorStream = openForReadingAsStringStream(errorFilename);

return result;
Expand Down
1 change: 1 addition & 0 deletions include/tcframe/problem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class BaseProblem : protected ConstraintsCollector, protected IOFormatProvider {
}

virtual void InputFormat() = 0;
virtual void OutputFormat() = 0;

virtual void Constraints() { throw NotImplementedException(); }
virtual void Subtask1() { throw NotImplementedException(); }
Expand Down
14 changes: 13 additions & 1 deletion test/generator_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class FakeOperatingSystem : public OperatingSystem {
int A, B, K;
input >> A >> B >> K;

string output = Util::toString(A + B * K);
string output = Util::toString(A + B * K) + "\n";

ExecutionResult result;
result.exitCode = 0;
Expand All @@ -102,6 +102,8 @@ class ProblemWithSubtasks : public BaseProblem {
int A, B;
int K;

int result;

void Config() {
setSlug("problem");
}
Expand All @@ -111,6 +113,10 @@ class ProblemWithSubtasks : public BaseProblem {
applyLastSegment(), (applyLineSegment("K"), K);
}

void OutputFormat() {
applyLastSegment(), (applyLineSegment("result"), result);
}

void Subtask1() {
addConstraint([this] { return 1 <= A && A <= 1000; }, "1 <= A && A <= 1000");
addConstraint([this] { return 1 <= B && B <= 1000; }, "1 <= B && B <= 1000");
Expand Down Expand Up @@ -162,6 +168,8 @@ class ProblemWithoutSubtasks : public BaseProblem {
int A, B;
int K;

int result;

void Config() {
setSlug("problem");
}
Expand All @@ -171,6 +179,10 @@ class ProblemWithoutSubtasks : public BaseProblem {
applyLastSegment(), (applyLineSegment("K"), K);
}

void OutputFormat() {
applyLastSegment(), (applyLineSegment("result"), result);
}

void Constraints() {
addConstraint([this] { return 1 <= A && A <= 1000; }, "1 <= A && A <= 1000");
addConstraint([this] { return 1 <= B && B <= 1000; }, "1 <= B && B <= 1000");
Expand Down

0 comments on commit 8e1f530

Please sign in to comment.