Skip to content

Commit

Permalink
レベル1~3
Browse files Browse the repository at this point in the history
  • Loading branch information
AkitoShiga committed Dec 9, 2024
1 parent 8990a8b commit e45c8a9
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 11 deletions.
132 changes: 130 additions & 2 deletions lib/sg_strange_calendar.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,137 @@
# frozen_string_literal: true
require 'date'

class SgStrangeCalendar
private attr_reader :year, :today

MONTHS_INDEX = 0
WEEKDAYS_INDEX = 0
YEAR_SPACE_SIZE = 1
WEEKDAYS_SPACE_SIZE = 37
# 以下のハッシュのキーはDateのAPI仕様に依存している
MONTHS = (1..12).zip(%w[Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec]).to_h # Date#month
WEEKDAYS = (0..6).zip(%w[Su Mo Tu We Th Fr Sa]).to_h # Date#wday

private_constant *%i[
MONTHS_INDEX
WEEKDAYS_SPACE_SIZE
YEAR_SPACE_SIZE
WEEKDAYS_INDEX
MONTHS
WEEKDAYS
]

# @param [Integer] year 表示対象の年
# @param [Date] today 今日の(目立たせたい) 日付
# @return [SgStrangeCalendar] SgStrangeCalenderインスタンス
def initialize(year, today = nil)
# write your code here
@year = year
@today = today
end

# @param [Boolan] vertical 縦に表示するか
# @return [String] 変なカレンダー
def generate(vertical: false)
# write your code here
outline_filled_calendar = outline_filled_calendar()
day_filled_calendar = day_filled_calendar(outline_filled_calendar, vertical)
visualized_calendar(day_filled_calendar, vertical)
end

private

def outline_filled_calendar
calendar = Array.new(YEAR_SPACE_SIZE + MONTHS.size).map do
Array.new(YEAR_SPACE_SIZE + WEEKDAYS_SPACE_SIZE)
end

calendar[0][0] = year

MONTHS.each_key do |month_number|
calendar[month_number][MONTHS_INDEX] = MONTHS[month_number]
end

WEEKDAYS_SPACE_SIZE.times do |fill_time|
calendar[WEEKDAYS_INDEX][YEAR_SPACE_SIZE + fill_time] = WEEKDAYS[rotated_week_number(fill_time)]
end

calendar
end

def day_filled_calendar(calendar, vertical)
day_filled_calendar = calendar.dup

(Date.parse("#{year}-1-1")..Date.parse("#{year}-12-31")).each do |date|
day_filled_calendar[date.month][date.day + offset_days_each_month[date.month]] = date.day
end

if today
day_filled_calendar[today.month][today.day + offset_days_each_month[today.month]] = "[#{today.day}]"
end

day_filled_calendar
end

def rotated_week_number(week_fill_time)
week_fill_time % WEEKDAYS.size
end

# カレンダーは日曜日から始まるが月初の曜日はそれぞれ異なるのでその分のオフセットを保持
def offset_days_each_month
@offset_days_each_month ||= MONTHS.each_key.map do |month_number|
[month_number, Date.new(year, month_number, 1).wday]
end.to_h
end

def visualized_calendar(calendar, vertical)
# 一行目の項目のサイズに依存する
space_size = (vertical ? MONTHS : WEEKDAYS).values.max_by(&:size).size
calendar.map do |row|
row.map do |space|
case
when MONTHS.values.include?(space)
vertical ? space : space.ljust(year.to_s.size)
when WEEKDAYS.values.include?(space)
vertical ? space.ljust(year.to_s.size) : space
when space.nil?
' ' * space_size
else
space.to_s.rjust(space_size)
end
end
end => space_adjusted_calendar

directioned_calendar = vertical ?
space_adjusted_calendar.transpose :
space_adjusted_calendar

# todayが指定された際に、[]の分増えたスペースを調整
directioned_calendar.map do |row|
if vertical
vertical_emphasized_line(row)
else
horizontal_emphasized_line(row)
end.rstrip
(vertical ? vertical_emphasized_line(row) : horizontal_emphasized_line(row)).rstrip
end.join("\n").rstrip
end

def vertical_emphasized_line(line)
line.map do |space|
case space
when /\[\d{2}\]/
space
when /\[\d{1}\]/
' ' + space
else
space + ' '
end
end.join
end

def horizontal_emphasized_line(line)
line.join(' ')
.sub(/(?<=\[\d{1}\]) {1}/, '')
.gsub(/ {1}(?=\[\d{2}\])/,'')
.gsub(/((?<=\[\d{2}\]) {1})/, '')
end
end
9 changes: 0 additions & 9 deletions test/sg_strange_calendar_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ def test_level_1_for_2025
end

def test_level_2_for_2024_01_01
skip "レベル2にチャレンジする人はこの行を削除してください"
expected = <<~TXT.chomp
2024 Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo
Jan [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
Expand All @@ -66,7 +65,6 @@ def test_level_2_for_2024_01_01
end

def test_level_2_for_2024_12_09
skip "レベル2にチャレンジする人はこの行を削除してください"
expected = <<~TXT.chomp
2024 Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo
Jan 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
Expand All @@ -88,7 +86,6 @@ def test_level_2_for_2024_12_09
end

def test_level_2_for_2025_03_31
skip "レベル2にチャレンジする人はこの行を削除してください"
expected = <<~TXT.chomp
2025 Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo
Jan 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
Expand All @@ -110,7 +107,6 @@ def test_level_2_for_2025_03_31
end

def test_level_2_all
skip "レベル2にチャレンジする人はこの行を削除してください"
file_path = File.expand_path('level2.txt', File.dirname(__FILE__))
calendars = File.read(file_path).lines.each_slice(13).map(&:join).map(&:chomp)
from_date = Date.new(2025, 1, 1)
Expand All @@ -123,7 +119,6 @@ def test_level_2_all
end

def test_level_3_for_2024
skip "レベル2およびレベル3にチャレンジする人はこの行を削除してください"
expected = <<~TXT.chomp
2024 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Su 1 1
Expand Down Expand Up @@ -169,7 +164,6 @@ def test_level_3_for_2024
end

def test_level_3_for_2024_01_01
skip "レベル2およびレベル3にチャレンジする人はこの行を削除してください"
expected = <<~TXT.chomp
2024 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Su 1 1
Expand Down Expand Up @@ -216,7 +210,6 @@ def test_level_3_for_2024_01_01
end

def test_level_3_for_2024_12_09
skip "レベル2およびレベル3にチャレンジする人はこの行を削除してください"
expected = <<~TXT.chomp
2024 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Su 1 1
Expand Down Expand Up @@ -263,7 +256,6 @@ def test_level_3_for_2024_12_09
end

def test_level_3_for_2025_03_31
skip "レベル2およびレベル3にチャレンジする人はこの行を削除してください"
expected = <<~TXT.chomp
2025 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Su 1
Expand Down Expand Up @@ -310,7 +302,6 @@ def test_level_3_for_2025_03_31
end

def test_level_3_all
skip "レベル2およびレベル3にチャレンジする人はこの行を削除してください"
file_path = File.expand_path('level3.txt', File.dirname(__FILE__))
calendars = File.read(file_path).lines.each_slice(38).map(&:join).map(&:chomp)
from_date = Date.new(2025, 1, 1)
Expand Down

0 comments on commit e45c8a9

Please sign in to comment.