Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Level3までのコード #4

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions lib/calendar/month.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
require 'date'

module Calendar
class Month
NAMES = %w[Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec].freeze

def initialize(year:, value:)
@year = year
@value = value
@name = NAMES[@value - 1]
@day_count = day_count
@dates = (1..@day_count).map { |number| Date.new(@year.value, @value, number) }
end

def to_array
[@name, *([''] * first_date_wday), *@dates]
end

private

def day_count
case @value
when 1, 3, 5, 7, 8, 10, 12 then 31
when 4, 6, 9, 11 then 30
when 2
@year.leap_year? ? 29 : 28
else
raise 'Invalid month'
end
end

def first_date_wday
@dates.first.wday
end
end
end
85 changes: 85 additions & 0 deletions lib/calendar/table.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
module Calendar
class Table
def initialize(rows:, today: nil)
@rows = rows
@today = today
end

def generate(vertical: false)
vertical ? generate_with_vertical : generate_with_horizontal
end

private

def generate_with_horizontal
header = @rows.first.join(' ')
body = @rows[1..].map do |row|
[
"#{row.first} ",
*row[1..].map do |cell|
if cell.is_a?(Date)
string_format = cell == @today ? '[%-d]' : '%_2d'
cell.strftime(string_format)
else
' '
end
end
].join(' ')
end
text = [header, *body].join("\n")
return text unless @today

replace_today_for_horizontal(text:, today: @today)
end

def generate_with_vertical
header = transposed_rows.first.join(' ')
body = transposed_rows[1..].map do |row|
[
"#{row.first} ",
*row[1..].map do |cell|
if cell.is_a?(Date)
string_format =
if cell == @today
space_size = cell.day > 9 ? 0 : 1
' ' * space_size + '[%-d]'
else
'%_3d'
end
cell.strftime(string_format)
else
' '
end
end
].join(' ').rstrip
end
text = [header, *body].join("\n")
return text unless @today

replace_today_for_vertical(text:, today: @today)
end

def transposed_rows
return @transposed_rows if @transposed_rows

max_length = @rows.map { |row| row.length }.max
filled_rows = @rows.map do |row|
row + [''] * (max_length - row.length)
end
@transposed_rows = filled_rows.transpose
end

def replace_today_for_horizontal(text:, today:)
result = /[^\S\n\r]\[(#{today.day})\][^\S\n\r]?/.match(text)
captured = result.to_a[0]
text.gsub(captured, today.day > 9 ? captured.strip : captured.rstrip)
end

def replace_today_for_vertical(text:, today:)
result = /\[(#{today.day})\][^\S\n\r]?/.match(text)
captured = result.to_a[0]
text.gsub(captured, captured.rstrip)
end
end
end

32 changes: 32 additions & 0 deletions lib/calendar/year.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require_relative 'month'
require_relative 'table'
require 'date'

module Calendar
class Year
attr_reader :value, :today

def initialize(value:, today: nil)
@value = value
@today = today
@months = (1..Month::NAMES.size).map { |value| Month.new(year: self, value:) }
end

def leap_year?
date = Date.new(@value, 1, 1)
date.leap?
end

def generate(vertical: false)
rows = [header, *@months.map(&:to_array)]
table = Table.new(rows:, today: @today)
table.generate(vertical:)
end

private

def header
[@value.to_s, *(%w[Su Mo Tu We Th Fr Sa] * 5), 'Su', 'Mo']
end
end
end
6 changes: 4 additions & 2 deletions lib/sg_strange_calendar.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
require_relative 'calendar/year'

class SgStrangeCalendar
def initialize(year, today = nil)
# write your code here
@year = Calendar::Year.new(value: year, today:)
end

def generate(vertical: false)
# write your code here
@year.generate(vertical:)
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