🐡
Ruby初学者が解く「カレンダー作成問題」
はじめに
Ruby初学者のPHPerです。
プロを目指す人のためのRuby入門[改訂2版]を一周した後に何か良い勉強方法がないか調べていたところ、下記の記事を見つけたのでやってみました。
参考:アウトプットのネタに困ったらこれ!?Ruby初心者向けのプログラミング問題を集めてみた(全10問)
既に多くの方がネット上に解答を載せてくれていますが、個人的な備忘録も兼ねて残しておきたいと思います。
今回は「カレンダー作成問題」です。
カレンダー作成問題とは
元ネタは「たのしいRuby」に載っています。
問題の内容を下記です。Date クラスを使って、今月の1日と月末の日付と曜日を求め、次のような形式でカレンダーを表示させてください
April 2013
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
バージョンなど
- Ruby v3.1.2
ソース
calendar.rb
require 'date'
# class Calendar
class Calendar
DEFAULT_DATE = Date.today
attr_reader :target_date
def initialize(target_date = DEFAULT_DATE)
@target_date = target_date
end
def print_calendar
# 中央揃えした年月を出力
puts @target_date.strftime('%B %Y').center(20)
# 曜日一覧を出力
puts 'Su Mo Tu We Th Fr Sa'
# 月末と月初の日付を取得
this_year = @target_date.year
this_month = @target_date.month
first_day = Date.new(this_year, this_month, 1)
last_day = Date.new(this_month, this_month, -1)
# 冒頭の空白部分を出力
first_day_wday = first_day.wday
blank = ' ' * first_day_wday
print blank
# カレンダーの日付部分を出力
print_date(last_day, first_day_wday)
end
private
def print_date(last_day, first_day_wday)
(1..last_day.day).each do |day|
printf('%2d ', day)
puts "\n" if ((first_day_wday + day) % 7).zero?
end
puts "\n"
end
end
# 今月のカレンダー
this_month_calendar = Calendar.new
this_month_calendar.print_calendar
上記のコードの出力は下記です。
October 2022
Su Mo Tu We Th Fr Sa
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
説明
- クラス化
クラス化したことで指定月のカレンダーを簡単に出力できます。
2022年11月のカレンダーを表示させたい場合、下記です。
next_month_calendar = Calendar.new(Date.new(2022, 11, 1))
next_month_calendar.print_calendar
- private メソッド化
print_calendar
メソッドが冗長していたので簡潔に書くために、print_date
メソッドを作成しました。
each
の中は短いものの、複数行あるためdo ... end
で書いてます。
参考:プロを目指す人のためのRuby入門[改訂2版]
また、if文の中の処理は一行のみであり、内容もシンプルなため、後置ifにしました。
def print_date(last_day, first_day_wday)
(1..last_day.day).each do |day|
printf('%2d ', day)
puts "\n" if ((first_day_wday + day) % 7).zero? # 後置if
end
puts "\n"
end
残課題
- テストの作成(後日追記予定)
Discussion