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

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

ただいまの
回答率

87.60%

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

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,097

score 13

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

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

class SouvenirDistribution
    {

        public int Distribute(int totalSouvenirs, List<Person> p)
        {

            int numberOfPpl = p.Count;
            int division = totalSouvenirs / numberOfPpl;
            int remainder = totalSouvenirs % numberOfPpl;
            int result = 0;
            int i = 0;


            if (remainder == 0)
            {
                for (i = 0; i < p.Count; i++)
                {
                    result = division;

                }

            }


            else if(i<remainder)
            {
                for (i = remainder; i < p.Count; i++)
                {
                    result = division;

                }
                for (i = 0; i < remainder; i++)
                {
                    result = division + 1;
                }

            }

            return result;

        }
    }
}

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

//nameとageプロパティが入っています↓
List<Person> names = new List<Person>();

    private void BtnDivide_Click(object sender, RoutedEventArgs e)
        {
            SouvenirDistribution sd = new SouvenirDistribution();
            int totalSouvenirs = int.Parse(TxtTotalSouvenirs.Text);

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

            }

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

 public class Person
     {

        //プロパティ
        public int Age { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Name { get; set; }

        //コンストラクタ
        public Person(string name, int age) 
        {
            Age = age;            
            Name = name;
        }

        // 名前リストに表示される内容 「名前,年齢才」
        public override string ToString()
        {
            return  Name + ", " + Age + "才";

        }

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • takabosoft

    2019/01/23 13:54

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

    キャンセル

  • papinianus

    2019/01/23 14:01

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

    キャンセル

  • YAmaGNZ

    2019/01/23 14:03

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

    キャンセル

  • irm

    2019/01/23 17:27

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

    キャンセル

回答 3

+5

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

public class Person
{
    public string Name { get; set; }
}

public class PersonSharing : Person
{
    public int Share { get; set; }
}

public void Distribute(int totalSouvenirs, List<PersonSharing> persons)
{
    var remaining = totalSouvenirs;

    persons.ForEach(p =>
    {
        p.Share = totalSouvenirs / persons.Count;
        remaining -= p.Share;
    });

    foreach(var person in persons)
    {
        if (remaining < 1) break;

        person.Share ++;
        remaining--;
    }
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/23 17:40

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

    キャンセル

checkベストアンサー

+3

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

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


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

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/23 18:50

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

    キャンセル

+3

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

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

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

  • あくまで(誰か一人の)分配数を返したい
    引数でメンバーの誰かを指定できるようにする。
  • 戻り値の仕様を変更してもいいなら
    分配数のリストを返すようにする(papinianusさんの回答)
  • 戻り値が無くてもいいなら
    関数内で各メンバーの分配数を設定する(hihijijiさんの回答)

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/23 18:54

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

    キャンセル

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

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

関連した質問

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