滝の音

滝の音

名こそ流れてなお聞こえけれ

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

 

f:id:nozomi-hayashi:20180618064826g:plain

  • ケース2 a+2a

f:id:nozomi-hayashi:20180618064900g:plain

もうはいはいって感じですね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と表記するコードを入れ忘れていました。

じゃあそれの書き方もクイズにしておきます。

これは前回のブログでふれた気がするので気になる方は前回のものを読んでみてください。

 

f:id:nozomi-hayashi:20180618085212g:plain

 

 

今回は分数の処理は処理は省略で。

二項の計算なら見やすくかけるのですが

それより多い項数の計算は醜くなってしまうので。。。

 

ふう。

結構疲れてきました。。

 

次は(多項式)×(多項式)です。

また近いうちに。