LuaTeXで解の公式の問題(実数解・ルートが残る・ルートの簡略化なし)の問題と解答を作る

昨日の話の続きのようなものである。

今度は2次方程式の問題のうち、解の公式を使って解くものの問題と解答を生成できるものを作った。今日も、LuaTeXで強引にやっている。そんなに無理してTeXを使わず既製品を使えという話ですが・・・ネタだから問題ないということで。

次のようなものを作りたい。 f:id:baruku07:20180214204248p:plain

以下がソースである。まずはLua

--- 文字式の係数の処理
function add_plus_dimzero(num) --定数項
  if num > 0 then
     return "+" ..  num
  else 
    return num
  end
end

function add_plus_dimhighest(num) --最高次
 if num == 1 then
   return ""
 elseif num == -1 then
   return "-"
 else
   return num
 end
end

function add_plus(num) -- 定数項と最高次以外
 if  num == 1 then
   return "+"
 elseif num ==-1 then
   return "-"
 elseif num > 0 then
   return "+" .. num
 else
   return num
 end
end

function gen_polyform(ary) -- 係数の配列(n次から並んでいる)から多項式を生成
  str =""
  -- n次(最高次)の処理
     n = #ary -1 
     str = str ..add_plus_dimhighest(ary[1]) .. "x^ " .. n
  -- n次, 1, 定数項以外
  for i=2, #ary -2 do
     n=n -1
     str = str ..add_plus(ary[i]) .. "x^" .. n
  end 
 --1次式の処理(x^1はだめだから別枠)
    str = str .. add_plus(ary[#ary - 1]) ..  "x"
  --定数項
    str = str .. add_plus_dimzero(ary[#ary])  
  tex.print(str)
end

---2次方程式の解の公式の形(bが偶数や虚数のケースなども視野に入れて、解答の形を整形するための関数は別に用意することにする。)
function kai_form(ary)
  tex.print("\\frac{" .. ary[1] .. " \\pm \\sqrt{" .. ary[2] .. "}}{" .. ary[3]  .. "}")
end

-- 文字式にマイナスの数値を入れるときの括弧の追加
function add_minus_kakko(num)
   if num<0 then
     return "(" .. num .. ")"
   else
     return num 
   end
end

-- 解の公式に単純に数値を代入しただけの途中式を作る
function dainyushiki(ary)
  arystr ={}
  for i=1, #ary do
    arystr[i] = add_minus_kakko(ary[i])
  end
  bunshi = "\\frac{-" .. arystr[2] .. " \\pm \\sqrt{" .. arystr[2] .. "^2-4\\cdot" .. arystr[1] .. "\\cdot" .. arystr[3] .. "}}"
  bunbo = "{2 \\cdot " .. arystr[2]  .. "}"
  tex.print(bunshi .. bunbo)
end

-- 計算を実行して解を出力する(ただし、判別式が平方数・ルートの簡略化が発生・虚数が発生するケースには対応していない)
function h(ary)
  bunsi1 =  -ary[2]
  disc      = ary[2]*ary[2] - 4*ary[1]*ary[3]
  bunbo  = 2*ary[1]
  kai_form({bunsi1,disc,bunbo})
end

TeXの部分。

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

\newcommand{\gentoi}[3]{
 $\luaexec{gen_polyform({#1,#2,#3})} = 0$
 \begin{tcolorbox}[colframe=white,colback=white,width=6truecm,height=8pc,visible] %
 %widthの設定の際には、(-)が幅を取ることを想定して設定する。
\begin{gather*}
  x = \luaexec{dainyushiki({#1,#2,#3})} \\
  x = \luaexec{h({#1,#2,#3})}
\end{gather*}   
 \end{tcolorbox}
}

\begin{document}

\begin{enumerate}
 \item \gentoi{1}{3}{-5}
 \item \gentoi{2}{7}{-7}
 \item \gentoi{1}{-7}{3}
 \item \gentoi{3}{5}{-5}
\end{enumerate}
\end{document}

特に説明するべき点もない。

Luaのコードのほとんどは多項式の生成のためのものである。

多項式の生成部分はemathのprPolynomialを使えば3秒である。しかし、このためだけにemathを読み込ませるのはあまりに重すぎる。よって、簡単に自作した。最終的には、素のoverleafで使えるようにしたい、という思いがあるので、多項式を作る関数を自作した。

途中式色々

途中式を触りたいので、このように自作をしている。これぐらい書いておけば少々さわれば思い通りの式が作れる。

例えば、私はb2の部分の代入は、符号を書かずに(どうせ2乗だから)いかなる場合も+と思い込んで計算せよと指示している。よって、途中式のマイナスは取りさってしまいたい。-(-b)も、それぐらいひっくり返すだけなんだから暗算しろという。

場合によっては、いきなりb2を計算した値を書けとか、4acぐらいも暗算して書けという指示をすることもある。その場合は、1式目に-(-b)・b2・4acの計算した結果が入る。

学力層が高く無い集団を教えるのであれば、b2の計算結果・4acの計算結果・2aの計算結果を書いた式をもう一行作ることもありえる。

道はまだ遠い

まだ、対応すべきケースが様々ある。

  • 虚数解が発生するケース
  • ルートの中が平方数(この場合は因数分解で解答を作るようにする)
  • ルートを簡略化するケース
  • 偶数のケース

いろいろと面倒そうなので、暇なときにやりたい。

係数の設定

問題を作るときには、適度に手計算できるように係数を設定する。この「適度な」を適切に定義し、その「適度な」係数パターンの全パターンを何らかの形で列挙したものを持っておきたい。そうすれば、そこから代入して問題を作るだけである。これも今後の課題である。