🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

489閲覧

python3 ログファイルの解析

17issosu

総合スコア6

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/11/10 15:12

前提・実現したいこと

python3.7で、ログファイルを解析し、ブラックジャックのカウンティングをするというプログラムを組んでいます。

読み取るログファイルの中身は
♣6 ♡6 ♢A ♠5,♢9 ♡5 ♢4,0
♡9 ♡Q,♠6 ♢10 ♣4,-10
♣5 ♡10 ♢J,♣8 ♠7,-10
♠8 ♠J,♢6 ♣2 ♢5 ♠3 ♣Q,10
です。最後の0か10か-10は関係ないので無視し、
A,K,Q,J,10→-1
6,5,4,3,2→+1
その他→±0
で計算し、このログファイル全体の合計値を出します。

発生している問題・エラーメッセージ

合計値として5が出力されるはずですが、10が出力されてしまいます。

該当のソースコード

python

1import sys 2s=0 3 4try: 5 with open(sys.argv[1]) as fp: 6 for line in fp: 7 if line.find("A"or"K"or"Q"or"J"or"♢10"or"♡10"or"♠10"or"♣10")>=0: 8 num_m=line.count("A")+line.count("K")+line.count("Q")+line.count("J")+line.count("♢10")+line.count("♡10")+line.count("♠10")+line.count("♣10") 9 s-=num_m 10 else: 11 pass 12 13 if line.find("6"or"5"or"4"or"3"or"2")>=0: 14 num_p=line.count("6")+line.count("5")+line.count("4")+line.count("3")+line.count("2") 15 s+=num_p 16 else: 17 pass 18 19 print(s) 20 21except FileNotFoundError: 22 print("File read error")

補足情報(FW/ツールのバージョンなど)

windows10を使っています

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

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

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

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

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

guest

回答2

0

ベストアンサー

python

1import sys 2s=0 3 4try: 5 with open(sys.argv[1]) as fp: 6 for line in fp: 7 num_m=line.count("A")+line.count("K")+line.count("Q")+line.count("J")+line.count("♢10")+line.count("♡10")+line.count("♠10")+line.count("♣10") 8 s-=num_m 9 10 num_p=line.count("6")+line.count("5")+line.count("4")+line.count("3")+line.count("2") 11 s+=num_p 12 13 print(s) 14 15except FileNotFoundError: 16 print("File read error")

絵札と番号札とで条件分岐は不要なので、単純に数え上げればよいはずです。

投稿2019/11/10 15:37

NCC1701

総合スコア1680

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

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

17issosu

2019/11/10 15:46

ありがとうございます。確かに条件分岐は不要でした。しかし、上記のプログラムを実行すると5ではなく7を出力として得てしまいます。何が問題なのでしょうか・・・?
17issosu

2019/11/10 16:05

文字化けの問題でした・・・!!このプログラムで正常な出力が得られました。ありがとうございます
guest

0

##論理バグの原因と解法について

#####直接的原因

Python

if line.find("A"or"K"or"Q"or"J"or"♢10"or"♡10"or"♠10"or"♣10")>=0:

この条件は、次のように書いているのと同じです。

Python

1if line.find("A")>=0:

#####強引な解法

次のように、帰属判定した結果をorで結んでやります。
※ 帰属判定とは、リストなどのコレクションにある特定の要素が含まれるか調べること。

Python

1if line.find("A") >= 0 or line.find("K") >= 0 or line.find("Q") >= 0 or ...:

なお帰属判定にはin演算子を使うことが好ましいので、次のように書き換えると少しはマシです。
参考組み込み型 — Python 3.8.0 ドキュメント

Python

1if "A" in line or "K" in line or "Q" in line or ...:

any関数とジェネレータ式を使うとずっと簡略化できますが、回答の本旨に反するため省略します。

#####現実的な解法

既にNCC1701さんが回答されているとおり、不要な分岐を無くすことです。

論理演算について、もう少し詳しく

値にはいわゆるtruthyなものとfalsyなものが存在します。
これらについて乱暴に説明すると、bool関数に突っ込んだときtrueを返す値がtruthyです

Python

1>>> bool('spam') # 'spam' はtruthy 2True 3>>> bool('ham') # 'ham' はtruthy 4True 5>>> bool('') # '' はfalsy 6False

シーケンスについては、長さ0のものがfalsyに振舞うように設計されています。
文字列の場合、空文字列です。


or演算子は両オペランドの真偽を判断し、結果が確定した際の値を返します。
or演算の場合、最初に見つけたtruthyな要素を返すことになります。

Python

1>>> 'spam' or '' 2'spam' 3>>> '' or 'ham' 4'ham' 5>>> 6>>> 'spam' or 'ham' 7'spam' 8>>> 'ham' or 'spam' 9'ham' 10>>> '' or '' 11''

上記を踏まえると、"A" or "K" or ... が "A" を返すことが分かります。

##別解

私なら次のように書きます。

Python

1import sys 2 3 4def get_score(card): 5 rank = card[1:] 6 7 if rank in ['A', '10', 'J', 'Q', 'K']: 8 return -1 9 10 rank = int(rank) 11 if 2 <= rank <= 6: 12 return +1 13 14 return 0 15 16 17s = 0 18assert 1 < len(sys.argv), 'USAGE: .py logfile' 19with open(sys.argv[1]) as fin: 20 for line in fin: 21 cards1, cards2, _ = line.split(',') 22 cards1 = cards1.split() 23 cards2 = cards2.split() 24 25 s += sum(map(get_score, cards1)) 26 s += sum(map(get_score, cards2)) 27 28print(s)

Wandbox

投稿2019/11/10 16:22

LouiS0616

総合スコア35668

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問