こんにちは!じゃいごテックのあつしです。
今回はpaizaレベルアップ問題集から単語のカウントという問題を解説していきたいと思います。こちらは過去にスキルチェックで実際に出題されていた問題らしいです!
難易度は 1505±7 で、C級としては平均的な難易度の問題ですが、ハッシュに慣れていないと難しく感じるかもしれません。
単語のカウント(paizaランク C 相当) を解いてみる
※ paiza レベルアップ問題集 スキルチェック過去問題セットより
問題
スペースで区切られた英単語列が与えられます。
英単語列に含まれる英単語の出現回数を出現した順番に出力してください。
入力される値
半角スペースで区切られた長さNの文字列
期待する出力
単語、半角スペース、出現回数の順で1行に1単語で出現したすべての単語を、列に出現する順に出力してください。
条件
全てのテストケースにおいて以下の条件を満たします。
- 1 ≦ N ≦ 1,000
入力例1
red green blue blue green blue
出力例1
red 1
green 2
blue 3
入力例2
Apple Apricot Orange Cherry Apple Orange Cherry Orange
出力例2
Apple 2
Apricot 1
Orange 3
Cherry 2
攻略ポイント
ポイント
- 1行半角スペース区切りの単語を配列に格納する
- 配列に格納された単語を次々に取り出して出現回数をハッシュで集計する
- 集計したハッシュを "単語 + 半角スペース + 出現回数 " の形式の文字列に変換して出力する
参考記事
問題を解く流れ
入出力例をコピペしてヒアドキュメントで変数に代入しておきます。
INPUT1 = <<~"EOS" red green blue blue green blue EOS OUTPUT1 = <<~"EOS" red 1 green 2 blue 3 EOS INPUT2 = <<~"EOS" Apple Apricot Orange Cherry Apple Orange Cherry Orange EOS OUTPUT2 = <<~"EOS" Apple 2 Apricot 1 Orange 3 Cherry 2 EOS
下記の2行を追加して動作確認をしてみましょう。INPUT1, OUTPUT1
にどんなデータが入っているか確認出来たらこのコードは削除してOKです。
p INPUT1 p OUTPUT1 # > "red green blue blue green blue\n" # > "red 1\ngreen 2\nblue 3\n"
次に問題を解くメソッド(今回は solve
メソッドとします)を少しずつ作って行きます。
まずは、split
メソッドを使って半角スペース区切りの文字列から、単語を要素に持つ配列 words
を作ります。
def solve(input_line) # 半角スペース区切りの単語を配列に格納 words = input_line.split end
solve
メソッドの下に次の記述を追加してプログラムを実行してみます。
単語を要素に持つ配列が返っていればOKです!このコードを残したまま次に進みます。
p solve(INPUT1) # > ["red", "green", "blue", "blue", "green", "blue"]
次に配列 words
の先頭から順に単語を取り出して集計していきます。
集計には単語をキー、出現回数を値に持つハッシュを使います。
def solve(input_line) # 半角スペース区切りの単語を配列に格納 words = input_line.split # 集計用の空ハッシュを準備 word_count = {} # words から単語を次々に取り出す words.each do |word| # 単語が既出かを調べる if word_count[word] # 既出ならその単語の値に +1 する word_counnt[word] += 1 else # 初なら単語をキー、値を1でハッシュに追加 word_count[word] = 1 end end # word_countを返す word_count end
ここまで出来たらどのような値が返ってくるかプログラムを実行して確認してみましょう。
下記のように集計結果のハッシュが出力されていればOKです。
# > {"red"=>1, "green"=>2, "blue"=>3}
最終的に下記の形で返したいので、join
メソッドを使って各要素を改行区切りで結合します。最後の改行はjoin
で追加できないので別途追加します。
単語 + 半角スペース + 出現回数 + 改行
単語 + 半角スペース + 出現回数 + 改行
・
・
・
単語 + 半角スペース + 出現回数 + 改行
def solve(input_line) # 半角スペース区切りの単語を配列に格納 words = input_line.split # 集計用の空ハッシュを生成 word_count = {} # 単語を次々に取り出す words.each do |word| # 単語が既出かを調べる if word_count[word] # 既出ならその単語の値に +1 する word_counnt[word] += 1 else # 初なら単語をキー、値を1でハッシュに追加 word_count[word] = 1 end end # "単語 + 半角スペース + 出現回数 + 改行" の形式の文字列を返す word_count.map{ |word, count| "#{word] #{count}" }.join("\n") << "\n" end
これで solve
メソッドは完成です!動作確認してみましょう。 solve(INPUT2)
も同様に確認しましょう。
# どのような値が返って来ているか? p solve(INPUT1) # "red 1\ngreen 2\nblue 3\n" # OUTPUT1と同じか? p solve(INPUT1) == OUTPUT1 # > true # puts で出力して改行を確認 puts solve(INPUT1) # > red 1 # > green 2 # > blue 3
最後に solve
メソッドに与える引数を gets
に変更したら完成!一応動作も確認してみましょう。
入出力の変数部分は提出時は不要ですので solve
メソッド定義以降をコピペして提出します。
解答コード
def solve(input_line) # 半角スペース区切りの単語を配列に格納する words = input_line.split # 単語集計用の空ハッシュを生成する word_count = {} # 単語を次々に取り出す words.each do |word| # 取り出した単語が既出かを調べる if word_count[word] # 既出ならその単語の値を +1 する word_count[word] += 1 else # 初なら単語をキー、値を1でハッシュに追加 word_count[word] = 1 end end word_count.map { |word, count| "#{word} #{count}" }.join("\n") << "\n" end puts solve(gets)
他の解答例
puts
メソッドに配列を渡すと要素ごとに改行して出力します。
solve(INPUT1) == OUTPUT1
は false
になりますが、指示通りの出力が出来ていますので正解となります。
def solve(input_line) # 半角スペース区切りの単語を配列に格納する words = input_line.split # 単語集計用の空ハッシュを生成する word_count = {} # 単語を次々に取り出す words.each do |word| # 取り出した単語が既出かを調べる if word_count[word] # 既出ならその単語の値を +1 する word_count[word] += 1 else # 初なら単語をキー、値を1でハッシュに追加 word_count[word] = 1 end end # 表示形式を整えた配列を返す word_count.map { |word, count| "#{word} #{count}" } end puts solve(gets)
group_by
メソッドを使うとかなり短く書けます
def solve(input_line) # 半角スペース区切りの単語を配列に格納する words = input_line.split # group_byメソッドで集計して出力形式を整えた配列を返す words.group_by(&:itself).map { |word, count| "#{word} #{count.length}" } end puts solve(gets)
今回のまとめ
ハッシュにキーを与えると、そのキーが存在する場合は値を返し、存在しない場合は nil
が返ってくることを利用して、条件分岐と出現回数のカウントアップを行いました。
ハッシュは複数のデータをわかりやすい形で管理することが出来るのでとても便利です。
C級問題からはハッシュの出番も増えてくると思います!