paiza プログラミング

[Ruby]paiza クラス・構造体メニュー 静的メンバ (paizaランク B 相当)の解説 前半: STEP1~3

static_member_1

こんにちは!じゃいごテックのあつしです。

今回は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クラスのインスタンスを生成します。
      • インスタンス変数@numbernumberを代入します。
      • インスタンス変数@namenameを代入します。
      • インスタンスemployee配列employeespushします。
    • "getnum""getname"ならpublic_sendメソッドで該当メソッドを実行し、結果をresultpushします。
  • 処理結果を改行で連結して末尾に改行を加えて返します。

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配列employeespushします。
    • "getnum""getname"ならpublic_sendメソッドで該当メソッドを実行し、結果をresultpushします。
  • 処理結果を改行で連結して末尾に改行を加えて返します。

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配列employeespushします。
    • "change_num"なら引数に整数にしたparamを与えてchange_numメソッドを実行します。
    • "change_name"なら引数にparamを与えてchange_nameメソッドを実行します。
    • "getnum""getname"ならpublic_sendメソッドで該当メソッドを実行し、結果をresultpushします。
  • 処理結果を改行で連結して末尾に改行を加えて返します。

今回のまとめ

前半はクラスの基礎的な問題を解きました。

  • クラスの定義
  • インスタンス変数(ゲッター・セッター)
  • initializeメソッド(コンストラクタ)
  • インスタンスメソッド

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



【PR】アルゴリズム学習でお世話になった本


アルゴリズム関連の技術書は大抵C/C++で書かれていますが、ある程度プログラムが出来れば、処理の流れは理解することが出来ます。






通称: 螺旋本。C++で解説されています。AOJ(Aizu Online Judge)を運営している会津大学の渡辺准教授が書いた本です。データ構造や計算量の内容から丁寧に書いてありますのでアルゴリズム学習の最初の参考書としてオススメです。







通称: 蟻本。C++で解説されています。競技プログラミング中級者の定番書と言われていて、競技プログラミングで利用できる色々なアルゴリズムを学ぶことが出来ます。かなり高度な内容も含まれているので1冊分を完全に理解するのにはかなりの時間がかかりそうですが、手元に置いて何度も読み返しています。







通称: チーター本。C#, C++, JAVAでTopcoderの問題を解説しています。初心者~中級者向けに書かれているので解説が非常に丁寧です。







Python3でアルゴリズムを解説している本です。講義スタイルの本で、図やフローチャートを使ってアルゴリズムとデータ構造についてしっかりと説明されています。代わりにコードは少なめです。Pythonコードが読めなくても十分理解できると思います。


-paiza, プログラミング
-, ,

© 2024 じゃいごテック