【ABC305】FortranでA,B,C問題


## A - Water Station
問題は[こちら](https://atcoder.jp/contests/abc305/tasks/abc305_a)です。
回答は以下の通りです。

**Nを5で割った際の少数点以下(Ansとします)の値を使い、最寄りの給水所を探します。**

具体的には、少数点以下の値によって３パターンの場合分けを行います。
    ①　Ans = 0.0：給水所にいます。
    ②　Ans > 0.5：１つ先の給水所が近いです。
    ③　Ans < 0.5：１つ前の給水所が近いです。

```Fortran
program ABC305a
    implicit none
    real N, kyori_5, kyori_mod, Ans
    !入力
    READ (*, *) N
    !
    kyori_5 = int(N/5)
    Ans = N/5 - kyori_5
    kyori_mod = mod(N, 5.0)

    !最寄りの給水所の場合分け
    if (kyori_mod == 0) then
        write (*, *) int(N)
    else if (Ans > 0.5) then
        Ans = kyori_5*5 + 5
        write (*, *) int(Ans)
    else
        Ans = kyori_5*5
        write (*, *) int(Ans)
    end if
end
```

## B - ABCDEFG 
問題は[こちら](https://atcoder.jp/contests/abc305/tasks/abc305_b)です。
回答は以下の通りです。

初めに各文字間の距離を登録しておきます。
**pとqの入力後、始点となる文字を探し、そこから終点の文字が見つかるまで距離を累加していきます。**

ただし、pとqのどちらが始点になるかはわかりません。
そこで今回は、pとqは予め昇順に並び替えておきました。

`なお、昇順に並び替える際の比較、始点、終点の検索は文字をASCIIコードに変換する事で行なっています。`
[ASCIIコードはこちらにまとめられています。](http://www3.nit.ac.jp/~tamura/ex2/ascii.html)

```Fortran
program ABC305b
    implicit none
    integer i, j
    integer Ans
    character(1) p, q, kari
    integer kyori(6)
    data kyori/3, 1, 4, 1, 5, 9/
    !入力
    read (*, *) p, q
    !昇順に並び替え
    if (iachar(p) > iachar(q)) then
        kari = p
        p = q
        q = kari
    end if

    !距離の計算
    Ans = 0
    do i = 65, 71
        if (iachar(p) == i) then
            do j = i + 1, 71
                if (iachar(q) == j) then
                    Ans = Ans + kyori(j - 65)
                    write (*, *) Ans
                    stop
                else
                    Ans = Ans + kyori(j - 65)
                end if
            end do
        end if
    end do
end

```


## C - Snuke the Cookie Picker 
問題は[こちら](https://atcoder.jp/contests/abc305/tasks/abc305_c)です。
回答は以下の通りです。

初めにグリッド上を全て調べ、**各行でクッキーが連続して配置されている開始地点と終了地点を調べます。**
例えば、
    ...###.##..
なら開始地点が4、終了地点が6になります。
この操作によって、開始地点と終了地点の情報が各行ごとに得られます。


次に、開始地点の最小値(以下、最小値)と終了地点の最大値(以下、最大値)を求めます。
例えば、
    ....
    .##.
    .###
    .###
    .###
なら、最小値が2、最大値が4になります。

ここで上記の例からも分かる様に、**クッキーが欠けている行以外は、開始地点と終了地点の値がどちらも最小値、最大値と同じ値になります。**

**従って、クッキーの開始地点と終了地点が最大値、最大値と一致しない行がクッキーが欠けている行になります。**
先ほど例で言うと、2行目の終了地点が3になっており最大値と一致していません。

最後に対象の行のマスを１つずつ調べ、その中から欠けている部分を探します。

```Fortran
program ABC305c
    implicit none
    integer i, j
    integer H, W, cnt_min, cnt_max
    character(:), allocatable :: c(:)
    integer, allocatable:: cnt_cookie(:, :)

    !値の入力
    read (*, *) H, W
    allocate (character(W) :: c(H))
    allocate (cnt_cookie(H, 2))
    read (*, *) (c(i), i=1, H)

    !初期化
    cnt_cookie = 0
    cnt_min = 100000
    cnt_max = 0

    !クッキーの位置の収集
    do i = 1, H
        do j = 1, W
            if (c(i) (j:j) == '#') then
                call cookie(j, W, c(i), cnt_cookie(i, 1), cnt_cookie(i, 2))
                if (cnt_min > cnt_cookie(i, 1)) cnt_min = cnt_cookie(i, 1)
                if (cnt_max < cnt_cookie(i, 2)) cnt_max = cnt_cookie(i, 2)
                exit
            end if
        end do
    end do

    !欠けたクッキーの検索
    do i = 1, H
        if (cnt_cookie(i, 1) /= 0) then
            if (cnt_cookie(i, 1) /= cnt_min .or. cnt_cookie(i, 2) /= cnt_max) then
                do j = cnt_min, cnt_max
                    if (c(i) (j:j) /= '#') then
                        write (*, *) i, j
                        stop
                    end if
                end do
            end if
        end if
    end do
contains

    !クッキーのスタート位置、エンド位置の検索
    subroutine cookie(j, W, c, start, end)
        integer j, k, W, start, end
        character(W) c
        start = j
        do k = j, W
            if (c(k:k) == '.') then
                end = k - 1
                return
            end if
        end do
        end = W
    end subroutine
end program
```


## 余談
<details><summary> 感想</summary><div>

- 今回もB問題まで解けました。
- B問題の難易度は文字に関する処理かどうかで難易度が上下する気がします。(Fortranだと特に)
- C問題はACにならないケースの原因探してたら終わりました。
</div></details>