paiza プログラミング

[Ruby]paiza スキルチェック過去問題セット 単語のカウント(paizaランク C 相当)の解説

単語のカウント

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

今回は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) == OUTPUT1false になりますが、指示通りの出力が出来ていますので正解となります。

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級問題からはハッシュの出番も増えてくると思います!

 

 



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


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






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







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







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







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


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

© 2024 じゃいごテック