第136回【Python】経理

現在取り組んでいるのは、paiza ラーニング問題集「クエリメニュー」になります。

はじめに

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

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

ルナちゃんはとにかく甘えん坊です。膝の上に乗りたがります。時々、自宅からリモート会議に出席しているのですが、ルナちゃんはデビュー済みです。ミュートが間に合わず、鳴き声もデビュー済みです。ちょっと雰囲気の悪い会議の際に、ルナちゃんの一声で、なんだかカメラ越しの皆さんの表情が丸くなりました。

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

経理

paiza には N 個の部署があり、名前はそれぞれ S_1 … S_N です。
経理係となったあなたは、どの部署が何円のどのような買い物をしたかを記録するように言われました。
どの部署が何円で何を買ったかの領収書が K 枚与えられるので、各部署の会計表を作成しましょう。

N K
S_1
...
S_N
A_1 P_1 M_1
...
A_K P_K M_K

・1 行目では、部署の数 N と与えられる領収書の枚数 K が与えられます。
・続く N 行のうち、 i 行目では、i 番目に登録されている部署名 S_i が与えられます。
・続く K 行のうち、 i 行目では、 i 枚目の領収書に書かれていた部署名 A_i , 注文番号 P_i , その金額 M_i が半角スペース区切りで与えられます。


期待する出力

S_1
P_1 M_1
...
-----
S_2
P_1 M_1
...
-----
...
-----
S_N
P_1 M_1
...
-----

・各部署について次の形式で出力してください。
・1 行目では、登録されている部署名 S_i を出力してください。
・2 行目以降には、注文番号 P_1 … とその値段 M_1 … を入力された順に半角スペース区切りで出力してください。
・各部署の出力の後ろに以下の通り区切りを出力してください。

-----

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

・1 ≦ N ≦ 100,000
・1 ≦ K ≦ 100,000
・A_i は S_j のいずれか (1 ≦ i ≦ K , 1 ≦ j ≦ N)
・S_i は 20 文字以下の文字列 (1 ≦ i ≦ N)
・0 ≦ P_i ≦ 10^10 (1 ≦ i ≦ K)
・1 ≦ M_i ≦ 10,000 (1 ≦ i ≦ K)


入力例

3 6
A
B
C
A 1 100
B 2 100
A 3 500
C 4 895
C 5 890
A 6 2685

出力例

A
1 100
3 500
6 2685
-----
B
2 100
-----
C
4 895
5 890
-----

昔ながらの経理的なお仕事だけれど、最大 10 万も部署があって、最大 10 万も領収書が届けられたら、まとめるのにどれだけの時間がかかるか。ブラック企業の比じゃないね。

Python
N,K = map(int,input().split())
receipts = { input():[] for _ in range(N) }

for _ in range(K):
    A,P,M = input().split()
    receipts[A].append((P,int(M)))
    
for k,v in receipts.items():
    print(k)
    for P,M in v:
        print(P,M)
    print('-----')

辞書の要素を配列にして append で追加していく。その後の unpack にしても、Python は便利だなー。

VBA
Sub query_primer__accounting()

    NK = Split(Cells(1, 1), " ")
    N = Val(NK(0))
    k = Val(NK(1))
    
    Dim dic As Object
    Set dic = CreateObject("Scripting.Dictionary")
    
    For i = 1 To N
        A = Cells(i + 1, 1)
        dic.Add A, Array()
    Next
        
    For i = 1 To k
        APM = Split(Cells(i + N + 1, 1), " ")
        A = APM(0)
        P = APM(1)
        m = APM(2)
        temp = Split(Join(dic(A), vbCrLf) & vbCrLf & "(" & P & "," & m & ")", vbCrLf)
        dic(A) = temp
    Next
    
    For Each A In dic
        Debug.Print A
        For i = 1 To UBound(dic(A))
            Debug.Print Replace(Replace(Replace(dic(A)(i), "(", ""), ")", ""), ",", " ")
        Next
        Debug.Print "-----"
    Next
    
End Sub

いつもの如くの paiza が用意してくれている境界値データで約 185 秒。そして、Debug.Print をしなければ、約 1.6 秒。電子データで提出してくれるようになれば定時で帰れると思う。

最後に

VBA で、辞書型に add していないのに、Item が一つ追加されてしまう現象に悩まされた。これは、VBA の仕様のようで、存在しない Key に対して値を取得しようとすると、Key を作成してしまうらしい。

今回のコードだと、最後の Debug.Print のブロックで、For Each ● In dic の●に A 以外が入っていると発生してしまった。最初の dic.add に A としているため、A 以外のものは存在しない Key であると判定されてしまったようだ。なかなか躓いてしまった。

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

Python学習,Python,paiza

Posted by LeoSaki