質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.47%

  • Java

    14116questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

javanによる開発 重みのある配列をシャッフルして選択する

受付中

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,363

s36a

score 2

javaに関する質問なんですが,配列をシャッフルして選択された際に.
選択されたものに重みを付けて,2回目シャッフルする際に,
その重みを考慮した選択にするにはどのようにしたらよいでしょうか?

ちょっとイメージしにくいかもしれませんが,

例えば,1〜100の配列があった際に,シャッフルして10個の配列を選びます.
選択された10個の配列には重みを付けます.
そして,もう1回シャッフルする際に先ほど選択した10個の配列(重みのある)が出やすくするような感じにシャッフルをしたいのですが...

<追記>回答ありがとうございます.ちょっとやってみているのですが,ちょっとうまくいきません.


           ArrayList<Integer> list = new ArrayList<Integer>();
                    
    for ( int y = 0; y < 100; y++ ) {
                        list.add(y);
                    }

                    Collections.shuffle(list);

          for(int i=0; i<10; i++) {
                    int x = 0;
                    x = list.get(i);
                }


<追記2>
import java.util.*;
import java.lang.*;
import java.io.*;

public class Test1{
    public static void main(String []args){
    
        
        ArrayList<Integer>random = new ArrayList<Integer>();
        ArrayList<Integer> copy = new ArrayList<Integer>();
        
            for (int y = 0; y < 100; y++ ) {
                random.add(y);
            }
        
        
        System.out.println("1回目シャッフルした場合");
        Collections.shuffle(random);
        System.out.println(random);
        
        for(int f=0; f<10; f++) {
           int x_list   = random.get(f);
            copy.add(x_list);
            random.add(x_list);
        }
        
        System.out.println("1回目に採用する10個の数字は");
        System.out.println(copy);

        System.out.println("2回目行うときにランダムリストに1回目の数字を追加");
        System.out.println(random);
        
    
        }
    }

ここまでは書けました.やはり再度シャッフル際にリストから弾く場合はremoveを使うのでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • swordone

    2015/09/04 00:18

    すみません,具体例を挙げて説明していただけますか?

    キャンセル

  • s36a

    2015/09/05 00:23

    みなさんありがとうございます. 頑張ってやってみます!

    キャンセル

回答 4

+1

要素と重みをひも付けて管理するべきだと思います.そのためのクラスを用意します.
下記のコードは汎用的にするためにジェネリクスを使っていますが型固定でも構いません.
public class ElementWithWeight<T>{
    private T element;  //要素
    private int weight;  //重み
    
    public ElementWithWeight<T>(T element){
        this.element = element;
    }

    //...ほか,必要そうなメソッドはいくつかあるが省略
}
配列をシャッフルし,特定の要素に重み(≠1)をつけたとします.
以下,かなりゴリ押しですが
  1.  まず,すべての重みの合計を算出する(重みがないものは1)
  2.  合計値未満の乱数を発生させる
  3.  配列の先頭から順に要素の重みを取り出し,重みの合計を出す
  4.  乱数<重みの合計となった時点の要素と先頭を入れ替える
  5.  1. の重みの合計から4. で選ばれた要素の重みを引き,2. に戻る.ただし,3. で取り出すのはすでに選んだ個数分先の要素から(2周目であれば2番目,インデックス番号1から)
こうなると思います.


追記
自分でコードを書いてみたら,どうやらジェネリクスを持つ要素の配列は作れないようなので,ジェネリクスを使わず型を固定して使ったほうが良さそうです.

追記2
もっと別の方法では,重みのある要素の数を増やしてしまうという方法が考えられます.
重みを付ける要素が決まったあと,Listにその要素を増えた重み分追加します.
そしてシャッフルしたあと,重複する要素の内最初に出てくるもの以外を取り除く必要があります.

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

方向性が違うようなので、回答は消します

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/04 19:08 編集

    消します

    キャンセル

  • 2015/09/05 13:38 編集

    消します

    キャンセル

0

実装方法よりも、仕様を詰めたほうがいいと思います。

>選択した10個の配列(重みのある)が出やすくする
を如何にシステム化できるように落としこむか?が課題です。

例えば、以下の様な感じは如何でしょうか。

1.100個の要素から10個をランダムに取り出す。
2.10個のうち、何個採用するかランダム(5以上10未満)に決める。
3.10個のうち、上記で取得した採用数をランダムに抽出する。...A
4.抽出されなかった90個のうち、Aで不採用とした数だけランダムで抽出する。...B
5.AとBをマージする。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/05 13:13

    TetsujiMiwaさんありがとうございます!
    ちょっとやってみたのですが,あまり10個の配列(重みのある)を選んでくれるような感じにはなりませんでした.やはり,一回採用したらその数だけ増やして,採用されたら抽出するとかにしないといけないかもしれないです...

    キャンセル

  • 2015/09/05 13:24

    どういう重みの付け方をしているのですか?
    重み付けはあくまで確率の操作で,その数字が確実に選ばれる保証はしませんよ?

    キャンセル

  • 2015/09/05 14:47

    s36aさん

    重複抽出の対処が必要ですが、
    数を増やすというのもいいアイデアですね。
    10個の配列をそれぞれ10個ずつ増やせば、効果が見えるかもしれないです。

    キャンセル

  • 2015/09/05 14:52

    swordoneさん
    例えば,10個選ばれた際にその10個を追加して,二回目選ぶ際の確率を上げるなどです...

    キャンセル

  • 2015/09/05 14:55

    TetsujiMiwaさん
    たたその方法だと重複した場合の対処をどうしようかと...
    選択されたさいに選ばれたものを追加していくのはいいんですが,被ったときにどのようにして弾くのが...問題ですよね...

    キャンセル

  • 2015/09/05 15:05

    s36aさん

    その際は、重複個数分だけ再抽選となるでしょうね。

    キャンセル

  • 2015/09/05 15:25

    私の回答に書きましたが,重みの分数を増やしてシャッフルして,
    その後重複分をリストから消せばいいのでは?

    キャンセル

  • 2015/09/05 15:55

    swordoneさん
    removeで消すとかでしょうか?

    キャンセル

  • 2015/09/05 16:04 編集

    そうです.
    最初の位置はindexOf,最後の位置はlastIndexOfで取得できるので,
    前者と後者を比較して違えば後者をremoveする,という方法があるのではないでしょうか.
    もっとも,最初から重複する要素があった場合には使えませんが・・・

    キャンセル

0

定石としては
重みの累積和を計算し
例)重みw={1,1,2,6}に対して累積重みsw={1,2,4,10}

累積重みの一番最後までの乱数を生成し、
例)0~10

要素を先頭から見て、累積重みが初めて生成した乱数以下になるものを選択します。

0   1   2       4                       10
|---|---|-------|-----------------------|
< 1>< 1><  2   ><          6           >
            *
*:生成した乱数
この場合先頭を要素[0]として要素[2]が抽選された。
重みが大きい要素ほど区間が広くなるので、重みを反映した確率で抽選できる。

複数を抜き出す場合は、抽選されたものをリストから抜かずに再び抽選(復元抽出)し、
同じものを引いたらやり直すか、(結果的に非復元抽出)
抽選されたものをリストから抜いて、抜き出すたびに累積重みを計算し直すかです

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    java オブジェクトのリストから特定の値をもったオブジェクトを取得

    javaを勉強中の初心者です ArrayListで作ったリストのオブジェクトから特定の値を持ったオブジェクトを取得する方法を教えて下さい。 例えば、Memberクラスが持ってい

  • 解決済

    単語ごとの出現回数を出現順に表示するには、HashMapとArrayListが必要か

    単語ごとの出現回数を出現順に表示するには、HashMapとArryaListが必要でしょうか。 下記の例よりももっとスマートかつコード量が少なく使用するメモリの量が少ない方法がある

  • 解決済

    listの参照があいまいです

    この前質問させていただいたときに回答して下さった方のソースをコンパイルしてみたんですが(いらないimportまで書いてると思いますが気にしないでください)listの参照があいまいで

  • 解決済

    クイズを作りたいのだがうまくいかない。

    クイズのコンソールアプリケーションを作りたいのですが、どういう風に設計すればいいのか分からず困っています。仕様は以下の通りです。 ・用意した問題がランダムに表示される。 ・選択肢

  • 解決済

    重複しない乱数の発生方法(Collections.shuffleの処理速度)

    リストをシャッフルする Collections.shuffle というメソッドがありますが、かなり大量のリスト(1000以上)をシャッフルするとなるとやはり処理時間がかかるでし

  • 解決済

    配列へランダムに数字を入れたいです。

    前提・実現したいこと javaで156個の配列にランダムでそれぞれ1~13の数字を同じ数だけ入れたいです。 マークが関係なくジョーカーが入っていないトランプを3組混ぜるイメージ

  • 解決済

    for文を使用したバブルソート

    前提・実現したいこと 以下の条件を持つプログラムを作成しようとしています。 1.『end』が入力されるまで入力値を受け付ける 2.『end』が入力された後、入力値をバブル

  • 解決済

    Javaでマス当てゲームを作りたい

    前提・実現したいこと Javaで5*5のマス目から当たりを見つけるプログラムを作りたいと考えています。 インターネットで下記のプログラムを見つけ応用できないかと思っています。

同じタグがついた質問を見る

  • Java

    14116questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。