滝の音

滝の音

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

VBAで中学数学の問題を扱おう! その1 (単項式)×(単項式)の計算(前半)

こんばんは~。

VBAのことをブログに書いてからちょっとだけブログアクセス数が増えました。

ありがたいことです。

意外と需要があるのかな???

 

さて。

今回から数回にわたって「中学数学の問題を扱おう!」の記事を書きたいと思います。

 

ひとくちに中学数学といってもいろいろあると思いますが。。

今回はその中でも根幹に来るであろう「計算」について。

 

特に(単項式)×(単項式)について書きたいと思います。

今回からの記事ではできるだけコードについて説明を書いていこうと思っています。

 

とりあえずざっくりと単項式について定義して。

その後にいくつかのケースを解決するコードを書いてみようかなと。

 

  • 単項式って?

単項式は掛け算のみからなる式。

ということにしましょう!

 

  • ケース1  2×3

つまりは(数字)×(数字)ですね。

Sub ケース1()
 Dim siki(1) As Integer '扱う式を代入
 Dim answer As Integer  '答え
 siki(0) = 2
 siki(1) = 3
 answer = siki(0) * siki(1)
End Sub

 

ま。

この処理ができないのに今回のブログを書こうとは思わないですよねw

これで処理できますが。

とりあえずユーザーフォーム仕様にでもしよう。

。。。
Private Sub CB1_Click()
 Dim siki(1) As Integer '扱う式を代入
 Dim answer As Integer  '答え
 siki(0) = Val(TB1)
 siki(1) = Val(TB2)
 answer = siki(0) * siki(1)
 TB3 = answer
End Sub

 

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

テキストボックスを左からTB1,TB2,TB3

計算と表記されているコマンドボタンをCB1

と定義しています。

コード自体は最初に書いたものとほとんどおんなじです。

 

せっかく作ったことですし。

以降はユーザーフォームを使っていきましょうか。。

正直ユーザーフォームは初心者だからうまく使えるか不安。。

 

  • ケース2 2a×3

つまりは(文字式)×(数字)ですね。

文字式が入ってくると少しずつ難しくなってきます。。

まずはsikiとanswerをintegerからstringに変更します。

Dim siki(1) As String '扱う式を代入
 Dim answer As String  '答え
 siki(0) = TB1
 siki(1) = TB2

ここからはいろいろな処理方法があると思いますが。

僕が取ろうと思っている処理は。

 

それぞれの式を数字と文字に分ける。

数字同士を処理する。

文字同士を処理する。

 

です。

 

新しくmoji(1)とkazu(1)を定義します。

あとtrgtも定義します。これは処理用の仮箱?

 Dim trgt As String
 Dim kazu(1) As String
 Dim moji(1) As String

次にsiki(0)とsiki(1)をkazuとmojiに分けます。

一気に書くとわかりにくいのでとりあえずsiki(0)だけ処理しましょう。

 j = 0
 For i = 1 To Len(siki(j))
    trgt = Mid(siki(j), i, 1)
    If trgt Like "[a-z]" Then
        moji(j) = moji(j) & trgt
    Else
        kazu(j) = kazu(j) & trgt
    End If
 Next

次の処理を簡単に書くためにj=0として書きました。

中身にチラッと触れると。

 

trgtにsiki(0)の1文字目を入れる。

それがアルファベットだったらmojiに追加。

それ以外だったらkazuに追加。

 

です。

じつはこの処理にはめちゃくちゃ問題があるのですが。。。

少なくともケース2は処理できるので良しとします。

というか。

いきなり強すぎるコードを載せちゃうとつまらないですよねw

 

 For j = 0 To 1
    For i = 1 To Len(siki(j))
       trgt = Mid(siki(j), i, 1)
       If trgt Like "[a-z]" Then
           moji(j) = moji(j) & trgt
       Else
           kazu(j) = kazu(j) & trgt
       End If
    Next
 Next

 

これでsiki(0)とsiki(1)に処理を施しました。

次はmojiとkazuを処理します。

 answer = Val(kazu(0)) * Val(kazu(1))
 answer = answer & moji(0) & moji(1)

 

ちょっと横着しちゃいました。

とりあえずこれでケース2をクリア。

 

Private Sub CB1_Click()

 Dim siki(1) As String '扱う式を代入
 Dim answer As String  '答え
 
 siki(0) = TB1
 siki(1) = TB2
 
 Dim trgt As String     '処理用の箱
 Dim kazu(1) As String  '数を割り振る
 Dim moji(1) As String  '文字を割り振る
 
 For j = 0 To 1
    For i = 1 To Len(siki(j))
       trgt = Mid(siki(j), i, 1)
       If trgt Like "[a-z]" Then
           moji(j) = moji(j) & trgt
       Else
           kazu(j) = kazu(j) & trgt
       End If
    Next
 Next
 
 answer = Val(kazu(0)) * Val(kazu(1))
 answer = answer & moji(0) & moji(1)
 
 TB3 = answer
End Sub

 

  • ケース3 2b×ac

これは(文字式)×(文字式)

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

 

とりあえずケース2のコードで処理してみました。

ん???

いろいろ突っ込みどころがありますねw

 

まず本筋と違うところで。

画像が見にくいですねw

次から気をつけますw

 

次は本筋で。

 

なぜか数が0になっている。

文字の順番がアルファベット順になっていない。

 

2b×ac=2abc

でないとだめですよね。

 

逆に言うと上に書いた二つの問題をクリアすればケース3も合格なのですが。

 

まずは簡単なほうから修正しますか。

 

なぜか数が0になっていることから。

これは初期値が原因です。

kazuの初期値は""です。

今回はkazu(1)は""のまま。

そのせいでVal(kazu(0)) * Val(kazu(1))の結果が""になってしまいます。

解決策は初期値を変えること。

For i = 0 To 1
    If kazu(i) = "" Then
        kazu(i) = 1
    End If
 Next

。。。

うそついちゃいました。

初期値を変えるのはその後の処理が大きく変わってしまいそうなので。

未定義のkazuを1と定義することにしました。

 

2b×ac=2bac

修正1は完了。

 

次は文字をアルファベット順に並べます。

この解決策はわれながら頭いいなーと思っちゃいますw

なんちって

 

sikiの割り振りかたを大幅に変更。

moji(1)をmoji(1,26)と定義します。

26にピンとくるひともいるかな?

そう。アルファベットの数です。

siki(0)について

一文字ずつ処理。

もしも数字だったら今までどおりkazuに入れる。

もしも文字だったら。

aならmoji(0,1)に、cからmoji(0,3)に、xならmoji(0,24)に入れる。

 Dim tmp As Integer
 For j = 0 To 1
    For i = 1 To Len(siki(j))
       trgt = Mid(siki(j), i, 1)
       If trgt Like "[a-z]" Then
           tmp = Asc(trgt) - 96
           moji(j, tmp) = moji(j, tmp) & trgt
       Else
           kazu(j) = kazu(j) & trgt
       End If
    Next
 Next

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

 

ローカルウィンドウを見るとこんな感じになります。

この処理方法は。。

 Dim pre As String
 For i = 1 To 26
    pre = pre & moji(0, i) & moji(1, i)
 Next

answer = Val(kazu(0)) * Val(kazu(1))
 answer = answer & pre

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

いえーい。

クリア。

もしかするとめちゃくちゃ効率の悪い定義法なのかもしれませんが。

これなら確実に文字をアルファベット順に処理できます。

 

あー。

ついでにkazuの処理も変更しますか。

kazuという変数を除去してmoji(0,0)とmoji(1,0)に代用させます。

これは表記の問題なのですが変数は少ないほうが何かと楽かなと思います。

こうするとmojiという変数で数字を処理するのも気持ち悪いので。

moji(1,26)をelement(1,26)に変更しましょう。

 

ケース3を処理するコード。

Private Sub CB1_Click()

 Dim siki(1) As String '扱う式を代入
 Dim answer As String  '答え
 
 siki(0) = TB1
 siki(1) = TB2
 
 Dim trgt As String             '処理用の箱
 Dim tmp As Integer             '処理用の箱
 Dim element(1, 26) As String   '数と文字を割り振る
 
 For j = 0 To 1
    For i = 1 To Len(siki(j))
       trgt = Mid(siki(j), i, 1)
       If trgt Like "[a-z]" Then
           tmp = Asc(trgt) - 96
           element(j, tmp) = element(j, tmp) & trgt
       Else
           element(j, 0) = element(j, 0) & trgt
       End If
    Next
 Next
 
 '未定義のkazuを1と定義
 For i = 0 To 1
    If element(i, 0) = "" Then
        element(i, 0) = 1
    End If
 Next
 
 Dim pre As String
 
 For i = 1 To 26
    pre = pre & element(0, i) & element(1, i)
 Next
 
 answer = Val(element(0, 0)) * Val(element(1, 0))
 answer = answer & pre
 
 TB3 = answer
End Sub

 

ちょっと疲れてきたので。

今日はここまで。

一気に書くつもりでしたが。。

後半は後日ということで。。