質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

487閲覧

Python3のコードをもっと早く走らせたい。改善案お教えください。

nono33

総合スコア17

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

1クリップ

投稿2020/07/28 12:00

某サイトの問題です。ただし、問題そのものを載せてしまうと規定に違反するので詳細は伏せます。

下記コードで目的の結果は得られています。しかし、実際にコードを走らせると時間切れになってしまいます。
どの部分が遅くなっている原因でしょうか?
どうすれば早くなりますか?お教えください。

Python3

1mono=[[300, 3], [140, 5], [200, 5]] 2a = ['ok 1 1 1', 'ok 3 4 0', 'no 1 1 1', 'ok 3 4 0', 'ok 0 0 2', 'add 1 0 0'] 3for i in range(6): 4 aa=a[i].split() 5 if aa[0]=='ok': 6 aa=aa[1:] 7 aa=[int(x) for x in aa] 8 price=0 9 err=0 10 for j in range(len(aa)): 11 if aa[j] > mono[j][1]: 12 err=1 13 if err==1: 14 print(-1) 15 else: 16 for j in range(len(aa)): 17 price=price+mono[j][0]*aa[j] 18 bread[j][1]=mono[j][1]-aa[j] 19 print(price) 20 elif aa[0]=='add': 21 aa=aa[1:] 22 aa=[int(x) for x in aa] 23 for k in range(len(aa)): 24 mono[k][1]=mono[k][1]+aa[j]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

can110

2020/07/28 12:08

問題が分からないと回答できないと思うのですが、いかがお考えでしょうか?
cateye

2020/07/28 12:12

「規定に違反する」のは、問題文だけですか?・・・回答を、他者に聞くには良いのですか?
nono33

2020/07/28 14:03 編集

ご質問ありがとうございます。 can110さん、そうですね。問題文からだいぶ離れているのでもう少し背景を記載します。 monoには3種類、それぞれ値段と個数が入力されています。 aにはある行為が6回入力されています。 行為名がOKの場合はmonoからそれぞれ記載の個数分ずつ売ります。 行為名がaddの場合は、monoにそれぞれの個数を追加します。 行為名がOKの場合は売上金priceを出力 行為名OKの注文を達成できない場合には-1を出力します。 cateyeさん、ありがとうございます。 > 回答を、他者に聞くには良いのですか? 回答を尋ねる行為も違反ですが、私はこの問題にすでに回答済み(一度しか挑戦できないため)なので大丈夫です。
yymmt

2020/07/28 14:15

前提条件がもう少し欲しいです。 1. listを足し合わせるのにsum()は利用可能でしょうか? 2. numpy等のパッケージは利用可能でしょうか? 3. monoを分解してmono_price, mono_countとするのは可能でしょうか?
nono33

2020/07/28 14:30

yymmt様 ご質問ありがとうございます。 1. listを足し合わせるのにsum()は利用可能でしょうか? 2. numpy等のパッケージは利用可能でしょうか? 3. monoを分解してmono_price, mono_countとするのは可能でしょうか? 上記全て可能ですが、 例えば3の場合は、途中に mono_price=[x[0] for x in mono] のようにコードを入れる必要があります。 宜しくお願いいたします。
yymmt

2020/07/28 14:48

monoやaは与えられたものとして、自分でパースしなさいと理解しました。
nono33

2020/07/28 14:51

そうです。宜しくお願いいたします。
guest

回答1

0

ベストアンサー

どの部分が遅くなっている原因でしょうか?

下記のように実行するとプロファイラが動きますので、関数の呼び出し回数や実行時間を調べることができます。

terminal

1python -m cProfile hoge.py

実行結果は

terminal

1 25 function calls in 0.002 seconds 2 3 Ordered by: standard name 4 5 ncalls tottime percall cumtime percall filename:lineno(function) 6 1 0.000 0.000 0.002 0.002 hoge.py:1(<module>) 7 1 0.000 0.000 0.000 0.000 hoge.py:22(<listcomp>) 8 4 0.000 0.000 0.000 0.000 hoge.py:7(<listcomp>) 9 1 0.000 0.000 0.002 0.002 {built-in method builtins.exec} 10 7 0.000 0.000 0.000 0.000 {built-in method builtins.len} 11 4 0.002 0.000 0.002 0.000 {built-in method builtins.print} 12 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 13 6 0.000 0.000 0.000 0.000 {method 'split' of 'str' objects}

となりました。一回だけだとほとんど分かりませんが、1000回くらいループすると、どの部分が遅いか分かります。print()が非常に重いのでコメントアウトやリダイレクトすると良いかも知れません。

どうすれば早くなりますか?

高速化のポイントとしては

  • 重い処理を同等の軽い処理に置き換える
  • loopを減らす・内包表記を使う
  • 不要な処理は実行しない

ということです。例えば回数が多く呼ばれている関数(ここではlen()やsplit())が削除できないか、あるいは高速化できないかを考えます。例えば一例として

  • range()ではなく既存のリストでループ
  • 文字列比較に先頭文字の'a'と'o'のみ比較
  • noのときはsplit()処理が不要のためsplit処理をif後に実施

以上を行うことで実行時間は私の環境では60%くらいまで短縮できました。

python

1mono=[[300, 3], [140, 5], [200, 5]] 2a = ['ok 1 1 1', 'ok 3 4 0', 'no 1 1 1', 'ok 3 4 0', 'ok 0 0 2', 'add 1 0 0'] 3for aa in a: 4 if aa[0]=='o': 5 price = 0 6 for count, m in zip(aa.split()[1:], mono): 7 count = int(count) 8 if count > m[1]: 9 price = -1 10 break 11 else: 12 price += m[0] * count 13 m[1] -= count 14 print(price) 15 elif aa[0]=='a': 16 mono=[[m[0], m[1] + int(count)] for count, m in zip(aa.split()[1:], mono)]

投稿2020/07/28 17:24

yymmt

総合スコア1615

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nono33

2020/07/29 00:44

yymmt様、丁寧な解説・コードだけでなく、考え方までお教え頂きとても勉強になりました。 高速化などについてはなかなか勉強する方法が無かったのでとても助かりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問