paizaラーニング 翌営業日 - その2 (paizaランク B 相当)

[paizaのレベルアップ問題集](https://paiza.jp/works/mondai/dateset/working_day_2?language_uid=c-sharp&t=6c0424e940bcda83212220621be45aa3)をYoutubeの解説動画を視聴する前に解いたもの

```c#

    class Program
    {
        static void Main(string[] args)
        {
            string[] input = Console.ReadLine().Trim().Split(' ');
            int M = int.Parse(input[0]);
            int D = int.Parse(input[1]);
            string d = input[2];
            //曜日を数値に変換
            int day = 0;
            switch (d)
            {
                case "SUN":
                    day = 0;
                    break;
                case "MON":
                    day = 1;
                    break;
                case "TUE":
                    day = 2;
                    break;
                case "WED":
                    day = 3;
                    break;
                case "THU":
                    day = 4;
                    break;
                case "FRI":
                    day = 5;
                    break;
                case "SAT":
                    day = 6;
                    break;
            }

            int[] nextWorkingDay = new int[2]; //翌営業日の日付
            do
            {//月～木、日なら翌日が営業日
             //金なら3日後が営業日
             //土なら2日後が営業日
                switch (day % 7)
                {
                    case 5:
                        {
                            nextWorkingDay = NextWorkingDay(M, D, 3);
                            M = nextWorkingDay[0];
                            D = nextWorkingDay[1];
                            day += 3;
                            break;
                        }
                    case 6:
                        {
                            nextWorkingDay = NextWorkingDay(M, D, 2);
                            M = nextWorkingDay[0];
                            D = nextWorkingDay[1];
                            day += 2;
                            break;
                        }
                    default:
                        {
                            nextWorkingDay = NextWorkingDay(M, D, 1);
                            M = nextWorkingDay[0];
                            D = nextWorkingDay[1];
                            day++;
                            break;
                        }
                }
            } while (isPublicHoliday(M, D)); //翌営業日が祝日ならば次の営業日を求める
            Console.WriteLine("{0}月{1}日", nextWorkingDay[0], nextWorkingDay[1]);
        }
        //2019年の祝日かどうかを判断
        static bool isPublicHoliday(int month, int day)
        {
            List<int[]> publicHoliday = new List<int[]>();
            publicHoliday.Add(new int[] { 1, 1 });
            publicHoliday.Add(new int[] { 1, 14 });
            publicHoliday.Add(new int[] { 2, 11 });
            publicHoliday.Add(new int[] { 3, 21 });
            publicHoliday.Add(new int[] { 4, 29 });
            publicHoliday.Add(new int[] { 4, 30 });
            publicHoliday.Add(new int[] { 5, 1 });
            publicHoliday.Add(new int[] { 5, 2 });
            publicHoliday.Add(new int[] { 5, 3 });
            publicHoliday.Add(new int[] { 5, 4 });
            publicHoliday.Add(new int[] { 5, 5 });
            publicHoliday.Add(new int[] { 5, 6 });
            publicHoliday.Add(new int[] { 7, 1 });
            publicHoliday.Add(new int[] { 7, 15 });
            publicHoliday.Add(new int[] { 8, 11 });
            publicHoliday.Add(new int[] { 8, 12 });
            publicHoliday.Add(new int[] { 9, 16 });
            publicHoliday.Add(new int[] { 9, 23 });
            publicHoliday.Add(new int[] { 10, 14 });
            publicHoliday.Add(new int[] { 10, 22 });
            publicHoliday.Add(new int[] { 11, 3 });
            publicHoliday.Add(new int[] { 11, 23 });

            return publicHoliday.Any(n => n[0] == month && n[1] == day);
        }
       
        //日付から何日後の日付を求める
        static int[] NextWorkingDay(int month, int day, int a)
        {
            for (int i = 0; i < a; i++)
            {
                //翌日の日付を求める
                day++;
                //月末を超えていた場合
                if (day > lastDay(month))
                {
                    day = 1;
                    month++;
                }
                if (month > 12)
                {
                    month = 1;
                }
            }
            return new int[] { month, day };
        }
        //各月の最終日を返す
        static int lastDay(int month)
        {
            switch (month)
            {
                case 2:
                    return 28;
                case 4:
                case 6:
                case 9:
                case 11:
                    return 30;
                default:
                    return 31;
            }
        }
    }
}
```
###課題
要素がint[]型のListにある値が含まれているかを判断するのに当初は以下のようにcontainsメソッドを使ったが上手くいかなかった。

````c#
List<int[]> publicHoliday = new List<int[]>();
            publicHoliday.Add(new int[] { 1, 1 });
            publicHoliday.Add(new int[] { 1, 14 });
            publicHoliday.Add(new int[] { 2, 11 });
            publicHoliday.Add(new int[] { 3, 21 });
           
return publicHoliday.Contains(new int[] { month, day });
````
[ここ](https://www.urablog.xyz/entry/2018/06/10/070000)に書いてあるようにインスタンスの参照先が違うから上手くいかなかった？
とりあえず[こちらの](https://www.atmarkit.co.jp/ait/articles/1703/15/news019.html)以下の記述を読んで適当に書き直した。

````c#
List<int> list = new List<int> {1,2,3,4,5,6,7,8,9,10,};

// 偶数が含まれているかどうかを調べる
// 【1】LINQのAny拡張メソッド
bool result1 = list.Any(n => n % 2 == 0);
WriteLine(result1);
// 出力：True

// 【2】List<T>クラスのExistsメソッド
bool result2 = list.Exists(n => n % 2 == 0);
WriteLine(result2);
// 出力：True
````
###追記
[Youtubeの解説動画](https://www.youtube.com/watch?v=VejSTRCVbjQ&t=1802s)を視て書き直したもの

```c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NextWorkingDayModelAnser
{
    class Program
    {
        static int dayToInteger(string d)
        {
            switch (d)
            {
                case "SUN":
                    return 0;
                case "MON":
                    return 1;
                case "TUE":
                    return 2;
                case "WED":
                    return 3;
                case "THU":
                    return 4;
                case "FRI":
                    return 5;
                case "SAT":
                    return 6;
                default:
                    throw new Exception();
            }
        }
        static int[] tomorrow(int M, int D, int d)
        {
            d = (d + 1) % 7;
            switch (M)
            {
                case 2:
                    if(D == 28)
                    {
                        return new int[] { 3, 1, d };
                    }
                    break;
                case 4:
                case 6:
                case 9:
                case 11:
                    if(D == 30)
                    {
                        return new int[] { M + 1, 1, d };
                    }
                    break;
                default:
                    if(D == 31)
                    {
                        return new int[] { M + 1, 1, d };
                    }
                    break;
            }
            return new int[] { M, D + 1, d };
        }

        static List<int[]> Holidays = new List<int[]>()
        {
            new int[]{1,1},
            new int[]{1,14},
            new int[]{2,11},
            new int[]{3,21},
            new int[]{4,29},
            new int[]{4,30},
            new int[]{5,1},
            new int[]{5,2},
            new int[]{5,3},
            new int[]{5,4},
            new int[]{5,5},
            new int[]{5,6},
            new int[]{7,1},
            new int[]{7,15},
            new int[]{8,11},
            new int[]{8,12},
            new int[]{9,16},
            new int[]{9,23},
            new int[]{10,14},
            new int[]{10,22},
            new int[]{11,3},
            new int[]{11,23}
        };

        static bool isHoliday(int M, int D)
        {
            int[] date = new int[] { M, D };
            return Holidays.Any(n => n[0] == M && n[1] == D);
        }
        static int[] nextBusinessDate(int M, int D, int d)
        {
            int[] nextDate = tomorrow(M, D, d);
            M = nextDate[0]; 
            D = nextDate[1];
            d = nextDate[2];
            if(d == 0 || d == 6) {  //日曜化土曜
                return nextBusinessDate(M, D, d);
            }
            else if (isHoliday(M, D))
            {
                return nextBusinessDate(M, D, d);
            }else{
                return new int[] { M, D };
            }
        }
        static void Main(string[] args)
        {
            string[] input = Console.ReadLine().Trim().Split(' ');
            int M = int.Parse(input[0]);
            int D = int.Parse(input[1]);
            int d = dayToInteger(input[2]); //曜日を０から６に変換する
            int[] date = nextBusinessDate(M, D, d);　//date[0]: 月、 date[1]: 日
            Console.WriteLine("{0}月{1}日",date[0],date[1]);
        }
    }
}
```
メソッドの再帰呼び出しが勉強になった。