[itbase2024]Fortran 入出力・条件分岐・繰り返し 練習問題

練習問題 1

「入出力」の資料 (こちら) で使った input.txt のファイルに書かれた数字を読んで画面に書くプログラムを作りなさい. ただし, ファイルの中の複数行の数値を読むために繰り返し (do ループ) を使うこと.

ヒント

  • 「入出力」の資料 (こちら) のプログラム例の inputfromfile.f90 を改良すると良いでしょう.

練習問題 2

練習問題 1 で作ったプログラムを変更し, ファイルに書かれた数字を配列に読むようにしなさい.

ヒント

  • 下のような配列を宣言して read 文で数値を配列に読み込むと良い

    integer :: val1(5)
    integer :: val2(5)

練習問題 3

次の関数 f(x) を考える.

f(x) = sin(x) * cos(2*x)

0 <= x <= 4*pi (pi は円周率) の範囲にわたって f(x) の値を計算し, x の値と f(x) の値をファイルに出力するプログラムを作りなさい. そして, 出力した結果のファイルを, gnuplot を使ってグラフにしなさい. なお, プログラムでの f(x) の値の計算では, 0 <= x <= 4*pi の範囲を 0.125 おきに, x = 0.000, 0.125, 0.250, ... の値を計算すること.

さらに, gnuplot では

gnuplot> plot sin(x)*cos(2*x)

によってグラフを描けるので, プログラムで計算して得たグラフと plot sin(x)*cos(2*x) のグラフを重ね書きして, 正しい値を計算できていることを確認すること.

出力例

$ ./calcfx
 0.00000000       0.00000000
 0.125000000      0.120798893
 0.250000000      0.217117399
 0.375000000      0.267997533
 0.500000000      0.259034723
 0.625000000      0.184494242
 0.750000000       4.82172184E-02
 ...

ヒント

  • 繰り返しを使って x = 0.000, 0.125, 0.250, ... の値を求めましょう.
  • それぞれの x の値に対して f(x) を計算しましょう.
  • x と f(x) の値をファイルに出力しましょう.
  • プログラム例 (この例は画面に数字を出力します. ファイルに出力するように変更してください.)

練習問題 4

1 から 1000 までのフィボナッチ数列を計算するプログラムを作りなさい. フィボナッチ数列とは, 最初の 2 つの数値が 1 で, それ以降の数値が 直前の数値 2 つの和になっている数列です: 1, 1, 2, 3, 5, 8, ...

ヒント

  • 順番に少しずつ作ってみましょう.
  • 最初の 2 つの数値を入れる変数 (「変数1」と「変数2」) を用意しましょう.
  • 二つの数値の和を入れる変数 (「変数3」) を用意しましょう.
  • 変数1と変数2の和を変数3に代入して, それを出力しましょう.
    • この式はその後も使う一般形です.
  • 次の数値は, この時点で変数2と変数3に入っている数値の和です. この和を上の一般形の式で計算するにはどのようにしたらよいでしょうか.
  • プログラム例

練習問題 5

キーボードから整数を入力し, その数値が素数かどうかを調べるプログラムを 作りなさい.

ヒント

  • 順番に少しずつ作ってみましょう.
  • キーボードから整数を入力しましょう.
  • 素数かどうか判定しましょう.
    • 素数とは何であったのかを思い出してみましょう.

練習問題 6

1 から 99 までの整数を表示させ, 3 の倍数および 3 がつく整数の時にだけ「アホになる」プログラムを作りなさい. 「アホになる」は「"Aho!" と出力する」の意味です.

余裕があれば, 99 までと言わず, 任意の数までで正しい答えが出るような プログラムにしなさい.

出力例

$ ./nabeatsu
         1
         2
         3  Aho!
         4
         5
         6  Aho!
         7
         8
         9  Aho!
        10
        11
        12  Aho!
        13  Aho!
       ...

ヒント

  • 順番に少しずつ作ってみましょう.
  • 繰り返しを使って 1 から 99 までの整数を出力しましょう.
  • 1 から 99 までの整数のうち, 3 の倍数の時に "Aho!" と出力するように変更しましょう.
  • 上に加えて, 3 がつく整数の時に "Aho!" と出力するように変更しましょう.
    • 3 がつく数字であるかどうかをどのように判定すればよいか考えてみましょう.

練習問題 7

100 個の乱数を, その試行回数とともにファイルに保存する プログラムを作りなさい.

出力例

出力を保存したファイルの中身の例は下のようになります.

$ cat random.txt                    <- 結果を保存したファイルの中身を表示
         1  0.997559547
         2  0.566824675
         3  0.965915322
         4  0.747927666
         5  0.367390871
         6  0.480636895
         7   7.37542510E-02
         8   5.35517931E-03
         9  0.347081244
         ...

この例の 1 カラム目が試行回数で, 1 回目, 2 回目, 3 回目, ... を表します. 2 カラム目が生成された乱数です. (別の言い方をすると, 1 番目の乱数, 2 番目の乱数, 3 番目の乱数, ... です.)

gnuplot でグラフを描く際には, 1 カラム目を横軸, 2 カラム目を縦軸として, 点がランダムに分布していることを確認しなさい.

ヒント

  • 乱数は自分で計算して生成しても良いですが, Fortran で乱数を使う方法が予め準備されています. <ここ>を参考にしてみましょう.
  • プログラム例

練習問題 8

モンテカルロ法 (ヒント参照) を使って, 円周率 (の近似値) を求めるプログラムを作りなさい.

ヒント

  • プログラムでは, 乱数を使うことが良くあります. 乱数を使ったプログラミング手法は, 総称としてモンテカルロ法と呼ばれています.
  • 順番に少しずつ作ってみましょう.
  • ひとつ前の問題にならって, 多数の乱数を生成するプログラムを作りましょう.
  • モンテカルロ法で円周率の近似値を求めるには, 半径 1 の円の面積がπであることを使います. <ここ>の説明を参考にしてみましょう.

練習問題 9

<このデータファイル>は, 2017 年のゴルフマスターズトーナメントの 最終結果です.

左に競技者の名前, 右に打数を載せており, 競技者の Family name の アルファベット順に並んでいます. このリストを, 成績の優秀な順に並び替えて出力するプログラムを 作りなさい.

ヒント

  • 順番に少しずつ作ってみましょう.
  • ファイルの中の名前 (First name, Family name) と打数を読み込むための配列を用意し, 配列にファイルの内容を読み込みます.
  • データを打数の少ない順に並び替えます.
    • 並び替え (ソート) の方法は自分で考えてみると面白いと思いますが, 効率的な方法がいくつか考案されていますので, ここでは, 最も簡単な方法の 一つである「バブルソート」に基づいて, 簡単に説明しておきます.
    • 方法の中心的な部分は, ある行 (データ) の打数を一つ前の行の打数と比較し, 一つ前の行の打数よりも小さければ置き換えることです. そうでなければ何もしません.
    • これを一番最後の行から順に, 前に向かって繰り返し, 一番前の行まで繰り返します.
    • 次に, 同じことを最後の行から前に向かって, 二行目まで繰り返します.
    • 次に, 同じことを最後の行から前に向かって, 三行目まで繰り返します.
    • ...
    • 同じことを繰り返し, 最後の行までたどり着いたら行 (データ) の並び替えは終了です. この結果として, データ (行) は打数が少ない順に上から並んでいるはずです.
  • プログラム例 (データの読み込みのみ)