先週の課題

まずは先週の課題を片付けましょう。

今週の問題

Zeller の公式

Zeller の公式を用いると,年月日から曜日を調べることができる. y を西暦年,m を月,d を日として,

w = y + [y/4] - [y/100] + [y/400] + [2.6*m + 1.6] + d

で整数 w を定義する. この w を 7 で割った余りが曜日となる(0 から 6 が日曜日から土曜日に対応する). ただし,1月と2月は前年の13月と14月とすること (例えば,2001年1月20日の曜日を計算する場合,2000年13月20日として上式に代入する). [x] はガウス記号で x を超えない整数を表す.

Zeller の公式を Fortran プログラムとして書くと次のようになる.

w = y + y/4 - y/100 + y/400 + (13*m+8)/5 + d

ただし,1月と2月の場合の修正を加えた年月日が整数 y, m, d である.

年月日を表す3つの整数 year, month, day を引数とし,曜日に対応する整数を返す関数 zeller(year, month, day) を定義せよ. 1月と2月の場合に,不用意に仮引数を変更しないように気をつけること. 動作検証用に今日の曜日を調べるメインプログラムも作成せよ.

!------------------------------------------------------------
! Zeller の公式
! 西暦年月日 (year, month, day) を入力すると日曜日から土曜日に対応する
! 整数 0, 1, ..., 6 を返す.有効範囲は 1583 年から 3999 年(未確認)
!------------------------------------------------------------
integer function zeller(year, month, day)
  implicit none
  integer, intent(IN) :: year, month, day
  ! 作業用の変数
  integer :: y, m, d, w

  ! year, month, day を変更しないように作業変数にコピー
  y = year
  m = month
  d = day

  ! 1, 2 月の場合の修正
  if (m == 1 .OR. m == 2) then
     !*****************************************************************
     ! この部分を考えましょう
     !*****************************************************************
  end if

  ! Zeller の公式(w を求める)
  !*****************************************************************
  ! この部分を考えましょう
  !*****************************************************************

  ! w を 7 で割った余りが曜日になる
  zeller = mod(w, 7)

  return
end function zeller

!------------------------------------------------------------
! 今日の曜日を調べる
!------------------------------------------------------------
program test
  implicit none
  integer :: zeller

  write(*,*) zeller(2113, 12, 9)

  stop
end program test

Zeller の公式 (2)

西暦2000年から2999年の1000年間に13日の金曜日は何回あるか.

覆面算

次の覆面算の解を求めるプログラムを作成し,実際に解を求めよ.

   KYOTO
+) OSAKA
────────
   TOKYO

ただし,解は次の条件を満たすものであること.

ヒント: 文字ごとに do ループを回せばよい. 異なる文字に同じ数字が入っている場合は cycle 文でループをスキップする. cycle 文が実行されると処理がその do ループの最後に移動し,結果的にループの次の繰り返しに移る.