最終講 卒業研究と卒業試験
第3話 課題2 9次ラテン方陣の作成
前話の課題の解答例
Public Class Form1
'変数の宣言と初期化
Dim a(3, 3) As Integer, x(9) As Integer, y(9) As Integer, s As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim ss as Integer
s = 0
DataGridView1.Rows.Clear()
h()
f(0)
DataGridView1.Rows.Add() '1行追加
'見出し表示
ss = Int(s /3)
DataGridView1(7,4 * (ss + 1)).Value() = "順"
DataGridView1(8,4 * (ss + 1)).Value() = "列"
DataGridView1(9,4 * (ss + 1)).Value() = "方"
DataGridView1(10,4 * (ss + 1)).Value() = "陣"
DataGridView1(11,4 * (ss + 1)).Value() = "総"
DataGridView1(12,4 * (ss + 1)).Value() = "数"
'総数表示
DataGridView1(13,4 * (ss + 1)).Value() = s
End Sub
Sub h()
For i = 0 To 8
x(i) = i Mod 3
y(i) = Int(i / 3)
Next
End Sub
Sub f(ByVal g As Integer)
If s = 100 Then Exit Sub '計算時間が膨大なので100個で止めている。
Dim h, sa, ss As Integer
For i = 0 To 8
a(y(g), x(g)) = i + 1
h = 1
If g > 0 Then
For j = 0 To g - 1
If a(y(j), x(j)) = a(y(g), x(g)) Then
h = 0
Exit For
End If
Next
End If
If h = 1 Then
If g + 1 < 9 Then
f(g + 1)
Else
sa = s Mod 3
ss = Int(s / 3)
For j = 0 To 2
If sa = 0 Then DataGridView1.Rows.Add() '1行追加
For k = 0 To 2
DataGridView1(k + 4 * sa, j + 4 * ss).Value = a(j, k)
Next
Next
If sa = 0 Then DataGridView1.Rows.Add() '1行追加
s = s + 1 '総数カウント
If s = 100 Then Exit Sub '計算時間が膨大なので100個で止めている。
End If
End If
Next
End Sub
End Class
(
注
VBAでは、Dim h, sa, ss As Integerにように宣言することが出来ませんので、
勘違いしていましたが、VB2010ではそのように宣言して問題がないことが、
わかりました。どのバージョンからまとめて宣言できるようになったかは知りませんが、
VC++に対抗するためにそう変えたのではないでしょうか。
ずっとだめだと思っていましたが、C言語のように
w = w + a
も
w += a
と簡略表現が許されています。
)
さらに、改良して計算時間が計測できるように変更したいと思います。
時刻を収納する変数はDateTime型です。したがいまして、
Dim 変数名 As DateTime
と宣言されます。
現在時刻はNowで取得できます。
例えば、時刻を収納する変数をhjとすれば、
hj = Now
です。
計算を始める前に現在の時刻を取得し、計算終了後にもう一度現在時刻を取得し、
2つの時刻差を秒単位で示せばいいことになります。
ですから、現在時刻を取得するDateTime型の変数は2つ用意しなければなりません。
そして、時刻差を収納する変数はTimeSpan型です。
ですから、変数宣言部分では
Dim hj, ow As DateTime, sa As TimeSpan, ss As Integer
などとしておきましょう。
尚、時刻差を収納する変数saを秒に変換するときは、sa.TotalSecondsとします。
では、コーティングを考えてみてください。
解答例は、例によって30行下。
Public Class Form1
'変数の宣言と初期化
Dim a(3, 3) As Integer, x(9) As Integer, y(9) As Integer, s As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim hj, ow As DateTime, sa As TimeSpan, ss As Integer
hj = Now
s = 0
DataGridView1.Rows.Clear()
h()
f(0)
ss = Int(s / 3)
DataGridView1.Rows.Add() '1行追加
DataGridView1(7, 4 * (ss + 1)).Value() = "順"
DataGridView1(8, 4 * (ss + 1)).Value() = "列"
DataGridView1(9, 4 * (ss + 1)).Value() = "方"
DataGridView1(10, 4 * (ss + 1)).Value() = "陣"
DataGridView1(11, 4 * (ss + 1)).Value() = "総"
DataGridView1(12, 4 * (ss + 1)).Value() = "数"
DataGridView1(13, 4 * (ss + 1)).Value() = s '総数表示
ow = Now
sa = ow - hj
DataGridView1(9, 4 * (ss + 1) + 1).Value() = "計"
DataGridView1(10, 4 * (ss + 1) + 1).Value() = "測"
DataGridView1(11, 4 * (ss + 1) + 1).Value() = "時"
DataGridView1(12, 4 * (ss + 1) + 1).Value() = "間"
DataGridView1(13, 4 * (ss + 1) + 1).Value() = sa.TotalSeconds '計測時間表示
End Sub
・
・
・
実行例
さて、9次ラテン方陣の解答例を示しましょう。
Public Class Form1
'変数の宣言と初期化
Dim a(9, 9) As Integer, x(81) As Integer, y(81) As Integer, s As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim hj, ow As DateTime, sa As TimeSpan
hj = Now
s = 0
DataGridView1.Rows.Clear()
h()
f(0)
DataGridView1.Rows.Add() '1行追加
DataGridView1(7, 10 * s).Value() = "順"
DataGridView1(8, 10 * s).Value() = "列"
DataGridView1(9, 10 * s).Value() = "方"
DataGridView1(10, 10 * s).Value() = "陣"
DataGridView1(11, 10 * s).Value() = "総"
DataGridView1(12, 10 * s).Value() = "数"
DataGridView1(13, 10 * s).Value() = s '総数表示
ow = Now
sa = ow - hj
DataGridView1.Rows.Add() '1行追加
DataGridView1(9, 10 * s + 1).Value() = "計"
DataGridView1(10, 10 * s + 1).Value() = "測"
DataGridView1(11, 10 * s + 1).Value() = "時"
DataGridView1(12, 10 * s + 1).Value() = "間"
DataGridView1(13, 10 * s + 1).Value() = sa.TotalSeconds '計測時間表示
End Sub
Sub h()
For i = 0 To 80
x(i) = i Mod 9
y(i) = Int(i / 9)
Next
End Sub
Sub f(ByVal g As Integer)
If s = 100 Then Exit Sub
Dim h As Integer
For i = 0 To 8
a(y(g), x(g)) = i + 1
h = 1
If x(g) > 0 Then
For j = 0 To x(g) - 1
If a(y(g), x(g)) = a(y(g), j) Then
h = 0
Exit For
End If
Next
End If
If h = 1 Then
If y(g) > 0 Then
For j = 0 To y(g) - 1
If a(y(g), x(g)) = a(j, x(g)) Then
h = 0
Exit For
End If
Next
End If
End If
If h = 1 Then
If g + 1 < 81 Then
f(g + 1)
Else
For j = 0 To 8
DataGridView1.Rows.Add() '1行追加
For k = 0 To 8
DataGridView1(k, j + 10 * s).Value = a(j, k)
Next
Next
DataGridView1.Rows.Add() '1行追加
s = s + 1
If s = 100 Then Exit Sub
End If
End If
Next
End Sub
End Class
実行例
変更点は、紺で示されています。配列の次数を変更し、
If g > 0 Then
For j = 0 To g - 1
If a(y(j), x(j)) = a(y(g), x(g)) Then
h = 0
Exit For
End If
Next
End If
が
If x(g) > 0 Then
For j = 0 To x(g) - 1
If a(y(g), x(g)) = a(y(g), j) Then
h = 0
Exit For
End If
Next
End If
If h = 1 Then
If y(g) > 0 Then
For j = 0 To y(g) - 1
If a(y(g), x(g)) = a(j, x(g)) Then
h = 0
Exit For
End If
Next
End If
End If
と変わっています。課題1では、行列の中に同じ数字が入ってはいけないという条件だったのに対して、
ラテン方陣では、行または列の中のみに同じ数字が入ってはいけないという条件だからです。
行または列に同じ数字が入らなければ、行列の中に同じ数字が入ってもよいのです。
前半
If x(g) > 0 Then
For j = 0 To x(g) - 1
If a(y(g), x(g)) = a(y(g), j) Then
h = 0
Exit For
End If
Next
End If
で行のチェックをしています。
後半
If h = 1 Then
If y(g) > 0 Then
For j = 0 To y(g) - 1
If a(y(g), x(g)) = a(j, x(g)) Then
h = 0
Exit For
End If
Next
End If
End If
で列のチェックを
同じものがあるとh = 0 となり、
If h = 1 Then
If g + 1 < 81 Then
f(g + 1)
Else
For j = 0 To 8
DataGridView1.Rows.Add() '1行追加
For k = 0 To 8
DataGridView1(k, j + 10 * s).Value = a(j, k)
Next
Next
DataGridView1.Rows.Add() '1行追加
s = s + 1
If s = 100 Then Exit Sub
End If
End If
が実行ず、ループが次に進むようになっています。
尚、皆さんFor i = 0 To 8の9とIf g + 1 < 81 Thenの81に注意して下さい。
行や列に入る数字(セルの内容)は1から9まで(a(y(g), x(g)) = i + 1 + 1があるので0から8は1から9までとなる)
であるのに対して、セル番号は0から80までです。
繰り返しますが、セル番号(セルのラベル)とセルの内容(セルに入る1から9までの数字)は明確に区別しないといけません。
明瞭に区別していないと、プログラムは訳のわからないものとなります。
さて、皆さん課題3
課題2に条件
C ブロックの数字が重複してはならない。
を付け加えてください。
に挑戦しましょう。
第2話へ 第4話へ
VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
数学研究室に戻る