[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/org-mathsheet 29648b4824 12/18: Documented, prefer / fo
From: |
ELPA Syncer |
Subject: |
[elpa] externals/org-mathsheet 29648b4824 12/18: Documented, prefer / for fractions |
Date: |
Thu, 10 Apr 2025 18:58:54 -0400 (EDT) |
branch: externals/org-mathsheet
commit 29648b4824c8a60e4cef779921c5562957d319dc
Author: Ian Martins <ianxm@jhu.edu>
Commit: Ian Martins <ianxm@jhu.edu>
Documented, prefer / for fractions
---
example.org | 78 +++++++++---------
mathsheet.org | 252 +++++++++++++++++++++++++++++++++++-----------------------
2 files changed, 193 insertions(+), 137 deletions(-)
diff --git a/example.org b/example.org
index 19ea901393..5aae6f8a69 100644
--- a/example.org
+++ b/example.org
@@ -1,14 +1,6 @@
* add and subtract
#+name: add-sub-1
-| weight | order | template | descr
|
-|--------+-------+-----------------------+-------------------------------------------|
-| 3 | 1 | [1..10] + [0..10] | simple
|
-| 2 | 2 | [1..10] + [8..12] | second number bigger
|
-| 2 | 2 | [1..12] + [0..10] | first number bigger
|
-| 1 | 3 | [a=2..10] - [1..$a] | small number subtraction, positive
result |
-
-#+name: add-sub-2
| weight | order | template | descr
|
|--------+-------+--------------------------------------+-----------------------------------------|
| 3 | 1 | [1..10] + [0..10] | simple
|
@@ -19,21 +11,33 @@
| 0 | 0 | [$a*[1..5]] / [a=1..10] | division
|
| 5 | 5 | [a=1..10] + [b=0..10] - [0..($a+$b)] | three with
subtraction, positive result |
-#+BEGIN: problem-set :templates "add-sub-2" :count 12 :instruction "Compute
the answer"
-| problem | answer |
-|-----------+--------|
-| 2 + 6 | 8 |
-| 6 + 4 | 10 |
-| 9 + 5 | 14 |
-| 4 + 9 | 13 |
-| 6 - 4 | 2 |
-| 6 + 12 | 18 |
-| 5 + 3 + 1 | 9 |
-| 4 + 1 - 3 | 2 |
-| 2 + 7 - 5 | 4 |
-| 1 + 7 - 5 | 3 |
-| 9 + 6 - 7 | 8 |
-| 2 + 0 - 0 | 2 |
+#+BEGIN: problem-set :templates "add-sub-1" :count 24 :prob-cols 3
:instruction "Compute the answer"
+| problem | answer |
+|------------+--------|
+| 5 + 6 | 11 |
+| 1 + 5 | 6 |
+| 4 + 7 | 11 |
+| 7 + 1 | 8 |
+| 5 + 4 | 9 |
+| 9 + 1 | 10 |
+| 5 - 4 | 1 |
+| 3 + 13 | 16 |
+| 7 + 8 | 15 |
+| 9 + 12 | 21 |
+| 4 + 9 | 13 |
+| 8 - 5 | 3 |
+| 8 + 5 + 4 | 17 |
+| 6 + 6 + 3 | 15 |
+| 7 + 9 - 1 | 15 |
+| 3 + 2 - 0 | 5 |
+| 8 + 7 - 4 | 11 |
+| 5 + 4 - 7 | 2 |
+| 2 + 9 - 6 | 5 |
+| 1 + 3 - 0 | 4 |
+| 9 + 5 - 3 | 11 |
+| 7 + 8 - 12 | 3 |
+| 8 + 4 - 7 | 5 |
+| 8 + 2 - 8 | 2 |
#+END:
* algebra
@@ -41,20 +45,20 @@
| weight | order | template | descr
|
|--------+-------+---------------------------------------+-----------------------|
| 3 | 1 | x / ([2..4] + [a=0..5]) = [$a..10] | simple
|
-| 3 | 2 | [$a*[2..10]] / x = [a=1,2,4] | simple
|
+| 2 | 2 | [$a*[2..10]] / x = [a=1,2,4] | simple
|
+| 2 | 3 | x/[-5..-1,1..5] + [1..10] = [-10..10] | double range
sequence |
+| 1 | 3 | x = x/[a=2..6] + [round([1..20]/$a)] | var twice
|
| 1 | 3 | x^2 = sqrt([16 - $a] + [a=1..5]) | sqrt
|
-| 3 | 4 | [-5..-1,1..5] x + [0..10] = [-10..10] | double range
sequence |
-| 3 | 4 | x = 2/x + sin([1..10]) | trig, two vars
|
-#+BEGIN: problem-set :templates "algebra-1" :count 8 :instruction "Solve for x"
-| problem | answer |
-|--------------------+-------------------|
-| x / (2 + 3) = 9 | x = 45 |
-| x / (3 + 3) = 9 | x = 54 |
-| 8 / x = 2 | x = 4 |
-| 36 / x = 4 | x = 9 |
-| x^2 = sqrt(12 + 4) | x = 2 |
-| -5 x + 8 = 0 | x = 8:5 |
-| -2 x + 3 = 0 | x = 3:2 |
-| x = 2/x + sin(2) | x = 1.43177096141 |
+#+BEGIN: problem-set :templates "algebra-1" :count 8 :prob-cols 2 :instruction
"Solve for x"
+| problem | answer |
+|--------------------+---------|
+| x / (3 + 0) = 4 | x = 12 |
+| x / (2 + 2) = 5 | x = 20 |
+| 6 / x = 2 | x = 3 |
+| 7 / x = 1 | x = 7 |
+| x = x/3 + 3 | x = 9/2 |
+| x/-2 + 1 = 7 | x = -12 |
+| x^2 = sqrt(15 + 1) | x = 2 |
+| x/-5 + 6 = 6 | x = 0 |
#+END:
diff --git a/mathsheet.org b/mathsheet.org
index 73279900a5..12634096c8 100644
--- a/mathsheet.org
+++ b/mathsheet.org
@@ -11,10 +11,15 @@ someone else. It could be useful for a teacher, tutor,
homeschool
parent, or any parent.
** Examples
Here are some example worksheets generated by this tool:
-1. arithmatic
-2. algebra
-** Parts
-There are two main components involved in generating a worksheet:
+1. [[file:add-sub-1.pdf][arithmatic]]
+2. [[file:algebra-1.pdf][algebra]]
+
+They were generated using [[file:example.org][this configuration]].
+** Requirements
+[[https://www.gnu.org/software/texinfo/manual/texinfo/html_node/Format-with-texi2dvi-or-texi2pdf.html][texi2pdf]]
is required to generate the PDF worksheet. Without it you can
+still generate the table of problems and solutions.
+** Usage
+There are two main components involved in defining a worksheet:
1. the problem templates
2. the problem-set block
*** Problem Templates
@@ -41,7 +46,7 @@ In additon to expressions where the answer is a number,
templates can
be equations where the solution is found by solving for the
variable. For example, consider this template:
#+begin_example
-[1..5] x + [0..10] = [-10..10]
+[1..5] x + 3 = [-10..10]
#+end_example
This can produce the following problems:
#+begin_example
@@ -55,6 +60,7 @@ These are the field rules:
- [1,3,5] :: choose randomly from 1, 3 or 5
- [-3..-1,1..3] :: choose a random number from -3 to -1 or 1 to 3
- [10/(2-1)] :: evaluate the expression
+- [round(sin(0.3))] :: expressions can use math functions
- [a=...] :: assign the variable a to the number chosen for this field
- [-2..$a] :: any number from -2 to the value assigned to ~a~ in another
field
@@ -63,6 +69,10 @@ These are the field rules:
The ability to keep track of the random number chosen in one field and
use it to influence another allows the template to be written to avoid
answers that are negative or don't divide evenly.
+
+These math functions are allowed: sqrt, sin, cos, tan, asin, acos,
+atan, floor, ceil, round. Find more details about each of these
+functions in the emacs calc manual.
**** Template Examples
Here are a few more examples:
@@ -71,33 +81,47 @@ Division problem that divides evenly
[$a*[1..5]] / [a=1..10]
#+end_example
-Addition and subtraction, still with a positive result
+Addition and subtraction, but ensure a positive result
#+begin_example
[a=1..10] + [b=0..10] - [0..($a+$b)]
#+end_example
-*** The Problem Template Table
+Division and ensure we don't divide by zero
+#+begin_example
+[-10..10] / [-5..-1,1..5]
+#+end_example
-You may want to have more than one type of problem on a worksheet, so
+*** The Problem Template Table
+**** Overview
+In order to make it possible to have more than one problem template on
+a worksheet, each worksheet is configured with a set of templates in a
+templates table. For example
-Each table defines a worksheet. Each time the worksheet is generated
-the problems are re-randomized.
+#+name: first-sheet
+| weight | order | template | descr |
+|--------+-------+---------------------+------------------------|
+| 3 | 1 | [1..10] + [1..20] | addition |
+| 1 | 2 | [a=1..10] - [0..$a] | subtraction above zero |
The table contains the following columns:
-- weight :: the relative number of this type of problem to include on
- the worksheet.
-- order :: problems are ordered on the sheet in ascending order. two
- problems with the same order will be intermingled.
+- weight :: The relative number of this type of problem to include on
+ the worksheet. A weight of zero means the template will not be
+ used. For ~first-sheet~ three out of four of the worksheet problems
+ will be addition.
+- order :: Troblems are ordered on the sheet in ascending order. Two
+ problems with the same order will be intermingled. For ~first-sheet~
+ all of the addition problems will come first.
- template :: this is the template used to generate problems of this
- type. Templates are described in more detail below.
-- descr :: just your notes, not used in worksheet generation.
+ type.
+- descr :: This column is just for your notes. It is not used in
+ worksheet generation.
+Also notice that the table is assigned a name. That name will be used
+to refer to it later.
**** Examples
+Here is another example template table.
-We label the table so that we can refer to it from the dynamic block
-that generates the worksheet. Only the first three columns are used.
-
-#+name: firstset
+#+name: second-sheet
| weight | order | template | descr
|
|--------+-------+-------------------------------+------------------------------|
| 3 | 1 | [1..10] + [0..10] | simple
|
@@ -108,7 +132,28 @@ that generates the worksheet. Only the first three columns
are used.
| 0 | 0 | [$a*[1..5]] / [a=1..10] | division
|
*** Problem-Set Block
**** Overview
-**** Examples
+The second thing needed to generate a mathsheet is an
[[https://orgmode.org/manual/Dynamic-Blocks.html][org dynamic
+block]]. Here is an example:
+
+#+BEGIN: problem-set :templates "first-set" :count 20 :instruction "Compute
the solution"
+#+END:
+
+The block name must be ~problem-set~ and it must specify the following
parameters
+- ~:templates~ :: The name of the templates table to use
+- ~:count~ :: the total number of problems to put on the sheet
+- ~:prob-cols~ :: the number of columns in which to lay out the problems
+- ~:instruction~ :: a brief instruction that will be included at the top
+ of the sheet to guide the student
+
+@@html:<kbd>@@C-c@@html:</kbd>@@ @@html:<kbd>@@C-c@@html:</kbd>@@ on
+the block ~BEGIN~ line or ~END~ line will trigger mathsheet to generate a
+new set of problems. The new problems and answers will be written to a
+table in the body of the dynamic block, and you will have the option
+(via a yes or no prompt in the mini bar) to write those problems to a
+PDF. On "yes", mathsheet will write a PDF to a file named by the
+template table name. If an existing file exists it will be
+overwritten. On "no", nothing will be written.
+
* Code walkthrough
** Problem generation
*** Header
@@ -300,7 +345,9 @@ be ambiguous:
(sequence (list (or range value) (* "," space (or range value)))
`(vals -- (seq-random-elt vals)))
(range value ".." value
- `(min max -- (+ (random (- max min)) min)))
+ `(min max -- (if (>= min max)
+ (error "Range bounds must be increasing")
+ (+ (random (- max min)) min))))
(value (or (substring (opt "-") (+ digit)) var-rhs parenthetical)
`(v -- (if (stringp v) (string-to-number v) v)))
(parenthetical "(" (or expression value) ")")
@@ -334,7 +381,7 @@ test with
#+end_src
#+RESULTS:
-: 8
+: 3
*** Replace field
@@ -461,21 +508,19 @@ other examples
*** Generate problem set from templates
-1. load table
-2. determine how many of each
- 1. sort by weight, low to high
- 2. for each row
- 1. calculate number, round with min 1, but 0->0
- 3. for last entry (highest weight) just take however many are left.
- 4. produce '(order template nil) for each problem
- 5. convert to '(order problem answer)
-3. sort
-4. loop through list, replacing entry with '(problem . solution)
+This reads in the templates, figures out how many of each based on
+weights and the number of problems needed, generates the problem set,
+figures out the answers, then reorders.
+
+The reordering is done because if multiple templates are assigned the
+same ~order~, they should be intermingled, but we add all problems for
+each template sequentially. In order to mix them up we shuffle the
+whole set and then reorder by ~order~.
#+name: generate-problems
#+begin_src elisp :tangle mathsheet.el
(defun mathsheet--generate-problems (template-name count)
- "Generate COUNT problems based on TEMPLATE-NAME
+ "Use templates from TEMPLATE-NAME to generate COUNT problems
Generate problems and answers based on what is defined in the
given template table. The template table defines problem
@@ -485,12 +530,14 @@ other examples
(save-excursion
(goto-char (point-min))
(search-forward-regexp (org-babel-named-data-regexp-for-name
template-name) nil t)
+
;; read table from buffer, drop header, convert fields to numbers or
strings
(setq templates (mapcar
(lambda (row) (list (string-to-number (nth 0 row))
(string-to-number (nth 1 row))
(substring-no-properties (nth 2
row))))
- (seq-drop (org-table-to-lisp) 2))))
+ (seq-drop (org-table-to-lisp) 2)))) ; load the table,
drop the header
+
;; sort by weight (low to high)
(setq templates (sort templates (lambda (a b) (< (car a) (car b))))
;; calc total weight
@@ -498,6 +545,7 @@ other examples
(seq-reduce (lambda (total item) (+ total (car
item)))
templates
0)))
+
;; calculate number for each row
(dotimes (ii (length templates))
(let* ((item (nth ii templates))
@@ -518,11 +566,15 @@ other examples
(alg-vars (alist-get :alg-vars fill-ret))
(calc-string (if (not alg-vars)
problem
- (format "solve(%s,[%s])" problem
(string-join (seq-uniq alg-vars) ","))))
+ (format "solve(%s,[%s])"
+ problem
+ (string-join (seq-uniq alg-vars)
","))))
(solution
(replace-regexp-in-string (rx (or "[" ".]" "]"))
""
- (calc-eval calc-string))))
+ (calc-eval `(,calc-string
+ calc-prefer-frac t
+ calc-frac-format
("/" nil))))))
(cond
((member problem problem-set) ; dedup problems
(setq dup-count (1+ dup-count))
@@ -554,14 +606,13 @@ other examples
** Update problem-set block
This generates a problem set and writes it to the dynamic block. This
-is triggered by C-c C-c on the dynamic block header.
+is triggered by ~C-c C-c~ on the dynamic block header or footer.
-~params~ is a property list of params on the block header line
-I need to extract the values
+~params~ is a property list of params on the block header line.
-- :templates :: templates
-- :count :: 10
-- :instruction :: "Solve for x"
+First we generate the problems and answers, then we write them out to
+a table in the dynamic block, finally, if the user wants it, we
+generate a PDF with these problems.
#+begin_src elisp :tangle mathsheet.el
(defun org-dblock-write:problem-set (params)
@@ -570,8 +621,9 @@ I need to extract the values
PARAMS is a plist with the properties set on the dynamic block
header, which includes `:tempates' which is the name of the
templates table, `:count' which is the number of problems to put
- on the worksheet, and `:instruction' which is the content of the
- instruction line at the top of the page"
+ on the worksheet, `:prob-cols' for the number of columns to use
+ for problems, and `:instruction' which is the content of the
+ instruction line at the top of the page."
;; write the table header
(insert "| problem | answer |\n")
@@ -599,48 +651,39 @@ I need to extract the values
(mathsheet--gen-worksheet
(plist-get params :templates)
(plist-get params :instruction)
- problems))))
+ problems
+ (plist-get params :prob-cols)))))
#+end_src
** Generate PDF
*** Lay out page
-this wraps the problems with a tex header and footer.
+This wraps the problems with a tex header and footer.
+
+This template doen't use noweb but it uses noweb syntax (~<<label>>~) to
+mark where mathsheet will insert content. It's not possible actually
+use noweb here since this template must be tangled to mathsheet.el as
+a template.
-solution for how to enumerate with circled numbers from
[[https://latex.org/forum/viewtopic.php?p=40006&sid=d202f756313add2391c3140fbeafe2ff#p40006][here]]
+I found the solution for how to enumerate with circled numbers
[[https://latex.org/forum/viewtopic.php?p=40006&sid=d202f756313add2391c3140fbeafe2ff#p40006][here]].
#+name: page
#+begin_src latex :results value silent
- \documentclass[12pt]{article}
- \usepackage[top=1in, bottom=0.8in, left=0.8in, right=0.8in]{geometry}
- \usepackage{fancyhdr}
- \newsavebox{\myheadbox}% Heading storage box
+ \documentclass[12pt]{exam}
+ \usepackage[top=1in, bottom=0.5in, left=0.8in, right=0.8in]{geometry}
\usepackage{multicol}
\usepackage{rotating}
\usepackage{xcolor}
- \usepackage{enumitem}
- \usepackage{tikz}
- \newcommand*\circled[1]{%
- \tikz[baseline=(C.base)]\node[draw,circle,inner sep=1.2pt,line
width=0.2mm,](C) {#1};}
- \newcommand*\CircledItem{%
- \stepcounter{enumi}\item[\circled{\theenumi}]}
-
- \pagestyle{fancy}
- \lhead{\textmd{\textsf{Name: }}}
- \rhead{\textmd{\textsf{Date: \today}}}
- \cfoot{}
+ \pagestyle{head}
+
\header{Name:\enspace\makebox[2.2in]{\hrulefill}}{}{Date:\enspace\makebox[2.2in]{\hrulefill}}
\begin{document}
- \noindent\textbf{<<instruction>>}
- \vspace{.2cm}
- \renewcommand{\familydefault}{\ttdefault}
+ \noindent <<instruction>>
- \begin{multicols}{2}
- \begin{enumerate}[itemsep=0.5cm]
- <<problems>>
- \end{enumerate}
- \end{multicols}
+ \begin{questions}
+ <<problems>>
+ \end{questions}
\vspace*{\fill}
@@ -652,18 +695,19 @@ solution for how to enumerate with circled numbers from
[[https://latex.org/foru
\begin{minipage}{\linewidth}
\color{gray}
\footnotesize
- \begin{multicols}{4}
- \begin{enumerate}
- <<answers>>
- \end{enumerate}
- \end{multicols}
+ \begin{questions}
+ <<answers>>
+ \end{questions}
\end{minipage}
\end{turn}
\end{document}
#+end_src
*** Convert calc to latex
-Convert a calc expression to latex format.
+This converts a calc expression to latex format. The problems and
+answers are generated in standard emacs calc format. If they are to be
+written to a PDF we convert them to latex. emacs calc already knows
+how to convert between formats, so we let it do it.
#+name: convert-to-latex
#+begin_src elisp :tangle mathsheet.el
@@ -679,19 +723,19 @@ Convert a calc expression to latex format.
(concat "$" latex-expr-cleaned "$")))
#+end_src
*** Write PDF
-
-This writes the generated into a local file and runs ~texi2pdf~ to
-convert it to a pdf. We save it as ~[template-name].tex~ and the final
-worksheet is named ~[template-name].pdf~. Each execution with the same
-template name will overwrite the same file.
-
+This inserts instruction line and generated problems into the page
+template, writes it to a local file, then runs ~texi2pdf~ to build a
+PDF. We save it as ~[template-name].tex~ and the final worksheet is
+named ~[template-name].pdf~. Each execution with the same template name
+will overwrite the same file.
#+begin_src elisp :results silent :tangle mathsheet.el
- (defun mathsheet--gen-worksheet (file-name instruction problems)
+ (defun mathsheet--gen-worksheet (file-name instruction problems prob-cols)
"Generate a worksheet with PROBLEMS.
Write a file named FILE-NAME. Include the INSTRUCTION line at the
- top."
+ top. The problems will be arranged in PROB-COLS columns. The
+ answers will be in 4 columns."
(with-temp-file (concat file-name ".tex")
(insert mathsheet--worksheet-template)
@@ -700,22 +744,30 @@ template name will overwrite the same file.
(replace-match "")
(insert instruction)
- (goto-char (point-min))
- (search-forward "<<problems>>")
- (replace-match "")
- (dolist (row problems)
- (if (cadddr row)
- (insert (format"\\CircledItem %s\\vspace{4cm}\n"
- (mathsheet--convert-to-latex (car row))))
- (insert (format"\\CircledItem %s =
\\rule[-.2\\baselineskip]{2cm}{0.4pt}\n"
- (mathsheet--convert-to-latex (car row))))))
+ (let ((answ-cols 5))
+ (goto-char (point-min))
+ (search-forward "<<problems>>")
+ (replace-match "")
+ (dolist (group (seq-partition problems prob-cols))
+ (insert (format "\\begin{multicols}{%d}\n" prob-cols))
+ (dolist (row group)
+ (if (cadddr row)
+ (insert (format"\\question %s\n"
+ (mathsheet--convert-to-latex (car row))))
+ (insert (format"\\question %s =
\\rule[-.2\\baselineskip]{2cm}{0.4pt}\n"
+ (mathsheet--convert-to-latex (car row))))))
+ (insert "\\end{multicols}\n")
+ (insert "\\vspace{\\stretch{1}}\n"))
- (goto-char (point-min))
- (search-forward "<<answers>>")
- (replace-match "")
- (dolist (row problems)
- (insert (format "\\CircledItem %s\n"
- (mathsheet--convert-to-latex (cadr row))))))
+ (goto-char (point-min))
+ (search-forward "<<answers>>")
+ (replace-match "")
+ (dolist (group (seq-partition problems answ-cols))
+ (insert (format "\\begin{multicols}{%s}\n" answ-cols))
+ (dolist (row group)
+ (insert (format "\\question %s\n"
+ (mathsheet--convert-to-latex (cadr row)))))
+ (insert "\\end{multicols}\n"))))
(shell-command (concat "texi2pdf " file-name ".tex")
(get-buffer-create "*Standard output*")))
#+end_src
- [elpa] branch externals/org-mathsheet created (now d211483197), ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet 688e66613b 03/18: Can produce problems from template, ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet 0038935262 02/18: initial, ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet 29648b4824 12/18: Documented, prefer / for fractions,
ELPA Syncer <=
- [elpa] externals/org-mathsheet c3b9570c2b 10/18: Use latex math formatting, allow exponent and sqrt, ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet d4415d4e63 05/18: can generate worksheets using new templates, ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet d241eb01d5 07/18: Fixed field index and var-list reference, cleanup, ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet 8c6b1e9cce 09/18: Add instruction and use template name for worksheet, ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet b57ce5acc2 06/18: Tangle instead of executing source blocks in place, ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet b7025320d5 01/18: Initial commit, ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet d7db7a61d1 08/18: Can produce algebra worksheets, ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet 4cfa9040d2 11/18: Added math funcs, multi range sequences, worksheet instruction, ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet 36fb466ca2 15/18: Fixed links to org files, ELPA Syncer, 2025/04/10
- [elpa] externals/org-mathsheet 1cd7959d03 04/18: Can generate sheet based on templates, ELPA Syncer, 2025/04/10