計算プリントを自動生成する その14_2 解析関数
はじめに
前回までに、「3数以上からなる計算式の問題」を作成できるようになりました。
今回はその問題の答えを求める関数を書きます。
解析関数
この関数自体は、前に凍結した「その11」の時に考えていました。
使い道はよくわからないけど便利かもしれないな~と思って。
これが当時に書けていたらもうちょっと頑張れたかもですね。
ただ、これには「Fraction」クラスを用いているので、当時の手持ちでは無理でしたが。
コード
Function Int_Calculation_Analyze(ByVal str As String) '---------------------- '整数の計算式の答えを求める '---------------------- '---------------------- '変数の定義 '---------------------- Dim num() As Fraction '数字を仕分ける変数 Dim ope() As String '演算子を仕分ける変数 Dim i As Integer '繰り返しの制御変数 Dim trgt As String '仕分けのアシスト変数 Dim stock As String '仕分けのアシスト変数 Dim cnt As Integer '仕分けのアシスト変数 Dim trgt2 As String '計算のアシスト変数 Dim ans As Fraction '計算のアシスト変数 Rtrn: '---------------------- '変数の初期化 '---------------------- cnt = 0 stock = "" trgt = "" trgt2 = "" ReDim num(cnt) ReDim ope(cnt) Set ans = New Fraction '---------------------- 'strをopeとnumに分ける '---------------------- For i = 1 To Len(str) trgt = Mid(str, i, 1) Select Case trgt Case Is = "+", "-", "×", "÷" ReDim Preserve num(cnt) ReDim Preserve ope(cnt) Set num(cnt) = New Fraction num(cnt).Con (stock) ope(cnt) = trgt stock = "" cnt = cnt + 1 Case Else stock = stock & trgt End Select Next If stock <> "" Then ReDim Preserve num(cnt) Set num(cnt) = New Fraction num(cnt).Con (stock) stock = "" End If '---------------------- '条件を満たしている場合は終了 '---------------------- If cnt = 0 Then Int_Calculation_Analyze = str Exit Function End If '---------------------- '計算を行う '---------------------- trgt2 = "" For i = 0 To UBound(ope) Select Case ope(i) Case "×" trgt2 = num(i).str & ope(i) & num(i + 1).str ans.Va = num(i).Va * num(i + 1).Va ans.Vb = num(i).Vb * num(i + 1).Vb str = Replace(str, trgt2, ans.str, , 1) GoTo Rtrn Case "÷" trgt2 = num(i).str & ope(i) & num(i + 1).str ans.Va = num(i).Va * num(i + 1).Vb ans.Vb = num(i).Vb * num(i + 1).Va str = Replace(str, trgt2, ans.str, , 1) GoTo Rtrn End Select Next For i = 0 To cnt Select Case ope(i) Case "+" trgt2 = num(i).str & ope(i) & num(i + 1).str ans.Va = num(i).Va * num(i + 1).Vb + num(i).Vb * num(i + 1).Va ans.Vb = num(i).Vb * num(i + 1).Vb str = Replace(str, trgt2, ans.str, , 1) GoTo Rtrn Case "-" trgt2 = num(i).str & ope(i) & num(i + 1).str ans.Va = num(i).Va * num(i + 1).Vb - num(i).Vb * num(i + 1).Va ans.Vb = num(i).Vb * num(i + 1).Vb str = Replace(str, trgt2, ans.str, , 1) GoTo Rtrn End Select Next '---------------- '予期せぬ処理の場合はSTOP '---------------- Stop End Function
正直あまり格好良くない関数です。
格好良い関数が思いつかなかったのでしかたない。
悲しいですが、できることをやっていくだけです。
「それでも良かれと思った道を選ぶ」って言葉を思い出します。
灼眼のシャナというライトノベルで出てくるのですが笑
クラスモジュール「Fraction」
そうそう。 今回のAnalyze関数を動かすために、Fractionにも関数を足しました。
Public Va As Integer '分子 Public Vb As Integer '分母 Private Sub Class_Initialize() Va = 0 Vb = 1 End Sub Property Get str() As String '-------------------- 'Va/Vb '-------------------- If Va = 0 Then str = "0" ElseIf Vb = 1 Then str = Va Else str = Va & "/" & Vb End If End Property Function Con(str) '------------------- '文字式から分子と分母を得る '------------------- Dim trgt As String Dim stock As String Dim i As Integer If str = "" Then Exit Function If InStr(str, "/") = 0 Then Va = Val(str) Exit Function End If For i = 1 To Len(str) trgt = Mid(str, i, 1) If trgt = "/" Then Va = Val(stock) stock = "" Else stock = stock & trgt End If Next If stock = "" Then Vb = 1 Else Vb = Val(stock) End If End Function Function Fit() '--------------------- '約分 '--------------------- Dim L As Integer '最大公約数 L = Application.WorksheetFunction.Gcd(Va, Vb) Va = Va / L Vb = Vb / L End Function
ちょっと気持ちの悪いコードになってしまいましたが、今は考えたくないので書き直しは保留。
まとめ
コードは管理不細工ですが。
これで「ランダム作成した問題の答えを求める」ことができます。
次回は「答えから問題を書き換える」について書きます。