🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Java

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

3回答

4813閲覧

java サイコロを3つ投げたときの目の和が何通りあるか

hadake7616

総合スコア8

Java

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

0クリップ

投稿2019/12/06 14:35

編集2019/12/06 16:19

前提・実現したいこと

プログラミングを始めたばかりの初心者です。

サイコロを3つ同時になげて目の和(n)になるのは何通りあるかのプログラムを書きました。

入力された値「n」になるパターンが何通りあるかをcountにしました。がうまくいきません。
nの範囲は 3<=n<=18です
です

例:n=3の時は(1,1,1)しかないのでcount=1

コードの説明

countは後で確率を出すときに使うかもしれないのでdouble型にしてます

与えられたnをdice配列に格納する。
dice[0]=1(1の目)、dice[1]=1(1の目)、dice[2]=n-2した値を初期値としていれる
dice[2]>6になるまで、dice[2]-=1 dice[1]=+1する
dice[2]=6かつdice[1]>6ならdice[0]=+1 dice[1]=+1として初期値を作る
///数える///
※ここがうまくいきません。
例1
n=4のとき
[1,1,2]→[1,2,1]→[2,1,1] 3通り
例2:
n=18のとき
[6,6,6] 1通り

数はあってると思うのですが、あっていませんでした。ソースコードで、条件式・配列の要素数を直書きしていてあまり良くない気がします。
修正したほうがいいと思うのですが、どのように書いたらキレイに書けるのでしょうか。

よろしくおねがいします。

追記

問題の説明文を修正しました。
nは3<=n<=18の範囲で入力されるものとします。

アルゴリズムがうまくいっていませんでしたので、修正案を教えていただけると助かります。

サイコロを4つに増やしてたときに、修正箇所が少なくて済むようにしたいです。
まずは3つで動くようにしたいです。

xが見にくいためnに変更しました

該当のソースコード

java

1 2import java.util.*; 3 4public class Main { 5 public static void main(String args[] ) { 6 Scanner sc = new Scanner(System.in); 7 int n= sc.nextInt();//目の和を入力 8 int[] dice={1,1,(n-2)};//サイコロ3つの配列 9 double count=1;//何通りあるかのカウント 10 //初期値 11 while (dice[2]>6){ 12 dice[2]-=1; 13 dice[1]+=1; 14 } 15 while (dice[1]>6){ 16 dice[0]+=1; 17 dice[1]-=1; 18 } 19 //通り数 20 while (dice[1]>6 || dice[2]>1){ 21 22 dice[2]-=1; 23 dice[1]+=1; 24 count++; 25 if (dice[2]==1 || dice[1]==6){ 26 int tmp=dice[1]; 27 dice[0]+=1; 28 dice[1]=dice[2]; 29 dice[2]=tmp-1; 30 if(dice[0]==7){ 31 break; 32 }else count++; 33 } 34 } 35 System.out.print(count); 36 } 37} 38

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

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

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

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

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

hadake7616

2019/12/06 15:00

コードの載せ方を教えていただきありがとうございます。
jimbe

2019/12/06 15:12 編集

> どのように書いたらキレイに書けるのでしょうか どのような書き方が「キレイ」とお思いでしょうか. > while (dice[1]>6| dice[2]>1){ これは合っていますか? > 数はあってると思うのですが 2 や 19 を入力した時も合っていますか?
FoyLand

2019/12/06 15:12

確認なのですが、求めるのは「目の和が何通りあるか」ではなく「和が x になる目の出方は何通りあるか」ではありませんか?
guest

回答3

0

与えられた数 n を 3つの数字(1..6の範囲) の和で表す組み合わせを求めるという方針にするとよいのでは?

n - 1 に対して 2 つの数の和 (1 以上で) にする組みあわせ数
n - 2 に対して 2 つの数の和 (2 以上で) にする組みあわせ数
n - 3 に対して 2 つの数の和 (3 以上で) にする組みあわせ数
...
n - 6 に対して 2 つの数の和 (6 以上で) にする組みあわせ数
を足し算することになります。
これは 再帰でかけそうです。
再帰でかきておけば、サイコロの個数を 3 以外¥に変更することも簡単にできそうな気がします。

投稿2019/12/06 23:07

katoy

総合スコア22324

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

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

0

ベストアンサー

考え方を変えてみると良さそうな場合もあります.

java

1public class Main { 2 public static void main(String[] args) { 3 Map<Integer,List<String>> map = createAllPatternMap(6, 3); //6面体サイコロ3個 4 5 Scanner sc = new Scanner(System.in); 6 int n = sc.nextInt();//目の和を入力 7 System.out.println("全"+(map.containsKey(n) ? map.get(n).size() : 0)+"件"); 8 } 9 10 // (diceSides) 面体サイコロ (numberOfDice) 個による合計毎のパターンを全て抽出する. 11 private static Map<Integer,List<String>> createAllPatternMap(int diceSides, int numberOfDice) { 12 Map<Integer,List<String>> map = new HashMap<>(); 13 for(int i=0; i<Math.pow(diceSides,numberOfDice); i++) { 14 int sum = 0; 15 StringBuilder sb = new StringBuilder(numberOfDice); 16 for(int j=0; j<numberOfDice; j++) { 17 int dice = (int)(i/Math.pow(diceSides,j))%diceSides+1; 18 sum += dice; 19 if(sb.length() > 0) sb.append('-'); //表示時用の区切り 20 sb.append(dice); 21 } 22 if(!map.containsKey(sum)) map.put(sum, new ArrayList<>()); 23 map.get(sum).add(sb.toString()); 24 } 25 return map; 26 } 27}

全パターンは map.get(n) で得る List<String> に入っていますので, 確認する場合はそれを表示してください.


パターンを保存しない例を追加しておきます.

java

1public class Main { 2 public static void main(String[] args) { 3 Map<Integer,Integer> map = createAllPatternCountMap(6, 3); //6面体サイコロ3個 4 5 Scanner sc = new Scanner(System.in); 6 int n = sc.nextInt();//目の和を入力 7 System.out.println("全"+map.getOrDefault(n, 0)+"件"); 8 } 9 10 // (diceSides) 面体サイコロ (numberOfDice) 個による合計毎のパターン件数を全て抽出する. 11 // ループでの(6面体サイコロ2個の場合の)表現例: 12 // 6面体2個の全パターン数=6の2乗=36 13 // 全パターン <-> 6進数 <-> 10進数(i) 14 // 11,12,13,14,15,16 00,01,02,03,04,05 0, 1, 2, 3, 4, 5 15 // 21,22,23,24,25,26 10,11,12,13,14,15 6, 7, 8, 9,10,11 16 // 31,32,33,34,35,36 20,21,22,23,24,25 12,13,14,15,16,17 17 // 41,42,43,44,45,46 30,31,32,33,34,35 18,19,20,21,22,23 18 // 51,52,53,54,55,56 40,41,42,42,44,45 24,25,26,27,28,29 19 // 61,62,63,64,65,66 50.51.52.53.54.55 30,31,32,33,34,35 20 private static Map<Integer,Integer> createAllPatternCountMap(int diceSides, int numberOfDice) { 21 Map<Integer,Integer> map = new HashMap<>(); 22 for(int i=0; i<Math.pow(diceSides,numberOfDice); i++) { 23 int sum = 0; 24 for(int j=0; j<numberOfDice; j++) { 25 sum += (int)(i/Math.pow(diceSides,j))%diceSides+1; 26 } 27 map.put(sum, map.getOrDefault(sum, 0)+1); 28 } 29 return map; 30 } 31}

投稿2019/12/06 16:36

編集2019/12/07 05:09
jimbe

総合スコア13201

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

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

hadake7616

2019/12/06 17:09

Listはまだ勉強できてないですが、こちらのコードで勉強させていただきたいと思います
jimbe

2019/12/07 03:19 編集

List 部分は現状は確認の為だけにあり, それによって 4~5行コードが大きくなっています. もし本当にパターン数だけでよければそれだけ減らせます.
jimbe

2019/12/07 04:31 編集

アルゴリズムとしましては, 全パターンを得る為に「x 面体サイコロ n 個」を「x 進数 n 桁」と見立てて, ループカウンタ i が 0 からその最大値まで(を10進数で)回るとしています. j のループはその i の x 進数での各桁毎に dice を求めています. (x 進数各桁は 0~(x-1) なので +1 しています.)
guest

0

・サイコロは1から6のいずれかの目を出すことができます。
・今回はサイコロを3つ投げます。
・6 * 3 = 18 が答えで良いのでは?

投稿2019/12/06 15:43

編集2019/12/06 15:56
Orlofsky

総合スコア16417

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

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

Zuishin

2019/12/06 15:47

X が乗算記号に見えました。
Orlofsky

2019/12/06 15:55

* に変えます。笑い
Zuishin

2019/12/06 15:59

「掛ける」で良かったんですか…… X = 3 の場合 1 通りしか無いので、18 だとまずいんではないでしょうか。
FoyLand

2019/12/06 16:16

実は質問のタイトルと質問文中で聞いていることが食い違っていて、本当は「サイコロを3つ同時になげて目の和(x)になるのは何通りあるか」を聞きたいそうです。 またタイトル通りに解釈したとしても和の最小値は3(3つとも1が出た時)なので、18-3+1=16通りであると思われます。
hadake7616

2019/12/06 16:21

すみません。もろもろ変更しました。 もっと伝える努力をしていきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問