LuaTeXでルートの簡略化の計算問題と解答を生成

昨日の2次元方程式のファイルを、ルートの簡略化が発生するケースに拡張したいと考えている。その一歩として、ルートの簡略化をするためのコードを書いた。

結果として、次のような計算問題と解答までは作れるようになった。途中式はまだ。

f:id:baruku07:20180215224623p:plain

Luaのコード

-- 素因数分解。i番目の要素にiで何回割れるかが入る。結果として素因数のところ以外には全て0が入る。
function prime_division1(num) 
x = num
ary={}
ary[1] = 1 --1つ目の要素に1を詰めておかないと、2,3のときに正しい値を返さない
 for i=2,num do
   ary[i] = 0
    while x%i ==0 do
      ary[i] = ary[i] + 1
      x = math.floor(x/i)
    end
 end
  return ary
end

-- 与えた数のルートの簡略化a\sqrt{b}を{a,b}の配列の形で返す
function kanyakuka(soinsuu_ary) 
 a = 1
 b = 1
  for i=2, #soinsuu_ary do
   k = ary[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}として出力。
function root_exp(kanyakuka_ary)
  a = kanyakuka_ary[1]
  b = kanyakuka_ary[2]
  if    b == 1 then
    tex.print{a}
  elseif a == 1 then --これを最初のif節にすると\sqrt{1}が出力になるのでダメ。
    tex.print("\\sqrt{" .. b .. "}")
  else
    tex.print(a .. "\\sqrt{" .. b .."}")
  end
end

TeXのコード

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

\newcommand{\kanyakuka}[1]{
 \luaexec{root_exp(kanyakuka(prime_division1(#1)))}  
}

\newcommand{\gentoi}[1]{
$\sqrt{#1}$
 \begin{tcolorbox}[colframe=white,colback=white,width=3truecm,height=4pc,visible] %
 \[
 \kanyakuka{#1}
 \]
 \end{tcolorbox}
}

\begin{document}

\gentoi{4}
\gentoi{12}
\gentoi{121}
\gentoi{128}

\end{document}

やっていることは

  1. prime_division1で素因数分解(配列で返す)
  2. kanyakukaで各素因数ごとにx\sqrt{y}の形を作り、xの部分のみををかけたものとyの部分をかけたものを作る。(と結果としてa\sqrt{b}の形が得られる)
  3. 2.をroot_expでtexでa\sqrt{b}の形で表現する。

である。以下1.と3.について簡単にコメント。

1. prime_division1で素因数分解

素因数をキーに、個数を値にしたテーブルを作るのが自然である。しかし、テーブルのキーは文字列として扱われるかもしれない(調べていない)。そのあたりを調べたくなかったのでこのように書いた。

大きい数を扱うつもりはない・速度は気にしない、ということなので、nまでの全ての整数を並べた配列を作っておき、そこに素因数の個数を格納する方針を取った。

2で割って割れるだけ割る -> 2割った回数を記録 -> 3で割って割れるだけ割る -> 3で割った回数を記録なので、単純に書ける。

2/16修正

prime_division1のループの終端をmath.floor(num1/2)をnumに修正。それに合わせて上の文も\sqrt{n}までをnまでに修正。最後の最後で、たぶんroot{n}までで大丈夫だろうと良く考えずにやったのが大うっかり。

素数の場合で考えると、明らかに自分自身の数に素因数の個数1が入らないとだめなので、自分自身の数までループは回すしかない。

3. root_exp

整数になるケースも含めて対応をする。1\sqrt{b}やa\sqrt{1}という表現はありえないので、それを回避するために簡単な場合分けを書いている。

感想(余談)

この問題も、emathにあるような気がしないでもない。うまくみつけられないが。

なお、素因数分解の問題もこれを少し工夫すればいけそうである。ただし、素因数分解はemathに既製品はある。

この問題も、一応は自作する価値が私にとってある。途中式を、素因数分解の筆算を横に並べるという形では書きたく無いということがあるからである。おおざっぱに、九九で分解して、それをさらに細かく分解していくというスタイルでの途中式を書きたい。