APL/Jシンポジウム 2004/12/11

 

Jの正規表現プログラミングU

数式処理システムへの利用

 

西川 利男

 

1.はじめに

 正規表現(Regular Expression)とは文字列を含む記号処理にいわゆるパターン・マッチングを積極的に利用するユニークなプログラミング技法である.Webのシステム言語であるPerlで良く知られているが,Jでも可能であり,かえって簡明で,われわれJユーザにとっては配列言語=Array Processing Language (APL)に加えるもう一つの特徴とさえ言えよう.[1]

 一方,数学教育において最近「リテラシー」という言葉で,「数学をいかに使いこなすか」の習得がさけばれている.数学の真の目的は数値計算にあるのではなく,数式の扱い方,数式を使っての問題の記述,その解決にある.その意味では学校数学でもっと数式処理の活用がなされるべきである.

 数式処理の基本は計算ではなく,記号処理である.数式処理への正規表現の有効性をみる意味でJにより小さな数式処理システムの開発を試みた.その大要は先に技術史教育学会で発表したが[2], ここではJの正規表現を利用したコーディングの詳細について述べる.

 

2.数式処理の基本の操作

 一般に数式処理の基本となる操作には,次のようなものがあろう.

@ 同類項について四則演算をおこなう.

A 多項式については巾乗の降巾または昇巾の順に整理する.

B かっこをはずし,式を展開する.

C 多項式の微分演算をおこなう.

他にも三角関数などいろいろな数学関数,因数分解,積分など数式の操作は限りなくあるが,とりあえずは上のような数式の処理を対象とした.

 

3.Jによる数式処理システムの考え方

 システムに入力された数式は一連の文字列として処理することになる.数式とは,これを良く見ると,数字列と文字列との並び(数学的には係数と変数との積)を数学的に意味のある単位(これを数学項と呼ぶことにする)として,その間に演算記号を挿入した構造が繰り返されたものと見ることができる.

Jにより数式処理システムの構築のため,処理を次のように項目に分けて行う.なおJの該当する関数をかっこ内に記した.

・処理1 数学項の単位での分割 

数式を上の数学項ごとに分割する.これにはJのボックス化による表示を利用する.(adjust)

ここで数学項は次のような文字列で成り立っている.

 +/-の符号 数字列(整数,帯小数など数値) 名前(変数名)

           -123.4x

・処理2 巾乗表記を繰り返し表記へ変換 

名前(変数名)には上のような単純なもの以外に巾乗を含む場合もある.なお巾乗は通常の肩付き小文字ではなく記号^を用いて表す.

   文字列^数字列

   2.4x^3, -3r^2, …

このように入力された巾乗表記は繰り返し表記に変換する. 

  数学項の場合 x^4 ⇒ xxxx                 (pow2rp)

    かっこの場合 (…)^3 ⇒ (…)(…)(…)         (par2rpp)

・処理3 数学項への整合処理

 実際に入力された数式は,次のようにいろいろの場合が起きる.これらを処理しやすくするため,以下のような数学項に統一整合化する.(liketm)

   ax ⇒ +1ax

     -ax ⇒ -1ax

     1.2x ⇒ +1.2x

     (…) ⇒ +1(…)

     -(…) ⇒ -1(…)

  定数項は大文字N(値1)を掛けた形に変換して処理する.

   1.23  ⇒ +1.23N

 

・処理4 数学項の代数和処理

  数式は本来,+, - の2項演算の記号でつながれた数学項の連続した繰り返しであるが,Jのプログラミングの容易さを考え,これを以下のように +, - 正負の符号を持つ数学項の代数和として処理する.(liketm)

  2.3x-4.5y+6z ⇒ (+2.3x)+(-4.5y)+(+6z)

・処理5 数学項の整理

 変数名をabc順並べ替え,それに応じて項の整理を行う.これによって同類項になるものが生ずる.(liketm)

   cxab, xbac, bcax ⇒ abcx

・処理6 同類項の計算

 同類項ごとにまとめて,係数の四則演算を行い,一つの数学項とする.その結果,係数が0になった数学項は削除する.(liketm)

      1.2x+3.4x4.8x = -0.2x

      1.2x+3.4x4.6x = +0x ⇒ 削除

 

・処理7 多項式の整理

  多項式の巾乗を降巾あるいは昇巾の順に並べ替える.その結果得られる同類項について四則計算を行う.(liketm)

 

・処理8 かっこをはずして展開

  単純項とかっこの場合 a(c+d…) ⇒ ac+ad…   (unpar)

   かっこ同士の場合   (a+b…)(c+d…) ⇒ ac+ad+bc+bd…  (unpar2)

 

・処理9 後処理

 いろいろな処理を行った結果が通常の数式表示と不自然になった場合,最後に整形を行う.巾乗の繰り返し表示を記号^による表示に戻すなど.(liketm)

・処理10  多項式の微分

 公式にしたがって微分を行う.(dx, dif)

  x^n ⇒ nx^n-1

 

4.J正規表現プログラミングのコーディング例

詳細は付録のプログラムリストを見ていただくとして,正規表現プログラミングのコーディングの例として関数liketmを見てみよう.

正規表現の各パターンを数値係数に対しては

   pnumber =: '[\+]*[\-]*[[:digit:]]*\.*[[:digit:]]*'

変数名には

   pnamevar =: '[\+]*[\-]*[[:alpha:]]*(\^[[:digit:]])*'

これらから出来る数学項には

   pmathvar =: '[\+]*[\-]*[[:digit:]]*\.*[[:digit:]]*[[:alpha:]]'

のように指定する.

  これらの正規表現パターンを用いて,数値係数,変数名,数学項は次のように簡単に取り出せる.

   pnumber rxall '123.45x-abc'

+------++-++++

|123.45||-||||

+------++-++++

   pnamevar rxall '123.45x-abc'

+++++++-+----+

|||||||x|-abc|

+++++++-+----+

   pmathvar rxall '123.45x-abc'

+-------+----+

|123.45x|-abc|

+-------+----+

 

  次のような簡単な数式を例として,関数liketmの基本部分をやってみる.

   F0 =. '1.2x+0.4y+10.5x+3y-4x'

まず,文字列をボックス表示で数学項にまとめる.

   ]V =. pmathvar rxall F0

+----+-----+------+---+---+

|1.2x|+0.4y|+10.5x|+3y|-4x|

+----+-----+------+---+---+

関数takenumを用いて係数値だけを取り出す.(関数定義は付録を参照)

   ]N =: takenum L:0 V            

+---+----+-----+--+--+

|1.2|+0.4|+10.5|+3|-4|

+---+----+-----+--+--+

関数takenamを用いて変数名だけを取り出す.(関数定義は付録を参照)

   ]M =: takenam L:0 V

+-+-+-+-+-+

|x|y|x|y|x|

+-+-+-+-+-+

同じ変数名を持つ係数数値の代数和を求める.

   ]S =: ": L:0 ;/ +/"1 (M=/M)#,>". L:0 N

+---+---+---+---+---+

|7.7|3.4|7.7|3.4|7.7|

+---+---+---+---+---+

変数名,係数をまとめる.

   ]MS =: (\:~ ~. |: M ,: S)

+-+---+

|y|3.4|

+-+---+

|x|7.7|

+-+---+

上の処理を基本にさらに細かい処理を加えた関数liketmを作用させると次のように同類項の計算が行われる.

   liketm F0

7.7x+3.4y

 

5.J数式処理システムの実行例

 いくつかの例について,実行のようすを途中経過とともに示してみる.

かっこをほどいて同類項を整理する面倒な計算は次のようになる.

   run '3.14-0.5y+2.3(a+b)(c-d)-4(3.2x+1.5y)+10.4+2(x-y)-c(-a+b)'

+----------+--------------++-------------+-----+-------++--------+

|3.14 -0.5y|+2.3(a+b)(c-d)||-4(3.2x+1.5y)|+10.4|+2(x-y)||-c(-a+b)|

+----------+--------------++-------------+-----+-------++--------+

3.14 -0.5y++2.3ac-2.3ad+2.3bc-2.3bd+-12.8x-6y+10.4++2x-2y++1ca-1cb

13.54+3.3ac-2.3ad+1.3bc-2.3bd-10.8x-8.5y

 

かっこの中に多項式が入った例は次のようになる.

   run '12.5+0.5x(12-3x+2x^2)^2+12.5x-3.5'

+----+---------------------------+----------+

|12.5|+0.5x(12-3x+2xx)(12-3x+2xx)|+12.5x-3.5|

+----+---------------------------+----------+

12.5++72x-18xx+12xxx-18xx+4.5xxx-3xxxx+12xxx-3xxxx+2xxxxx+12.5x-3.5

9+84.5x-36x^2+28.5x^3-6x^4+2x^5

 

よくある展開の公式は次ぎのとおり得られる.  

   run '(a-b)(a^2+ab+b^2)'

++----------------+

||1(a-b)(aa+ab+bb)|

++----------------+

++1aaa+1aab+1abb-1baa-1bab-1bbb

a^3-b^3

この例では内部での処理のようすも見られるであろう.

   run '(a+b+c)(a^2+b^2+c^2-ab-bc-ca)'

++---------------------------+

||1(a+b+c)(aa+bb+cc-ab-bc-ca)|

++---------------------------+

++1aaa+1abb+1acc-1aab-1abc-1aca+1baa+1bbb+1bcc-1bab-1bbc-1bca+1caa+1cbb+1ccc-1cab-1cbc-1cca

a^3-3abc+b^3+c^3

多項式の微分は非常に簡単である.

   dx '9+84.5x-36x^2+28.5x^3-6x^4+2x^5'

        +84.5   -72x^1  +85.5x^2-24x^3  +10x^4 

84.5-72x+85.5x^2-24x^3+10x^4

 

 このようにJの正規表現プログラミングは数式処理システムの構築に非常に有効であった.また,Jの正規表現プログラミングはその特徴を生かして,いろいろな別の分野へも適用でき,J言語のさらに広い可能性を約束しているといえよう.

 

文献

[1] 西川利男「Jの正規表現プログラミング−I,正規表現とは−Perlと比較しつつ,Jのボックス表示の文字化け解消への利用」J言語研究会資料2004/9/25.

[2] 西川利男「Jの正規表現プログラミングと数式処理のすすめ−数学教師はなぜコンピュータが嫌いか−」技術史教育学会2004全国大会(厚木)研究発表講演論文集 p.15 (2004).


付録 Jの正規表現プログラミングの要点(文献[1] より再録)

正規表現によるパターンの指定

・個々の文字            'abc', '3.14', 'にほんご'(2バイト文字も可能)

・特殊文字              '\.'⇔ピリオドそのもの,'\('⇔かっこ

・すべての文字   .(ピリオド)

・いずれか1文字       '[a-z]', '[A-Z]', '[0-9]'

                       '[aeiou]'       母音文字

                    '[[:alpha:]]'    英文字

                    '[[:alnum:]]'    英数文字

                    '[[:digit:]]'    数字

                    '[[:space:]]'    スペース

                    '[[:punct:]]'    区切り文字

                    '[[:cntrl:]]'    制御文字

・除いた文字        '[^aeiou]'        母音を除いた文字

・繰り返し *  0回〜    'ab*c'        ac, abc, abbc, abbbc にマッチ

           +  1回〜    'ab+c'        abc, abbc, abbbc にマッチ

           ?  0回/1回 'ab?c'        ac, abc にマッチ

・文字列の繰り返し       かっこ( )でくくる

・取り出し反復           かっこ( )でくくる

 

正規表現の基本操作関数

・マッチした文字列にしるしをつける.

   '[[:digit:]]+' tryall 'abc234def43'  

abc234def43

   ^^^   ^^

・マッチした文字列を取り出す.

   '[[:digit:]]+' rxall 'abc234def43'

+---+--+

|234|43|

+---+--+

・マッチした文字列を置換する.

   ('[[:digit:]]+';'***') rxrplc 'abc234def43'

abc***def***

・マッチした文字列に操作を行う.

   '[[:alpha:]]+' |. rxapply 'abc234def43'

cba234fed43

        
プログラムリスト

NB. Symbolic Formula Manipulation by Toshio Nishikawa

NB.   Using J Regular Expression

NB. revised as formulax.js 2004/9/3

NB. liketm, nparc, nparf

NB. OK - more than 3 terms in parenthesis 2004/8/22

NB. OK - power of more than 3 parentheses 2004/8/28 

 

wr=: 1!:2&2

 

NB. J Regular Expression Tools ======================

load 'main\regex.js'

 

try =: dyad define  NB. try original function

y. ,: ' ^' #~ 0 >. {. x. rxmatch y.

)

NB. tryall by T.N. 2004/7/19 modified from try function

NB. f.g.

NB.    '[aeiou]+' tryall 'These reveal various examples'

NB. These reveal various examples

NB.   ^ ^  ^ ^^   ^ ^^^  ^ ^   ^

NB.    'に+' tryall 'にほんごににたことば'

NB. にほんごににたことば

NB. ^^      ^^^^      

orsp =: ('^'"_)`(' '"_)@.=      NB. eq=> ' ', nq=>'^'

tryall =: dyad define

n0 =: 0 >. x. rxmatches y.      NB. take only positive, if _1(=no match) => 0

n1 =: {. "(2) n0                NB. convert to 2 dim array

n2 =: n1 #' ^'                  NB. convert to 'sp^' pattern

n3 =: orsp/n2

y. ,: n3

)

 

NB.  Test Examples ============================================

F0 =: '1.2x+0.4y+10.5x+3y-4x'

F1 =: '1.2x+0.4x^2+0.5-2.8x^2+2.5x-3.2-12.4x'

F2 =: '1.2x+0.4x^2-3.4x^3+0.5-2.8x^2+2.5x-3.2-12.4x+0.5x^3'

F3 =: '3.14-0.5y+2.3(a+b)(c-d)-4(3.2x+1.5y)+10.4+2(x-y)-c(-a+b)'

F4 =: '3.2(x+2y)^2'

F5 =: '4.5(x+y)(x-y)'

F6 =: '12.5+0.5x(12-3x+2x^2)^2+12.5x-3.5'

 

run =: liketm@nparc@nparf

 

NB. e.g. run '(a+b+c)(a^2+b^2+c^2-ab-bc-ca)' => a^3-3abc+b^3+c^3

NB. e.g. run '(a+b+c)^2' => a^2+2ab+2ac+b^2+2bc+c^2

 

NB.  Regular Expression Patterns for Math Formulas =============

poperator =: '\+*\-*'

 

pnumber =: '[\+]*[\-]*[[:digit:]]*\.*[[:digit:]]*'

pnamevar =: '[\+]*[\-]*[[:alpha:]]*(\^[[:digit:]])*'

pmathvar =: '[\+]*[\-]*[[:digit:]]*\.*[[:digit:]]*[[:alpha:]]*(\^[[:digit:]])*'

pmathvar0 =: '[[:digit:]]*\.*[[:digit:]]*[[:alpha:]]*'

 

pmathtm =: pmathvar, poperator, pmathvar

pmathpar =: pmathvar, '\(', pmathtm, '\)'

 

pmathpar2 =: '\(', pmathtm, '\)\(', pmathtm, '\)'

pmathparv =: pmathvar, '\(', pmathtm, '\)\(', pmathtm, '\)'

 

NB. liketerm calc., zero-cancel, order upward etc =================

NB. x^3 <=> xxx using pow2rp, rp2pow, 8/17

liketm =: 3 : 0

wr y.

y =. ((-.@(' '&=)) # ]) y.

y =. pow2rp y                NB. x^3 => xxx

V =: pmathvar rxall y   NB. math term

N =: takenum L:0 V      NB. number coefficient

M =: takenam L:0 V      NB. variable name

n =: (>V -: L:0 N)#i.#V

M =: (<'N') n } M

M =: /:~ L:0 M                NB. sort by variable names

S =: ": L:0 ;/ +/"1 (M=/M)#,>". L:0 N

MS =: (\:~ ~. |: M ,: S)

MS =: /: ~ MS           NB. sort upward

SM =: (|."1 MS)  , "1 <'+'

R0 =: , > SM       

R1 =. (-.'N' = R0)#R0

R2 =. (-.' ' = R1)#R1

R3 =. ('\+_';'-') rxrplc R2

R4 =. ('\_';'-') rxrplc R3

R5 =. ('\+0[[:alpha:]]+|\-0[[:alpha:]]+';'') rxrplc R4

R6 =. '1[[:alpha:]]+' (}.) rxapply R5

R7 =. '\+1[[:alpha:]]+|\-1[[:alpha:]]+' ({. , 2&}.) rxapply R6

}: R8 =. rp2pow R7        NB. xxx => x^3

)

 

NB. extract number coefficient

takenum =: 3 : 0

, > {. pnumber rxall y.

)

 

NB. extract variable name

takenam =: 3 : 0

, > {: pnamevar rxall y.

)

 

 

NB.  convert power to repeated form, x^3 => xxx ===============

pow2rp =: 3 : 0

'[[:alpha:]]\^[[:digit:]]' ((".@{:) # {.) rxapply y.

)

 

NB. convert repeated form to power, xxx => x^3 ================

rp2pow =: 3 : 0

NB. wr '([[:alpha:]])\1+' rxall y.

'([[:alpha:]])\1+' pp rxapply y.

)

pp =: 3 : 0

({.y.},'^',":#y.

)

 

 

NB. convert powered parenthesis to repeated parenthesesn ========

NB. (..)^n => (..)(..)

NB.    par2rpp '(x+y)^4'

NB. (x+y)(x+y)(x+y)(x+y)

NB.    liketm unpar2 par2rpp '(a+b+c)^2'

NB. a^2+2ab+2ac+b^2+2bc+c^2

par2rpp =: 3 : 0              

'\(.+\)\^[[:digit:]]' powp rxapply y.

)

powp =: 3 : 0

pa =. (_2}.y.)

pb =. <: ". {:y.

pa,(^: pb) pa

)

 

NB. unparenthesize in repeated style =============================

NB.   nparf '2x+(x+y)^2-(a-b)^3+5'

NB. 2x+(x+y)(x+y)-(a-b)(a-b)(a-b)+5

nparf =: 3 : 0

y. =. pow2rp y.

if. 0 = +/')^' E. y. do. y. return. end.

opp =. {."1 {."2 '\(' rxmatches y.

cpp =. {."1 {."2 >:'\^' rxmatches y.

R =. (opp,. >: -/"1 cpp,.opp) rxcut y.

S =. (0 < ># L:0 R)#R

T =. ''

i =. 0

while. i < #S

  do.

    SI =. >i{S

    if.  (+/@('('&=)) SI

      do. T =. T, par2rpp SI

      else. T =. T, SI

    end.

   i =. i + 1

  end.

T

)

 

 

 

 

NB. unparenthesize and calculation 1 ===========================

NB.   Coefficient case - requires 'adjust' before 'unpar'

NB.   C(X+Y+Z+,..) => CX+CY+CZ+,...

NB. eg. unpar adjust '3.14(x+2y-3z)' => +3.14x+6.28y-9.42z

NB. OK - more than 3 terms in parenthesis 2004/8/22

unpar =: 3 : 0

NB. wr y.

if. 0 = +/ '(' E. ,>y. do. ,>y. return. end.

CXY =. ''

jo =: (0 = (>y.) i."(1) '(')#i.#>y.             NB. open paren

jc =: (0 = (>y.) i."(1) ')')#i.#>y.             NB. close paren

j =. 0

i =. 0

while. i < #y.

  do.

     if. (i >: (j{jo) - 1) *. (i < (j{jc) - 1)

         do.

            kn =. (j{jc) - (j{jo)

            C =: >(i){y.

            k =. 2

            while. k <: kn

              do.

                 Z =. >(i+k){y.

                 CZ =.(":(". takenum C)*(". takenum Z)),(takenam C),(takenam Z)

                 CXY =. CXY, '+', CZ

                 k =. k + 1

              end.                   

            i =. i + (kn+2)

            j =. j + 1

         else.

            CXY =. CXY, > i{y. 

            i =. i + 1

         end.

  end.

CXY =. ('\+_';'-') rxrplc CXY

('_';'-') rxrplc CXY

)

 

FA =: '2a(x-3y)'

FB =: '2a(x-3y)-3x(4a+5)'

FC =: '8x+3z+2a(x-3y)-7x+6ay-3x(4a+5)'

NB. adjust into boxed in math normal format (=sign+number+varname) =====

NB. requisite routine before using 'unpar'

adjust =: 3 : 0

y =. ((-.@(' '&=)) # ]) y.

D =. (pmathvar,'|\(|\)') rxall y

i =. 0

while. i < #D

 do.  B =. >i{D

      if. 0=# B do. goto_n1. end.

      if. ('(' = {.B) +. (')' = {.B) do. goto_n1. end.

      if. ('+' = {.B) +. ('-' = {.B) do. goto_n1. end.

      C =. pmathvar0 ('+'&,) rxapply B

      D =. (<C)  i } D

label_n1.

     i =. i + 1

end.

E =.  D

i =. 0

while. i < #E

 do.  B =. >i{E

      if. 0=# B do. goto_n2. end.

      C =. '[\+\-][[:alpha:]]' ({. , ('1'&,@(}.))) rxapply B

      E =. (<C)  i } E

label_n2.

     i =. i + 1

end.

E

)

 

 

 

NB. unparenthesize and calculation 2 ====================================

NB. double parentheses (..)(..) case

NB. OK - more than 3 terms in parenthesis 2004/8/22

NB. liketm unpar2 '(x+y)(x+y)' => x^2+2xy+y^2

NB. liketm unpar2 '(x+y)(x-y)' => x^2-y^2

NB. liketm unpar2 '3.14+4(3.2x+1.5y)+2.3+2(x-y)-0.5c(-3z+4y)'

NB. liketm unpar2 '3.14+2.3a(a+b)(c-d)-4a(3.2x+1.5y)+10.4+2(x-y)-c(-a+b)'

NB. liketm unpar2 '3.2+3(2a+3b-c)(x+y-z)-pqr'

NB. liketm unpar2 '(a-b)(a^2+ab+b^2)' => a^3-b^3

NB. liketm unpar2 '(a+b+c)^2'

pmt =: rxcomp pmathvar,'\(.+\)\(.+\)'

unpar2 =: 3 : 0

if. +/ ')(' E. y.  NB. (..)(..) ? 

  do.  NB. (..)(..) exists

    XYZ =. ({."2 pmt rxmatches y.) rxcut y.

    if. 2 = $XYZ do. XYZ =. XYZ, <'' end.

    y =: 1{XYZ

        if. '(' = {. > y do. y1 =. '1',L:0 y else. y1 =.  y end.

    PQ =. (0{ 2}."2 (pmathvar,'\((.+)\)\((.+)\)') rxmatches >y1) rxcut >y1

    C =. pow2rp (L:0) 0{PQ    NB. coefficient

    P =. pow2rp (L:0) 1{PQ    NB. first paren

    Q =. 3{PQ        NB. second paren

    CP =. adjust unpar adjust (>C),(>P),')'

    S =. ''

    k =. 0

    while. k < #CP

      do.        NB. unparen calculation

         C1 =. (>k{CP)

         C2 =. '(', (pow2rp ,>Q), ')'

         C3 =. C1, C2

         S =. S, unpar adjust C3       

         k =. k + 1

      end.

        (unpar adjust >0{XYZ), S, (unpar adjust >2{XYZ)

  else.  NB. (..)(..) not exists

    unpar adjust y.

  end.

)

 

 

NB. unparenthesize and calculation 3 ================================

NB. n-th power parentheses 2004/8/29

NB. requisite 'outpar', 'inpar', 'unpar2'

NB.   run '(x+y)^4' => x^4+4x^3y+6x^2y^2+4xy^3+y^4

NB.   run '2z-(x-y)^3-4' => -4-x^3+3x^2y-3xy^2+y^3+2z

nparc =: 3 : 0

wr NA =: outpar par2rpp y.

NB =. ''

j =. 0

while. j < #NA

  do.

  NJ =. ,> j{NA

  if. 0 < (+/@ ('('&=)) NJ

        do.

                y =. inpar NJ

                NP =. {.y

                NQ =. }.y

                i =. 0

                while. i < (<:#y)

                  do.

                    NR =. unpar2 (,>NP), (,>{.NQ)

                    NP =. '(', NR, ')'

                    NQ =. }.NQ

                    i =. i + 1

                end.

                NB =. NB, '+', }. }:NP

        else.

                NB =. NB, NJ

        end.

j =. j + 1

end.

NB

)

 

 

NB. box innermost paren 2004/8/29

NB.   inpar '(a+t)(s-t+1.2)(s+t)'

NB. +-----+---------+-----+

NB. |(a+t)|(s-t+1.2)|(s+t)|

NB. +-----+---------+-----+

inpar =: 3 : 0

opp =. {."1 {."2 '\(' rxmatches y.

clp =. {."1 {."2 '\)' rxmatches y.

R =. (opp,. >: -/"1 clp,.opp) rxcut y.

S =. (0 < ># L:0 R)#R

)

 

NB. box outermost paren  2004/8/29

NB. include coef before paren into the term within the paren

NB. '+(x+y)' => '+1(x+y)' revised 2004/9/3

NB.   outpar '12-(z+c)(x-y)-34x-5.2+3.4(a+b)(c+d)(r-q)+t(a-x)+0'

NB. +--+------------+--------+-------------------++-------+--+

NB. |12|-1(z+c)(x-y)|-34x-5.2|+3.4(a+b)(c+d)(r-q)||+t(a-x)|+0|

NB. +--+------------+--------+-------------------++-------+--+

outpar =: 3 : 0

if. '(' = {.y. do. y. =. '1', y. end.

op =: >: {."1 {."2 '[^\)]\(' rxmatches y.

cl =: >: {."1 {."2 '\)[^\(]' rxmatches y.

R =: (op,.-/"1 cl,.op) rxcut y.

S =: R

i =. 0

while. i< <:#R

  do.

NB.     wr (":i),' = ',, (>i{R)

     if.  0 = (+/@ ('('&=)) >i{R

        do.

           if. -. ('+'=({:>i{R)) +. ('-'=({:>i{R))

             do. S1 =. (}: pmathvar rxall >i{R)

                 S2 =. (({: pmathvar rxall >i{R) ,L:0 (i+1){R)

                 S =: (<,>S1) i } S

                 S =: (<,>S2) (i+1) } S

             else.  S1 =. (}: >i{R)

                    S2 =. (({: >i{R) ,L:0 (i+1){R)

                 S =: (<,>S1) i } S

                 S =: (<,>S2) (i+1) } S

             end.

        end.

     i =. i + 1

  end.

NB. wr S

i =. 0

NY =. ''

while. i<#S

 do.

  if. 0 < +/ ')('&E.,>i{S do.

     NX =. ,>i{S

     if. '+(' -: 2{. NX do. NX =. '+1(', (2}. NX) end.

     if. '-(' -: 2{. NX do. NX =. '-1(', (2}. NX) end.

     NY =. NY, <NX   

  else.

     NY =. NY, i{S

  end.

    i =. i + 1

 end.

NY

)

 

NB. differential of X ===============================================

NB.         dx '1.2x+0.4x^2-3.4x^3+0.5-2.8x^2+2.5x-3.2-12.4x+0.5x^3'

NB.        -8.7-4.8x-8.7x^2

dx =: 3 : 0

liketm , > dif L:0 adjust y.

)

 

dif =: 3 : 0

if. +/ '^' E. y.

  do.

    'C X N' =. ('x\^' rxmatches y.) rxcut y.

    D =. (":(". C)*(". N)), 'x^', (": <:". N)

    if. '_' = {. D do. D =. ('_';'-') rxrplc D else. D =. '+', D end.

  else.

    if. +/ 'x' E. y. do. D =. }: y. else. D =. '' end.

  end.

)