AOJをC#で解く②~ITP1_2~

#はじめに
[前回の記事](https://qiita.com/hikarutakenouch/items/4e1cfe582a20546b7643)はAOJのITP1_1について解説しました。

今回は[AOJ](https://onlinejudge.u-aizu.ac.jp/home)の[ITP1_2](https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/2)の解説です。

#[ITP1_2](https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/2)
ITP1_2は条件分岐がテーマになっています。if文が出てくるかんじですね。

##A問題 - [Small, Large or Equal](https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/2/ITP1_2_A)

**問題**
２つの整数 a, b を読み込んで、a と b の大小関係を出力するプログラムを作成して下さい。

**制約**
-1,000 ≤ a, b ≤ 1,000

**数値例**
1)
*input* : 1 2
*output* : a < b

2)
*input* : 4 3
*output* : a > b

3)
*input* : 5 5
*output* : a == b

---

**解法**
数値を読み込んで、if文で、

- a < b
- a > b
- a == b

の3つに条件分岐するだけです。

```ITP1_2_A.cs
using System;

namespace ITP1_2_A
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] s = Console.ReadLine().Split();
            int a = int.Parse(s[0]);
            int b = int.Parse(s[1]);

            if (a < b)
            {
                Console.WriteLine("a < b");
            }
            else if (a > b)
            {
                Console.WriteLine("a > b");
            }
            else
            {
                Console.WriteLine("a == b");
            }
        }
    }
}

```

**コメント**
if文は二つの分岐のときは`if`と`else`で、3つ以上の分岐の時は、`if`と`else if`で最後の分岐が`else`となります。あと最後の`else`の時は()の条件指定は必要ないです。

なお、入力の部分のやり方は、`string`型の配列で読み込み、それを`int`型に変換するというやり方をとっています。けっこうよく使うので覚えておくといいです。

##B問題 - [Range](https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/2/ITP1_2_B)
**問題**
３つの整数a, b, cを読み込み、それらが a < b < cの条件を満たすならば"Yes"を、満たさないならば"No"を出力するプログラムを作成して下さい。

**制約**
0 ≤ a, b, c ≤ 100

**数値例**
1)
*input* : 1 3 8
*output* : Yes

2)
*input* : 3 8 1
*output* : No

---
**解法**
a < b < c であることを判定すればよいので、if文の条件式をが`a < b && b < c`であればYes、そうでなければNoを返すプログラムにすればよいです。`a < b < c`と一気に書くことはできないので、ANDを表す論理演算子`&&`を使います。ちなみにORを表したい場合は`||`です。

```ITP1_2_B.cs
using System;

namespace ITP1_2_B
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] x = Console.ReadLine().Split();
            int a = int.Parse(x[0]);
            int b = int.Parse(x[1]);
            int c = int.Parse(x[2]);

            if (a < b && b < c)
            {
                Console.WriteLine("Yes");
            }

            else
            {
                Console.WriteLine("No");
            }
        }
    }
}

```
**コメント**
特にないですが、書いていて自分ですごく気になったのがなんで`a < b < c`という書き方はできないのかってことですね。ゴリゴリの機械学習エンジニアやってる友だちによると、この書き方をサポートしている言語もあって構文解析がめんどくさいからではないかということを言われました。slackでぱって聞いただけだったので、今度ちゃんと話聞いたり、いろいろ調べてまとめようと思います。

##C問題 - [Sorting Three Numbers](https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/2/ITP1_2_C)
**問題**
３つの整数を読み込み、それらを値が小さい順に並べて出力するプログラムを作成して下さい。

**制約**
1 ≤ ３つの整数 ≤ 10,000

**数値例**
*input* : 3 8 1
*output* : 1 3 8


---
**解法**
いくつか解き方があります。最も基本的なのは、3つの数値の大小関係を把握して大きい順に並び替えて出力するというものです。B問題の要領で、

- `a < b && b < c`：そのまま出力
- `a < b && b > c`：`a < c`と`a > c`の場合で分けて出力。
- `a > b && b < c`：`a < c`と`a > c`の場合で分けて出力。

という形式になると思います。

今回僕がやってるのはLINQというC#のライブラリを使っています。
`int[] x = Console.ReadLine().Split().Select(int.Parse).ToArray();`
これは`Console.ReadLine().Split()`で読み込んだ文字列を`Select(int.Parse)`でint型に変換し、`ToArray`で配列に格納しています。

そしてここからがLINQのすごく便利なところなのですが、Sortメソッドを使えば、一発で昇順に並び替えてくれます。あとはそれを出力するだけです。

```ITP1_2_C.cs
using System;
using System.Linq;

namespace ITP1_2_C
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] x = Console.ReadLine().Split().Select(int.Parse).ToArray();

            Array.Sort(x);
            Console.WriteLine(x[0] + " " + x[1] + " " + x[2]);
        }
    }
}

```
**コメント**
LINQについては僕もまだまだ学んでる途中なのですが、すごく便利なのでC#やる時は調べとくといいです！特に配列などの処理は便利なものが多いのです！！

##D問題 - [Circle in a Rectangle](https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/2/ITP1_2_D)
**問題**
長方形の中に円が含まれるかを判定するプログラムを作成してください。次のように、長方形は左下の頂点を原点とし、右上の頂点の座標 (W,H) が与えられます。また、円はその中心の座標 (x,y) と半径 r で与えられます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/326440/b9f38a6a-c579-a232-89c5-57706fe3895f.png)


**制約**

- 100≤x,y≤100
- 0<W,H,r≤100


**数値例**
1)
*input* : 5 4 2 2 1
*output* : Yes

2)
*input* : 5 4 2 4 1
*output* : No


---
**解法**
だめなパターンは何か？を考えると解けます。

まずxとyがともに正の値を取る第一象限にある場合は、

- x + r > W
- y + r > H

となる時がだめなパターンです。

次に、xまたはyが負の値を取るときもだめなパターンです。
なのでこれのパターンをコードに落として、if文の条件文に入れたらおっけーです。その際、ANDじゃなくてORで記述することに気をつけて。


```ITP1_2_D.cs
using System;

namespace ITP1_2_D
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] i = Console.ReadLine().Split(' ');

            int W = int.Parse(i[0]);
            int H = int.Parse(i[1]);

            int x = int.Parse(i[2]);
            int y = int.Parse(i[3]);
            int r = int.Parse(i[4]);

            if (x < 0 || y < 0 || x + r > W || y + r > H)
            {
                Console.WriteLine("No");
            }
            else
            {
                Console.WriteLine("Yes");
            }
        }
    }
}

```
**コメント**
今回のようにダメなパターンをだして潰すというやり方はけっこう有効な場合が多いので、問題解決のメソッドとして身につけておくとよいと思います。競プロだけでなく他の多くの事象にも当てはまると思うので。

#さいごに
読んでくれてありがとうございます。
説明の過不足や言葉の誤用あれば指摘オネガイシマス。（ないはずだが...）