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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

9713閲覧

1習慣で身につくC#言語のチャレンジ問題の解答コードがわからない

vnsa7221

総合スコア348

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

1クリップ

投稿2017/06/26 12:39

編集2017/06/27 06:53

###前提・実現したいこと
現在C#を勉強するにあたり、「一週間で身につくC#言語」サイトを参照しながら勉強しております。
一通り基礎編の練習問題を解き終えたので、チャレンジ問題に挑戦しているところです。
現在Prob8-2において、重複判定をどのように実装すればよいかわからない状態です。

Prob8-1

a,b,cを、いずれも1以上100以下の整数とするとき、aa+bb=c*cを満たす、全てのa,b,cの組み合わせ全てと、その数を求め、画面に表示しなさい。ただし、a,bの数値の組み合わせが同じものも別のものとしてもかまわない。具体的には、a=3,b=4,c=5と、a=4,b=3,c=5は別の組み合わせとする。

Prob8-2←今ここを解いている

prob8-1.のデータから、重複を取り除いた組み合わせと、その数を表示するプログラムを作りなさい。具体的には、a=3,b=4,c=5と、a=4,b=3,c=5は同じものとみなす。

###発生している問題・エラーメッセージ
重複する場合は表示させないという実装において、どのように実装すればよいのかわからない。

###該当のソースコード

C#

1// prob8-1の解答 2using System; 3using System.Collections.Generic; 4using System.Linq; 5using System.Text; 6using System.Threading.Tasks; 7 8namespace Problem8_1 9{ 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 int a, b, c; 15 16 for(a = 1; a <= 100; a++) 17 { 18 for(b = 1; b <= 100; b++) 19 { 20 for(c = 1; c <= 100; c++) 21 { 22 int x = a * a; 23 int y = b * b; 24 int z = c * c; 25 26 if(x + y == z) 27 { 28 Console.WriteLine("a = {0} b = {1} c = {2}", a, b, c); 29 } 30 } 31 } 32 } 33 } 34 } 35}

C#

1// prob8-2の解答 2using System; 3using System.Collections.Generic; 4using System.Linq; 5using System.Text; 6using System.Threading.Tasks; 7 8namespace Problem8_2 9{ 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 int a, b, c; 15 int m = 0; 16 int[,] ary = new int[1000, 3]; 17 18 for(a = 1; a <= 100; a++) 19 { 20 for(b = 1; b <= 100; b++) 21 { 22 for(c = 1; c <= 100; c++) 23 { 24 int x = a * a; 25 int y = b * b; 26 int z = c * c; 27 28 if(x + y == z) 29 { 30 ary[m, 0] = a; 31 ary[m, 1] = b; 32 ary[m, 2] = c; 33 34 m++; 35 } 36 } 37 } 38 } 39 40 //Console.WriteLine("{0}", ary.Length); 41 42 for(int i = 0; i < ary.GetLength(0); i++) 43 { 44 if(ary[i, 0] != 0 && ary[i, 1] != 0 && ary[i, 2] != 0) 45 { 46 Console.WriteLine("a = {0} b = {1} c = {2}", ary[i, 0], ary[i, 1], ary[i, 2]); 47 } 48 } 49 } 50 } 51}

###試したこと
①Prob8-1を最初利用しようとしたが、重複を判定する場合は一度該当する数値をデータとして保持しないと無理ではないかと思い、二次元配列に該当数字をpush

②該当数字を配列に格納したが、数値0,0,0が出てきてしまうのでいったんif文にて0,0,0を非表示←この部分もなんとかしたい。

③重複判定を行おうとしたが、どのようにすれば良いのか手詰まりとなってしまっている状態

###補足情報(言語/FW/ツール等のバージョンなど)
現在勉強中のため、お手数をおかけしてしまい申し訳ございませんが、わかりやすいアドバイスを頂けると幸いでございます。
またもし別の方法や簡単な方法等ございましたらそちらに関するアドバイスもありがたいです。
よろしくお願いいたします。

###追記
回答より頂いたアドバイスを参照に作成

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6 7namespace Problem8_2 8{ 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 int a, b, c; 14 int m = 0; 15 int[,] ary = new int[1000, 3]; 16 17 for(a = 1; a <= 100; a++) 18 { 19 for(b = 1; b <= 100; b++) 20 { 21 for(c = 1; c <= 100; c++) 22 { 23 int x = a * a; 24 int y = b * b; 25 int z = c * c; 26 27 if(x + y == z) 28 { 29 // prob8-1より本制御文追加 30 if(a <= b) 31 { 32 Console.WriteLine("a = {0} b = {1} c = {2}", a, b, c); 33 } 34 } 35 } 36 } 37 } 38 39 //Console.WriteLine("{0}", ary.Length); 40 41 //for(int i = 0; i < ary.GetLength(0); i++) 42 //{ 43 // if(ary[i, 0] != 0 && ary[i, 1] != 0 && ary[i, 2] != 0) 44 // { 45 // Console.WriteLine("a = {0} b = {1} c = {2}", ary[i, 0], ary[i, 1], ary[i, 2]); 46 // } 47 //} 48 } 49 } 50}

ただなんとなく腑に落ちない部分があるので、頂いたアドバイスを参照にもう少し作ってみる

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

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

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

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

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

guest

回答2

0

ベストアンサー

本件の場合重複しているかどうかはa,bの値のみのよって決まる(成立する組み合わせはa,bが決まればcは自ずと決まるので)と考えてよいと思います。さらにa,bを交換したものの重複を排除するなら最初からa <= bとなるような組み合わせについてのみチェックすることで重複排除そのものをしなくてよくなります。

(1) 問題文を読む限りは「望む結果が得られればよく、Prob8-1のアルゴリズムや結果のデータを利用する必要はない」と思います。

(2) 配列は一旦確保してしまうと、そこに有効なデータがあろうがなかろうが要素が存在してしまうので、「配列に格納されている有効な要素数」を別途変数で管理しないと「見てはいけない要素を見てしまう」結果になります。つまりfor(int i = 0; i < ary.GetLength(0); i++)は適切なループの仕方ではありません。for(int i = 0; i < m; i++)とするのが順当です。
なお、配列の多くの要素は多分無駄になりますし「1000要素で本当に大丈夫?」といった不安もあるのではないでしょうか?そんな場合は「可変長の列」を表現するクラスを使う方が素直に書けます。例えばListを用いれば次のように書けます。

C#

1var list = new List<int[]>(); 2... 3if (x + y == z) { 4 list.add(new int[] { a, b, c }; 5} 6... 7for (int i = 0; i < list.Count; i++) { 8 ... 9}

(3) 最初に述べた方法にすればやる必要がなくなります。もし練習のために重複排除の論理を作るなら...

C#

1for (int i = 0; i < m; i++) { 2 bool found = false; 3 for (int j = 0; j < i; j++) { 4 if (i番目の解とj番目の解が重複している) { 5 found = true; // 重複解が見つかったことを覚える 6 break; 7 } 8 } 9 if (!bound) { 10 i番目の解を印字 11 } 12}

(なお重複排除を行うために実際の応用プログラミングでまともにループで書くことは少ないと思います。Dictionaryなどのクラスに解を登録した上で「このデータって登録済みですか?」と問い合わせるメソッドを用いれば簡単に求まるからです。そのようなクラスをうまく使うには「登録する要素が等しいかどうかを比較できるクラスにする」といったより応用的な設計が必要になってきます。しかしながらプログラミングの練習をする上ではまず自前でループを書いて論理を考える練習をすることは価値があると思います。)

投稿2017/06/26 13:46

KSwordOfHaste

総合スコア18394

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

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

vnsa7221

2017/06/27 06:50

KSwordOfHasteさん回答ありがとうございます。 可変長のListというものがあるんですね。その部分はまだ触ったことないので初めて知りました。 今回いただいたアドバイスを参照として、せこいですがProb8-1のif(x + y == z)の下にif(a <= b)を追加することで期待していた結果を得ることを確認できました。 ただこれだけだとなんか腑に落ちないというか、きちんと解いたという感じがしないので、頂いたアドバイスを参照にもう少し作りこんでいきたいと思います。 ご丁寧なアドバイスありがとうございました。
guest

0

問題文にあるモノをコードで表現する。この場合、a, b, c を「ピタゴラス数」としてまとめことを考えるとよいです。

2つのピタゴラス数 p1 と p2 に対して、「同じか」がしりたいので、IComparable を実装してください。

あとは HashSet に詰めれば解決。

投稿2017/06/26 13:19

koko_u

総合スコア936

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

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

vnsa7221

2017/06/27 06:45

koko_uさん回答ありがとうございます。 すみません。自分の勉強不足もあり、それぞれの英単語が何を示すのかがよくわからない状態でした。 この部分はググりながら進めるしかないですね。 丁寧なアドバイスいただきありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問