第157回【Python】配列のソート、文字と整数の組のソート2

現在取り組んでいるのは、paiza ラーニング問題集「B ランクレベルアップメニュー」になります。

はじめに

猫とキャンプと野球観戦と AWS が大好きな旦那、LeoSaki です。モフモフしたい。

Python をゼロから勉強してみよう、のコーナー 157 回目です。

雨の日に、バイクで転んだことがあります。前を走っていたバイクが突然進路を変えてきて、それを避けようとして転びました。10 m 以上滑りました。そのときは早く立て直さないとという気持ちで立ち上がり、バイクも動いたため目的地に向かいました。目的地に着いたらおもいっきり引かれました。右半身がボロボロで血だらけでした。突然激痛に襲われて、大変だったのを覚えています。

それでは、今日も頑張ってみようと思います。

今回取り組む内容について

以下は、前回までに取り組んだ問題とまったく同じなので、飛ばします。
コードは数書いてナンボとかカッコつけたこと書いてましたが、あまりにも多いので挫折しました。

STEP: 1 インクリメント
STEP: 5 数字のみの出力
STEP: 6 昇順ソート出力

配列のソート (paizaランク D 相当)

指定した配列を定義し、配列の要素を昇順に並び替えて、全て出力してください。

なし

1, 3, 5, 6, 3, 2, 5, 23, 2
を要素に持つ配列をプログラムで定義し、使用すること。


期待する出力

昇順に並び替えて、1要素ごとに改行して出力してください。
最後は改行し、余計な文字、空行を含んではいけません。


すべてのテストケースにおいて、以下の条件をみたします。

なし


入力例

なし

出力例

なし

また並び替えか。VBA で書くのは面倒なんだよなぁ。Python はとても簡単。

Python
li = [1, 3, 5, 6, 3, 2, 5, 23, 2]
li.sort()
for v in li:
    print(v)
VBA
Sub sort_add_3()

    Dim li() As Variant
    li = Array(1, 3, 5, 6, 3, 2, 5, 23, 2)
    
    Call QuickSort(li(), LBound(li), UBound(li))
    
    For Each v In li
        Debug.Print v
    Next
    
End Sub

Private Sub QuickSort(ByRef argAry() As Variant, ByVal lngMin As Long, ByVal lngMax As Long)
 
    Dim i As Long
    Dim j As Long
    Dim vBase As Variant
    Dim vSwap As Variant
    vBase = argAry(Int((lngMin + lngMax) / 2))
    i = lngMin
    j = lngMax
    Do
        Do While argAry(i) < vBase
            i = i + 1
        Loop
        Do While argAry(j) > vBase
            j = j - 1
        Loop
        If i >= j Then Exit Do
        vSwap = argAry(i)
        argAry(i) = argAry(j)
        argAry(j) = vSwap
        i = i + 1
        j = j - 1
    Loop
    If (lngMin < i - 1) Then
        Call QuickSort(argAry, lngMin, i - 1)
    End If
    If (lngMax > j + 1) Then
        Call QuickSort(argAry, j + 1, lngMax)
    End If
     
End Sub

文字と整数の組のソート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

ちょっと応用の入った並び替え。これだって、Python なら簡単なんだけど。

Python
n = int(input())
dic = {}

for _ in range(n):
    s,d = input().split()
    if s in dic:
        dic[s] += int(d)
    else:
        dic[s] = int(d)
        
for k,v in sorted(dic.items(),key=lambda x:x[1],reverse=True):
    print(k,v)
VBA
Sub sort_add_9()

    N = Cells(1, 1)

    Dim dic As Object
    Set dic = CreateObject("Scripting.Dictionary")
    
    For i = 1 To N
        sd = Split(Cells(i + 1, 1), " ")
        s = sd(0)
        D = Val(sd(1))
        If dic.exists(s) Then
            dic(s) = dic(s) + D
        Else
            dic.Add s, D
        End If
    Next

    arrKeys = dic.Keys
    
    Dim arrList()
    ReDim arrList(dic.Count - 1, 1)
    
    For i = LBound(arrKeys) To UBound(arrKeys)
        arrList(i, 0) = dic(arrKeys(i))
        arrList(i, 1) = arrKeys(i)
    Next
    
    Call QuickSort_dic_reverse(arrList, LBound(arrList, 1), UBound(arrList, 1))
    
    dic.RemoveAll
    
    For i = LBound(arrList) To UBound(arrList)
        dic.Add arrList(i, 1), arrList(i, 0)
    Next
    
    For Each v In dic
        Debug.Print v & " " & dic(v)
    Next
    
    
End Sub

Private Sub QuickSort_dic_reverse(ByRef arrList() As Variant, ByVal minIDX As Long, ByVal maxIDX As Long)
 
    Dim valMEDIAN As Variant
    Dim arrTEMP() As Variant
    Dim i As Long
    Dim j As Long
     
    'ソート範囲の上下限を設定
    i = minIDX
    j = maxIDX
     
    '基準値としてインデックスの中央値のデータを使用します。
    valMEDIAN = arrList(Int((minIDX + maxIDX) / 2), 0)
 
    Do
        'インデックスの小さい方から値を比較していく
        Do While arrList(i, 0) > valMEDIAN
            i = i + 1
        Loop
         
        'インデックスの大きい方から値を比較していく
        Do While arrList(j, 0) < valMEDIAN
            j = j - 1
        Loop
         
        'インデックスが逆転したらループ抜け
        If i >= j Then Exit Do
         
        '配列を定義
        ReDim arrTEMP(0, 1)
         
        '配列内のデータの入れ替え1
        arrTEMP(0, 0) = arrList(i, 0)
        arrList(i, 0) = arrList(j, 0)
        arrList(j, 0) = arrTEMP(0, 0)
         
        '配列内のデータの入れ替え2
        arrTEMP(0, 1) = arrList(i, 1)
        arrList(i, 1) = arrList(j, 1)
        arrList(j, 1) = arrTEMP(0, 1)
         
        '配列の初期化
        Erase arrTEMP
         
        'インデックスの加減算
        i = i + 1
        j = j - 1
    Loop
     
    '再帰でソートが完了するまで繰り返し
    If (minIDX < i - 1) Then Call QuickSort_dic_reverse(arrList, minIDX, i - 1)
    If (maxIDX > j + 1) Then Call QuickSort_dic_reverse(arrList, j + 1, maxIDX)
     
End Sub

最後に

なんか実務でもありそうな感じの問題でした。実際、並べ替えはいろんな場面で使うし、そのパターンは多岐に渡るしで、それこそ VBA では限界を感じてしまう部分です。(もちろん、ワークシートを利用してしまう、という奥の手を使えばいいのですけれど)

ちょっとやばい。Python 書くより、VBA を調べる方が楽しくなってしまっている。Python のお勉強のための時間なのに!

引き続き、よろしくお願いいたします!

Pythonpaiza,学習,Python

Posted by LeoSaki