Gezmat - generator of sets of mathematical and other problems

 polski 
 pionie.com 

Gezmat - generator of sets of mathematical and other problems

Version 2018-04-08
Automatic production of sets of problems, every set in many versions with different numerical values, pictures, choice of questions etc.
For each version automatic production of files with:
  • only problems (PDF, LaTeX)
  • problems and answers (PDF, LaTeX)
  • problems, hints and answers (PDF, LaTeX, txt)
Program and problems are available for free, under open licences:
  • Program: GNU GPL
  • Problems : CC BY-SA
 More information  can be found on this page or in the LICENCE directory of the package.

Examples of sets (1 version, PDF: P - problems, PA - problems with answers, PHA - problems with hints and answers, 4 versions as PDF, TEX, TXT in each ZIP archive):
All problems (1 version):  P  PA  PHA  ZIP 
Easily choose the problems and prepare your own sets by simple edition of the configuration text file.
Specify the maximal number of decimal places for basic level problems; id of these problems ends with -dpc.
At the moment there are only 35 problems prepared to demonstrate the concept. They are mainly on the primary school level. More problems, with graphs and more advanced pictures, are already prepared in  Polish  and will be translated into English.

Script checking available C++11 compilers and setting the default one. Examples of drawings in Asymptote included in LaTeX.

Start
$ tar xf Gezmat-[...].tgz
$ cd Gezmat-[...]/
Install  necessary packages  on the systems with APT (Ubuntu, Mint, Debian):
$ sudo ./install-pkgs-for-gezmat.bash
Enter the password, later confirm (Enter or Y). On other systems you have to install manually the required packages.
$ ./gezmat.bash def/en-simple_test.gzm
In the directory
Outputs/en-simple_test-[...]/
will apprear directiories pdf, tex, txt with sets of problems.
On Mac OS try:
$ export CXX=clang++ ; ./gezmat.bash def/en-simple_test.gzm
On Ubuntu/Mint/Debian you can use clang++ instead of g++-6:
$ export CXX=clang++-3.6 ; ./gezmat.bash def/en-simple_test.gzm
Instead of the default compiler g++-6 you can set another one using a script that checks available compilers:
$ unset CXX ; ./set-compiler-for-gezmat.bash
The script will check the available compilers (it takes a while) and then save the information about the user selection in the file
.gezmat.cfg
This is a more convenient way than setting the CXX variable yourself at the beginning of each session.
Required software:
  • terminal/console (this is not a "window" program)
  • bash shell
  • g++-6 or clang++-3.6 compiler with standard libraries
  • LaTeX/TeX: latex, dvips (texlive packages); ghostscript with ps2pdf. Or: pdflatex
  • Asymptote (vector graphics)
The package was tested on Linux.  How to easily install these packages. 

Gezmat also runs in Windows Subsystem for Linux on Windows 10 (install guide).

Program works on Mac OS systems, too.

We would be grateful for information if you succeed to run Gezmat on other system.
Example of a production of a set defined in the file
def/en-simple_test.gzm
Produced are 3 versions. For each version files PDF and LaTeX with the extension:
  • _ha include problems, hints, answers, information about authors, date of last modification, and identifiers (ids) of problems
  • _a include problems with answers
Other PDF and LaTeX files contain only problems, and the TXT file problems with hints and answers. The commands are invoked in the console, at the root directory of the package, which is created after extracting the tgz archive (eg. Gezmat-2016-07-14/). A folder Outputs/en-simple_test... is created to which are transferred the generated files with extensions pdf, tex, txt; other files (such as dvi, ps) can be found in the working directory Work_files/other (this directory is overwritten each run of the program).
$ ./gezmat.bash def/en-simple_test.gzm 3
$ cd Outputs/en-simple_test-2016-07-14-22/
$ ls -1 *
en-simple_test_v01_a.pdf
en-simple_test_v01_a.tex
en-simple_test_v01_ha.pdf
en-simple_test_v01_ha.tex
en-simple_test_v01.pdf
en-simple_test_v01.tex
en-simple_test_v01.txt
en-simple_test_v02_a.pdf
...
en-simple_test_v02_ha.pdf
...
en-simple_test_v02.pdf
...
en-simple_test_v02.txt
...
en-simple_test_v03_ha.pdf
...
The file  def/all_problems_en.gzm  contains ids of all problems in English, do not edit this file. Instead, change its name, for example to en-my-test.gzm, change the description and leave only chosen problems. Then produce your sets in the same way as with the file en-simple_test.gzm.

A configuration file does not have to be in the directory def/. You can store your configuration files in the directory priv-def/, for example.

A configuration file must have .gzm extension and its first 7 lines have to contain in the following order:
  1. Title (any string)
  2. Language code, only pl or en for now
  3. Decimal mark, dot or comma for example
  4. Maximal number of decimal places in case of basic level problems (0 or 1, or 2 for example)
  5. Place and date (any string)
  6. Author of the configuration file (any string)
  7. Description (any string)
In "any strings" LaTeX commands can be used.
In the following non-emty lines - that can be separated with empty ones - as the first word must be present:
  • a word gzm that introduces a Gezmat  command 
  • or an identifier (id) of the problem
All identifiers of problems can be found in the file def/all_problems_en.gzm or in the files in the directory
Outputs/all_problems_en... with _ha in the name.
Relevant is only an identifier, the title can be kept for convenience. A sample file defining a set:
Test
en
.
1
Warszawa, 2016-07-31
\emph{ Prepared by \textbf{ J.F.} } % LaTeX
Good luck!

en-numbers-0000500 "Number of pages"
en-numbers-0001000 "Plums"

  gzm comment Indentation is OK
  en-numbers-0002000 "Apples"

en-rectangles-0001000 "Sides of rectangles"

en-speed-distance-time-0004000-dpc "Cycling speed"
For people who can program in any language the possibility to add new problems (C++, LaTeX, Asymptote). Each problem is written as a lambda expression.
For authors of the problems - fragments of the files in the directory src/:
// Random integer in
// [min, max] for n=0
// [min*10^n, max*10^n] for n>0
// r(4,6) returns number in [4, 6]
// r(4,6,2) returns number in [400, 600]
int r(int min, int max, int n=0)

// String corresponding to real/10^n
// (move decimal mark n places to the left)
// s(102,2) --> "1.02"
// s(102) --> "102"
// s(30,3) --> "0.03"
string s(int number, int n=0)

// Plums - simplified version
addProblem
("en-numbers-0001000", // ID (string)
"Plums", // Title (string)
"Piotr Nieżurawski", // Authors (string)
"2016-07-11", // Date of the last update (string)
1, // Difficulty (int)
[]{ // Lambda expression (returns vector<string>)

   string text = "John had ";
   int n = 3*r(5,12);
   text += s(n);
   text += " plums. Then he ate one-third of them. How many plums has John now?";

   vector<string> pV;
   pV.push_back(text);

   // Hint
   text = "How much is ";
   text += s(n) + ":3? Answer: " + s(n/3) + ".";

   pV.push_back(text);

   // Answer
   text = "John has ";
   int answer = 2*n/3;
   text += s(answer);
   text += " plums.";

   pV.push_back(text);

   return pV;

} // End of lambda expression
); // End of addProblem

Authors of problems are indicated in the file  all_problems_en_ha.pdf 
Authors of problems in chronological order:
Piotr Nieżurawski    Piotr.Niezurawski@pionie.com 

Code, coordination, web page:
Piotr Nieżurawski    Piotr.Niezurawski@pionie.com 
Other my projects:  pionie.com 

Want to help, report a bug, ask? Visit
 discussion group Gezmat EN 
or send a mail to the coordinator  Piotr.Niezurawski@pionie.com .

Plans: problems at the level of primary education, fractions; physics problems for high school, problems with generated tables, graphs (motion, dynamics, thermodynamic processes). An independent team is working on a graphical user interface for Gezmat.
GNU GPL
Program Gezmat is available under the terms of the open licence
GNU General Public License as published by the Free Software Foundation version 3
https://www.gnu.org/licenses/gpl.txt

Descriptions of problems produced by running the Gezmat code or files with extension .gzm defining the sets of problems are available under the terms of the open licence CC BY-SA 4.0,
Creative Commons - Attribution - ShareAlike 4.0 International Public License
http://creativecommons.org/licenses/by-sa/4.0/
If you modify the sets of problems and want to publish them, include a clearly visible reference to the project's web page gezmat.com where authors of the code and problems are listed. Detailed reference to an author per each problem is not necessary. Such derivative work, according to the licence, should contain as well the licence information at least in the form of clearly visible CC BY-SA 4.0

For more information about licence of Gezmat see the files in the directory LICENCE in the package.

If you modify files with the code of Gezmat, and you want to redistribute it in any way, add in the modified file your name and e-mail address in the appriopriate 'Authors' line, add the date of modification. Include only what you created or what is in public domain.

Sent to the coordinator or publicly accessible modifications and submissions indicate the contributors' assent for inclusion of that software in the canonical version under the project's license. Please, inform the coordinator about your contributions and modifications.

To install necessary packages on the systems with APT (Ubuntu, Mint, Debian) run:
$ sudo ./install-pkgs-for-gezmat.bash
Enter the password, later confirm (Enter or Y).
The following packages are installed:
  • g++-6 with standard libraries (the Ubuntu test repository is added)
  • selected TeXLive packages, including texlive-lang-english
  • Ghostscript
  • Asymptote
  • python

If you prefer pdflatex instead of latex:
$ ./gezmat.bash def/en-sets.gzm 1 pdflatex
Remember to indicate the number of versions (in this case it cannot be empty). More versions:
$ ./gezmat.bash def/en-sets.gzm 4 pdflatex

Commands that can be placed starting at the 8 line in the configuration file (def/*.gzm)
Commands used only once per a set, affect the whole set:
gzm for-all-vspace 2cm
Insert vertical space after each problem (only P).  ZIP 
gzm only-number
Only the number of the problem, without a line break (only P).  ZIP 
gzm only-number-and-title
The numer and title of the problem, without "Problem -" (only P).  ZIP 
gzm header-left \textbf{Name:}
Insert a text in the header on the left.  ZIP 
gzm search-id speed
Choose only problems (in the chosen language) whose ids include regular expression.  more   ZIP 
gzm search-description John
Choose only problems (in the chosen language) whose descriptions include regular expression.  more   ZIP 
gzm search-author Nieżurawski
Choose only problems (in the chosen language) whose list of authors includes regular expression.  more   ZIP 
gzm shuffle
Shuffle randomly problems.  ZIP 
Generate much more versions of the set and select those with the best layout of text and pictures.
To shuffle only a group of problems use from-group-choose command and choose as many problems as there are in the group.
gzm all-problems-config
Prepare a set with all problems in the chosen language and the file def/all_problems_*.gzm.  ZIP 
gzm geometry letterpaper, verbose, tmargin=2cm, bmargin=2cm, lmargin=2cm, rmargin=2cm, headheight=0.7cm, headsep=2mm
Define page paramters. Default: a4paper, verbose, tmargin=2cm, bmargin=2cm, lmargin=2cm, rmargin=2cm, headheight=0.7cm, headsep=2mm.  ZIP 
gzm points 1.45 2
Write a number of points at each problem. The first number (optional, real) is the factor by which diff, the difficulty of the problem, will be multiplied: the number of points for a problem = integer part of [factor]*[diff of a problem]. The second number (optional, integer) is the minimum number of points per problem (each problem will have at least this number of points). If only gzm points is used, without numbers, the number of points for the problem is equal to its diff value.

The diff values ​​are listed in the PHA file (*_ha.pdf). For convenience, the total number of points for a set is printed in the terminal after the generation of the set in which command points is used. Defining a set you can modify the assigned diff value with the command gzm difficulty [integer]. Combined use of these two commands allows you to obtain a desired total number of points for a set with a guarantee that the given problem will have the same number of points in each set version.
  ZIP 
Commands that can be placed in the configuration file after a line with the problem identifier:
gzm vspace 4cm
Insert vertical space after the problem (only P).  ZIP 
gzm insert ~\\ Check \textit{the result}!
Insert a text after the problem.  ZIP 
gzm insert-before ~\\ \textbf{Breathe!} \\[-1em]
Insert a text before the problem.  ZIP 
gzm grid 0.5cm 17cm 3cm
Insert a grid after the problem; parameters: step, width, height; no space between units (here cm) and numbers (only P).   ZIP 
Width of the grid = width of the text:
gzm grid 0.5cm \textwidth 5cm
Grid at the end of the page and on the next page.
en-numbers-0000500 "Number of pages"

gzm insert \\ \begin{tikzpicture} \draw[step=0.5cm,gray!60,thick] (0, 0) grid (\textwidth, 9.5cm); \end{tikzpicture}

gzm grid 0.5cm \textwidth \textheight
Warning: everything added by "insert" appears as well in files with hints and answers (PA, PHA).
gzm difficulty 2
Modify the assigned to the problem diff (difficulty) value. Parameter: new diff value. Refer to the command gzm points  ZIP 
Commands that apply to a group of problem identifiers:
gzm from-group-choose 2
  en-numbers-0000310 "Addition in columns, 100"
  en-numbers-0000315 "Addition in columns, 150"
  en-numbers-0000320 "Addition in columns, 1500"
gzm end-group
Choose randomly and in random order the specified number of identifiers from the group of identifiers (here 2 from 3).   ZIP 
Generate much more versions of the set and select those with the best layout of text and pictures.

Special commands:
gzm comment Anything here
Comment.

Examples of searches of the problems containing a regular expression. The following commands can be placed starting from the 8 line in the configuration file (def/*.gzm). The regular expression must start after an interval of exactly one space after the command. Remove unnecessary spaces after the end of the phrase.

If you use two or three of commands search-author, search-description, search-id, the problems fulfilling all conditions are selected.  ZIP 
gzm search-id time
Choose problems whose id includes "time".
gzm search-id apple|plum
Choose problems whose id includes "apple" or "plum".
gzm search-id (?!.*set.*)(^.*$)
Choose problems whose id does not include "set".
gzm search-description [Aa]pple
Choose problems whose description includes "Apple" or "apple".
gzm search-description [Aa]pple|[Pp]lum
Choose problems whose description includes "Apple" or "apple" or "Plum" or "plum".
gzm search-description (?!.*John.*)(^.*Mark.*)
Choose problems whose description does not include "John" and includes "Mark".
gzm search-description (?!.*ectangle.*)(^.*)
Choose problems whose description does not include "ectangle".
gzm search-description (?!.*area.*)(^.*length.*)
Choose problems whose description does not include "area" and includes "length".
gzm search-description (?=.*[Pp]eeble)(?=.*[Ss]ee)
Choose problems whose description includes at the same time, in any order ["peeble" or "Peeble"] and ["see" or "See"]
Ids directly indicated in the configuration file are ignored.
Ids of chosen problems - and description of the regular expression - are stored in the file with ".rgx" extension in the subdirectory in Outputs. You can use this list of identifiers to define your set of problems.
In Gezmat the regular expressions supported by function regex_search from library regex (C++) are used, according to  the ECMAScript syntax , in case-sensitive mode.

Hints for authors of problems - easy start
In the directory src/, from the file
en-createProblemGeneratorMap-problems-include.cxx
copy one problem to the existing file
your-problems-include.cxx
In this file edit the problem. In the main Gezmat directory:
./gezmat.bash def/en-prepare-all-problems-config.gzm
And find your problem in produced files.
You can also create in the directory priv-def a file similar to the file def/en-simple_test_search-author.gzm to produce a set only with all your problems. That is:
cp def/en-simple_test_search-author.gzm priv-def/en-Your-Name-all_problems.gzm
Change "Nieżurawski" to your name. Then:
./gezmat.bash priv-def/en-Your-Name-all_problems.gzm

Hints for authors of problems - descriptions of functions

r(number,...)
// Random integer in:
// [min, max] for n=0
// [min*10^n, max*10^n] for n>0
// r(4,6) returns number in [4, 6]
// r(4,6,2) returns number in [400, 600]
int r(int min, int max, int n=0)
r(vector)
// Random integer from the input vector
// r({0, 3, 7}) returns one of numbers: 0, 3, 7.
int r(vector<int> vec)
s(...)
Only numbers as arguments:
// Return string corresponding to real/10^n (move period n places to the left)
// For example:
// s(102,2) --> "1.02"
// s(1020,3) --> "1.02"
// s(102) --> "102"
// s(3,2) --> "0.03"
string s(const int number, const int n=0)
A number and strings as arguments:
// Return string depending on the number:
// s(n,"apple","apples"): 1 apple, 2 apples...
// s(n,"times"): once, twice, 3 times...
string s(const int number, const string formA, const string formB = "", const string formC = "")
An example - see "Pebbles".

o(number, numberOfSignificantDigits)
// Function returns int rounded to specified number of significant digits
// Example: o(12332, 2) -> 12000
// Example: o(-12332, 2) -> -12000
// Example: o(1252, 2) -> 1300
// Example: o(-1252, 2) -> -1300
int o(const int number, const int numberOfSignificantDigits)
shuf(vector)
// Return shuffled vector
vector<T> shuf(vector<T> vec)
powInt(k, n)
// Function "power of k to n" returns k^n, only for n>=0.
int powInt(const int k, const int n)
p10(number)
// "power of 10" returns 10^n, for n>=0.
int p10(int n)
itod(number)
// Function returns double from int
// Example: itod(11) --> 11.0
double itod(const int i)
dtoi(number)
// Function returns int from double rounded by std::round()
// Example: dtoi(10.8) --> 11
int dtoi(const double d)
writeContainerElements(Iterator, Iterator)
// Function returns a string with sequence of integers or strings from a container separated by comma, e.g.: 1, 3, 5, 6
string writeContainerElements(Iterator it, const Iterator end, const string separator = ", ", const string flag = "")
in(x, leftBracket, a, rightBracket)
// Function returns LaTeX string of the form: x \in leftbracket a rightbracket, e.g. t \in { 10, 20, ..., 100 }
string in(string x, string leftBracket, string a, string rightBracket)
in(x, leftBracket, a, b, rightBracket)
// Function returns LaTeX string of the form: x \in leftbracket a, b rightbracket, e.g. t \in [ 10, 20 [
string in(string x, string leftBracket, string a, string b, string rightBracket)
In gezmat.cxx in namespace gezmatTools you can find definitions of other useful functions and objects:
numberToVectorOfStrings
numberLength
tableForOperation
triangleOfNumbers
tableWithTriangleOfNumbers
NumberSnakePicture

Hints for authors of problems - additional compiler options
To verify formally a new problem, run Gezmat with the option check:
./gezmat.bash def/en-sets.gzm 5 check
or
./gezmat.bash def/en-sets.gzm 5 pdflatex check
It is necessary to specify the number of versions. This option switches on additional compiler options:
-fsanitize=undefined
-fsanitize=integer-divide-by-zero
-fsanitize=float-divide-by-zero
-fsanitize=signed-integer-overflow
-fsanitize=float-cast-overflow
-fsanitize=bounds-strict
-fsanitize=address
-fuse-ld=gold
Unfortunately, the compilation is then much longer.

Hints for authors of problems - shorter compilation time while testing a new problem
In the file
src/gezmat.cxx
in the function
void createProblemGeneratorMap ()
comment lines
#include "pl-createProblemGeneratorMap-problems-include.cxx"
#include "en-createProblemGeneratorMap-problems-include.cxx"
Then only problems in the file
src/your-problems-include.cxx
are compiled.

Hints for the authors of the drawings - Asymptote in LaTeX
I recommend that you first prepare a separate file in which the drawing is defined in the language  Asymptote . Production of the picture defined in the file collision.asy:
asy collision.asy
A file collision.eps in the Encapsulated Postscript format is created. After checking that the picture is correct, you can integrate the Asymptote program into a problem description in Gezmat.

Note! We do not attach just the final drawings (files *.eps) to Gezmat!

How to insert a drawing-program in Gezmat? Take a look at the following examples. Also look at the problem descriptions in which the following text is located:
\begin{asy}
This is the beginning of the program in Asymptote inserted in LaTeX.

Here are some examples of pictures in Asymptote. Pay attention to changes that should be made by inserting the Asymptote code in LaTeX - we remove the lines with "locale", and in the case of individual graphs the lines with "size", and we adjust the size of the drawing.

Hints for the authors of the drawings - Asymptote in LaTeX
A simple scheme - a bullet and a pendulum.
 hit-pendulum.asy 
 hit-pendulum.eps 
 hit-pendulum.tex 
 hit-pendulum.pdf 

Hints for the authors of the drawings - Asymptote in LaTeX
A simple scheme - an inclined plane and a brick.
 incline-with-box.asy 
 incline-with-box.eps 
 incline-with-box.tex 
 incline-with-box.pdf 

Hints for the authors of the drawings - Asymptote in LaTeX
A simple graph x(t).
 graph-simple.asy 
 graph-simple.eps 
 graph-simple.tex 
 graph-simple.pdf 

Hints for the authors of the drawings - Asymptote in LaTeX
Many graphs (rows and columns) - an illustration of the standing wave.
 multiple-sinuses.asy 
 multiple-sinuses.eps 
 multiple-sinuses.tex 
 multiple-sinuses.pdf