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

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

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

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

Q&A

解決済

2回答

188閲覧

pythonによる安全なポーンの数の判定

panamax

総合スコア22

Python 3.x

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

0グッド

0クリップ

投稿2018/03/27 04:46

前提・実現したいこと

8×8マスのチェス盤面にn個(0<n<=8)のポーンだけが置かれているのを想定します。ポーンは隣接した斜め前にある敵の駒を、そのマスに動かすことによって取ることができます。(今回は敵の駒は登場しませんが。)この時、あるポーンAが他のポーンの隣接した斜め前にあればポーンAは安全であるとします。ここで、ポーンが置かれているマスの座標のセットが与えられた時に、幾つのポーンが安全であるかを整数で返す関数を作成しました。しかし、あるポーンが置かれているマスの座標のセットを与えた時に、関数が誤った結果を返しました。(7と返すところを8と返してしまった。)
誤った結果を返してしまった原因を探りましたが解らなかったので、原因を教えていただきたいです。

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

関数が誤った結果を返したときに与えられた、ポーンが置かれているマスの座標のセットはhogeです。
hoge = ["a1","b2","c3","d4","e5","f6","g7","h8"]
これは以下のようなポーンの配置を表しています。

python

18[ ][ ][ ][ ][ ][ ][ ][p] 27[ ][ ][ ][ ][ ][ ][p][ ] 36[ ][ ][ ][ ][ ][p][ ][ ] 45[ ][ ][ ][ ][p][ ][ ][ ] 54[ ][ ][ ][p][ ][ ][ ][ ] 63[ ][ ][p][ ][ ][ ][ ][ ] 72[ ][p][ ][ ][ ][ ][ ][ ] 81[p][ ][ ][ ][ ][ ][ ][ ] 9 a b c d e f g h

該当のソースコード

定義した関数と、hogeを引数として関数を実行した結果は以下です。(今回質問をするにあたって、関数の挙動を可視化するためにprintやreturn(a)を追加しましたが、本来はreturn(b)のみが返り値です。)

定義した関数

python

1def safe_pawns(hoge): 2 hoge = [i.replace('a','1') for i in hoge] 3 hoge = [i.replace('b','2') for i in hoge] 4 hoge = [i.replace('c','3') for i in hoge] 5 hoge = [i.replace('d','4') for i in hoge] 6 hoge = [i.replace('e','5') for i in hoge] 7 hoge = [i.replace('f','6') for i in hoge] 8 hoge = [i.replace('g','7') for i in hoge] 9 hoge = [i.replace('h','8') for i in hoge] 10 a=[] 11 b=0 12 for j in hoge: 13 a.append(int(j)) 14 for k in a: 15 print('kの値は',k) 16 if (k+11 & k-9) in a: 17 b += 2 18 print('bの値は',b,'パターン1') 19 elif (k+11 & k-9 & k+2) in a: 20 b += 1 21 print('bの値は',b,'パターン2') 22 elif (k+11 or k-9) in a: 23 b += 1 24 print('bの値は',b,'パターン3') 25 for l in range(len(a)):  #特殊なポーンの配置の場合を想定したもので、ここが原因になってるわけではないと思います。 26 if (a[l]+20 in a) & (a[l]+11 in a) & (a[l]+9 not in a): 27 b -= 1 28 return(b,a)

実行結果

python

1kの値は 11 2bの値は 1 パターン3 3kの値は 22 4bの値は 2 パターン3 5kの値は 33 6bの値は 3 パターン3 7kの値は 44 8bの値は 4 パターン3 9kの値は 55 10bの値は 5 パターン3 11kの値は 66 12bの値は 6 パターン3 13kの値は 77 14bの値は 7 パターン3 15kの値は 88 16bの値は 8 パターン2 17 18(8, [11, 22, 33, 44, 55, 66, 77, 88])  #本来は7と返すところを8と返してしまっている

試したこと

今回の疑問は、実行結果の最後の方の「bの値は 8 パターン2」という部分で、なぜ「パターン2」になっているのかということです。このようになっている原因について教えていただきたいと思っています。

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

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

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

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

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

Zuishin

2018/03/27 05:03

その前にどういう意図で組んだのか解説してください。k + 11 は k の右前にあるポーンで、k - 9 は左前にあるものだということはわかります。そのビット論理積が何を意味するのかわかりませんしパターンの意味もわかりません。
guest

回答2

0

ベストアンサー

判定アルゴリズムは確認していません。
if中の(k+11 & k-9 & k+2)は各値を**&演算した結果**になります。
すなわち上記コードk=88では66になるのでリストa内に存在すると(誤?)判定されています。

ちなみに&andとすると(k+11 and k-9 and k+2)の最後の解釈結果k+2の結果90となりますが、これが意図した値かどうかは判定アルゴリズムによります。

Python

1k = 88 2 3b = (k+11 & k-9 & k+2) # 各値を&演算した結果 = 66 4print(b) 5print( (99 & 79 & 90)) # =66 と同じ 6 7b = (k+11 and k-9 and k+2) # 文の最後の解釈結果 = k + 2 = 90 8print(b) 9print( True and 'aaa' and k+2) # =90 と同じ

投稿2018/03/27 05:34

can110

総合スコア38262

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

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

panamax

2018/03/27 06:37 編集

ご返答ありがとうございます。さらに質問が3つあります。 1. 「print( (99 & 79 & 90)) # =66 と同じ」とありますが、なぜそこで66が出力されるのでしょう? 例えば、「print( (99 & 99 & 99)) # =99 」となることについてはわかるのですが、なぜ99,79,90という全く異なる3つの整数について&演算をすると、66という整数が出力されるのかが解らないです。そもそも&演算についての私の理解が足りないとは思うのですが、&演算は「ベン図においてそれぞれの領域が重なっている領域を返す」というような認識です。 2. 「&をandとすると(k+11 and k-9 and k+2)の最後の解釈結果k+2の結果90となります」とありますが、なぜ「and」の場合はk+2だけしか考慮されないのでしょうか?「and」を使っているのにも関わらず最後の解釈結果k+2だけが出力されるのでは「and」が正常に機能してないと思うのですが、それでもエラーが出ずにプログラムが実行されるのはなぜなのでしょうか? 3. 「print( True and 'aaa' and k+2)」とありますが、「'aaa'」とは何を表しているのでしょうか?
can110

2018/03/27 07:11 編集

>1 &は「ビットAND演算子」です。各値の両方のビットが立っている部分だけ1になります。 たとえば 5 & 4 -> 0b101 & 0b100 -> 0b100 = 4 になります。 >2 ざっくりと回答すると「pythonはそういうふうにできている」からです。 「x and y」も「式」で、その解釈(and演算)結果の値が返ります。 その他の言語ではandやor演算の結果はbool(true/false)型が返ることが多いですが pythonでは「x」や「y」の値がそのまま返ります。 >3 `aaa`自体にとくに意味はないです。Trueである値であれば何でもよいという意味で用いました。 2と3の詳細については[Python の or と and 演算子の罠](https://qiita.com/keisuke-nakata/items/e0598b2c13807f102469)が参考になるかと思います。
panamax

2018/03/27 07:40

理解しました。ビット演算について知識がなかったのでとても勉強になりました。 丁寧な回答ありがとうございました。m(_ _)m
guest

0

ロジックが難解でよくわからないのですが、オチモノの定石として外をとりあえず囲わないと例外処理がいろいろ出るような。
そして、上のルールを信じれば、答えは2では?

python

1import numpy as np 2 3def safe_pawns(hoge): 4 hoge = [i.replace('a','1') for i in hoge] 5 hoge = [i.replace('b','2') for i in hoge] 6 hoge = [i.replace('c','3') for i in hoge] 7 hoge = [i.replace('d','4') for i in hoge] 8 hoge = [i.replace('e','5') for i in hoge] 9 hoge = [i.replace('f','6') for i in hoge] 10 hoge = [i.replace('g','7') for i in hoge] 11 hoge = [i.replace('h','8') for i in hoge] 12 a=[] 13 for j in hoge: 14 a.append([int(j[0]),int(j[1])]) 15 16 board = np.zeros((10,10)) 17 board[:,0] = 1 18 board[:,-1] = 1 19 board[0,:] = 1 20 board[-1,:] = 1 21 for x, y in a: 22 board[x][y] = 1 23 24 b = 0 25 for x, y in a: 26 if board[x+1][y+1] == 1 and board[x-1][y+1] == 1: 27 b += 1 28 print(b) 29 30hoge = ["a1","b2","c3","d4","e5","f6","g7","h8"] 31safe_pawns(hoge)

投稿2018/03/27 06:45

mkgrei

総合スコア8560

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問