0
0

More than 1 year has passed since last update.

【Python】プログラミング問題 文字と整数の組のソート2  を自分なりに解説【paiza】

Last updated at Posted at 2022-10-10

はじめに

paizaラーニングはプログラミング学習が出来るプラットフォームです。
問題はランク付けしてあり、ランクが上がると難易度がアップします。
paizaラーニングのレベルアップ問題はユーザー同士で解答を教え合ったり、コードを公開することが可能です。
自分が難しいと感じた問題のコードを解説することでスキルアップをする事が今回の目的でした。

誤りや改善点がありましたらご指摘頂けますと嬉しいです。

お題 

お題のリンク

問題文

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つ入ります。
文字列は標準入力から渡されます。

期待する出力

文字とまとめた数値の組を各行で出力してください。
文字と数値は半角スペースで区切ってください。

お手本コード

num = int(input())
inputs = {}
result = {}

for i in range(num):
    tmp = input().split()

    exist = False
    for (key, value) in inputs.items():
        if key == tmp[0]:
            exist = True

    if exist:
        inputs[tmp[0]] = inputs[tmp[0]] + int(tmp[1])
    else:
        inputs[tmp[0]] = int(tmp[1])

# ソート用にkeyとvalueを反転させた辞書を作る
for (key, value) in inputs.items():
    result[value] = key

result = sorted(result.items(), reverse=True)

for i in result:
    print(i[1] + " " + str(i[0]))

解説

考え方

以下の考え方で実現します

  1. 標準入力が何回行われるかという値を取得してfor文の繰り返し回数に指定する。2~5を繰り返す
  2. 標準入力で受け取った値を辞書のキーとバリューとして使う値に分割する
  3. 2で取得したキーの値が既出かどうかを確認する
  4. 既出の場合は1で取得したバリューを辞書内の同キーのバリューに足算する
  5. 未出の場合は1で取得したキーとバリューを辞書に追加する
  6. 2~5で作成した辞書をソートするためにキーとバリューを反転した辞書を作成する
  7. 6で作成した辞書をsorted関数で降順にソートする。キーと値のタプルのリストになる
  8. 7で作成したリストからキー、バリューに使用していた値を繰り返して出力する

2~5のコードの詳細

初見で考え方は思い付いたのですが、お手本を見るまでは実現させるイメージがつきませんでした。
お手本コード内の以下の箇所にあたります。

for i in range(num):
    tmp = input().split()

    exist = False
    for (key, value) in inputs.items():
        
        if key == tmp[0]:
            exist = True

    if exist:
        inputs[tmp[0]] = inputs[tmp[0]] + int(tmp[1])
    else:
        inputs[tmp[0]] = int(tmp[1])

取得したキーの値が既出かどうかを確認する の判断は
毎回、作成段階のリストからキーを一つずつ取り出して、今回のキーと同じであるか比較します。
初期値をFalseに設定しておき、同じであればTrueを返します。

Trueの場合は作成中辞書の今回のキーのバリューを今回のバリューと足算した値にします。
False、未出の場合は今回のキーとバリューを辞書に追加します。

コードの改善箇所

@shiracamus さんに改善点をご教示頂いたのでシェアしたいと思います。
ありがとうございます!

前述の2~5のコード箇所の簡略化

取得したキーの値が既出かどうかを確認する 箇所を
if tmp[0] in inputs: の一行で行うことが出来ます。

for i in range(num):
    tmp = input().split()

    if tmp[0] in inputs:
        inputs[tmp[0]] = inputs[tmp[0]] + int(tmp[1])
    else:
        inputs[tmp[0]] = int(tmp[1])

前述の6~7のコード箇所の簡略化

反転した辞書は不要で、キーを対象としてソートを行うことが可能です。
以下一行で実現出来ます

result = sorted(inputs.items(), key=lambda x: x[1], reverse=True)

処理速度が向上したり、視認性が良くなるのでより良いコードを知れる事はすごく嬉しいです。

おわりに

競技プログラミングな問題は「考え方」と「実現方法」の理解が大切ですね。
今は問題を一つでも多くといて自分の中に吸収していきたいです。

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0