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

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

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

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

Q&A

解決済

3回答

1753閲覧

お土産を分配するためのクラス

irm

総合スコア25

C#

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

0グッド

0クリップ

投稿2019/01/23 04:48

編集2019/01/23 08:08

お土産を人に分配するプログラム内で、お土産の数を計算するクラスを作りました。お土産を人数で割ったときの余剰分を、リストの上にいる人から一つずつわけていくことを意図しています。(あるいは、トランプを一枚ずつ配るときのように、全員にお土産を1つずつ順番に配っていき、お土産がなくなるまで続ける方法も可です。)

しかし、せっかく分配のためのコードを書いたものの、return値があるため、最後のdivision + 1が適応されて、すべての人に同じ数でtotalSouvenirsの数を超えたかたちになってしまいます。なにかよい方法はないものでしょうか。もしくは、intでなくて、voidにしたらうまく行くでしょうか。解決法を探しています。

C#

1class SouvenirDistribution 2 { 3 4 public int Distribute(int totalSouvenirs, List<Person> p) 5 { 6 7 int numberOfPpl = p.Count; 8 int division = totalSouvenirs / numberOfPpl; 9 int remainder = totalSouvenirs % numberOfPpl; 10 int result = 0; 11 int i = 0; 12 13 14 if (remainder == 0) 15 { 16 for (i = 0; i < p.Count; i++) 17 { 18 result = division; 19 20 } 21 22 } 23 24 25 else if(i<remainder) 26 { 27 for (i = remainder; i < p.Count; i++) 28 { 29 result = division; 30 31 } 32 for (i = 0; i < remainder; i++) 33 { 34 result = division + 1; 35 } 36 37 } 38 39 return result; 40 41 } 42 } 43} 44

メインウィンドウ内のDistributeメソッド適用箇所です↓BtnDivide_Clickは、ボタンにより分配が実行されます。

C#

1//nameとageプロパティが入っています↓ 2List<Person> names = new List<Person>(); 3 4 private void BtnDivide_Click(object sender, RoutedEventArgs e) 5 { 6 SouvenirDistribution sd = new SouvenirDistribution(); 7 int totalSouvenirs = int.Parse(TxtTotalSouvenirs.Text); 8 9 int i = 0; 10 int numberOfSouvenirs = sd.Distribute(totalSouvenirs,names); 11 for(i = 0; i < names.Count; i++) 12 { 13  //Personクラス内のToString()メソッド内の内容で構成された人名リストに、お土産の分配数が追加される形です。 14 NameList.Items[i] += $" {numberOfSouvenirs} 個"; 15 16 } 17

こちらが、Personクラスです。

C#

1 public class Person 2 { 3 4 //プロパティ 5 public int Age { get; set; } 6 public string FirstName { get; set; } 7 public string LastName { get; set; } 8 public string Name { get; set; } 9 10 //コンストラクタ 11 public Person(string name, int age) 12 { 13 Age = age; 14 Name = name; 15 } 16 17 // 名前リストに表示される内容 「名前,年齢才」 18 public override string ToString() 19 { 20 return Name + ", " + Age + "才"; 21 22 } 23 24 }

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

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

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

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

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

takabosoft

2019/01/23 04:54

Distribute関数は何を引数に取って、どんな処理をして、何を返す関数なのでしょうか?
papinianus

2019/01/23 05:01

仕様をより具体的に言語化するか、これを利用しているコードとPersonの定義の開示をするか、どちらかをご対応ください。
YAmaGNZ

2019/01/23 05:03

タイトルを意味の分かるものにしてください
irm

2019/01/23 08:27

ありがとうございます。追記対応しました。
guest

回答3

0

こんなの如何でしょう?
肝はPersonを拡張してプロパティを増やすところかな?

C#

1public class Person 2{ 3 public string Name { get; set; } 4} 5 6public class PersonSharing : Person 7{ 8 public int Share { get; set; } 9} 10 11public void Distribute(int totalSouvenirs, List<PersonSharing> persons) 12{ 13 var remaining = totalSouvenirs; 14 15 persons.ForEach(p => 16 { 17 p.Share = totalSouvenirs / persons.Count; 18 remaining -= p.Share; 19 }); 20 21 foreach(var person in persons) 22 { 23 if (remaining < 1) break; 24 25 person.Share ++; 26 remaining--; 27 } 28}

投稿2019/01/23 05:15

hihijiji

総合スコア4150

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

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

irm

2019/01/23 08:40

ありがとうございます。なるほど、こういう書き方があるのですね。Shareプロパティの作成もそうですが、数的な処理の仕方など、全体的な考え方がとても参考になりました。自分のコードに当てはめようとしていますが…。
guest

0

ロジックを考えるヒントだけです。

すでに多くのコメントがされていますが、作成されたDistribute関数は何をしたいのでしょうか。一人当たりの分配数を返すものを想定しているのだと思いますが、端数がある場合、多い人と少ない人ができるわけですが、その情報はどうするのでしょう。

呼び出し側ではその情報を持ち合わせず知りえないわけですから、関数の考え方の方向を変える必要があります。

  • あくまで(誰か一人の)分配数を返したい

引数でメンバーの誰かを指定できるようにする。

  • 戻り値の仕様を変更してもいいなら

分配数のリストを返すようにする(papinianusさんの回答)

  • 戻り値が無くてもいいなら

関数内で各メンバーの分配数を設定する(hihijijiさんの回答)

投稿2019/01/23 08:39

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

irm

2019/01/23 09:54

ありがとうございます。そうですね、お土産を人数で割った商のいわゆる余りの扱いに困っていました。ゆっくり読ませていただきます。
guest

0

ベストアンサー

そういう使い方がしたいなら、こうかな(関数の実装はともかく、int[]を返す)

csharp

1public int[] Distribute(int totalSouvenirs, List<Person> p) 2{ 3 int division = totalSouvenirs / p.Count; 4 int remainder = totalSouvenirs % p.Count; 5 return Enumerable.Repeat(division + 1, remainder).Concat(Enumerable.Repeat(division, p.Count - remainder)).ToArray(); 6}

csharp

1int[] numberOfSouvenirs = sd.Distribute(totalSouvenirs,names); 2for(i = 0; i < names.Count; i++) 3{ 4 //Personクラス内のToString()メソッド内の内容で構成された人名リストに、お土産の分配数が追加される形です。 5 NameList.Items[i] += $" {numberOfSouvenirs[i]} 個"; 6}

投稿2019/01/23 08:27

編集2019/01/23 08:28
papinianus

総合スコア12705

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

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

irm

2019/01/23 09:50

こちらでできました^^ありがとうございます!intの配列的なものも思いつき質問前に試そうとしたのですが、いまいちうまくいかずにいました。return部分が参考になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問