# Help with writing base 10 addition/subtraction formula

I am preparing this small tutorial for addition and subtraction formulas for kids who have a strong understanding of base-10 representation and also have a good enough understanding of addition and subtraction as its reverse in basic sense. The idea is to generate this online tutorial using Ximera Project.

Ximera is a wonderful educational project which allows people who know LaTeX and some basic programming to create wonderful online (and PDF) mathematical content.

Here is what I would like to do in multiple steps:

1. Given a random positive integer (can use sagetex or randomization packages of latex), I would like to write it as sums of base-10 blocks. (This I can partially do.) But I would like to be able to do this for a random number by first converting the given number to a list which can be then introduced with \answer{\sage{my_list[my_entry]}} command for each of the blocks. Then when I run the code within the Ximera server, it becomes a nice online problem where the person needs to introduce the base ten block entries. Basically, not being dependent on the number of digits is the issue. $12345=\answer{10000}+\answer{2000}+\answer{300}+\answer{40}+\answer{5}$

2. The I would like to generate the idea of "renaming" in base 10 addition. So, it should look like something like this for a d-digit addition (say d=3, a=987, b=74). Don't forget: I would like to do this for two random integers.

    \documentclass{article}
\begin{document}
$\begin{array}{ *{10}{r} } &&&1,000s&\star& 100s&\star & 10s& \star &1s \\ \hline &987&=&\answer{0}&+& \answer{900}&+&\answer{80}&+&\answer{7} \\ &74&=&\answer{0}&+& \answer{0}&+&\answer{70}&+&\answer{4} \\ +&&&&&&&& \\ \hline &rename&:&&& &+&\answer{10}&& \\ &&+&\answer{0}&+& \answer{900}&+&\answer{80}&& \\ &&+&\answer{0}&+& \answer{0}&+&\answer{70}&+&\answer{1} \\ +&&&&&&&& \\ \hline &rename&:&&+&\answer{100} &&&& \\ &&+&\answer{0}&+& \answer{900}&+&&& \\ &&+&\answer{0}&+& \answer{0}&+&\answer{60}&+&\answer{1} \\ +&&&&&&&& \\ \hline &rename&:&\answer{1000}&& &&&& \\ &&+&\answer{0}&+& \answer{0}&+&&& \\ &&+&\answer{0}&+& \answer{0}&+&\answer{60}&+&\answer{1} \\ +&&&&&&&& \\ \hline &&=&\answer{1000}&+& \answer{0}&+&\answer{60}&+&\answer{1} \\ +&&&&&&&& \\ \hline &\answer{1061}&=&&&&&&& \end{array}$
\end{document}

1. Finally, I want to use the same idea for subtraction!

2. I know that this does not have the best look! Animation is something I will think of this later.

• Your write-up isn't entirely clear, I'm afraid. At the moment, the code you posted could be compiled without further ado by (a) defining \newcommand\answer[1]{#1} in the preamble and (b) encasing the array environment in a $...$ "wrapper". What is \answer supposed to do? And, is your main question about how to come up with the random integers (here: 987 and 74)? Please advise. – Mico Jun 10 '18 at 6:36
• Most (almost all?!) contributors to this site are likely unfamiliar with Project Chimera. If your posting is about how to implement your project in Project Chimera, it's almost certainly off-topic for this site. If, instead, your question is about how to replicate/duplicate what's going on over at the Project Chimera site using pdfLaTeX, XeLaTeX, or LuaLaTeX along with suitable packages, you should state that explicitly -- and you should probably leave off any and all references to Project Chimera, as that's not germaine to a LaTeX-based solution. Please advise. – Mico Jun 10 '18 at 7:14
• You can treat ximera as a document class in latex. \answer{my_var} mostly matters when converting the file to an html file. When converted on a website, it leaves those places as answer boxes. Here is the link for the addition image I shared with you after being converted to an html. ximera link There are other errors on it, don't worry about it (even the title says subtraction but I have an addition description.) – barish Jun 10 '18 at 21:19
• I've taken the liberty of making your code minimally compilable, mainly by providing a dummy definition for \answer, and adding a screenshot. Feel free to revert. – Mico Jun 11 '18 at 20:08

I'm not sure I fully understood your requirements. (Actually, I'm pretty sure that I have not understood the requirements fully...) Anyway, here's a fully LuaLaTeX-based implemenation of the basic setup you describe, along with two screenshots. The first screenshot shows the case when no carry operations are required, and the second shows the case when 3 carry operations are required.

Here's the first screenshot:

And here's the second:

About the code: First, store the Lua code in an external file called base10.lua:

function base10_addition()
-- create 2 integer-valued random numbers, <1000
num1 = math.random(999)
num2 = math.random(999)

-- Get base10 elements of num1 and num2
num1_1    = num1 % 1e1
num1_10   = num1 % 1e2 - num1_1
num1_100  = num1 - num1_10 - num1_1
num1_1000 = 0
num2_1    = num2 % 1e1
num2_10   = num2 % 1e2 - num2_1
num2_100  = num2 - num2_10 - num2_1
num2_1000 = 0

-- show the two numbers and their base-10 reps
tex.sprint ( "&"..num1.."&=&"..num1_1000.."&+&"..num1_100.."&+&"..num1_10.."&+&"..num1_1.."\\\\" )
tex.sprint ( "&"..num2.."&=&"..num2_1000.."&+&"..num2_100.."&+&"..num2_10.."&+&"..num2_1.."\\\\" )
tex.sprint ( "\\cmidrule(l){9-10}" )
tex.sprint ( "+\\\\ \\addlinespace " )

-- check if overflow in 1s column
num2_1=num1_1+num2_1
if num2_1 > 9 then
num2_1 = num2_1-10
tex.sprint ( "&\\mbox{rename}&&&&&+&10\\\\" )
carry = 10
else
carry = 0
end
tex.sprint ( "&&&"..num1_1000.."&+&"..num1_100.."&+&"..num1_10.."\\\\" )
tex.sprint ( "&&&"..num2_1000.."&+&"..num2_100.."&+&"..num2_10.."&+&"..num2_1.."\\\\" )
tex.sprint ( "\\cmidrule(lr){7-8}" )
tex.sprint ( "+\\\\ \\addlinespace " )

-- check if overflow in 10s column
num2_10=num1_10+num2_10+carry
if num2_10 > 90 then
num2_10 = num2_10-100
tex.sprint ( "&\\mbox{rename}&&& + &100\\\\" )
carry=100
else
carry=0
end
tex.sprint ( "&&&"..num1_1000.."&+&"..num1_100.."\\\\" )
tex.sprint ( "&&&"..num2_1000.."&+&"..num2_100.."&+&"..num2_10.."&+&"..num2_1.."\\\\" )
tex.sprint ( "\\cmidrule(lr){5-6}" )
tex.sprint ( "+\\\\ \\addlinespace " )

-- check if overflow in 100s column
num2_100=num1_100+num2_100+carry
if num2_100 > 900 then
num2_100 = num2_100-1000
tex.sprint ( "&\\mbox{rename}&& 1000 \\\\" )
carry=1000
else
carry=0
end
if carry>0 then
tex.sprint ("&&&")
else
tex.sprint ("&&=&")
end
tex.sprint ( num2_1000.."&+&"..num2_100.."&+&"..num2_10.."&+&"..num2_1.."\\\\" )
if carry>0 then
tex.sprint ( "\\cmidrule(lr){4-4}" )
tex.sprint ( "+\\\\" )
end
tex.sprint ( "\\midrule " )

-- print the final base-10 rep
if carry>0 then
num2_1000=num2_1000+carry
tex.sprint ( "&&=&"..num2_1000.."&+&"..num2_100.."&+&"..num2_10.."&+&"..num2_1.."\\\\" )
tex.sprint ( "\\midrule" )
end

-- print the final result
tex.sprint ( "=&" .. num1+num2 )
end


And here's the LaTeX code.

% !TEX TS-program = lualatex
\documentclass{article}
\directlua{ dofile ( "base10.lua" ) } % load the Lua code
\usepackage{array,booktabs}
\newlength\mylen
\settowidth\mylen{rename} % define width of 2nd col.

\begin{document}
$\begin{array}{@{} l w{r}{\mylen} *{4}{cr} @{}} &&&1000\mbox{s}&\star& 100\mbox{s}&\star & 10\mbox{s}& \star &1\mbox{s}\\ \midrule \directlua{base10_addition()} % the Lua function does almost all the work \end{array}$
\end{document}

• +1 for divination work, I copied it all over to more mundane xint notations :) – user4686 Jun 10 '18 at 10:29
• can we do this for any two numbers with any number of digits (say at most 10?) – barish Jun 10 '18 at 21:16
• @barish - It certainly could be done... Given my professed uncertainty about what you actually wish to achieve as well as my profound unfamiliarity with Ximera, I deliberately didn't go overboard in my answer, in terms of scalability. Can you tell me if this answer is even useful to you? – Mico Jun 10 '18 at 21:26
• @Mico: This was very helpful as it is especially if I would like to avoid writing a code using sagetex which is essentially python itself. My goal is to self generate the files as I wish. This way, to generate multiple problems, I will only need one function. But it is sometimes painful to do that. If we use python, the we can make it write whole tex code and save it to a tex file, which is totally OK. I just taught it would doable this way but I think I pushed it too much. Thanks though! As for those who worry about \answer{} in Ximera, it is not really a part we need to worry! – barish Jun 14 '18 at 8:49
• I will try to use one of the codes here over my code for now and then try to use some beautiful java inspired environment called validators to avoid writing parts again and again. Again my goal here is to avoid using procedural addition/subtraction forms until a student feels comfortable doing it without losing its meaning. It is common mistake to teach kids the algorithms over meaning and then expect them to use it for the rest of their lives! – barish Jun 14 '18 at 8:52

### updated

moved from comment: If I understand correctly what you would need on TeX side is code which will generate LaTeX mark-up for a table, with \answer macros containing as arguments the pre-calculated answers. This is quite distinct from current status of my answer or @Mico's which evaluates "on-the-fly" during (lua|pdf)latex compilation. Please advise. We can of course generate such arrays with random inputs and pre-calculated answers and output them to some file from where it can be input again; without packages that is quite easy up to numbers of 9 digits (TeX can handle numbers up to 10 digits, but <2^{31} so for avoiding overflow in adding, 9 digits is maximal). But it would be as easy to generate LaTeX using say Python. If I write it using TeX only, chances are only a few dozen people will understand the TeX code (99% of LaTeX users do not program). If you write it using Python, everybody will understand what the code does.

So I have converted original answer into one which generates latex snippets, more or less like example provided in OP.

• all the \cmidrule etc... got removed
• the code does not scale very easily for more digits, if the number of digits is an input variable: because it uses variables like num1_1000 and it is cumbersome to automatize such names.
• my original answer focused on translating Lua code from @Mico to xint code, hence kept the naming of variables etc. The idea is that this gives very readable code. If I were to start over I would use core TeX with #1, #2, #3 etc... things to fetch digits, of course code would then be TeX core. No need for xint package then, except perhaps for its improved random number generator compared to engine \pdfuniformdeviate (or \uniformdeviate). Such a core approach would make scaling to more digits a bit easier. But only up to 9 digits.
• I have also changed random number generation to guarantee 3 digits-numbers (100<= x < 1000), which makes more likely to see a carry and how it is handled.

Anyway, in the example next, the code generate 5 LaTeX snippets as external files (and then \input's them for checking visually in PDF output if they work fine). The third one looks like this:

\begin{array}{rrrrrrrrrr}
&&&1,000s&\star & 100s&\star & 10s& \star &1s \\
\hline
+&&&&&&&& \\
\hline
+&&&&&&&& \\
\hline
+&&&&&&&& \\
\hline
+&&&&&&&& \\
\hline
+&&&&&&&& \\
\hline
\end{array}


As explained in the comment above, I sense that the matter is to generate LaTeX snippets which get converted to HTML. Then it is easier to use, say Python, to generate the LaTeX snippets, because there seems to be here no matter of actually using the LaTeX for PDF generation: this is why all typographical improvments from @Mico answer got removed.

Anyway, the code is pretty straightforward, but as already said above does not scale easily because of the naming scheme of variables. Also I had to do some guess-work about what is expected regarding various + signs, I reinstored some which had been cut out from @Mico's answer.

Generating code:

\documentclass{article}

\usepackage{xintexpr}[2018/05/18]% because we use randrange()

\newwrite\forximera
\newcounter{outcount}

\makeatletter
\stepcounter{outcount}%
\immediate\openout\forximera=\jobname-xim\the\value{outcount}.tex
\immediate\write\forximera{%
\string\begin{array}{rrrrrrrrrr}^^J%
\@spaces&&&1,000s&\star& 100s&\star & 10s& \star &1s \string\\^^J%
\@spaces\string\hline}%
%
%% create 2 integer-valued random numbers, <1000
%% make them 100 <= x < 1000
\xintdefiivar num1 := randrange(100, 1000);%
\xintdefiivar num2 := randrange(100, 1000);%
%
%
%% Get base10 elements of num1 and num2
\xintdefiivar num1_1    := num1 /: 10;% /: is modulo operator
\xintdefiivar num1_10   := num1 /: 100 - num1_1;%
\xintdefiivar num1_100  := num1 - num1_10 - num1_1;%
\xintdefiivar num1_1000 := 0 ;%
\xintdefiivar num2_1    := num2 /: 10;%
\xintdefiivar num2_10   := num2 /: 100 - num2_1;%
\xintdefiivar num2_100  := num2 - num2_10 - num2_1;%
\xintdefiivar num2_1000 := 0 ;%
%
%
%% show the two numbers and their base-10 reps
\immediate\write\forximera{\@spaces
&\xinttheiiexpr num1\relax
\immediate\write\forximera{\@spaces
&\xinttheiiexpr num2\relax
%%
\immediate\write\forximera{\@spaces+&&&&&&&& \string\\^^J%
\@spaces\string\hline}%
%%
%% check if overflow in 1s column
\xintdefiivar num2_1:=num1_1+num2_1;%
\xintifbooliiexpr{num2_1 > 9}
{\xintdefiivar num2_1 := num2_1-10;%
\xintdefiivar carry := 10;%
}
{\xintdefiivar carry := 0;}%
\immediate\write\forximera{\@spaces
\string\\}%
\immediate\write\forximera{\@spaces
\string\\}%
%%
\immediate\write\forximera{\@spaces+&&&&&&&& \string\\^^J%
\@spaces\string\hline}%
%
%
%% check if overflow in 10s column
\xintdefiivar num2_10:=num1_10+num2_10+carry;%
\xintifbooliiexpr{num2_10 > 90}
{\xintdefiivar num2_10 := num2_10-100;%
\xintdefiivar carry := 100;%
}
{\xintdefiivar carry := 0;}%
\immediate\write\forximera{\@spaces
\immediate\write\forximera{\@spaces
%%
\immediate\write\forximera{\@spaces+&&&&&&&& \string\\^^J%
\@spaces\string\hline}%
%
%
%% check if overflow in 100s column
\xintdefiivar num2_100:=num1_100+num2_100+carry;%
\xintifbooliiexpr{num2_100 > 900}
{\xintdefiivar num2_100 := num2_100-1000;%
\xintdefiivar carry := 1000;%
}
{\xintdefiivar carry := 0;}%
\immediate\write\forximera{\@spaces
\xintifbooliiexpr{carry>0}{&&+&}{&&=&}%
\string\\}%
%%
\immediate\write\forximera{\@spaces+&&&&&&&& \string\\^^J%
\@spaces\string\hline}%
%%
%% print the final base-10 rep
\xintifbooliiexpr{carry>0}
{\xintdefiivar num2_1000:=num2_1000+carry;%
\immediate\write\forximera{\@spaces
\string\\}%
%%
\immediate\write\forximera{\@spaces+&&&&&&&& \string\\^^J%
\@spaces\string\hline}%
%%
}
{}% no false branch
%% print the final result
\immediate\write\forximera{\@spaces
\string\end{array}}%
%
% close output file
\immediate\closeout\forximera
}

\usepackage{array}

\begin{document}\pagestyle{empty}\thispagestyle{empty}

\pdfsetrandomseed 12345678

% testing the files, give \answer some definition.

$\input \jobname-xim1$

Again
$\input \jobname-xim2$

Again
$\input \jobname-xim3$

Again
$\input \jobname-xim4$

Again
$\input \jobname-xim5$

\end{document}


### original anwer

I'm not sure I fully understood your requirements. (Actually, I'm pretty sure that I have not understood the requirements fully...) Anyway, here's a fully xintexpr-based implementation of the basic setup you describe, along with two screenshots.

Here are two more, because the author is so proud of this plagiarism of original author @Mico:

About the code: First we do all the work in LaTeX code.

Admission of guilt: I said already I copied @Mico's code. I translated back from Lua to xint. But everything could be done with no package whatsoever, with some \edef and \numexpr and \pdfuniformdeviate.

A proposito, we need very recent version of xint because it acquired randrange() function only then.

Second: there is no second step... ;-).

\documentclass{article}

\usepackage{xintexpr}[2018/05/18]% because we use randrange()

% temporarily make definitions have global scope, because
% xint creation of variable is scope obedient and is lacking
% user interface for global scope (should be added in future)
\globaldefs1
%
% no need to reset \globaldefs afterwards explicitely
% as its setting will be extinguished after first cell...
%
%% create 2 integer-valued random numbers, <1000
\xintdefiivar num1 := randrange(1000);%
\xintdefiivar num2 := randrange(1000);%
%
%
%% Get base10 elements of num1 and num2
\xintdefiivar num1_1    := num1 /: 10;% /: is modulo operator
\xintdefiivar num1_10   := num1 /: 100 - num1_1;%
\xintdefiivar num1_100  := num1 - num1_10 - num1_1;%
\xintdefiivar num1_1000 := 0 ;%
\xintdefiivar num2_1    := num2 /: 10;%
\xintdefiivar num2_10   := num2 /: 100 - num2_1;%
\xintdefiivar num2_100  := num2 - num2_10 - num2_1;%
\xintdefiivar num2_1000 := 0 ;%
%
%
%% show the two numbers and their base-10 reps
&\xinttheiiexpr num1\relax
&=&\xinttheiiexpr num1_1000\relax
&+&\xinttheiiexpr num1_100\relax
&+&\xinttheiiexpr num1_10\relax
&+&\xinttheiiexpr num1_1\relax\\
&\xinttheiiexpr num2\relax
&=&\xinttheiiexpr num2_1000\relax
&+&\xinttheiiexpr num2_100\relax
&+&\xinttheiiexpr num2_10\relax
&+&\xinttheiiexpr num2_1\relax\\
\cmidrule(l){9-10}
%
%
%% check if overflow in 1s column
\globaldefs1
\xintdefiivar num2_1:=num1_1+num2_1;%
\xintifbooliiexpr{num2_1 > 9}
{\xintdefiivar num2_1 := num2_1-10;%
\xintdefiivar carry := 10;%
&\mbox{rename}&&&&&+&10\\
}
{\xintdefiivar carry := 0;}%
&&&\xinttheiiexpr num1_1000\relax
&+&\xinttheiiexpr num1_100\relax
&+&\xinttheiiexpr num1_10\relax
\\
&&&\xinttheiiexpr num2_1000\relax
&+&\xinttheiiexpr num2_100\relax
&+&\xinttheiiexpr num2_10\relax
&+&\xinttheiiexpr num2_1\relax
\\
\cmidrule(lr){7-8}
%
%
%% check if overflow in 10s column
\globaldefs1
\xintdefiivar num2_10:=num1_10+num2_10+carry;%
\xintifbooliiexpr{num2_10 > 90}
{\xintdefiivar num2_10 := num2_10-100;%
\xintdefiivar carry := 100;%
&\mbox{rename}&&& + &100\\
}
{\xintdefiivar carry := 0;}%
&&&\xinttheiiexpr num1_1000\relax
&+&\xinttheiiexpr num1_100\relax\\
&&&\xinttheiiexpr num2_1000\relax
&+&\xinttheiiexpr num2_100\relax
&+&\xinttheiiexpr num2_10\relax
&+&\xinttheiiexpr num2_1\relax\\
\cmidrule(lr){5-6}
%
%
%% check if overflow in 100s column
\globaldefs1
\xintdefiivar num2_100:=num1_100+num2_100+carry;%
\xintifbooliiexpr{num2_100 > 900}
{\xintdefiivar num2_100 := num2_100-1000;%
\xintdefiivar carry := 1000;%
&\mbox{rename}&& 1000 \\
}
{\xintdefiivar carry := 0;}%
\xintifbooliiexpr{carry>0}{&&&}{&&=&}%
\xinttheiiexpr num2_1000\relax
&+&\xinttheiiexpr num2_100\relax
&+&\xinttheiiexpr num2_10\relax
&+&\xinttheiiexpr num2_1\relax
\\
\xintifbooliiexpr{carry > 0}
{\cmidrule(lr){4-4}+\\}
{\midrule}%
%
%
%% print the final base-10 rep
\globaldefs1
\xintifbooliiexpr{carry>0}
{\xintdefiivar num2_1000:=num2_1000+carry;%
&&=&\xinttheiiexpr num2_1000\relax
&+&\xinttheiiexpr num2_100\relax
&+&\xinttheiiexpr num2_10\relax
&+&\xinttheiiexpr num2_1\relax
\\
\midrule}
{}% no false branch
%
%
%% print the final result
=&\xinttheiiexpr num1+num2\relax
}

\usepackage{array,booktabs}
\newlength\mylen
\settowidth\mylen{rename} % define width of 2nd col.

\begin{document}

$\begin{array}{@{} l w{r}{\mylen} *{4}{cr} @{}} &&&1000\mbox{s}&\star& 100\mbox{s}&\star & 10\mbox{s}& \star &1\mbox{s}\\ \midrule \BaseTenAddition % the xintexpr-based macro does almost all the work \end{array}$

Again
$\begin{array}{@{} l w{r}{\mylen} *{4}{cr} @{}} &&&1000\mbox{s}&\star& 100\mbox{s}&\star & 10\mbox{s}& \star &1\mbox{s}\\ \midrule \BaseTenAddition % the xintexpr-based macro does almost all the work \end{array}$
\thispagestyle{empty}
\end{document}

• +1. More than happy to upvote it. Thanks for the attribution... :-) – Mico Jun 10 '18 at 10:41
• @Mico, thanks! I translated manually but after a while I could have used some automatization... I have to add some way to globally define variables in xint, precisely for usage in tabulars. The \globaldefs1  trick lacks robustness. – user4686 Jun 10 '18 at 10:49
• Can I now generalize it to random numbers upto say 10 digits so that it will create columns itself? – barish Jun 10 '18 at 21:16
• this is possible but the design takes a width which growth quadratically in terms of number of digits. Do you need the number of digits to be a variable? P.S. the current implementation is not very convenient to get scaled to more digits. So before adding any extras I would need to be told more precisely what is final aim. – user4686 Jun 10 '18 at 21:46
• the final aim is to generate this online set of problems which will go from easy to hard in teaching methods of subtraction and addition without actually sacrificing the idea behind the algorithm. Moreover, for ximeraproject there is something called a validator and i am planning to write a validator for this whole thing where you are not expected to update unnecessarily. But it is a later step. – barish Jun 10 '18 at 22:18