VBAで中学数学の問題を扱おう! その3 同類項をまとめる
中学数学の問題を扱おうのその3は「足し算」です。
正確には「同類項をまとめる」ですが。
その1,2で単項式の掛け算を行いましたが
その知識を使う場面はあるだろうかないだろうか。。。
今回も簡単なケースを考えてそれを処理できるコードを書いていくようにします。
- 同類項をまとめるとは?
同じ文字式の単項式を
それらの係数を用いて計算する。
ということで。
- ケース1 3+8
方針としては。
式を単項式に分ける。
同類項をまとめる。
表記する。
という感じ。
式を単項式に分けるための仕組みは
前回の「文字式の仕分け」プロシージャに似ているのでそれをちょっと修正する感じで。
Sub 単項式への分解(trgt, kou)
Dim char As String '処理用の箱
Dim stock As Integer '処理用の箱
Dim n As Integer 'kouの数を指定
Dim minus As Integer '-の処理用の箱
minus = 1
n = 0
ReDim Preserve kou(n)
For j = 1 To Len(trgt)
char = Mid(trgt, j, 1)
Select Case Asc(char) - 96
Case -51 '-の場合
If n <> 0 Then
Call 項の切り替え(n, kou, stock, minus)
End If
minus = -1
Case -53 '+の場合
Call 項の切り替え(n, kou, stock, minus)
Case -48 To -39 '0~9の場合
stock = stock & Val(char)
Case -2 '^の場合
Case 1 To 26 'アルファベットの場合
Case Else
MsgBox "考慮されていない文字が入っています"
Stop
End Select
Next
n = UBound(kou)
kou(n) = stock * minus
End Sub
ーーーーーーーーーーーーーー
Sub 項の切り替え(n, kou, stock, minus)
n = UBound(kou)
kou(n) = stock * minus
stock = 0
minus = 1
ReDim Preserve kou(n + 1)
End Sub
ちょっと今回の処理には高級すぎるコードですが
変に劣化させて書くのもなーと思ったのでこんな感じに。
おそらくこの部分は最後まで大きな変化なく終えるでしょう。
前がんばったのでこれくらいはいいよねw
次は同類項をまとめる処理。
こちらは始めて書くコードなのでどんどん変化させていくことになるでしょう。
Sub 同類項をまとめる(kou, cul)
For i = 0 To UBound(kou)
cul = cul + Val(kou(i))
Next
End Sub
われながら低級なコードですが。
3+5+4-8みたいな複数の単項式の計算にも耐えられる設計なのはほめられるところ。
まとめてみると。
Private Sub CB1_Click()
Dim siki As String
Dim kou() As String
Dim cul As Integer
Dim answer As String
siki = TB1
trgt = siki
Call 単項式への分解(trgt, kou)
Call 同類項をまとめる(kou, cul)
answer = Format(cul)
TB2 = answer
End Sub
ーーーーーーーーーーーーーーーーーーー
Sub 単項式への分解(trgt, kou)
Dim char As String '処理用の箱
Dim stock As Integer '処理用の箱
Dim n As Integer 'kouの数を指定
Dim minus As Integer '-の処理用の箱
minus = 1
n = 0
ReDim Preserve kou(n)
For j = 1 To Len(trgt)
char = Mid(trgt, j, 1)
Select Case Asc(char) - 96
Case -51 '-の場合
If n <> 0 Then
Call 項の切り替え(n, kou, stock, minus)
End If
minus = -1
Case -53 '+の場合
Call 項の切り替え(n, kou, stock, minus)
Case -48 To -39 '0~9の場合
stock = stock & Val(char)
Case -2 '^の場合
Case 1 To 26 'アルファベットの場合
Case Else
MsgBox "考慮されていない文字が入っています"
Stop
End Select
Next
n = UBound(kou)
kou(n) = stock * minus
End Sub
Sub 項の切り替え(n, kou, stock, minus)
n = UBound(kou)
kou(n) = stock * minus
stock = 0
minus = 1
ReDim Preserve kou(n + 1)
End Sub
ーーーーーーーーーーーーーーーーー
Sub 同類項をまとめる(kou, cul)
For i = 0 To UBound(kou)
cul = cul + Val(kou(i))
Next
End Sub
- ケース2 a+2a
もうはいはいって感じですねw
前回起きた問題と大体同じ。
文字を認識する。
aの係数が1とする。
がクリアすべき問題。
今回のやり方はなんだか回りくどい感じがするのですが
現状の自分の力ではこれよりうまくかけないですね。。
まずは単項式に分解する際に一工夫。
文字への対応のためにstock_lineを足しました。
Sub 単項式への分解(trgt, kou)
Dim char As String '処理用の箱
Dim stock As Integer '処理用の箱
Dim stock_line As String '処理用の箱
Dim n As Integer 'kouの数を指定
Dim minus As Integer '-の処理用の箱
minus = 1
n = 0
ReDim Preserve kou(n)
For j = 1 To Len(trgt)
char = Mid(trgt, j, 1)
Select Case Asc(char) - 96
Case -51 '-の場合
If n <> 0 Then
Call 項の切り替え(n, kou, stock, stock_line, minus)
End If
minus = -1
Case -53 '+の場合
Call 項の切り替え(n, kou, stock, stock_line, minus)
Case -48 To -39 '0~9の場合
stock = stock & Val(char)
Case -2 '^の場合
Case 1 To 26 'アルファベットの場合
stock_line = stock_line & char
End Select
Next
n = UBound(kou)
kou(n) = Format(stock * minus) & "," & stock_line
End Sub
ーーーーーーーーーーーーーーーー
Sub 項の切り替え(n, kou, stock, stock_line, minus)
If stock = 0 Then stock = 1
If stock_line = "" Then stock_line = "0"
n = UBound(kou)
kou(n) = Format(stock * minus) & "," & stock_line
stock = 0
stock_line = ""
minus = 1
ReDim Preserve kou(n + 1)
End Sub
これによって
kou(0)=1,a
kou(1)=2,a
というように係数と文字式の間にカンマが入ります。
つぎにcoという配列を使ってkouの係数と文字式を別の箱に入れます。
これは次の処理を書きやすくするため。
次の処理とは。
同じ文字式の係数を計算すること。
この処理のこなし方が下手だなという気がするのですが
ちょっと改善の方法がわからないので今回はこんな感じで。
Sub 同類項をまとめる(kou)
Dim trgt As String
Dim tmp As Integer
Dim co() As String
Dim n As Integer
ReDim co(UBound(kou), 1)
For i = 0 To UBound(kou)
trgt = kou(i)
tmp = InStr(trgt, ",")
co(i, 0) = Mid(trgt, 1, tmp - 1)
co(i, 1) = Mid(trgt, tmp + 1)
Next
For j = 0 To UBound(kou) - 1
For i = j + 1 To UBound(kou)
If co(j, 1) = co(i, 1) Then
co(i, 0) = Val(co(i, 0)) + Val(co(j, 0))
co(j, 0) = ""
End If
Next
Next
n = 0
ReDim kou(n)
For i = 0 To UBound(co, 1)
If co(i, 1) <> "" Then
ReDim Preserve kou(n)
kou(n) = co(i, 1) & co(i, 2)
n = n + 1
End If
Next
End Sub
最後に計算結果を出すための関数restoration2について。
そのうち名前を変えるかもですw
シンプルな機能なのでコードを読んでください。
Function restoration2(kou) As String
For i = 0 To UBound(kou)
If Left(kou(i), 1) <> "-" And i > 0 Then
tmp = tmp & "+"
End If
tmp = tmp & kou(i)
Next
restoration2 = tmp
End Function
なんか。
うまく書けたーと思うことがあるんですが。
自分で条件を難しくしてそれをがんばってクリアしているだけなことがあって。
やっぱり格好いいコードはシンプルなんだろうなぁと思います。
今回のコードはぜんぜんシンプルじゃないw
最後にまとめると。
Private Sub CB1_Click()
Dim siki As String
Dim kou() As String
Dim cul As Integer
Dim answer As String
siki = TB1
trgt = siki
Call 単項式への分解(trgt, kou)
Call 同類項をまとめる(kou)
answer = restoration2(kou)
TB2 = answer
End Sub
ーーーーーーーーーーーーーーーーーーー
Sub 単項式への分解(trgt, kou)
Dim char As String '処理用の箱
Dim stock As Integer '処理用の箱
Dim stock_line As String '処理用の箱
Dim n As Integer 'kouの数を指定
Dim minus As Integer '-の処理用の箱
minus = 1
n = 0
ReDim Preserve kou(n)
For j = 1 To Len(trgt)
char = Mid(trgt, j, 1)
Select Case Asc(char) - 96
Case -51 '-の場合
If n <> 0 Then
Call 項の切り替え(n, kou, stock, stock_line, minus)
End If
minus = -1
Case -53 '+の場合
Call 項の切り替え(n, kou, stock, stock_line, minus)
Case -48 To -39 '0~9の場合
stock = stock & Val(char)
Case -2 '^の場合
Case 1 To 26 'アルファベットの場合
stock_line = stock_line & char
End Select
Next
n = UBound(kou)
kou(n) = Format(stock * minus) & "," & stock_line
End Sub
Sub 項の切り替え(n, kou, stock, stock_line, minus)
If stock = 0 Then stock = 1
If stock_line = "" Then stock_line = "0"
n = UBound(kou)
kou(n) = Format(stock * minus) & "," & stock_line
stock = 0
stock_line = ""
minus = 1
ReDim Preserve kou(n + 1)
End Sub
ーーーーーーーーーーーーー
Sub 同類項をまとめる(kou)
Dim trgt As String
Dim tmp As Integer
Dim co() As String
Dim n As Integer
ReDim co(UBound(kou), 1)
For i = 0 To UBound(kou)
trgt = kou(i)
tmp = InStr(trgt, ",")
co(i, 0) = Mid(trgt, 1, tmp - 1)
co(i, 1) = Mid(trgt, tmp + 1)
Next
For j = 0 To UBound(kou) - 1
For i = j + 1 To UBound(kou)
If co(j, 1) = co(i, 1) Then
co(i, 0) = Val(co(i, 0)) + Val(co(j, 0))
co(j, 0) = ""
End If
Next
Next
n = 0
ReDim kou(n)
For i = 0 To UBound(co, 1)
If co(i, 1) <> "" Then
ReDim Preserve kou(n)
kou(n) = co(i, 1) & co(i, 2)
n = n + 1
End If
Next
End Sub
ーーーーーーーーーーーーーーーーーーーー
Function restoration2(kou) As String
For i = 0 To UBound(kou)
If Left(kou(i), 1) <> "-" And i > 0 Then
tmp = tmp & "+"
End If
tmp = tmp & kou(i)
Next
restoration2 = tmp
End Function
- ケース3 2a^2 +4a^2
これが今回の最後かな。
現状のコードでは答えが空欄になってしまいます。
が。
ちょっとした工夫をするだけで簡単にクリアできます。
んー。
じゃあこれはクイズにしておきますw
興味のある方は考えてみてください。
あ。
コードを動かしていて気づいたのですが。
1bをbと表記するコードを入れ忘れていました。
じゃあそれの書き方もクイズにしておきます。
これは前回のブログでふれた気がするので気になる方は前回のものを読んでみてください。
今回は分数の処理は処理は省略で。
二項の計算なら見やすくかけるのですが
それより多い項数の計算は醜くなってしまうので。。。
ふう。
結構疲れてきました。。
また近いうちに。