LuaTeXでルートの簡略化の計算問題の解答の作成(虚数のケースに対応)

以前の記事でルートの簡略化の問題を作るスクリプトを書いた。

もともと、これは二次方程式を解く問題の解答を自動生成するために作ったものである。よって、虚数にも拡張しておきたいという自然な欲求がある。そこで、虚数も混み(ルートの中身をマイナス)で作成したものをここに示す。

以下のような計算問題を考える。

f:id:baruku07:20180218222634p:plain

Luaの部分は次の通り。無駄に行数が多い・・・

-- 素因数分解。i番目の要素にiで何回割れるかが入る。結果として素因数のところ以外には全て0が入る。
function prime_division1(num) 
x = math.abs(num)
 ary={}
 if num>=0 then
   ary[1] =1
 else
   ary[1] = -1 -- 虚数の場合1を-1個かけられているという扱いをする。後の処理をきれいにするため。
 end
 for i=2,math.abs(num) do
   ary[i] = 0
    while x%i ==0 do
      ary[i] = ary[i] + 1
      x = math.floor(x/i)
    end
 end
 if num ==0 then --0の場合は1を0個のみ持つことにする。以下の処理がこれで不都合ないかは深く検討していない。(今後の課題)
  ary[1] =0
 end
  return ary --i番目にiが何回かけられている回数が格納されている。
end

-- 与えた数のルートの簡略化a\sqrt{b}を{a,b}の配列の形で返す
function kanyakuka(soinsuu_ary) ----i番目にiが何回かけられているかが格納されている配列を想定。
 a = 1
 b = soinsuu_ary[1] --実数なら1, 虚数なら-1
  for i=2, #soinsuu_ary do
   k = ary[i] -- 素因数iが何回掛けられているかを表している。
     if k>0 then
       a = a*i^(math.floor(k/2))
       b = b*i^(k%2) --割り切れる場合は0乗になって1がかけられて値不変。
     end     
  end
  return {a,b}
end

-- {a,b}の配列をa\sqrt{b}として出力。aやbには0以外の整数がくることが想定。
function root_exp(kanyakuka_ary)
  a = kanyakuka_ary[1]
  b = kanyakuka_ary[2]
  str = ""
  -- sqrt{b}の部分の生成
  function root_part(y) 
    str =""
    if math.abs(y) ~= 1 then -- +-1以外・ルート+-1は何も出力しない。
      str = "\\sqrt{" .. math.abs(y)  .. "}" -- 虚数の場合にマイナスを取り去る。実数ならそのまま。
    end
    if y<0 then --虚数であればをiくっつける
      str = str .. "i"
    end    
    return str
  end
  --aの部分の生成
  function int_part(x,y) 
    if (x==1 and y==1) or x~=1  then --1と整数部が1以外
      str =x
    else
      str =""
    end   
  return str   
  end
  str = int_part(a,b) .. root_part(b)
  return(str)
end

TeXの部分

\documentclass{ltjsarticle}
\usepackage{luacode}
\usepackage{amsmath}
\usepackage{tcolorbox}
\begin{luacode*}
-- ここに上のluaのコードが入る
\end{luacode*}

\newcommand{\gentoi}[1]{
 $\sqrt{#1 } $
 \begin{tcolorbox}[colframe=white,colback=white,width=2truecm,height=3pc,top=-2mm,visible] %
 \[
 \luaexec{tex.print(root_exp(kanyakuka(prime_division1(#1))))} 
 \]
\begin{gather*}
\end{gather*}   
 \end{tcolorbox}
}

\begin{document}

\begin{enumerate}
 \item \gentoi{-3}
 \item \gentoi{-16}
 \item \gentoi{-8}
 \item \gentoi{8}
 \item \gentoi{-1}
 \end{enumerate}
\end{document}

地味に書いていっているのでやたらに行数はかさんでいるがやっていることは単純で、ほぼ実数のみに対応するものと同じである。

  1. prime_division1で素因数分解
  2. kanyakukaでルートの外に出すべきものを外に出す
  3. root_expでa\sqrt{b}の形にする(aの文字列の生成部分とbの文字列の生成部分を内部で関数化して別々に考察している)

3.の部分に手を加えて虚数に対応した。いくつか簡単に説明しておく。

1. prime_division1

実数のみ考えるときに書いたものと同じく、配列のi要素に素因数iが何回かけられているかが入っている。ただし、マイナスの素因数に対応するため、マイナスの場合は1の個数が-1回かけられているとみなすことにした。

3. root_exp

a\sqrt{b}は色々と例外ルールがあり、それに対応する場合分けを書く必要がある。aがこうでbがこうで、とやっているとごちゃごちしていたので、aとbにわけて考えて後からくっつけることにした。

aについて

aについては、次のようにしている。

  • a=1以外のときは、そのままaを出力
  • a=1, b=1のときもそのままaを出力
  • それ以外のとき( a=1, b \neq 1 )のときは、何もしない。(aを省略)

\sqrt{b}について

bの絶対値が平方数のときは、ルートそのものを一切書かなくて良い。

\sqrt{b}に書くべきは符号を取り去ったものなので、bの絶対値をルートの中に書いたものを作ることにする。

さらに、b<0のときは、この部分にiを出力する必要があるので、そのようにしている。