C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[10]: 関数作成


(過去ログ 25 を表示中)

[トピック内 33 記事 (1 - 20 表示)]  << 0 | 1 >>

■10989 / inTopicNo.1)  関数作成
  
□投稿者/ ハツ (1回)-(2007/12/03(Mon) 20:57:19)

分類:[C#] 


組み合わせ関数をC#言語で作成したいです。

「あ い う」 なら 「あい あう いう あ い う あいう」の7個を返すもので
「あ い う え」なら15個返す関数を作成したいんですが、数時間考えましたが、
一つ一つ作る三つの場合、四つの場合などのロジックしか思いつきません
まとめて 三つの場合でもいくつでも出せる方法を教えてください

お願いします


引用返信 編集キー/
■10990 / inTopicNo.2)  Re[1]: 関数作成
□投稿者/ Jitta on the way (48回)-(2007/12/03(Mon) 21:19:34)
No10989 (ハツ さん) に返信
>
> 組み合わせ関数をC#言語で作成したいです。
>
> 「あ い う」 なら 「あい あう いう あ い う あいう」の7個を返すもので
> 「あ い う え」なら15個返す関数を作成したいんですが、数時間考えましたが、
> 一つ一つ作る三つの場合、四つの場合などのロジックしか思いつきません
> まとめて 三つの場合でもいくつでも出せる方法を教えてください
>
> お願いします
>
>

あいう を、横に並べます
「あ」がペアになれるのは、なし、「い」と「う」です
なしはそのまま終わり
「あい」がペアになれるのは、なし、「う」です

ペアを探すところを再入可能なメソッドとすれば、上記のようなアルゴリズムで実装できます。


再入可能なメソッド:自分を呼び出すことができるメソッド
引用返信 編集キー/
■10992 / inTopicNo.3)  Re[2]: 関数作成
□投稿者/ επιστημη (701回)-(2007/12/03(Mon) 22:04:44)
επιστημη さんの Web サイト
N文字あるとき、1〜2^N-1 の数を二進表現にすりゃいいんじゃね?

あいう
001 = う
010 = い
011 = いう
100 = あ
101 = あう
110 = あい
111 = あいう

引用返信 編集キー/
■10996 / inTopicNo.4)  Re[3]: 関数作成
□投稿者/ ハツ (2回)-(2007/12/04(Tue) 00:33:40)
No10992 (επιστημη さん) に返信
> N文字あるとき、1〜2^N-1 の数を二進表現にすりゃいいんじゃね?
>
> あいう
> 001 = う
> 010 = い
> 011 = いう
> 100 = あ
> 101 = あう
> 110 = あい
> 111 = あいう
すみません、上のは例えばの話です。
数字 「1 2 3 4 5」だろうが、文字「あいうえお ああああ ううう」だろうがなんだろうがです。
組み合わせの所のみ見ていただきたいです。お願いします
引用返信 編集キー/
■10999 / inTopicNo.5)  Re[4]: 関数作成
□投稿者/ カンタービレ (110回)-(2007/12/04(Tue) 01:16:25)
2007/12/04(Tue) 01:37:31 編集(投稿者)
No10996 (ハツ さん) に返信
> ■No10992 (επιστημη さん) に返信
>>N文字あるとき、1〜2^N-1 の数を二進表現にすりゃいいんじゃね?
>>
> すみません、上のは例えばの話です。
> 数字 「1 2 3 4 5」だろうが、文字「あいうえお ああああ ううう」だろうがなんだろうがです。
> 組み合わせの所のみ見ていただきたいです。お願いします

って、επιστημηサマの例もご自身の例えに置き換えればいいだけだと思いマスよ・・・。
例の「あ」が「あいうえお」だろうがなんだろうが、じゃないデスか。

例なので、敢えてVB.NETでεπιστημηサマの例をコード化してみました。
#ちょうど立ち上げてたのがVBだったのもありマスが。

   '// TextBox1に「あいうえお ああああ ううう」だろうがなんだろうがスペース区切りで入れてマス。
    Dim str() As String = Me.TextBox1.Text.Split(" ".ToCharArray)    '// 配列化
    Dim len As Long = str.Length     '// パターンの個数デス。
    Dim max As Long = 2 ^ len - 1    '// 2のべき乗(len)−1でパターン数を出しマス。 
    Dim arr(max - 1) As String       '// パターンを入れる配列デス。
    '// パターン数だけループしマス。
    For i As Long = 1 To max
        '// 2進表現にすりゃいいんじゃね部分のためのビット判定デス。
        For j As Long = len - 1 To 0 Step -1
            '// ビットが立っていればその対応する文字を加えマス。
            arr(i - 1) = IIf((i And 1 << j), str(j), "").ToString & arr(i - 1)
        Next j
    Next i

# おっしゃってる内容を、επιστημηサマのロジックに置き換えて、ぱっと書いたらこんな感じ・・(汗)
# 私はアルゴリズムの質問だと思って見てたのデスが、なんか違うコトだったのかしら。。

【追記】コードにコメントいれマス。このビット判定も数に限界ありマスね。

引用返信 編集キー/
■11000 / inTopicNo.6)  Re[4]: 関数作成
□投稿者/ mあ@反省中 (28回)-(2007/12/04(Tue) 01:17:24)
No10996 (ハツ さん) に返信
> ■No10992 (επιστημη さん) に返信
>>N文字あるとき、1〜2^N-1 の数を二進表現にすりゃいいんじゃね?
>>
>>あいう
>>001 = う
>>010 = い
>>011 = いう
>>100 = あ
>>101 = あう
>>110 = あい
>>111 = あいう
> すみません、上のは例えばの話です。
> 数字 「1 2 3 4 5」だろうが、文字「あいうえお ああああ ううう」だろうがなんだろうがです。

納得行かない回答だからってお前らわかってねーな、みたいな発言は良くないです。

> 組み合わせの所のみ見ていただきたいです。お願いします

だから上の例でいいんじゃないのかな?

(1)入力文字列を区切り文字単位で分割する。
(2)N番目とN+1...終わりまでを文字列連結し順番に ArrayList に格納する。
(3)(2)が終わったら、N+1 番目と N+2 ... 終わり。。。を繰り返す。


で完成。文字がいくつあっても同じ処理で全ての組み合わせを List で返却できますね。

(1)で取得した配列の参照位置をちょこちょこずらしながらループ回すだけでできちゃいますよね。

入力が string input = "あ い う えお かき";

string[] array = input.split(",");

for (int i=0;i < array.length-1;i++) {
   string src = array[i];
   for (int j=i+1;j < array.length;j++) {
      arrayList.add( src + array[j] );
   }
}
//
//1文字ずつListに格納する。

//全部連結したものを最後に付加する。

完成!

array[0] と array[1] => あい
array[0] と array[2] => あう
array[0] と array[3] => あえお
array[0] と array[4] => あかき
array[1] と array[2] => いう
array[1] と array[3] => いえお
...

なんかよサゲな感じがしませんか?





引用返信 編集キー/
■11001 / inTopicNo.7)  Re[5]: 関数作成
□投稿者/ カンタービレ (111回)-(2007/12/04(Tue) 03:50:37)
2007/12/04(Tue) 04:09:12 編集(投稿者)

No11000 (mあ@反省中 さん) に返信
> (1)入力文字列を区切り文字単位で分割する。
> (2)N番目とN+1...終わりまでを文字列連結し順番に ArrayList に格納する。
> (3)(2)が終わったら、N+1 番目と N+2 ... 終わり。。。を繰り返す。
>
>
> で完成。文字がいくつあっても同じ処理で全ての組み合わせを List で返却できますね。
>
> (1)で取得した配列の参照位置をちょこちょこずらしながらループ回すだけでできちゃいますよね。
>
> 入力が string input = "あ い う えお かき";
>
> string[] array = input.split(",");
>
> for (int i=0;i < array.length-1;i++) {
> string src = array[i];
> for (int j=i+1;j < array.length;j++) {
> arrayList.add( src + array[j] );
> }
> }
> //
> //1文字ずつListに格納する。
>
> //全部連結したものを最後に付加する。

これだけの説明だと、「あいうえおかき」まで作る部分がないというか足りなくないデス?
2つの要素の連結という部分は満たされるかも知れませんが、Jittaサマのいう再帰部分がないというか。。

あ、あと最初の例で
> 「あ い う」 なら 「あい あう いう あ い う あいう」の7個
とありマスが、「いあ」とか「うあ」とか逆はなくてもいいのかしら・・・。
引用返信 編集キー/
■11002 / inTopicNo.8)  Re[2]: 関数作成
□投稿者/ れい (259回)-(2007/12/04(Tue) 07:08:20)
つっこませてください。

No10990 (Jitta on the way さん) に返信
> ペアを探すところを再入可能なメソッドとすれば、上記のようなアルゴリズムで実装できます。
> 再入可能なメソッド:自分を呼び出すことができるメソッド

再入じゃなくて再帰です。
自分自身を呼ぶのは再帰的な関数。recursive。
他のスレッドから同時に入ってもOKなのが再入可能な関数。reentrant。
引用返信 編集キー/
■11004 / inTopicNo.9)  Re[3]: 関数作成
□投稿者/ Jitta on the way (49回)-(2007/12/04(Tue) 07:58:34)
No11002 (れい さん) に返信
> つっこませてください。
>
> ■No10990 (Jitta on the way さん) に返信
>>ペアを探すところを再入可能なメソッドとすれば、上記のようなアルゴリズムで実装できます。
>>再入可能なメソッド:自分を呼び出すことができるメソッド
>
> 再入じゃなくて再帰です。
> 自分自身を呼ぶのは再帰的な関数。recursive。
> 他のスレッドから同時に入ってもOKなのが再入可能な関数。reentrant。

すんません
携帯が「さいき」を変換できなく、「き」の漢字に自信がなかったんですorz 漢字の勉強してきます...
引用返信 編集キー/
■11005 / inTopicNo.10)  Re[4]: 関数作成
□投稿者/ επιστημη (702回)-(2007/12/04(Tue) 08:49:50)
επιστημη さんの Web サイト
No10996 (ハツ さん) に返信
>>001 = う
>>010 = い
>>011 = いう
>>100 = あ
>>101 = あう
>>110 = あい
>>111 = あいう
> すみません、上のは例えばの話です。
> 数字 「1 2 3 4 5」だろうが、文字「あいうえお ああああ ううう」だろうがなんだろうがです。
> 組み合わせの所のみ見ていただきたいです。お願いします

答えはとっくに出てるやん。
僕の示したヤツは 0番目の1を"あ" / 1番目の1を"い" / 2番目の1を"う" に対応付けてます。
"対応表を取りかえるダケ"やないのん?

引用返信 編集キー/
■11019 / inTopicNo.11)  Re[6]: 関数作成
□投稿者/ いしだ (66回)-(2007/12/04(Tue) 18:39:33)
こんにちは。

> これだけの説明だと、「あいうえおかき」まで作る部分がないというか足りなくないデス?

これは、

>>//全部連結したものを最後に付加する。

の部分でしょうね。

むしろ、「あうかき」等がカバーできてなさそうです。


>>「あ い う」 なら 「あい あう いう あ い う あいう」の7個
> とありマスが、「いあ」とか「うあ」とか逆はなくてもいいのかしら・・・。
最初の例の提示では、逆は無くてもよさそうですね。
引用返信 編集キー/
■11026 / inTopicNo.12)  Re[4]: 関数作成
□投稿者/ yamyam (10回)-(2007/12/05(Wed) 09:34:54)
2007/12/05(Wed) 10:43:53 編集(投稿者)

No10999 (カンタービレ さん) に返信

> 【追記】コードにコメントいれマス。このビット判定も数に限界ありマスね。
BitArrayクラスを...と思ったらシフト演算子が無い...。
継承してoperatorを...と思ったら継承が禁止されてた...。

シフト用の関数作って引数にBitArrayを放り込むか...とも思ったんですが、
今回の使い方くらいなら自分でビット管理用クラスを作っても良いかもしれないですね。

# いっそのことBoolean型の配列かListを代用するとか
# メモリの無駄使いですか?

[追記]
# あれ?シフト演算使わなくてもいいのか?インクリメント/デクリメントでのビット変化が表現できればいいだけなんだ。
引用返信 編集キー/
■11030 / inTopicNo.13)  Re[5]: 関数作成
□投稿者/ カンタービレ (115回)-(2007/12/05(Wed) 12:47:54)
> [追記]
> # あれ?シフト演算使わなくてもいいのか?インクリメント/デクリメントでのビット変化が表現できればいいだけなんだ。

デスね。パっと思いつくままに書いたものデスから、このコードそのままだと制限ありマス、
という意味で追記しました。
スレ主サマからのアクションがまだなので、伝わったかどうか不安なところもありマスが
表現方法は様々あるうちの一つとして見てもらえたらなと思いました。
引用返信 編集キー/
■11049 / inTopicNo.14)  Re[6]: 関数作成
□投稿者/ taguo (1回)-(2007/12/05(Wed) 23:36:18)
(空気を読まずに?)LINQで。

数が固定なら
foreach( var a in
from q in new[] { "あ", "" }
from w in new[] { "い", "" }
from e in new[] { "う", "" }
select q + w + e )
Console.WriteLine( a );

可変だと
foreach( var a in
"あ,い,う".Split( ',' )
.Select( s => new []{ s, "" }.AsEnumerable() )
.Aggregate( ( a1, a2 ) => from q in a1 from w in a2 select q + w ) )
Console.WriteLine( a );

引用返信 編集キー/
■11078 / inTopicNo.15)  Re[7]: 関数作成
□投稿者/ ID非公開 (1回)-(2007/12/06(Thu) 15:24:52)
 初めて投稿します。

 επιστημη さんのアルゴリズムで書いていけばよいと思います。
(私にはとても考え付きませんでした・・・)

> N文字あるとき、1〜2^N-1 の数を二進表現にすりゃいいんじゃね?
> 
> あいう
> 001 = う
> 010 = い
> 011 = いう
> 100 = あ
> 101 = あう
> 110 = あい
> 111 = あいう


ちなみに、
>【追記】コードにコメントいれマス。このビット判定も数に限界ありマスね。


 この点は問題ないと思います。
 なぜなら、32ビットでも組み合わせの数は40億通りを越えるので、
 結果を格納する文字列のサイズが4GBを遥かに超えてしまうためです。


 ためしに作ってみたコードを提示します(VBですが・・・)

 この関数は
「あ い う え」を渡すと
「あ い あい う あう いう あいう え あえ いえ あいえ
 うえ あうえ いうえ あいうえ」を返します。


   Public Shared Function Sample01(ByVal input As String) As String

        '全角スペースは半角に変換
        input = input.Replace(" ", " ")

        '配列に分割(空要素は入らない)
        Dim sep() As String = {" "}
        Dim Allinput() As String = input.Split(sep, StringSplitOptions.RemoveEmptyEntries)

        Dim cnt As Integer = Allinput.Length
        If cnt >= 33 Then Throw New ArgumentException("要素の数は32個以内にしてください")
        Dim sb As New StringBuilder

        'ここからメインの処理
        For src As UInt32 = 1 To Convert.ToUInt32(2 ^ cnt - 1)

            Dim mask As UInt32 = 1

            For i As Integer = 1 To cnt

                'ビットが立っていれば文字を追加
                If (src And mask) = mask Then
                    sb.Append(Allinput(i - 1))
                End If
                '型変換しないとエラーになる(なぜ?)
                mask = Convert.ToUInt32(mask * 2)

            Next

            sb.Append(" ")

        Next

        Return sb.ToString

    End Function


以上です。

引用返信 編集キー/
■11079 / inTopicNo.16)  Re[8]: 関数作成
□投稿者/ PATIO (1回)-(2007/12/06(Thu) 16:07:15)
要するにやりたい処理のパターン化が出来れば良いわけなので
既に御自分であげれられている処理例を見本に処理のパターン化を
試みれば良いわけですね。

パターン化が出来れば、組み合わせる物がどんな物でも基本的には
対応できるはずなのでそこは応用になります。

επιστημη さんのが一番整理されていてわかりやすいような気が
します。あとはその処理パターンにどうやって載せていくかだけですし。

直接の答えを求めるはどうかなぁ。
提示されたものを見てロジックパターンの括り出しができるなら
それも有りでしょうけれど、あんまり身にならないような気もします。
勉強でやっているならみんなのアドバイスを元にしてロジックの
パターン化をやって見たほうが良いと思いますよ。

引用返信 編集キー/
■11084 / inTopicNo.17)  Re[1]: 関数作成
□投稿者/ IIJIMAS (60回)-(2007/12/06(Thu) 16:45:57)
No10989 (ハツ さん) に返信

私もεπιστημη さんの■No10992の書き込みで解決ではと思ったので書き込みしてませんでしたが、まだ残っているので書き込みしてみるテスト。

> 一つ一つ作る三つの場合、四つの場合などのロジックしか思いつきません

その三つの場合、四つの場合の思いついたコードを掲載してていただければ、より早い段階でその考え方の方向で一般化したコードまたは考え方を誰かが掲載してくれたのではないでしょうか。

あと、質問内容がわかるように適切なタイトルつけてください。
引用返信 編集キー/
■11087 / inTopicNo.18)  Re[2]: 関数作成
□投稿者/ とおりすがり (4回)-(2007/12/06(Thu) 17:51:40)
2007/12/06(Thu) 17:53:11 編集(投稿者)
再帰パターンの実装例。見づらい!
多重Listにしなければもう少し判りやすかっただろうけど、汎用性も希望にあわせてみました。

	private void button1_Click(object sender, EventArgs e)
	{
		List<string> t = new List<string>(new string[]{"あ", "い", "う", "え"});
		List<List<string>> r = Combinatorial(t, Int32.MaxValue);
		foreach (List<string> v in r)
		{
			string ss = "";
			foreach (string s in v)
			{
				ss += s;
			}
			Debug.Print(ss);
		}
	}

	private List<List<string>> Combinatorial(IList<string> src, int nCount)
	{
		List<List<string>> resultCombi = new List<List<string>>();
		if (nCount > 0)
		{
			if (nCount > 1)
			{
				if (nCount > src.Count)
				{
					nCount = src.Count;
				}
				List<List<string>> parentCombi = Combinatorial(src, nCount - 1);
				resultCombi.AddRange(parentCombi);
				foreach (List<string> oneOfPattern in parentCombi)
				{
					List<string> clonePattern = new List<string>(oneOfPattern);
					clonePattern.Add(src[nCount - 1]);
					resultCombi.Add(clonePattern);
				}
			}
			resultCombi.Add(new List<string>(new string[] { src[nCount - 1] }));
		}
		return resultCombi;
	}

引用返信 編集キー/
■11093 / inTopicNo.19)  Re[8]: 関数作成
□投稿者/ カンタービレ (117回)-(2007/12/06(Thu) 20:49:50)
No11078 (ID非公開 さん) に返信
> >【追記】コードにコメントいれマス。このビット判定も数に限界ありマスね。
>
>  この点は問題ないと思います。
>  なぜなら、32ビットでも組み合わせの数は40億通りを越えるので、
>  結果を格納する文字列のサイズが4GBを遥かに超えてしまうためです。
>
> If cnt >= 33 Then Throw New ArgumentException("要素の数は32個以内にしてください")

問題ないかどうかを決めるのは私ではないので、33個以上の要素数を処理するには
それなりにコードを考える必要がありマスよ、という意味で「限界」と書いたつもりでした。

最初に
> まとめて 三つの場合でもいくつでも出せる方法を教えてください
いくつでもって・・・書いてるんデスもん。。
引用返信 編集キー/
■11096 / inTopicNo.20)  Re[9]: 関数作成
 
□投稿者/ れい (267回)-(2007/12/06(Thu) 21:37:55)
No11093 (カンタービレ さん) に返信
> いくつでもって・・・書いてるんデスもん。。

じゃあカウンターはLong型じゃなくてBigInteger型にしないと!
引用返信 編集キー/

次の20件>
トピック内ページ移動 / << 0 | 1 >>

管理者用

- Child Tree -