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

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

新規登録して質問してみよう
ただいま回答率
85.35%
コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

4718閲覧

Pythonで2個のサイコロの合計をグラフにする方法

Spursfun2002

総合スコア15

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/05/10 04:03

編集2020/05/10 05:40

#マークに従いながら、2個のサイコロを100回振って、各合計の(0〜12)回数をカウントして、グラフにしようとしています。
どのようなコードが適切か教えていただけると助かります!

  • 問題点

現在このコードは動きます、しかしながら結果が出力されると0〜99までの数字が順番にでるため、全くランダムではありません。「最後にroll_diceとupdate_listの両方を呼び出すforループを作成して、サイコロを振り、その振りの結果に基づいてリストを更新しないといけないです。 ループはサイコロを振る回数を繰り返す必要があります。」このような説明があるのですが、どうやるのかがまったくわかりません。

import random roll_list = [] #holds the number of times each number was rolled # has 13 spots (0 - 12). roll_list[1] is how many times # a 1 was rolled. num_rolls = 100 # number of times to roll the dice # initialize the roll_list[] so it has the correct number of spots def init_list(): for x in range(0,13): roll_list.append(x) # use a for loop and list.append( x ) to fill the roll_list with 13 zeros # returns the sum of the two dice that were rolled def roll_dice(): dice1 = random.randint(1, 6) dice2 = random.randint(1, 6) twodice = dice1 + dice2 return roll_dice() # roll 2 standard die and return the sum (should be from 2 to 12) # random.randint() will be helpful here # change this line so it returns the correct sum def update_list(): if twodice == 0: roll_list[0] += 1 elif twodice == 1: roll_list[1] += 1 elif twodice == 2: roll_list[2] += 1 elif twodice == 3: roll_list[3] += 1 elif twodice == 4: roll_list[4] += 1 elif twodice == 5: roll_list[5] += 1 elif twodice == 6: roll_list[6] += 1 elif twodice == 7: roll_list[7] += 1 elif twodice == 8: roll_list[8] += 1 elif twodice == 9: roll_list[9] += 1 elif twodice == 10: roll_list[10] += 1 elif twodice == 11: roll_list[11] += 1 elif twodice == 12: roll_list[12] += 1 return update_list() # add 1 to the list location associated with the total roll value # example: if the total of the roll is 7, then add 1 to roll_list[7] def print_histogram(): maxBar = str(13) for z in roll_list: p = str(z) if p <= maxBar: p += '*' return print_histogram() # for 100% create and print a histogram of the results of all # of the dice rolls for roll_dice in range(num_rolls): print(roll_dice) for update_list in range(num_rolls): print(update_list)

サンプルのアウトプットです。

Sample Output: [0, 0, 4, 2, 7, 12, 12, 22, 12, 13, 9, 3, 4] 0: 1: 2: **** 3: ** 4: ******* 5: ************ 6: ************ 7: ********************** 8: ************ 9: ************* 10: ********* 11: *** 12: ****

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

teamikl

2020/05/10 05:30

どのようにコードを動かされてますか? 見た感じ、どの関数も再帰呼び出しになっていて、呼び出してみても >現在このコードは動きます、しかしながら結果が出力されると0〜99までの数字が順番にでるため、 は確認できません。 print文自体がないので、どのように確認されてるのでしょう。 もし、手元のコードと違うもしくは追加でコードがある場合、 質問文のコードの編集で提示お願いします。
Spursfun2002

2020/05/10 05:33

すいません 重要なところが抜けていましたね。 すぐに修正いたしました。
teamikl

2020/05/10 05:37

インデントが崩れているので、出来れば最初のコードと同じ個所に編集をお願いします。 (コードにはクリップボードにコピーボタンがあるので、他の方が試しやすくなります) 問題の現象は確認出来ました。回答欄に書きますね
Spursfun2002

2020/05/10 05:39

すいません すぐ修正します。
guest

回答3

0

2個のサイコロを100回振って、各合計の(0〜12)回数をカウント

2個のダイスの目は独立して発生するものなので。ダイスAを100回、ダイスBを100回を独立に振って、回目ごとに合計値を数をカウントすることと同じことです。
よって以下のコードで出目とその出現数を計算することができます。

# ダイスAおよびBの出目をランダムに100個リスト化 Dice_A = np.random.choice([1,2,3,4,5,6],p=[1/6,1/6,1/6,1/6,1/6,1/6],size=100,replace=True) Dice_B = np.random.choice([1,2,3,4,5,6],p=[1/6,1/6,1/6,1/6,1/6,1/6],size=100,replace=True) # 出目を合計する。(ダイスAのN回目の出目とダイスBのN回目の出目を合計する) Total = Dice_A + Dice_B # 合計値単位に出現回数をカウントする。(Val:出目 Cnt:出目ごとの出現回数) Val , Cnt = np.unique(Total,return_counts=True)

説明文通りに実装しなさいということであれば無視してください。

投稿2020/05/10 09:40

R.Shigemori

総合スコア3376

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

回答ではないですが、他人のプログラムを読んでみるのもいい勉強になると思いますので、私ならこう書くという実装例を示しておきます。
なぜこのように書いて動くのか、プログラムをバラバラに分解して動作や言語仕様を確認してみてください。

python

1import random 2 3DICE_NUMBERS = 1, 2, 3, 4, 5, 6 4 5def roll_dice(num): 6 return [random.choice(DICE_NUMBERS) for _ in range(num)] 7 8def make_histgram(num_dice, roll_times): 9 histgram = [0] * (max(DICE_NUMBERS) * num_dice + 1) 10 for _ in range(roll_times): 11 histgram[sum(roll_dice(num_dice))] += 1 12 return histgram 13 14def print_histgram(histgram): 15 width = len(str(len(histgram))) 16 for i, times in enumerate(histgram): 17 print(f"{i:{width}}:", '*' * times) 18 19def main(): 20 histgram = make_histgram(num_dice=2, roll_times=100) 21 print(histgram) 22 print_histgram(histgram) 23 24if __name__ == '__main__': 25 main()

Pythonインタープリタでの動作確認例:

python

1>>> import random 2>>> DICE_NUMBERS = 1, 2, 3, 4, 5, 6 3>>> random.choice(DICE_NUMBERS) 42 5>>> random.choice(DICE_NUMBERS) 65 7>>> [random.choice(DICE_NUMBERS) for _ in range(2)] 8[4, 6] 9>>> [random.choice(DICE_NUMBERS) for _ in range(2)] 10[5, 1] 11>>> sum([5, 1]) 126

投稿2020/05/10 06:36

編集2020/05/10 07:41
shiracamus

総合スコア5406

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

問題の原因1 (追記されたコードより)

num_rolls = 100 for roll_dice in range(num_rolls): print(roll_dice) for update_list in range(num_rolls): print(update_list)

関数定義で "roll_dice", "update_list" があるので、
関数を呼び出したいという意図は感じられますが、
ここで実際に起こっているのは以下のコードと同じです。

python

1for num in range(100): 2 print(num)

for ... in の所は変数名で、range(100)から取り出された値が入ります。

解決策: ※ 100回繰り返しは init_list() の中でやりたいことと想定して回答します

import random num_rolls = 100 roll_list = [0] * 13 # update_list関数の為に0..12迄のリスト(長さ13)を準備 def update_list(twodice): # <== 引数: 値を受け取る # 合計値の出現数をカウント roll_list[twodice] += 1 def roll_dice(): dice1 = random.randint(1, 6) dice2 = random.randint(1, 6) twodice = dice1 + dice2 return twodice # <== 戻り値: 計算結果を返す def init_list(): for _ in range(num_rolls): # num_rolls回繰り返し twodice = roll_dice() # ダイスを振る update_list(twodice) # 集計 def print_histgram(): for num in range(len(roll_list)): count = roll_list[num] print("{:2} {}".format(num, "*" * count)) # グラフ出力 if __name__ == "__main__": init_list() print_histgram()

他の問題: roll_dice, update_list, print_histogram 関数もそれぞれ問題があります。
まだ、現状では関数の呼び出し自体がうまく行ってないことから、
問題点を把握されていないと思います。

python

1def roll_dice(): 2 ... # 省略 3 return roll_dice()

注意深くコードをみると、update_list(), print_histogram() も同じように
最後の return で自分自身を呼び出しています。
この様なコードを「再帰呼び出し」と言って、有用な場合もあるのですが
この場合は、永遠と同じ関数を呼び出し続けて最後にはエラーになります。

まずは、基本的な関数の使い方を調べて見て下さい。

  • 関数へ値を渡す方法 (引数)
  • 関数から値を返す方法 (戻り値)

関数の中身の処理自体(ダイスを2つ足し合わせる、出現頻度の集計)は、
(改善の余地はあるものの)期待通りのロジックになっているので大丈夫です。


  • 他の方法: 集計には collections.Counter が使えます。
  • グラフ出力 Pythonではシーケンス型と数値を掛けると、回数分繰り返します

python

1print("#" * 4) # => "####" 2 3roll_list = [0] * 13 4print(roll_list) # [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

参考:
PythonのCounterでリストの各要素の出現個数をカウント

投稿2020/05/10 06:17

teamikl

総合スコア8760

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Spursfun2002

2020/05/10 12:11

なるほど、もっと勉強します! 丁寧に問題点と改善を教えていただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問