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

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

ただいまの
回答率

88.10%

JavaScriptを用いた購入システムの券枚数決定のアルゴリズムについて

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 355

score 48

お世話になっております。

今回、券の購入システムの構築を勉強のため行っております。
方法の概要として
最小の購入金額<オッズによる払い戻しになるよう各券の購入枚数を求める計算式になっています。

具体的な方法は以下の通りです。

購入する券を配列に起こす(ary)。

haraiGenHairetuにオッズのみの配列を作成、bakenMaisuにはこれから購入して行く券の枚数を指定する配列(初期値は全て1枚とします)を準備

オッズ×馬券枚数を算出し、kakezan配列に代入

kakezan配列の最小値を求め、haraiGenHairetuMinに代入

bakenMaisuの合計を求める①

haraiGenHairetuMinの値があるharaiGenHairetuのインデックス番号をharaiGenIndexに代入

bakenMaisuのharaiGenIndex番目に+1をする(購入する馬券が一枚増える)

bakenMaisu[haraiGenIndex]=haraiGenBakenMaisu

もしbakenMaisu>haraiGenHairetuMinならば、①に戻る

正解としてはbakenMaisu[2,44,1,6,2,1,3,2,1,1,1,5,2,19,2,8,1]が最小購入金額ですが、この方法だと[2, 47, 1, 6, 2, 1, 3, 2, 1, 1, 1, 5, 2, 20, 3, 9, 1]が最終解となり若干差が生じます。

この差に付いては何が問題なのでしょうか。
また、より処理速度を上げるにはどういった点を修正する必要性があるでしょうか。

よろしくお願いいたします。

<script src="decimal.min.js"></script>
        <script>
            var ary = [
                ["2", 72.6], 
                ["4", 2.3],
                ["5", 151.8], 
                ["6", 18],
                ["7", 66.8],
                ["1-2", 347.2], 
                ["1-3", 37.4],
                ["1-4", 54],
                ["1-5", 662.7], 
                ["1-6", 169.6],
                ["1-7", 607.5],
                ["3-1", 23], 
                ["3-2", 86.8], 
                ["3-4", 5.4],
                ["3-5", 50.7], 
                ["3-6", 13],
                ["3-7", 177.8],

            ];

            var haraiGenHairetu = [];
            var bakenMaisu = [];
            var garaiKakeBakenMaisu = [];
            for(var i=0;i<ary.length;i++){
                    var haraiGen=ary[i][1];
                    haraiGenHairetu.push(haraiGen);
                    bakenMaisu.push(1);    
            }
            function kakeruGoukei(){
                    for(var i=0;i<ary.length;i++){
                        var kakezan = new Decimal(haraiGenHairetu[i]).times(bakenMaisu[i]).toNumber();
                        garaiKakeBakenMaisu.push(kakezan);
                    }
                    var haraiGenHairetuMin = Math.min.apply(null,haraiGenHairetu);

                    var sum  = function(bakenMaisu) {
                        var sum = 0;
                        bakenMaisu.forEach(function(elm) {
                            sum += elm;
                        });
                        return sum;
                    };

                    var haraiGenIndex = haraiGenHairetu.indexOf(haraiGenHairetuMin);
                    var haraiGenBakenMaisu=bakenMaisu[haraiGenIndex]+1;
                    bakenMaisu[haraiGenIndex]=haraiGenBakenMaisu;

                    while(sum(bakenMaisu)>haraiGenHairetuMin){
                        console.log(bakenMaisu);
                        var sum  = function(bakenMaisu) {
                            var sum = 0;
                            bakenMaisu.forEach(function(elm) {
                                sum += elm;
                            });
                            return sum;
                        };

                        garaiKakeBakenMaisu.splice(0, ary.length);
                        for(var i=0;i<ary.length;i++){
                            var kakezan = new Decimal(haraiGenHairetu[i]).times(bakenMaisu[i]).toNumber();
                            garaiKakeBakenMaisu.push(kakezan);
                        }
                        var haraiGenHairetuMin = Math.min.apply(null,garaiKakeBakenMaisu);

                        var haraiGenIndex = garaiKakeBakenMaisu.indexOf(haraiGenHairetuMin);
                        var haraiGenBakenMaisu=bakenMaisu[haraiGenIndex]+1;
                        bakenMaisu[haraiGenIndex]=haraiGenBakenMaisu;

                    }

                document.write("購入合計金額は"+sum(bakenMaisu)*100+"です。<br/>");
                var saisyou =(sum(bakenMaisu)*100)-(haraiGenHairetuMin*100);
                document.write("最小収益は"+saisyou+"です。");
                var haraiGenHairetuMax = Math.max.apply(null,garaiKakeBakenMaisu);
                var saidai =((haraiGenHairetuMax*100)-sum(bakenMaisu)*100);
                document.write("最大収益は"+saidai+"です。");


            }

            kakeruGoukei();
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • Orlofsky

    2019/12/17 10:47

    > var ary = [
    = の次に全角の空白が入っています。直されては?

    キャンセル

回答 1

checkベストアンサー

0

while(sum(bakenMaisu)>haraiGenHairetuMin){


↑の部分ですが、bakenMaisuがkuroishiさんが考える正解[2,44,1,6,2,1,3,2,1,1,1,5,2,19,2,8,1];の時、

sum(bakenMaisu) // = 101
haraiGenHairetuMin // = 98.9


なので、ループを抜けません。

なぜならば、その時点でのharaiGenHairetuMinは直前のループで計算されたものなので、馬券枚数に+1する前の値である、[2,43,1,6,2,1,3,2,1,1,1,5,2,19,2,8,1];に基づいて計算された結果だからです。

なので、問題は「bakenMaisuを変更したときにharaiGenHairetuMinを再計算していないから」です。


また、速度向上については、splicepushが遅いような気がしましたが、実際に試してはいません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/12/18 14:53

    ありがとうございました!質問の意図も汲み取っていただき、感謝しております。

    キャンセル

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

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

関連した質問

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