House Password

chekioの問題やろうぜシリーズ

問題文

斉藤くんはセキュリティに対する意識が低すぎて、いつも糞単純なパスワードを設定している。「ちゃんとしたパスワードかどうかをチェックするプログラム」を作るのが今回のミッションだ!今回定義する「ちゃんとしたパスワード」とは

  • 10文字以上で
  • 1文字以上の数字が含まれていて
  • 1文字以上の小文字と1文字以上の大文字が含まれている

この条件を満たすものとする。ちなみに使われる文字はASCII文字のみ。現実のWebサービスなどでもとてもよく見られるパスワードパターンだ。

おそらくchekioを初めて最初に取り組む事になる問題。問題自体よりもchekioのUIに戸惑ったりするかもしれないけれど、ちょっとやればすぐ慣れる!レッツゴー。

まずは超初心者向け回答から。

def checkio(data: str) -> bool:
    length_check = False
    if len(data) >= 10:
        length_check = True
    
    number_check = False
    for c in data:
        if c.isdigit():
            number_check = True
            break
    
    lower_check = False
    for c in data:
        if c.islower():
            lower_check = True
            break
    
    upper_check = False
    for c in data:
        if c.isupper():
            upper_check = True
            break
    
    if length_check == True and number_check == True and lower_check == True and upper_check == True:
        return True
    else:
        return False

条件チェッカーを作り、デフォルトをFalseに設定。チェッカーが通れば値がTrueに変わり、最後に全部のチェッカーがTrueになっていれば回答としてTrueを、そうでなければFalseを返すっていうやつ。ちょっとプログラミングをかじっている人が見たら「なんだこの冗長な糞コード」と思われるのも無理はないけれど、色々と学ぶべき事も多い。

isdigit(), islower(), isupper()など、教則本の最初の方に載っていて、結局いつ使うのか不明なメソッドを活用するチャンス!dataで与えられた文字を一個一個確認していくので、forループで回す。一応気持ちだけ処理速度を上げる為に、チェッカーがTrueになった段階でbreakを掛けている。

正規表現モジュールを使う場合

おそらくこれがマジョリティな方針になると思う。個人的には正規表現ってなんだか記号が多くて気持ち悪いので、好きではない。

import re

DIGIT_RE = re.compile('\d')
UPPER_CASE_RE = re.compile('[A-Z]')
LOWER_CASE_RE = re.compile('[a-z]')

def checkio(data):
    """
    Return True if password strong and False if not
    
    A password is strong if it contains at least 10 symbols,
    and one digit, one upper case and one lower case letter.
    """
    if len(data) < 10:
        return False
    
    if not DIGIT_RE.search(data):
        return False

    if not UPPER_CASE_RE.search(data):
        return False

    if not LOWER_CASE_RE.search(data):
        return False
        
    return True

elseって言わないで通すようにするのが少しだけPythonista。

setを使う方法

import string

upper = set(string.ascii_uppercase)
lower = set(string.ascii_lowercase)
digits = set(string.digits)


def checkio(data):
    letters = set(data)
    return bool(len(data) >= 10 and upper & letters and lower & letters and digits & letters)

他の人の回答を眺めてて、個人的に好きだったのがこのsetを使う方法。なるほどねー!
あとstringライブラリはこうゆう類の問題でよく使うので、シンタックスを覚えておこうとまでは言わないけれど、こうゆうのがあるっていう事だけ覚えておくと便利。

lower = ('abcdefghijklmnopqrstuvwxz')

なんてイチイチ書いてたら超絶面倒臭い訳で。。