こんにちは!じゃいごテックのあつしです。
今回はpaiza クラス・構造体メニュー から静的メンバという問題を解説します。
この問題集はクラスの静的メンバ(クラス変数)や継承に関する5個のSTEP問題(C~B級)とFINAL問題(B級)で構成されていて、STEP問題を解いて行けばFINAL問題も解けるはず!となっています。
この問題集はボリュームがありますので前半と後半で記事を分けます。
前半はコンストラクタ(initializeメソッド)とインスタンス変数の更新に関する問題です。
STEP問題を解いてみる(前半)
簡単な解説は付けていますが、難しいと感じたら下記の記事も参考にしてみて下さい。
STEP1: クラスの作成 (paizaランク C 相当)
STEP1 は指定されたインスタンス変数とインスタンスメソッドを持つクラスを定義し、入力されたデータでインスタンスメソッドを実行する問題です。
※ STEP2でコンストラクタを実装するので今回はゲッターとセッターを定義します。
Employeeクラス
- インスタンス変数
- 社員番号 @number : Integer (外部からの更新を許可)
- 名前 @name : String (外部からの更新を許可)
- インスタンスメソッド
- getnum : @number を返す
- getname : @name を返す
解答例
INPUT1 = <<~"EOS"
3
make 1 nana
getnum 1
getname 1
EOS
OUTPUT1 = <<~"EOS"
1
nana
EOS
INPUT2 = <<~"EOS"
7
make 2742 mako
getnum 1
make 2782 taisei
getname 2
make 31 megumi
getname 1
getname 3
EOS
OUTPUT2 = <<~"EOS"
2742
taisei
mako
megumi
EOS
class Employee
# クラス外から @number, @name の更新を許可
attr_writer :number, :name
def getnum
@number
end
def getname
@name
end
end
def solve(input_data)
# 入力データ受け取り
_, *requests = input_data.split("\n")
employees = []
result = []
requests.each do |request|
method, number, name = request.split
number = number.to_i
case method
when "make"
# インスタンス化してデータを入力する
employee = Employee.new
employee.number = number
employee.name = name
# employee を employees に push する
employees << employee
when "getnum", "getname"
# getnum 又は getname でデータを参照して result に push する
result << employees[number - 1].public_send(method)
end
end
# 処理結果を改行で連結し末尾に改行を加える
result.join("\n") << "\n"
end
puts solve(STDIN.read)
# [参考 確認用コード]
# p solve(INPUT1)
# > "1\nnana\n"
# > p solve(INPUT1) == OUTPUT1
# > true
# p solve(INPUT2)
# > "2742\ntaisei\nmako\nmegumi\n"
# > p solve(INPUT2) == OUTPUT2
# true
解答例: solveメソッドの処理内容
n件の命令を受け取り、半角区切りで分割して配列requestsに格納します。配列requestsの先頭から順に命令の1個目の要素を調べます。"make"ならEmployeeクラスのインスタンスを生成します。インスタンス変数@numberにnumberを代入します。インスタンス変数@nameにnameを代入します。インスタンスemployeeを配列employeesにpushします。
"getnum"か"getname"ならpublic_sendメソッドで該当メソッドを実行し、結果をresultにpushします。
- 処理結果を改行で連結して末尾に改行を加えて返します。
STEP2: コンストラクタ (paizaランク C 相当)
STEP2 は指定されたインスタンス変数とインスタンスメソッドを持つクラスを定義し、入力されたデータでインスタンスメソッドを実行する問題です。
※ STEP1と同じ問題ですが、コンストラクタ(initializeメソッド)でインスタンス変数を初期化します。
Employeeクラス
- インスタンス変数
- 社員番号 @number : Integer
- 名前 @name : String
- initializeメソッド(引数:number, name)
- @numberをnumberで初期化する
- @nameをnameで初期化する
- インスタンスメソッド
- getnum : @number を返す
- getname : @name を返す
解答例
INPUT1 = <<~"EOS"
3
make 1 nana
getnum 1
getname 1
EOS
OUTPUT1 = <<~"EOS"
1
nana
EOS
INPUT2 = <<~"EOS"
7
make 2742 mako
getnum 1
make 2782 taisei
getname 2
make 31 megumi
getname 1
getname 3
EOS
OUTPUT2 = <<~"EOS"
2742
taisei
mako
megumi
EOS
class Employee
# インスタンス変数の初期化
def initialize(number, name)
@number = number
@name = name
end
def getnum
@number
end
def getname
@name
end
end
def solve(input_data)
# 入力データ受け取り
_, *requests = input_data.split("\n")
employees = []
result = []
requests.each do |request|
method, number, name = request.split
number = number.to_i
case method
when "make"
# 引数に number, name を与えてインスタンス化して
# employees に push する
employees << Employee.new(number, name)
when "getnum", "getname"
# getnum 又は getname を呼び出して result に push する
result << employees[number - 1].public_send(method)
end
end
# 処理結果を改行で連結し末尾に改行を加える
result.join("\n") << "\n"
end
puts solve(STDIN.read)
# [参考 確認用コード]
# p solve(INPUT1)
# > "1\nnana\n"
# p solve(INPUT1) == OUTPUT1
# > true
# p solve(INPUT2)
# > "2742\ntaisei\nmako\nmegumi\n"
# p solve(INPUT2) == OUTPUT2
# > true
解答例: solveメソッドの処理内容
n件の命令を受け取り、半角区切りで分割して配列requestsに格納します。配列requestsの先頭から順に命令の1個目の要素を調べます。"make"なら続くパラメータ(number, name)を引数に与えてEmployeeクラスのインスタンスを生成します。インスタンスemployeeを配列employeesにpushします。
"getnum"か"getname"ならpublic_sendメソッドで該当メソッドを実行し、結果をresultにpushします。
- 処理結果を改行で連結して末尾に改行を加えて返します。
STEP3: クラスのメンバの更新 (paizaランク C 相当)
STEP3 は指定されたインスタンス変数とインスタンスメソッドを持つクラスを定義し、入力されたデータでインスタンスメソッドを実行してインスタンス変数を更新する問題です。
※ メソッドが増えますがSTEP1, STEP2と同じような問題です。
Employeeクラス
- インスタンス変数
- 社員番号 @number : Integer
- 名前 @name : String
- initializeメソッド(引数: number, name)
- @numberをnumberで初期化する
- @nameをnameで初期化する
- インスタンスメソッド
- getnum : @number を返す
- getname : @name を返す
- change_num(引数: number) : @numberをnumberで更新する
- change_name(引数: name) : @nameをnameで更新する
解答例
INPUT1 = <<~"EOS"
4
make 3 nana
getnum 1
change_num 1 5
getnum 1
EOS
OUTPUT1 = <<~"EOS"
3
5
EOS
INPUT2 = <<~"EOS"
12
make 2742 makoto
getnum 1
make 2782 taro
getname 1
getname 2
change_num 2 9927
change_name 1 mako
getnum 2
make 31 meu
change_name 3 meumeu
getnum 3
getname 1
EOS
OUTPUT2 = <<~"EOS"
2742
makoto
taro
9927
31
mako
EOS
class Employee
def initialize(number, name)
@number = number
@name = name
end
def getnum
@number
end
def getname
@name
end
def change_num(number)
@number = number
end
def change_name(name)
@name = name
end
end
def solve(input_data)
# 入力データ受け取り
_, *requests = input_data.split("\n")
employees = []
result = []
requests.each do |request|
method, number, param = request.split
number = number.to_i
case method
when "make"
# 引数に number, name を与えてインスタンス化して
# employees に push する
employees << Employee.new(number, param)
when "change_num"
# 引数に整数にした param を与えて change_num を実行
employees[number - 1].change_num(param.to_i)
when "change_name"
# 引数に param を与えて change_name を実行
employees[number - 1].change_name(param)
when "getnum", "getname"
# getnum 又は getname でデータを参照して result に push する
result << employees[number - 1].public_send(method)
end
end
# 処理結果を改行で連結し末尾に改行を加える
result.join("\n") << "\n"
end
puts solve(STDIN.read)
# [参考 確認用コード]
# p solve(INPUT1)
# > "3\n5\n"
# p solve(INPUT1) == OUTPUT1
# > true
# p solve(INPUT2)
# > "2742\nmakoto\ntaro\n9927\n31\nmako\n"
# p solve(INPUT2) == OUTPUT2
# > true
解答例: solveメソッドの処理内容
n件の命令を受け取り、半角スペースで分割して配列requestsに格納します。配列requestsの先頭から順に命令の1個目の要素を調べます。"make"なら続くパラメータ(number, name)を引数に与えてEmployeeクラスのインスタンスを生成します。インスタンスemployeeを配列employeesにpushします。
"change_num"なら引数に整数にしたparamを与えてchange_numメソッドを実行します。"change_name"なら引数にparamを与えてchange_nameメソッドを実行します。"getnum"か"getname"ならpublic_sendメソッドで該当メソッドを実行し、結果をresultにpushします。
- 処理結果を改行で連結して末尾に改行を加えて返します。
今回のまとめ
前半はクラスの基礎的な問題を解きました。
- クラスの定義
- インスタンス変数(ゲッター・セッター)
- initializeメソッド(コンストラクタ)
- インスタンスメソッド

前半は復習的な問題でした。
後半は継承や特異メソッド(クラスメソッド)を扱います!