質問: お世話になります。 かなり初歩的な質問になってしまいますが、お許し下さい。 0から19までの連続した値があるとし、そこから重複せずに 六つだけ取り出したいと思います。 やりたいことはたったこれだけなのですが、下記の条件を満たす方法で 実現したいと思っています。 1.コレクションなどの機能は使用しない 2.forやifなどといった、基本的な処理だけで実現したい 3.取得した後も、昇順に並んでいること 4.簡単なことだけに、極力コードを少なくしたい これでできればと思うのですが、なかなか良い方法が見つかりません。 私が自分で一つ考えてみたのは、 1.値を配列aに収める 2.乱数を使って、その並び方をシャッフルする 3.六つ分の配列bを作る 4.上から六つだけ取得し、aからbにforで入れていく 5.その配列をソートする というところまでは考えましたが、これだけのことをするのに 5ステップも費やすのがもったいなく思ってしまいます。 何より、一度シャッフルして再びソートするというのが無駄に思えてなりません。 これだけのことですが、もっと簡素に効率よく行える方法はありますでしょうか。 よろしくお願いします。 **転記(2016/4/13)** # 私(argus)の回答に対するコメントになっていますが、内容的に質問欄の方が良いかと思い転記します 不甲斐ない質問で、皆様に不快な思いをさせてしまい、申し訳ありません。 言語は今のところ、C# を使用して書いていますが、この C# は仮の土台で、 将来的には別の言語、Java、もしくは php に移植するつもりでいます。そういうこともあり、言語を絞らないで基本文系だけでというのもあり、またコレクションなどのクラスは重くなるため、少ないコードで実現できるなら、基本のアルゴリズムだけで済ませたかったというのも理由です。よって、Java にしろ php にしろ、コレクション系のものは使用できますが、『このクラスを使えば良い』というのではなく、アルゴリズム的に解決できる簡素な方法を模索しています。...さすがに、『20 の数字はどこからきたのか』というのには、返答のしようがありませんが。
回答: 以下の流れでソートしながら配列に流し込むシンプルなコードをC#で書いてみました。 1. 乱数の最大値を19→18→17...と減らしながら取得する 2. 取得済みの値より乱数の値が大きい場合は乱数をインクリメントして重複を回避する 3. 配列にソートしながら格納する コードを減らす意味でもバグを回避する意味でもコレクションやArray.Sortを使った方が良いと思いますが...。 ``` using System; using System.Linq; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { GetRandomArray(6).ToList().ForEach(i => Console.WriteLine(i)); Console.Read(); } /// /// 無作為に重複のない0-19の整数を任意の個数取得する /// /// 取得する数値の個数 /// private static int[] GetRandomArray(int count) { const int MAX_VALUE = 19; var result = new int[count]; var rnd = new Random(); for (var i = 0; i < count; i++) { //未設定の値として-1で初期化 result[i] = -1; //乱数の最大値をiに応じて減らしつつ、標本を取得 var sample = rnd.Next(MAX_VALUE + 1 - i); //配列の先頭からi個分の値をソートしながら埋めていく for (var j = 0; j <= i; j++) { if(result[j] < 0) { //未設定の値ならそのまま乱数をセット result[j] = sample; } else if(sample < result[j]) { //標本が配列の値より小さければ並べ替え var swap = result[j]; result[j] = sample; sample = swap; } else { //標本が配列の値より大きければインクリメントして重複を避ける sample++; } } } return result; } } } ```