Edited at

[Python] 型の把握は大事です


はじめに

最近Pyhonを勉強し始めた新人です。

今回はAtCoderを解いているときにはまってしまったことについて書きたいと思います。


はまってしまった問題

以下に問題を載せます。

B - Ordinary Number


問題

{1, 2, ..., n}の順列p={p1, p2, ..., pn}があります。

以下の条件を満たすようなpi(1 < i < n)がいくつあるかを出力せよ。


  • pi-1, pi, pi+1 の3つの数の中で、piが2番目に小さい。


制約


  • 入力はすべて整数である。

  • 3 <= n <=20

  • pは{1, 2, ..., n}の順列である。


考え方

pi-1, pi, pi+1の3つの数の中で、piが2番目に小さい。

すなわち以下の条件を満たせばよいと考えました。


  • pi-1 < pi < pi+1 または pi-1 > pi > pi+1

また、nの最大値が20のため、全部見ていっても問題ないですね。


実際に書いたコード

from sys import stdin

def main():
n = int(input())
p = stdin.readline().split()
count = 0
for i in range(1 , n-1):
if p[i-1] > p[i] >p[i+1] or p[i-1] < p[i] <p[i+1]:
count +=1
print(count)

if __name__ == "__main__":
main()

入力例では、正しく出力できたので提出してみましょう。


結果

WAです。

どうやら通らないテストケースがあるようです。

コードを見直してみると、pの中身がint型ではなく、str型になっていることがわかりました。

以下のように修正します。

from sys import stdin

def main():
n = int(input())
p = [int(x) for x in stdin.readline().split()]
count = 0
for i in range(1 , n-1):
if p[i-1] > p[i] >p[i+1] or p[i-1] < p[i] < p[i+1]:
count +=1
print(count)

if __name__ == "__main__":
main()

提出してみると

無事ACです!


反省

型の把握が甘かったことが今回の反省点です。

また、string型の比較である程度通ってしまったが故に、気づくのが遅くなってしまいました。


ちなみに

今回間違えてstring型で比較をしてしまいましたが、string型の比較はどのような挙動になるのか調べてみると、以下のサイトが見つかりました。

https://note.nkmk.me/python-str-compare/

上記のサイトによると、


Python3では文字列strはUnicodeであり、文字列の大小関係(順番)は文字のUnicodeコードポイント(文字コード)で判定される。

文字列も数値などと同様に<, <=, >, >=演算子で比較できる。1文字目が同じなら2文字目、3文字目...と順番に比較される。


以下はUnicode表の一部です。

そのため、同じ桁同士だとint型と同じ結果になりますが、桁が違うと、異なる結果になってしまいますね。