Header
2020-03-10
2020-09-07

paiza(パイザ)Cランク練習問題|宝くじのRubyサンプルコードと解説

2020 03 10 1bd4e0259e9c6c99 s

paiza(パイザ)Cランク相当の練習問題の解説とサンプルコードの|宝くじについてRubyサンプルコードと解説を記載します。

今回は問題文から直感で作成したサンプルコードとその後リファクタリングしたコードの2種類のサンプルコードを記載します

※両方ともpaiza公式ページで問題提出すると動作します。

この問題は回答提出するとpaiza公式でRubyのサンプルコードが用意されています。

問題の要件と概要は以下から

宝くじ

以下から公式の抜粋を元にプログラム化する際の思考の流れとサンプルコードを記載します

Cランク問題の宝くじの入出力値

以下公式抜粋

問題概要

今年もパイザ宝くじの季節がやってきました。パイザ宝くじ券には 100000 以上 199999 以下の 6 桁の番号がついています。毎年1つ当選番号 (100000 以上 199999 以下)が発表され、当たりクジの番号が以下のように決まります。

1等:当選番号と一致する番号
前後賞:当選番号の ±1 の番号(当選番号が 100000 または 199999 の場合,前後賞は一つしかありません)
2等:当選番号と下 4 桁が一致する番号(1等に該当する番号を除く)
3等:当選番号と下 3 桁が一致する番号(1等および2等に該当する番号を除く)

たとえば、当選番号が 142358 の場合、当たりの番号は以下のようになります。

1等:142358
前後賞:142357 と 142359
2等:102358, 112358, 122358, …, 192358 (全 9 個)
3等:100358, 101358, 102358, …, 199358 (全 90 個)

あなたが購入した n 枚の宝くじ券の各番号が入力されるので、それぞれの番号について、何等に当選したかを出力するプログラムを書いて下さい。

入力値

b
n
a_1
a_2
:
a_n

ここで、b は当選番号、n は購入した宝くじの数、a_1,…,a_n は購入した宝くじ券の番号をそれぞれ表します。

期待する出力

期待する出力は n 行から成ります。各 i 行目 (1 ≦ i ≦ n) には、a_i が何等に当たったかに応じて、以下の文字列を出力して下さい。

1等の場合: first
前後賞の場合: adjacent
2等の場合: second
3等の場合: third
それ以外(外れ)の場合: blank

入出力例(公式から抜粋)

入力例1
142358
3
195283
167358
142359

出力例1
blank
third
adjacent

問題をプログラム化する際の考え方

入力される値で以下のように記載されています。

ここで、b は当選番号、n は購入した宝くじの数、a_1,…,a_n は購入した宝くじ券の番号をそれぞれ表します。

ここで分かる事は

1:当選番号を入力する

2:プログラムとしては入力した回数だけ処理を行うということが分かります。

次に以下概要に注目します

1等:当選番号と一致する番号
前後賞:当選番号の ±1 の番号(当選番号が 100000 または 199999 の場合,前後賞は一つしかありません)
2等:当選番号と下 4 桁が一致する番号(1等に該当する番号を除く)
3等:当選番号と下 3 桁が一致する番号(1等および2等に該当する番号を除く)

この概要から

1:入力した当選番号から±1 の前後賞用の変数を生成

2:入力した当選番号から下 4 桁を抽出し2等の変数を生成

3:入力した当選番号から下 3 桁を抽出し3等の変数を生成

する事が必要だと判断しました。

次に入力例を見ると

入力例1
142358
3
195283
167358
142359

1行目が当選番号 

2行目が繰り返し処理の数

3行目以降は2行目で指定した数だけ、数値入力できる事が分かります

次に期待する出力で

期待する出力

1等の場合: first
前後賞の場合: adjacent
2等の場合: second
3等の場合: third
それ以外(外れ)の場合: blank

1:入力値の条件に合致すると文字列を出力する

2:出力値は必ず文字列である事

という事が分かります。

ここからプログラムに作成する手順を考えます

プログラム化する際にRuby的な処理を考える

1:当選番号を入力する

2:繰り返し処理回数を入力する

3:1の入力値から下4桁を取得し格納する変数を生成

4:1の入力値から下3桁を取得し格納する変数を生成

5:空配列を生成

6:2で指定した回数処理を行う

7:回数処理の数だけ宝くじ(数字)を入力させる

8:7で入力した内容を5の空配列に追加

9:配列に格納した、宝くじ(数字)の数だけ繰り返し処理をする

以下配列の繰り返し処理で考える

10:1の当選番号と7の値が完全に合致していれば文字列"first "を出力

11:1の当選番号と7の値の±1の番号の場合は文字列"adjacent"を出力

11:1の当選番号の下4桁と3の値が合致する場合は文字列"second"を出力

12:1の当選番号の下4桁と4の値が合致する場合は文字列"third"を出力

13:条件に合致しない場合は文字列"blank"を出力

paizaCランク問題宝くじのRubyサンプルコード

プログラム化する際に考えた事をRubyに当てはめます。

w_inning_number = gets.to_s.strip.chomp
counts = gets.to_i

second_w_inning_number = w_inning_number.slice(2..7).to_i
third_inning_number = w_inning_number.slice(3..7).to_i

strings = []

counts.times do
  string = gets.strip.chomp
  strings << string
end


strings.each do |st|
  if  st.chomp.to_i == w_inning_number.to_i
    puts "first"
  elsif  st.chomp.to_i  == w_inning_number.to_i + 1 or st.chomp.to_i  == w_inning_number.to_i - 1
    puts "adjacent"
  elsif  st.chomp.to_s.slice(2..7).to_i == second_w_inning_number
    puts "second"
  elsif  st.chomp.to_s.slice(3..7).to_i == third_inning_number
    puts "third"
  else
    puts "blank"
  end
end

リファクタリングする前のコード解説です

必ずリファクタリングしたコード解説もご覧ください

rubyでterminal上から値を取得するのはgetsメソッドです。

今回はgetsで取得した値は数字なので、to_iメソッドで

数字化します。

数値の下4桁を取得するにはRubyのstringクラスのsliceを用いています。

sliceメソッドはstringの文字列でないと対応できない為 当選番号を入力する際にはあえてto_sで文字列化してその後sliceして、数字化しています

w_inning_number = gets.to_s.strip.chomp
#中略

second_w_inning_number = w_inning_number.slice(2..7).to_i
third_inning_number = w_inning_number.slice(3..7).to_i

関連記事

RubyのStringクラスとよく使うメソッド

その後stringsという空配列を生成します。

その後times メソッドで、指定回数繰り返し処理を行うようにします。

繰り返し処理で番号を取得します

strings = []

counts.times do
  string = gets.strip.chomp
  strings << string
end

その後以下で配列分だけ処理を行い、 当選番号と入力された番号を比較して文字列を出力します

strings.each do |st|
  if  st.chomp.to_i == w_inning_number.to_i
    puts "first"
  elsif  st.chomp.to_i  == w_inning_number.to_i + 1 or st.chomp.to_i  == w_inning_number.to_i - 1
    puts "adjacent"
  elsif  st.chomp.to_s.slice(2..7).to_i == second_w_inning_number
    puts "second"
  elsif  st.chomp.to_s.slice(3..7).to_i == third_inning_number
    puts "third"
  else
    puts "blank"
  end
end

サンプルコードをリファクタリングする

以下がリファクタリングしたコードです。

class Lotteries
  def is_adjacent(my_number, w_inning_number)
    my_number == w_inning_number + 1 || my_number == w_inning_number - 1
  end

  def second_number(number)
    number % 10000
  end

  def third_number(number)
    number % 1000
  end

  def lottery(w_inning_number, counts)
    my_numbers = counts.times.map { |x| gets.strip.chomp.to_i }
    my_numbers.each do |my_number|
      if my_number == w_inning_number
        puts "first"
      elsif is_adjacent(my_number, w_inning_number)
        puts "adjacent"
      elsif second_number(my_number) == second_number(w_inning_number)
        puts "second"
      elsif third_number(my_number)  == third_number(w_inning_number)
        puts "third"
      else
        puts "blank"
      end
    end
  end
end

w_inning_number = gets.to_i
counts    = gets.to_i
lotteries = Lotteries.new
lotteries.lottery(w_inning_number, counts)

リファクタリングのポイント

クラスとインスタンスメソッドでまとめる

Lotteriesクラスを作成し、その中にlotteryというインスタンスメソッドを生成しました。

プログラミング言語に関わらずオブジェクト思考としてこのクラスとインスタンスメソッドの概念は必ず必要になります。

表示するメソッドと演算するメソッドを分ける

今回は当選番号と入力値から下4桁と下3桁の数値を生成する処理(secondnumberとthirdnumberメソッド)を作成しました

これにより数値生成と表示ようの処理が別々になりコードの可読性とメンテナンスが用意になります。

  def second_number(number)
    number % 10000
  end

  def third_number(number)
    number % 1000
  end

# 中略

      elsif second_number(my_number) == second_number(w_inning_number)
        puts "second"
      elsif third_number(my_number)  == third_number(w_inning_number)
        puts "third"

入力値は全て数字で行う

リファクタリングする前のコードでは以下の通り文字列化した後に、処理を行い数字化しています。

rubyは型指定がいらない言語ですが入力値を文字列かしたり数字化するのはrubyっぽくありません。

w_inning_number = gets.to_s.strip.chomp
# 中略
second_w_inning_number = w_inning_number.slice(2..7).to_i

その為リファクタリングコードは全て数字前提で動作するコードに設定しています

Cランク問題の宝くじを終えて思ったこと

今回は

1:文字列の加工

2:値の格納と表示設定を別々に行う

3:複数条件に跨がる処理を行う

事が必要です

どちらかというと3の力を見られているような気がしました。

非理系でエンジニアを目指している方はこのCランクは割と難しく感じると思いますので、1からCランクに到達するには 感覚ですが恐らく200時間以上かかると思われます。

関連問題

paizaのスキルチェックの難易度|各ランクの特徴・ランクアップのコツを現役エンジニアが解説

paiza(パイザ)Bランク練習問題|日別訪問者数の最大平均区間のRubyサンプルコードと解説

paiza(パイザ)Bランク練習問題|神経衰弱のRubyサンプルコードと解説

paiza(パイザ)Cランク練習問題|5以上の整数の合計のRubyサンプルコードと解説

paiza(パイザ)Cランク練習問題|検索履歴のRubyサンプルコードと解説

paiza(パイザ)Cランク練習問題|アルファベット探しのRubyサンプルコードと解説

paiza(パイザ)Cランク練習問題|単語のカウントのRubyサンプルコードと解説

paiza(パイザ)Cランク練習問題|野球の審判のRubyサンプルコードと解説

paiza(パイザ)Cランク練習問題|【競技7】奇数大好き山田さんのRubyサンプルコードと解説

Rubyで以下のような練習問題を用意しているので、回答できなかった方はまずは以下練習問題を試してみてください

Rubyの練習問題:配列編|初心者・独学者向け入門コンテンツ

Rubyの練習問題:文字列編|初心者・独学者向け入門コンテンツ

Rubyの練習問題:ハッシュ編|初心者・独学者向け入門コンテンツ

Rubyの練習問題:繰り返し処理編|初心者・独学者向け入門コンテンツ

Rubyの資格試験|Ruby技術者認定試験 (Silver version 2.1)の解説と対策概要

Rubyの練習問題:ファイル操作編|初心者・独学者向け入門コンテンツ

Rubyでバブルソートを行う

Rubyで二分探索(バイナリサーチ)を行う

paiza(パイザ)に慣れるとAtCoderアットコーダーもお勧めです

その他関連記事

未経験からエンジニアに転職した人間が考える、今からエンジニアに就職する方法

プログラミングポートフォリオとは|未経験からエンジニアに就職した人間が解説

職歴を作るためにSESに就職して、Web系エンジニアへ転職は可能か

業務SESやSIからWeb系エンジニア転職の志望企業の見つけ方

独学プログラミングの勉強手順|未経験からエンジニアに転職した人間が解説

あなたにお勧めの記事
前の記事
次の記事