Imports System.Text
Imports System.Windows.Forms
Imports System.Collections.Generic
Public Class Q7112984
Inherits Form
REM IDEで作るとこの辺が別ファイルになったり、開発者の意識から外されるでしょ?
REM 個人的にそうやって隠すのあまり好きじゃないんだよなー
Private label1 As Label
Private label2 As Label
Private textbox1 As TextBox
Private button1 As Button
REM 自分で検査する必要がなくなるので個人的には単なるテキストボックスよりこっちのほうが好み。
Private numberofAllItems As NumericUpDown
Private numberofSelectedItems As NumericUpDown
Public Sub New()
REM そのうちResourceManagerを用いる。
REM コントロールの配置は適当に配置。
Me.Text = "並び順サーチ"
numberofAllItems = New NumericUpDown()
numberofAllItems.AutoSize = false
numberofAllItems.Value = 6
numberofAllItems.Minimum = 0
numberofAllItems.Increment = 1
numberofAllItems.Left = 0
numberofAllItems.Width = 100
label1 = New Label()
label1.AutoSize = false
label1.Text = "個の中から"
label1.Left = 100
label1.Width = 100
REM わかりやすいインターフェースを提供できるなら
REM AllItemsの最大値をこちらの最大値として設定すべきだが
REM 下手に手を出すと分かりにくくなったり使いづらくなったりするので俺は敢えて設定しない。
numberofSelectedItems = New NumericUpDown()
numberofSelectedItems.AutoSize = false
numberofSelectedItems.Value = 3
numberofSelectedItems.Minimum = 0
numberofSelectedItems.Increment = 1
numberofSelectedItems.Left = 200
numberofSelectedItems.Width = 100
label2 = New Label()
label2.AutoSize = false
label2.Left = 300
label2.Width = 100
label2.Text = "個選んで並び替える"
button1 = New Button()
button1.AutoSize = false
button1.Text = "計算"
button1.Top = 50
button1.Left = 0
button1.Width = 100
textBox1 = New TextBox()
textBox1.AutoSize = false
textBox1.MultiLine = true
textBox1.Left = 0
textBox1.Top = 100
textBox1.Width = 300
textBox1.Height = 300
AddHandler Button1.Click,AddressOf Button1_Click
Me.Controls.Add(numberofAllItems)
Me.Controls.Add(label1)
Me.Controls.Add(numberofSelectedItems)
Me.Controls.Add(label2)
Me.Controls.Add(button1)
Me.Controls.Add(textbox1)
End Sub
Private Sub Button1_Click(sender As Object,e As System.EventArgs)
REM 何か加算演算子で改行加えるのってソースコード汚くなりやすいんだもん。
REM なら、例外の方もなおせよ(笑)>俺
Dim sb As StringBuilder = New StringBuilder()
Dim p As Permutation = New Permutation(Convert.ToInt32(numberofAllItems.Value),Convert.ToInt32(numberofSelectedItems.Value))
Dim list As List(Of List(Of Integer)) = New List(Of List(Of Integer))
While True
Dim x As List(Of Integer) = p.GetNext()
If x Is Nothing
Exit While
End If
list.Add(x)
End While
REM ラムダ式使っている以上気にする必要がないはずの範囲だけれど
REM .NET 2.0環境で実行したときにString.Join(String separator,params Object[])が
REM 選択され、Listが表示された痛い経験から、配列のオーバーロードを使いたがる。
For Each numbers As List(Of Integer) in list
REM この辺も何とかしたい
sb.AppendLine("{" + String.Join(",",numbers.ConvertAll(Function(i As Integer) i.ToString()).ToArray()) + "}")
Next
textbox1.Text = sb.ToString()
MessageBox.Show(list.Count.ToString())
End Sub
Public Shared Sub Main()
Dim form1 As Q7112984 = New Q7112984()
form1.ShowDialog()
End Sub
End Class
Class Permutation
Private x As List(Of Integer)
Private n As Integer
Private m As Integer
Public Sub New(n1 As Integer,m1 As Integer)
REM そのうち文字列操作を考えなくていい形にしたい。
If n1 < 1 Then
Throw New ArgumentException("nは1より大きくなれければなりません。" + "(n) = " + n.ToString())
End If
If m1 < 1 Then
Throw New ArgumentException("mは1より大きくなれければなりません。" + "(m) = " + m.ToString())
End If
If m1 > n1 Then
Throw New ArgumentException("mがnより大きいです。" + "(m,n) = (" + m.ToString() + "," + n.ToString() + ")")
End If
n = n1
m = m1
x = New List(Of Integer)
For i As Integer = 0 to m-1
x.Add(0)
Next i
End Sub
Public Function GetNext() As List(Of Integer)
Dim retval As List(Of Integer) = New List(Of Integer)(x)
While True
retval(retval.Count-1) = retval(retval.Count-1) + 1
For i As Integer = retval.Count - 1 to 1 Step -1
If retval(i) >= n Then
retval(i) = 0
retval(i - 1) = retval(i - 1) + 1
Else
Exit For
End If
Next
If retval(0) = n Then
Return Nothing
End If
REM VB.NETの製品バージョンに依存するかも。
REM 拡張メソッドIEnumerable<TSource> Enumerable.Distinct(this IEnumerable<TSource> source)
REM なんかMonoDevelop + vbncでプロジェクト作ると、プラットフォーム「.NET 4.0」が選択できない
If retval.Distinct().Count = retval.Count Then
Exit While
End If
End While
x = retval
Return retval
End Function
End Class