メインコンテンツへスキップ
見出し画像

【擬似言語②裏2】うるう年と通日 | ifの順番(基本情報技術者, 科目B, アルゴリズム)

    このNoteでは、「うるう年判定」と「通日計算(1月1日からの日数)」の擬似言語をテーマにします。

    「うるう年」は、実は「4年毎」とは限りません。例えば2000年は閏年ですが、2100年は閏年じゃないんです。1900年も違う。でも2400年は閏年。

    今回はif文で、正しく分岐する考え方を学びます。科目Bの問01によく出る問題です。

    テキストの基礎を生かして、プログラム的な考察/工夫を学んでいきます。基礎と実用にギャップを感じる方のために作りました。
    >【FEB】擬似言語の教科書Note

    ぜひ一緒に学習を進めていきましょう!


    このNoteは、私がIT専門学校で授業したことを基に作成しています。IT専門学校でFEは第一目標として、カリキュラムが構築されています。何も知らずに入学しても、1年生10月にはFE合格していきますよ。実績ある教育ノウハウを詰め込んだので、少しでも信頼して頂けたら嬉しいです。

    >全Noteへのリンク(FE節)
    ※科目Aのテーマ別/科目B/旧FE午後など沢山作りました!


    うるう年は、4年毎だけじゃなかった!

    「閏年は4年おき」。2000年は閏年なので、4年前の1996年も、4年後の2004年も閏年。確かに。

    下図はwindowsの右下のカレンダー。ご自分でも確かめて見て下さいね。ちょっと面白い。

    画像

    でも違うみたいですよ。

    画像

    2100年は2000年から100年後(=4年×25回)なので、閏年のはずですが、なぜか違います(平年)。でも2096年と2104年は閏年。

    閏年の条件は「4年おき」の他に2つあり(wikipedia, wikipedia数式)。

    • 4で割り切れる年は閏年。

    • でも100で割り切れる年は平年。

    • 400で割り切れる年は【必ず】閏年。

    100年毎、400年毎に注意が必要です。

    2100年が平年なのは「100で割り切れる年」だから。2200年も2300年も平年。

    2000年が閏年だったのは、「400で割り切れる年」だったから。「100で割り切れる年」だけど「400で~【必ず】閏年」なので。

    2400年も100で割り切れますが、400で割り切れるので閏年。




    条件とデータの抜け方

    3つの条件の順番。

    ごちゃごちゃ解説するより、図解を見れば良いでしょう。フローチャートに、簡単なデータをぶち込んで、正しく分岐するか。>擬似言語の解法11Note(2)

    画像
    画像
    画像




    400で割り切れるでOK?

    さて「2000を閏年、2100年を平年にするなら、200で割り切れる、でも良いのでは?」と思った方。鋭い!

    2100年が平年
    2000年が閏年
    1900年が平年
    1800年が閏年
    になるなら、200割りで判断できますね。

    残念。2000年の200年前1800年は、閏年じゃないです(uic社さんのカレンダー)。

    画像

    もっと遡って、1600年に閏年がありました。2000年から400年前。よって「400で割り切れる」を判定に使ってるんです。

    画像

    2000年は400年に一度の閏年だったんですね(語彙力)。2400年と2800年も閏年になってました。

    画像

    この頃には、月や火星旅行・深海とか行けるのでしょうか。

    攻殻機動隊みたいに義体化で、目が見えない人も義眼で見えるようになったり。電脳化でネット接続できたり、記憶の外部化ができたり。タチコマ(多脚思考戦車)もいたり。

    ドラゴンボールはどうなってるのか。ドラクエとFFはいくつになってるんでしょうか。楽しみですね!

    今も面白いけど。もっと/違った面白い世界になってて欲しいです。




    うるう年か判定する関数

    閏年判定のアルゴリズムが決まったので擬似言語にします。

    画像
    / true: うるう年, false: 平年*/
    ○論理型: isLeapYear(整数型: year)
      論理型: result  
    
      if ( year mod 400 が 0 に等しい) / うるう年 */
        result ← true  
      elseif ( year mod 100 が 0 に等しい) / 平年 */
        result ← false
      elseif ( year mod 4 が 0 に等しい) / うるう年 */
        result ← true
      else
        result ← false / 平年 */
      endif
    
      return result

    条件分岐の設計は完璧だったので組むだけでした。閏年である/ないをTrue/Falseで分けてるのがちょっとややこいかな。

    関数の上(or下)に意味をコメントすれば、後でも困らないかな。




    通日 = 前月までの日数 + 当月の日数

    通日を計算する擬似言語を組みます。

    各月の日数は、計算で求められないので、配列daysInMonth[]に予め登録しておきます。複雑なジャンケン勝敗表/ポケモンの属性ダメージ補正など同じ手口。>【擬似言語②裏】ジャンケンの結果テーブルのNote

    ○整数型: calculateDayOfYear(整数型: year, 整数型: month, 整数型: day)
      整数型の配列: daysInMonth ← {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
      整数型: totalDays ← 0, i
      
      / 閏年判定関数を呼び出して2月の日数を調整 */
      if (isLeapYear(year) = true)
        daysInMonth[2] ← 29
      endif
      
      / 前月までの合計日数を加算 */
      for (iを 1から month - 1 まで 1ずつ増やす)
        totalDays ← totalDays + daysInMonth[i]
      endfor
      
      / 当月の日数を加算 */
      totalDays ← totalDays + day
      
      return totalDays

    うるう年判定をして、必要あれば2月の日数を変更。

    通日計算。例えば「3月10日」の通日は、1~2月の日数(daysInMonth[1]と[2]の合計)に、3月の経過日数(10日)を足した日数。




    まとめ

    お疲れ様でした!

    科目B問01でよく見るテーマでした。

    個人的には、閏年や暦の歴史に興味が出てくれたら嬉しいです。私たちが当たり前に使っている暦/時間/長さや単位。人類の歴史や計算の試行錯誤の後に確立されたってちょっと分かります。すごいもんですね。


    こんな感じで、基礎を生かして実例で擬似言語を作って、さらにプログラム的な考察や工夫を深めていきたくて、理解シリーズを作ってます。>【FEB】擬似言語の教科書Note

    最後に私のお薦めの演習順番。
    ❶学習前の”分からせ”
    >【FEB】サンプル問題2のNote
    ❷テキスト
    >【FEB】擬似言語の教科書Note
    >【FEB】擬似言語の理解演習Note ←いまこの辺
    ↓※必要なら
    うかる! 基本情報技術者 [科目B・セキュリティ編](amazon)
    うかる! 基本情報技術者 [科目B・アルゴリズム編](amazon)
    ❸各年度の公開問題
    >【FEB】令和07年科目BのNote
    >【FEB】令和06年科目BのNote
    >【FEB】令和05年科目BのNote
    ➍解法の総復習(➋や➌と併用可)
    >【FEB】擬似言語の11の解法Note
    ➎模擬試験
    >【FEB】サンプル問題1のNote(擬似言語)
    >【FEB】サンプル問題1のNote(セキュリティ)


    この記事が参加している募集

     
     
    大学・専門学校の先生の解説Note。 学生時代にITパスポート試験・基本情報技術者試験・応用情報技術者試験を独学で高得点合格。情報処理安全確保支援士試験(セキスペ)・データベーススペシャリスト試験・ネットワークスペシャリスト試験・G検定なども取得。 2027年にPD-S受験予定。