Help us understand the problem. What is going on with this article?

[Fortran] H行W列からなる文字列をいい感じに受け取る [AtCoder]

はじめに

AtCoderの問題では、縦$H$行、横$W$列からなるマス目の状態を文字列で与えられます。これを受け取るプログラムをワンライナーで書こうとしましたが僕の力では出来ませんでした。

入力の仕様(例)

整数$W$,$H$と、$H$個の長さ$W$の文字列$S_i (1 \le i \le H)$が与えられます。$S_i$の$j$文字目の文字は上から$i$行目、左から$j$列目を表しています。

W H
S_1
S_2
:
S_h

入力例

5 3
abcde
fghij
klmno

自然な実装

まずは自然な受け取り方を考えます。入力の仕様から考えても、「長さ$W$の文字列要素を$H$個持つ配列」を用意すれば良さそうです。

program main
    use,intrinsic :: iso_fortran_env
    implicit none
    integer(int32):: w,h,i
    character(:),allocatable:: s(:)

    read*, w,h
    allocate(character(w):: s(h))
    read*, (s(i), i=1,h)

end program main

出来ました。これで十分な気がします。readしてる行の(..., i=1,h)というのはimplied doと言うやつです。[(i, i=1,10)]で、要素が1 2 3 4 5 6 7 8 9 10の配列を返します。Pythonの内包表記のような感じです。

欠点

$i$行$j$列目の要素にアクセスするときにちょっと面倒です。

    print*, s(i)(j:j) ! i行j列目の文字を表示

あと行と列でデータの持ち方が違う(文字列と文字配列)というのも気持ちが悪いですし、Row-majorなのも腹が立ちます。

いい感じにデータをもたせる

program main
    use,intrinsic :: iso_fortran_env
    implicit none
    integer(int32):: w,h,i
    character(1),allocatable:: s(:,:)
    character(:),allocatable:: lines(:)

    read*, w,h
    allocate(character(w):: lines(h))
    allocate(s(w,h))
    read*, (lines(i), i=1,h)
    s(:,:) = reshape([(transfer(lines(i),s(:,i)), i=1,h)], [w,h])
end program main

このように受け取るといい感じです。先程のデータの持ち方はlinesにやらせており、implied doとtransferとreshapeを使った前衛的なコードによって、1文字を2次元の配列で持つsにわたしています。

$i$行$j$列目の要素にアクセスするときはこのように書けます。

    print*, s(j,i) ! i行j列目の文字を表示

Column-majorでいい感じです。

欠点

先程より複雑になってしまいました。いっそのことライブラリにしてしまうのはどうでしょうか。

function read_grid(w,h) result(s)
    integer(int32),intent(in):: w,h
    character(1):: s(w,h)
    character(w):: lines(h)
    integer(int32):: i

        read*, (lines(i), i=1,h)
        s = reshape([(transfer(lines(i),s(:,i)), i=1,h)], [w,h])
end function

allocateしなくて良い分やや楽

使い方

program main
    use,intrinsic :: iso_fortran_env
    implicit none
    integer(int32):: w,h
    character(1),allocatable:: s(:,:)

    read*, w,h
    s = read_grid(w,h)
end program main

なかなか便利なライブラリじゃないでしょうか。

まとめ

いい感じの受け取り方を紹介+ライブラリ化をしました

Authns
python fortran atcoder緑 ゲーム作成 分子動力学法
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away