2

I made some command \pcoef and \mcoef that simplifies +- and -+ to -, and -- to + in arithmetic expressions, and a \coef that simplifies 1x and -1x to x and -x respectively. They are not really satisfying, since their use is a non natural arithmetic transcription.

I would like to produce +, - and * commands that could be use in a 'natural' way.

The following code contains the commands i made, and what i would like:

\documentclass[12pt,a4paper,notitlepage]{extarticle}
\usepackage{xfp} %for \fpeval,randint
\pagenumbering{gobble}
\setlength\parindent{0pt}

% the commands i made: not very natural use \newcommand{\coef}[1]{\ifnum\numexpr#1=1\else\ifnum\numexpr#1=-1 -\else #1\fi\fi} \newcommand{\pcoef}[1]{\ifnum\numexpr#1=1 + \else\ifnum\numexpr#1=-1 - \else\ifnum\numexpr#1>0 + #1 \else\ifnum\numexpr#1=0 + #1 \else #1\fi\fi\fi\fi} \newcommand{\mcoef}[1]{\ifnum\numexpr#1=1 - \else\ifnum\numexpr#1=-1 + \else\ifnum\numexpr#1>0 - #1\else + \fpeval{-#1}\fi\fi\fi}

% the commands i would like: \newcommand{+}{} % i don't need to move margin \renewcommand{-}{} \renewcommand{*}{} % i don't need line break in maths

\begin{document}

% data % later \a, \b, \c, \d will take random values, positive or negative \edef\a{ 15 } \edef\b{ -17 } \def\c{ 1 } \def\d{ -1 }

{\bf what i can do, but with non natural arithmetic transcription } \[2mm] $\a \pcoef{\b}$ \ % a+b : 15+-17 is changed to 15-17 $\a \mcoef{\b}$ \ % a-b : 15--17 is changed to 15+17 $\coef{\a} x \pcoef{\b}$ \ % ax+b : 15x+-17 is changed to 15x-17 $\coef{\b} x \pcoef{\a}$ \ % bx+a : -17x+15 is not changed

{\bf how to correct this, for a more natural arithmetics, like $\backslash$a$\backslash$+$\backslash$b, $\backslash$a$\backslash$-$\backslash$b, $\backslash$a$\backslash$*x$\backslash$+$\backslash$b,etc } \[2mm]

$\backslash$+:\ %+ : $\a + \b =\ $ \leftarrow the $\backslash$+ instead of + should replace +- by -. \

$\backslash$-:\ %- : $\a - \b =\ $ \leftarrow the $\backslash$- instead of - should replace -+ by -, and -- by +. \

$\backslash$*:\ %* %* not sure if possible, since it might regcognize an arbitraby long integer before % an alternative would therefore be *{c}x $\c * x =\ $\leftarrow the $\backslash$* instead of * should replace 1x by x. \ $\d x =\ $\leftarrow the $\backslash$* instead of * should replace -1x by -x. \ $\a x =\ $\leftarrow the $\backslash$* instead of * should replace a*x by ax if a is neither 1 or -1. \

\end{document}

Any help to achieve it would be appreciated.

  • So you want \coef to supress the 1 if its argument is 1 or -1 as well kill the *? On that note, why even use a *? Usually that means something different. Either there's no operator between a number and a variable or a \cdot. – Qrrbrbirlbel Dec 13 '22 at 14:02
  • No, i would like +, - and * command such that : \a + \b would replace \a \pcoef{\b} (simplifying +- to -); \a - \b would replace \a \mcoef{\b} (simplifying -+ to -, and -- to +); \a * x would replace \mcoef{\a} x (simplifying 1x to x and -1x to -x); My purpose is to write mathematics the more 'naturally' possible, and avoiding results such as x+-15, x--30, 1x or -1x, but have x-15, x+30, x and -x instead. – mathteacher Dec 13 '22 at 19:22

2 Answers2

4

With \regex_replace_all the documentation interface3.pdf

EDIT2:

EDIT3: with the comment of mathteacher, correction de \regex_replace_all:nnN { 1x } { x } #1 en \regex_replace_all:nnN { (^|[^\d])1([a-zA-Z\c{[A-Za-z]*}]+) } { \1\2 } #1

THE CODE

            \documentclass{article}
    %https://tex.stackexchange.com/questions/668419/simplify-arithmetics-1x-1x
    \ExplSyntaxOn
\NewDocumentCommand { \simp } { m m }
{
%https://www.alanshawn.com/latex3-tutorial/#macro-expansion-control-v
%
%   Constructing a command in token list
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% #1 to hold the result of the simplication
% #2 the expression
\tl_set:Nx #1 { #2 }
\regex_replace_all:nnN { +- } { - } #1
\regex_replace_all:nnN { -- } { + } #1
%\regex_replace_all:nnN { 1x } { x } #1 <-- wrong (for instance 11x)
\regex_replace_all:nnN { (^|[^\d])1([a-zA-Z\c{[A-Za-z]*}]+) } { \1\2 } #1
}

\ExplSyntaxOff
\begin{document}
\simp{\mysimp}{5+1x}
$\mysimp$


\simp{\mysimp}{5+11x}
$\mysimp$

\simp{\mysimp}{5+1\cos(t)}
$\mysimp$

\simp{\mysimp}{1\ln(x)}
$\mysimp$

\simp{\mysimp}{11\ln(t)}
$\mysimp$

%\newcommand{\a}{1}<----  ERROR
\newcommand{\mya}{1}
\newcommand{\myb}{-1}
%
% i use the name \mysimp, you can use another name
%
\simp{\mysimp}{\mya+\myb}
$\mysimp$


\renewcommand{\mya}{2}
\renewcommand{\myb}{-2}
\newcommand{\myc}{1}
\newcommand{\myd}{-3}
\simp{\mysimp}{\mya+\myb}
\simp{\mysimpdeux}{\myc x-\myd}
$\frac{\mysimp}{\mysimpdeux}$

\renewcommand{\mya}{-3}
\renewcommand{\myb}{3}
\renewcommand{\myc}{-1}
\renewcommand{\myd}{5}
\simp{\mysimp}{\frac{\mya+\myb}{\myc \cos(t)-\myd}}
$\mysimp$
\end{document}

enter image description here

EDIT4 A beginning of answer for the simplification of fraction.

            \documentclass{article}
        \ExplSyntaxOn
        \begin{document}
        \tl_set:Nn \l_tmpa_tl { -\ln(x) }
        $\l_tmpa_tl \rightarrow$           
        \regex_replace_all:nnN { \- \c{ln} } { \c{log} } \l_tmpa_tl        
        $\l_tmpa_tl$\\
        %
        \tl_set:Nn \l_tmpa_tl { -\frac{-3}{4} }
        %\tl_analysis_show:N \l_tmpa_tl 
        $\l_tmpa_tl \rightarrow$           
        \regex_replace_all:nnN { \- \c{frac} \cB\{ \- 3 \cE\} }  { \c{frac} \cB\{ 3 \cE\} } \l_tmpa_tl        
        $\l_tmpa_tl$
        \ExplSyntaxOff
    \end{document}

enter image description here

pascal974
  • 4,652
  • This is the kind of solution i'm looking for! However, it does not work for many use case: (1) it does not simplifie if argument contains commands, like \def\a{ -1 } \simp{1 + \a}. (2) in math mode like $\simp{1 -- 2}$, it gives error 'Missing $ inserted', preventing to build more complex expressions the fractions $\frac{\simp{\a + \b}}{\simp{\c x-\d}}$ or $\simp{\frac{\a + \b}{\c x-\d}}$. – mathteacher Dec 15 '22 at 15:58
  • I solved (2) replacing removing % around \l_my_tl. I guess that (1) deals with expansion, which i don't fully understand. – mathteacher Dec 15 '22 at 16:05
  • @mathteacher I found a solution with the tutorial mentioned in the answer. – pascal974 Dec 16 '22 at 12:17
  • Thanks, your code does the job! I added two lines: \regex_replace_all:nnN {\cS\ } {} #1 at the begining to make the command more tolerant to arguments begining with space, and \regex_replace_all:nnN { (^|[^\d])1([a-zA-Z]+) } { \1\2 } #1 at the end to simplifies not only 1x but also 1y, 1cos(t) or 1anyname. It won't work with 1\ln(x), but it is still enough for my needs. Season's greetings! – mathteacher Dec 28 '22 at 18:38
  • Indeed, there was a big bug fixed with your order. For \cos or \ln, add \c{[A-Za-z]*} (p.47 interface3). I modified the answer – pascal974 Dec 29 '22 at 12:21
  • I admit, I have trouble understanding the operation of the command you found (I'm looking for) – pascal974 Dec 29 '22 at 12:31
  • 1
    Thank you @pascal974 for the \c{[A-Za-z]*}. If by command you mean the regex (^|[^\d])1([a-zA-Z]+), (^|[^\d]) means that 1 sould be the first char or should be preceded by any non decimal char; ([a-zA-Z]+) for any following letter-word. So '1x' or '+1cos' matches, but '21x' doesn't). Then \1\2 makes their concatenation without the central 1. But i guess that you mean something else... – mathteacher Dec 29 '22 at 19:21
  • Thank you for the explanations, it was difficult to find in the doc. – pascal974 Dec 30 '22 at 03:38
  • Anyway, i found that this function is incompatible with some old versions of amsmath package. So to use both, one should update amsmath to the last version. – mathteacher Dec 31 '22 at 00:22
  • I'm thinking at simplifying also -\frac{-x}{y} to +\frac{x}{y} or \frac{x}{y} if this is the start. So i want regex to replace -\frac{- by \frac{. This will be an option in a star version of \simp, because this should not be used for -\frac{-x+y}{z}. I can't get regex to match \frac{ nor even \frac. That's strange, because it has no problem to replace \ln by \log. Should i open another post ? – mathteacher Dec 31 '22 at 03:08
  • If you try -\ln it don't work. I edited the answer for a start of reflection. With \tl_analysis_show:N \l_tmpa_tl, we can see the tokens I think it's better to open a new post, there will be more expl3 specialists who can answer. Should we simplify -\frac{-x-y}{-3}? – pascal974 Jan 02 '23 at 13:01
  • I didn't mean that i need to change \ln by \log, my purpose was just to wonder why i can match a command like \ln, but i can't match \frac, and even less \frac{. Anyway, thank you for your reflexion with the fractions. I couldn't imagine from the interface3(2022-12-17), pages50-51, that i could match brackets with \cB{ \ or \cE}. I do not need other simplifications like -\frac{-x-y}{-3} for the moment, but this might be a good idea for the future. Anyway, they will be easier to do when the first fraction will work... – mathteacher Jan 03 '23 at 17:28
  • ... I will try a more advanced exploit of your solution when i will have more time. I have presently some more urgent work to do before. I will add it here if i find it, or i may open a new post. – mathteacher Jan 03 '23 at 17:28
2

This is an absolutely tedious problem if you stick to LaTeX. If you're willing to use an external program it becomes much easier. LaTeX is an amazing document preparation system. Using the sagetex package will give you access to a computer algebra system, called Sage and the Python programming language. Here's a quick solution using sagetex.

\documentclass{article}
\usepackage{sagetex}
\begin{document}
\begin{sagesilent}
a = 15
b= -17
c = 1 
d = -1

def Add(a,b): if b>=0: return r"%s+%s"%(a,b) else: return r"%s-%s"%(a,abs(b))

def Sub(a,b): if b>=0: return r"%s-%s"%(a,b) else: return r"%s+%s"%(a,abs(b))

def Poly(a,b): R.<x>=ZZ[] return ax+b \end{sagesilent} Calculating $a+b$ where $a = \sage{a}$ and $b = \sage{b}$ yields $\sagestr{Add(a,b)}=\sage{a+b}$. Moreover $a-b$ is $\sagestr{Sub(a,b)}=\sage{a-b}$. For the linear expression $ax+b$ where $a=\sage{d}$ and $b=\sage{b}$ we have $\sage{Poly(d,b)}$. Reversing the terms gives $\sage{Poly(b,d)}$. Sage can even handle the multiplication of polynomials: $(\sage{Poly(c,d)})\cdot(\sage{Poly(b,b)})=\sage{Poly(c,d)Poly(b,b)}$. \end{document}

The result running in Cocalc is below: enter image description here

The scratchwork (setup) where you assign variables and define your functions is in the sagesilent blocks. This does not show in your document. Sage output used here involves \sage and \sagestr; \sage is for calculations (i.e. things in math mode) while \sagestr is for strings. To avoid problems with various LaTeX characters, such as \ we use r"" (raw string). The function Add(a,b) can be reasoned as follows: if b>=0 then return the raw string r"%s+%s"%(a,b). The %s is a placeholder for string data. What goes into the 2 spots are a and b. Since this string involves numbers, I call it as $\sagestr{Add(a,b)}=\sage{a+b}$. Sage, being a CAS, gives you the answer of a+b as a number when \sage{a+b} is called. If b is negative then return r"%s-%s"%(a,abs(b)) returns the raw string a minus absolute value of b, avoiding the +- problem. With polynomials, the power of Sage starts to shine. The function Poly(a,b) starts by declaring that we are working in the ring of polynomials with integer coefficients, R.<x>=ZZ[]. Tell Sage what a and b are and it takes care of reconciling your +- problems. Moreover, by working with a mathematical object as opposed to a string I can then have Sage take care of multiplying the polynomials together with \sage{Poly(c,d)*Poly(b,b)}.

Search this site for more sagetex examples. I've answered questions involving polynomials here and here.

Finally, Sage is not part of your LaTeX distribution. You can sign up for a free Cocalc account to experiment with sagetex and Sage. If you like it, it's possible to download Sage to your computer and sync it with your LaTeX distribution. This has been problematic for some; Cocalc is the easiest way to get started.

DJP
  • 12,451
  • Thank you for this nice idea DJP. I was thinking to call maxima from a shell command within latex, but i forgot about the existence if sage, which i haven't used for 15 yeays! I found an installer for windows, so i will experiment as the possibilities that offers sage and with sagetex. In the short run, for the simplifications of --, -+, +-, 1x and -1x, i prefer the solution based on regex proposed by pascal974, even if it needs some modification to handle variables. – mathteacher Dec 15 '22 at 17:01