Ruby paizaレベルアップ問題集(文字と整数の組のソート2-4)

paizaラーニング(初心者〜中級者向けのプログラミング学習サービス)の問題集をやってみる。

paiza.jp

共通ルール

入力

  • 入力値最終行の末尾に改行が1つ入ります。
  • 文字列は標準入力から渡されます。

出力

  • 最後は改行し、余計な文字、空行を含んではいけません。

7. 文字と整数の組のソート2 (paizaランク C 相当)

1行目に行数を表す整数 n、続く n 行の各行で「文字」と「整数」の組が空白区切りで入力されます。
n 個の組について、「文字」の値が同じ組同士の数値を足しわせてまとめ、まとめた数値の降順で、文字とまとめた数値の組を出力してください。

入力される値
n
S_1 D_1
S_2 D_2
...
S_i D_i
...
S_n D_n

S_i は「文字」で、D_i は「整数」です。

期待する出力
文字とまとめた数値の組を各行で出力してください。

条件
・1 ≦ n ≦ 10,000
・-10,000 ≦ D_i ≦ 10,000 (ただし、1 ≦ i ≦ n)
・S_iは1つの半角英文字

入力例

7
A 1
D 6
C 2
G 4
B 70
A 10
B 5

出力例

B 75
A 11
D 6
G 4
C 2

自分の解答

n = gets.to_i
hash = {}
n.times do
  k, v = gets.split
  hash[k].nil? ? hash[k] = v.to_i : hash[k] += v.to_i
end
ary = hash.sort_by { |key, value| value }.reverse
ary.each do |k, v|
  puts "#{k} #{v}"
end

ハッシュのキーに重複がある場合、以下のように単純にハッシュを作ると上書きされていって思うような値にならない。

# 入力例が入力された場合
n = gets.to_i
hash = {}
n.times do
  k, v = gets.split
  hash[k] = v.to_i
end
p hash
#=> {"A"=>10, "D"=>6, "C"=>2, "G"=>4, "B"=>5}
# 上書きされている

そのため、キー(k)がない(nilである)ときはそのまま値(v)を代入し、キーがすでに存在する場合は値を足すようにした。

hash[k].nil? ? hash[k] = v.to_i : hash[k] += v.to_i

Enumerable#sort_by (Ruby 2.7.0 リファレンスマニュアル)

Ruby ハッシュのソート - masuyama's notes (Scrapbox)