k-tokitoh

2019-05-27

Ruby手習い(Dateクラス)

アウトプットのネタに困ったらこれ!?Ruby 初心者向けのプログラミング問題を集めてみた(全 10 問) - give IT a try

上記記事のカレンダー作成問題。

出力結果

p-064% ruby calendar.rb
      May 2019
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

自分で書いたコード

require 'date'

def main
  puts calendar
end

def calendar
  today = Date.today
  title = today.strftime("%B %Y").center(20)
  head = "Su Mo Tu We Th Fr Sa"

  last_day = Date.new(today.year, today.month + 1, -1).day
  wday = Date.new(today.year, today.month, 1).wday

  body = "   " * wday
  d = 1

  (1..last_day).each do
    body << d.to_s.rjust(2)
    d += 1
    wday += 1
    body << (wday % 7 == 0 ? "\n" : " ")
  end

  [title, head, body].join("\n")
end

if __FILE__ == $0
  main
end

出題者による回答例

require 'date'

class CalendarRenderer
  DAY_LENGTH = 3
  WEEK_LENGTH = DAY_LENGTH * 7

  def initialize(year, month)
    @first_date = Date.new(year, month, 1)
  end

  def to_s
    (header_rows + body_rows).join("\n")
  end

  private

  def body_rows
    split_pattern = /.{#{DAY_LENGTH},#{WEEK_LENGTH}}/
    body_text.scan(split_pattern)
  end

  def body_text
    first_week_offset + calendar_text
  end

  def first_week_offset
    ' ' * @first_date.wday * DAY_LENGTH
  end

  def calendar_text
    last_day = @first_date.next_month.prev_day.day
    rjust_all 1..last_day
  end

  def header_rows
    [month_year, sun_to_sat]
  end

  def month_year
    indent_length = 1
    @first_date.strftime("%B %Y").center(WEEK_LENGTH + indent_length).rstrip
  end

  def sun_to_sat
    rjust_all %w(Su Mo Tu We Th Fr Sa)
  end

  def rjust_all(enum)
    enum.to_a.map{|e| e.to_s.rjust(DAY_LENGTH) }.join
  end
end

学んだこと