第100回【Python】辞書式ソート、ソート
現在取り組んでいるのは、paiza ラーニング問題集「C ランクレベルアップメニュー」になります。
はじめに
猫とキャンプと野球観戦と AWS が大好きな旦那、LeoSaki です。モフモフしたい。
Python をゼロから勉強してみよう、のコーナー 100 回目です。
とうとう 3 桁に到達しました。自分で自分をほめてあげたい。ウソ。まだまだ途上だと思います。もっといろいろなアルゴリズムを身に付けられるように学習続けます。
それでは、今日も頑張ってみようと思います。
辞書式ソート
正整数 n が与えられ、数のペアが n 個与えられます。各ペアの最初の数はりんごの個数を、その次の数はバナナの個数を表しています。これらの数のペアを以下の規則に従って、偉い順に並び替えてください。
1. ふたつのペアのりんごの数が異なる場合、りんごの数が多い方が偉い(この際、バナナの数は関係ない)。
2. りんごの数が同じである場合、バナナの数が多い方が偉い。
ペアを偉い順に並べ替え、改行区切りで n 行、順に出力してください。出力の各行は入力と同じく、 “a_i b_i" のように、りんごの個数とバナナの数が、この順に、半角スペースで区切られているものとします。
n
a_1 b_1
...
a_n b_n
1 行目に正整数 n が、 2 行目から (n + 1) 行目には半角スペース区切りの数のペア a_1 b_1, …, a_n b_n が、それぞれ改行区切りで与えられます。
すべてのテストケースにおいて、以下の条件をみたします。
・ 1 ≤ n , a_i, b_i ≤ 50 (1 ≤ i ≤ n)
入力例
2
1 3
2 2
出力例
2 2
1 3
りんごとバナナのどっちが偉いか、とか知らんわ。りんごもバナナも好き。
Python
N = int(input())
ab = [None]*N
for i in range(N):
a,b = map(int,input().split())
ab[i] = [a,b]
ab.sort(reverse=True)
for a,b in ab:
print(a,b)
VBA
Private Sub c_rank_sort_step3()
N = Cells(1, 1)
Dim AB() As Variant
ReDim AB(N - 1)
For i = 0 To N - 1
temp = Split(Cells(i + 2, 1), " ")
AB(i) = Format(temp(0), "00") & Format(temp(1), "00")
Next
Call QuickSort_desc(AB, LBound(AB), UBound(AB))
For Each v In AB
Debug.Print Val(Left(v, 2)) & " " & Val(Right(v, 2))
Next
End Sub
Private Sub QuickSort_desc(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_desc(argAry, lngMin, i - 1)
End If
If (lngMax > j + 1) Then
Call QuickSort_desc(argAry, j + 1, lngMax)
End If
End Sub
ソート
N 人の人々がおり、それぞれの人は金と銀を何キログラムか持っています。今は金の方が銀よりも価値が高いですが、ある日金と銀の価値が逆転して、人々の財産の多さは次のように決定されるようになりました。
1. 持っている銀が多い方が財産が多い。
2. 持っている銀が同じなら、持っている金が多い方が財産が多い。
それぞれの人が持っている金と銀のキログラム数が与えられるので、この規則にしたがって、財産を多い順に並び替えて出力してください。
N
g_1 s_1
...
g_N s_N
1 行目には人々の数を表す整数 N が与えられ、 2 行目から (N + 1) 行目には、人々が持っている金の量 g_i と銀の量 s_i がそれぞれ半角スペース区切りで N 行与えられます (1 ≤ i ≤ N)。
すべてのテストケースにおいて、以下の条件をみたします。
・1 ≤ N ≤ 50
・0 ≤ g_i, s_i ≤ 50(1 ≤ i ≤ N)
入力例
2
2 1
1 2
出力例
1 2
2 1
金よりも銀の方が価値がある世界。うん、どちらにしろ持ってないからあまり関係ない。
Python
N = int(input())
gs = [None]*N
for i in range(N):
g,s = map(int,input().split())
gs[i] = [s,g]
gs.sort(reverse=True)
for s,g in gs:
print(g,s)
Python のスワップは面白いと思う。自由自在。
VBA
Private Sub c_rank_sort_boss()
N = Cells(1, 1)
Dim GS() As Variant
ReDim GS(N - 1)
For i = 0 To N - 1
temp = Split(Cells(i + 2, 1), " ")
GS(i) = Format(temp(1), "00") & Format(temp(0), "00")
Next
Call QuickSort_desc(GS, LBound(GS), UBound(GS))
For Each v In GS
Debug.Print Val(Right(v, 2)) & " " & Val(Left(v, 2))
Next
End Sub
Private Sub QuickSort_desc(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_desc(argAry, lngMin, i - 1)
End If
If (lngMax > j + 1) Then
Call QuickSort_desc(argAry, j + 1, lngMax)
End If
End Sub
最後に
VBA での複数値によるソートは、こういうやり方もあるんだ、と面白がっていただけたら嬉しい。以前のお仕事で工夫して工夫していろいろ並べ替えをしていたのが役に立った。売上ごと、売上個数ごと、みたいなことをしてました。VBA を駆使して。
このやり方が正しいかどうかは知らないですが。
Python の swap は、とても便利だと思う。工夫次第でいろいろと使い方が広がる。このやり方も引き出しとして持っておくと良いと思います。
引き続き、よろしくお願いいたします!
ディスカッション
コメント一覧
まだ、コメントがありません