EXCELは2002ですが、97でも動くと嬉しいです。
《質問》
1~10をランダムに並べるためのプログラムを書きました。
これはこれで動くのですが、一行(3行目)だではなく
4行目にも、5行目にも同じことをしたい場合、
バブルソートの部分をサブルーチン(関数)にしたいのですが
X_v() = GetSortArray(n_s,n_v)()とはできません。.cloneもだめですよね。
かといって、要素毎に引くとその度にRndが効いて、1~10が並びません。
どのようにやるのが、スマートなのでしょうか?よろしくお願いします。
《以下プログラム》
Sub Bu_Click()
Dim i As Integer
Dim j As Integer
Const n_e = 10
Const n_s = 1
Dim X_r(n_e) As Long
Dim X_v(n_e) As Long
Dim temp1 As Long
Dim temp2 As Integer
Randomize
For i = n_s To n_e
X_r(i) = Int(Rnd * 10 ^ 9)
X_v(i) = i
Next i
For i = n_s To n_e - 1
For j = n_s To n_e - 1
If X_r(j + 1) < X_r(j) Then
temp1 = X_r(j + 1)
X_r(j + 1) = X_r(j)
X_r(j) = temp1
temp2 = X_v(j + 1)
X_v(j + 1) = X_v(j)
X_v(j) = temp2
End If
Next j
Next i
For i = 0 To n_e - 1
Cells(3, 3 + i).Value = X_v(i + 1)
Next i
End Sub
Public Function GetSortArray(s As Integer, e As Integer) As Long()
Dim r() As Long
Dim v() As Long
Dim temp1 As Long
Dim temp2 As Integer
ReDim r(e)
ReDim v(e)
Randomize
For i = s To e
r(i) = Int(Rnd * 10 ^ 9)
v(i) = i
Next i
For i = s To e - 1
For j = s To e - 1
If r(j + 1) < r(j) Then
temp1 = r(j + 1)
r(j + 1) = r(j)
r(j) = temp1
temp2 = v(j + 1)
v(j + 1) = v(j)
v(j) = temp2
End If
Next j
Next i
GetSortArray = v()
End Function
ありゃ?Tabのスペース消えますね。
No.1ベストアンサー
- 回答日時:
質問がちょっと分かりづらいのですが、以下のように変更してみました。
Sub Bu_Click()
Const n_e = 10
Const n_s = 1
Dim X_r() As Long
Dim X_v() As Long
'配列を引数として渡す
Call GetSortArray(n_s, n_e, X_r(), X_v())
For i = 0 To n_e - 1
Cells(3, 3 + i).Value = X_v(i + 1)
Next i
End Sub
Public Sub GetSortArray(s As Integer, e As Integer, r() As Long, v() As Long)
Dim temp1 As Long
Dim temp2 As Integer
ReDim r(e)
ReDim v(e)
Randomize
For i = s To e
r(i) = Int(Rnd * 10 ^ 9)
v(i) = i
Next i
For i = s To e - 1
For j = s To e - 1
If r(j + 1) < r(j) Then
temp1 = r(j + 1)
r(j + 1) = r(j)
r(j) = temp1
temp2 = v(j + 1)
v(j + 1) = v(j)
v(j) = temp2
End If
Next j
Next i
End Sub
あと
For j = s To e - 1
のところは
For j = s To e - i
にした方がちょっとだけ速くなります。
ありがとうございます。
これは97でも動きますね。
助かります。
要素をひとつずつ取り出すプログラムは
作ってみてだめだったのですが、
これ問題ないですね。う~ん、難しいです。
No.5
- 回答日時:
#3 です。
最初の質問の
> バブルソートの部分をサブルーチン(関数)にしたいのですが
> X_v() = GetSortArray(n_s,n_v)()とはできません。
については、
Sub Bu_Click()
Dim i As Integer
Const n_e As Integer = 10
Const n_s As Integer = 1
Dim X_v() As Long
X_v() = GetSortArray3(n_s, n_e)
For i = 0 To n_e - n_s
Cells(3, 3 + i).Value = X_v(i)
Next i
End Sub
↑で、要素をひとつずつ取り出して、動作すると思いますが。
また蛇足ですが、どのアルゴリズムを使うか、というより、
必要なのは v() だけなので、 r() もソートするのは無駄ではないかと、思いました。
そこで、今度は安定ソートで、、、
'変数はLong型に統一しました。
's As Integer, e As Integer なのに、GetSortArray As Long()なのは何故?
Function GetSortArray3(s As Long, e As Long) As Long()
Dim i As Long, j As Long
Dim r() As Long, v() As Long
Dim temp1 As Long, temp2 As Long
ReDim r(e - s), v(e - s)
Randomize
For i = 0 To e - s
r(i) = Int(Rnd * 10 ^ 9)
v(i) = i + s
Next i
'挿入ソートで、v() をソート、r() はソートしない
For i = 1 To e - s
temp1 = v(i): temp2 = r(temp1 - s)
For j = i - 1 To 0 Step -1
If temp2 >= r(v(j) - s) Then Exit For
v(j + 1) = v(j)
Next j
v(j + 1) = temp1
Next i
GetSortArray3 = v()
Erase r, v
End Function
皆様どうもありがとうございました。
乱数の話や、ソートアルゴリズムに関するご回答も大変参考になりました。
全員には、点数を差し上げられませんので、
大変心苦しいのですが、当初の質問は、関数(サブルーチン)の作り方であったこと。ご回答の順番。97への対応などで選択させて頂きます。
どうもありがとうございました。
No.4
- 回答日時:
こんにちは。
#2の回答者です。
>>r(i) = Rnd()
>↑これですと、私の環境(2002SP3)では
>1列目に『2や3』10列目に『10』が来る確率が高いです。
>なぜか『1』は真ん中当たり。(注 1~10を表示した場合)
調べてみましたが、確かに、少ない行数ですと、その傾向があるようです。
こちらが以前調べた範囲では、一様乱数に対しても、Rnd 関数は、ほぼ正規分布しているようです。どうも、Randomize の実行数が多すぎると問題が発生する可能性が強いのではないかと思います。ただ、その処置に関しては、お任せします。
資料:
http://support.microsoft.com/kb/828795/ja
Excel 2007 と Excel 2003 の RAND 関数について
http://support.microsoft.com/kb/28150/ja
RND と RANDOMIZE 方法の乱数を生成
実際、Excel 2003/2007に関して、サポートが言うほどに、新乱数生成ジェネレータでも、その乱数発生が完ぺきではないとは思っています。
私個人は、
int(Rnd()*10^9)
決定的なダメ出しがないと、変えられません。Rnd関数の代わりのNT乱数のアドインはあるのですが、それは万民むきではありません。
>e = e - s 'このままでは、-になるとだめですね。人にあげる訳ではないので良いか。
数の間の乱数を作るというなら、コードのが違います。
なお、配列変数は、ひとつにまとめようが、ふたつにしようが、ほとんど変わらないはずです。
'-------------------------------------------
Public Function GetSortArray(ByVal s As Integer, ByVal e As Integer) As Long()
Dim r() As Double
Dim v() As Long
Dim temp1 As Long
Dim temp2 As Integer
If s > e Then temp1 = e: s = e: e = temp1
ReDim r(e - s)
ReDim v(e - s)
Randomize
For i = 0 To e - s
r(i) = Rnd() 'お任せします。
v(i) = s + i
Next i
For i = 0 To e - s
For j = 0 To e - s - 1
If r(j + 1) < r(j) Then
temp1 = r(j + 1)
r(j + 1) = r(j)
r(j) = temp1
temp2 = v(j + 1)
v(j + 1) = v(j)
v(j) = temp2
End If
Next j
Next i
GetSortArray = v()
End Function
No.3
- 回答日時:
ランダムシャッフルですね?
Dim X_v() As Long '動的配列にして
X_v() = GetSortArray(n_s, n_e) '最後にカッコ()付けない
これで、ご希望の動作になるでしょう。
蛇足になるかもしれませんが、バブルソートで2つの配列を並び替えるのはスマート(?)ではないでしょう。
選択ソートのアルゴリズムを使って考えてみました。
Sub Bu_Click2()
Const n_e As Integer = 10
Const n_s As Integer = 1
Cells(3, 3).Resize(1, n_e - n_s + 1).Value = GetSortArray2(n_s, n_e)
'縦に出力する場合↓
'Cells(3, 3).Resize(n_e - n_s + 1).Value = WorksheetFunction.Transpose(GetSortArray2(n_s, n_e))
End Sub
Function GetSortArray2(s As Integer, e As Integer) As Integer()
Dim i As Integer, j As Integer, k As Integer
Dim r() As Long, v() As Integer
Dim temp1 As Long, temp2 As Integer
ReDim r(s To e), v(s To e)
Randomize
For i = s To e
r(i) = Int(Rnd * 10 ^ 9)
v(i) = i
Next i
For i = s To e - 1
temp1 = r(i): k = i
For j = i + 1 To e
If temp1 > r(j) Then
temp1 = r(j): k = j
End If
Next j
r(k) = r(i)
temp2 = v(k): v(k) = v(i): v(i) = temp2
Next i
GetSortArray2 = v()
End Function
ありがとうございます。
10個しかないので、バブルでもいいかなと思ったんですが
参考にします。
http://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%BC% …
ここで不安定と書いてあったので
あっ、備考みてなかった。
No.2
- 回答日時:
こんにちは。
ご自身が書いたコードではないのでしょうか。
良く分からないところがありますね。
>r(i) = Int(Rnd * 10 ^ 9)
Excel2002以下の乱数ジェネレータは精度が低いので、そのまま一様乱数をそのまま、Double 型で入れても良いと思うのですが、何か問題があったのでしょうか?
それと、もともと、Option Base 1 を使えばよいのですが、そうでないなら、配列変数の添え字を0から使ってもよいと思います。
Sub Bu_Click()
Dim i As Long
Dim ret As Variant
Const iST As Integer = 1
Const iED As Integer = 10
For i = 1 To 5 '5行出力
'縦に出力する可能性があるので変数ret を使う
ret = GetSortArray(iST, iED)
Cells(3 + i, 4).Resize(, UBound(ret) + 1).Value = ret
Next i
End Sub
Public Function GetSortArray(ByVal s As Integer, ByVal e As Integer) As Long()
Dim r() As Double
Dim v() As Long
Dim temp1 As Long
Dim temp2 As Integer
e = e - 1: s = s - 1 '0からに換える
ReDim r(e)
ReDim v(e)
Randomize
For i = s To e
r(i) = Rnd()
v(i) = i
Next i
For i = s To e
For j = s To e - 1
If r(j + 1) < r(j) Then
temp1 = r(j + 1)
r(j + 1) = r(j)
r(j) = temp1
temp2 = v(j + 1)
v(j + 1) = v(j)
v(j) = temp2
End If
Next j
Next i
GetSortArray = v()
End Function
この回答への補足
>Dim ret As Variant
> ret = GetSortArray(iST, iED)
> Cells(3 + i, 4).Resize(, UBound(ret) + 1).Value = ret
回答ありがとうございます。
↑こう書くものなのですね。ResizeとかUBoundとか初めて目にしました。
年に1回くらいしかVBA組まないので。(配列自体ほとんど使わない)
回答を参考に少し修正して、初期の目的を達成しました。ありがとうございます。
>r(i) = int(Rnd()*10^9)
この方がランダム性が良い気がします。(なんとなくですが)
>r(i) = Rnd()
↑これですと、私の環境(2002SP3)では
1列目に『2や3』10列目に『10』が来る確率が高いです。
なぜか『1』は真ん中当たり。(注 1~10を表示した場合)
《下記は、1~10だけでなく、2~11などにも対応》
Public Function GetSortArray(ByVal s As Integer, ByVal e As Integer) As Long()
Dim r() As Long
Dim v() As Long
Dim temp1 As Long
Dim temp2 As Integer
e = e - s 'このままでは、-になるとだめですね。人にあげる訳ではないので良いか。
ReDim r(e)
ReDim v(e)
Randomize
For i = 0 To e
r(i) = int(Rnd()*10^9)
v(i) = i + s
Next i
For i = 0 To e - 1
For j = 0 To e - 1
If r(j + 1) < r(j) Then
temp1 = r(j + 1)
r(j + 1) = r(j)
r(j) = temp1
temp2 = v(j + 1)
v(j + 1) = v(j)
v(j) = temp2
End If
Next j
Next i
GetSortArray = v()
End Function
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) エクセル マクロ(A1:A10)までの中で一番多く出た数字をB10に表示 6 2023/04/25 17:01
- Visual Basic(VBA) 数字が「0」の列を削除するため、下記のコードを実行しましたが、コンパイルエラーSubまたはFunct 3 2022/12/04 00:00
- Excel(エクセル) VBAの指示の内容 昨日こちらでご教示頂いたのですが初心者な為、一つ一つの指示が何をやっているのかわ 2 2022/10/25 18:08
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
- Visual Basic(VBA) ①ExcelVBAでカレンダーを作り、別のユザーフォームで日付を入力したいのですがエラーになります。 1 2023/02/17 18:39
- Visual Basic(VBA) ExcelVBAに関する質問 3 2023/02/17 10:47
- Visual Basic(VBA) VBA処理追加 こちらでご教示頂いたのですが回答完了させてしまいましたのでこちらからまた質問させてく 2 2022/10/27 09:57
- Visual Basic(VBA) excel vbaでvlooupの変数がわかりません。 7 2022/05/30 09:35
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Visual Basic(VBA) 稀に1円合いません? Sheet1から金額と個数を貼り付ける下記コードで、金額を切り上げるコードを何 3 2022/09/05 15:11
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
スペイン語 Es que... の文と...
-
ブラジル/ポルトガル語で…
-
テキエロってどういう意味です...
-
Cachito (坊や)の歌詞の意味...
-
I was sorry. ってありですか?
-
答えはbetterなのですがなぜmor...
-
A or B の意味
-
角砂糖はフランス語で?
-
pon de~ の意味
-
トスティの歌曲「セレナータ」...
-
スペイン語、重複の目的格代名...
-
比較に表現の Nothing と No ot...
-
英語文法の質問です。 The pric...
-
【英文】どちらが正しいですか?
-
don't have~ と have not~...
-
スペイン語で「彼(彼女)と一...
-
not+比較級と、no+比較級に共...
-
no less than= as many as にな...
-
スペイン語で歯医者はdentista...
-
スペイン語!大至急お願いします!
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
テキエロってどういう意味です...
-
te amo とは… te amoってスペイ...
-
スペイン語でわからないところ...
-
ブラジル/ポルトガル語で…
-
スペイン語 Es que... の文と...
-
PCのウイルスについて
-
このフランス語の和訳を教えて...
-
スペイン語で 私はあなたのこと...
-
Excel VBAにて、SpecialCells(x...
-
スペイン語が出来る方助けて下...
-
スペイン語のわかる方、教えて...
-
not+比較級と、no+比較級に共...
-
比較に表現の Nothing と No ot...
-
There is no〜 There is not an...
-
don't have~ と have not~...
-
トスティの歌曲「セレナータ」...
-
Cachito (坊や)の歌詞の意味...
-
ローマ字の書き方
-
A or B の意味
-
洋楽の歌詞についての質問(Gho...
おすすめ情報