あなたの番号を推測する

Oct 17 2020

1から63までの数字を考えるように求める単純なスクリプトは、数字のリストを提供し、あなたの番号がそのリストに含まれているかどうかを尋ねます。これをさらにリファクタリングできますか?リストを作成するためのより良い方法はありますか?何か改善はありますか?

x= [xx for xx in range(1,64)]
num_i = [i for i in range(1,64,2)]
num_ii = x[1::16]+ x[2::16]+ x[5::16]+ x[6::16]+ \
         x[9::16]+ x[10::16]+ x[13::16]+ x[14::16]
num_ii.sort()
num_iii= x[3::16]+ x[4::16]+ x[5::16]+ x[6::16]+ \
         x[11::16]+ x[12::16]+ x[13::16]+ x[14::16]
num_iii.sort()
num_iv=  x[7::16]+ x[8::16]+ x[9::16]+ x[10::16]+ \
        x[11::16]+ x[12::16]+ x[13::16]+ x[14::16]
num_iv.sort()
num_v= x[15::32]+ x[16::32]+ x[17::32]+ x[18::32]+ \
       x[19::32]+ x[20::32]+ x[21::32]+ x[22::32]+ \
       x[23::32]+ x[24::32]+ x[25::32]+ x[26::32]+ \
       x[27::32]+ x[28::32]+ x[29::32]+ x[30::32]
num_v.sort()
num_vi= [x for x in range(32,64)]
num_lists=[num_i,num_ii,num_iii,num_iv,num_v,num_vi]
addition_num= [1,2,4,8,16,32]
start_end= ["Think of a number between 1 and 63","I think the number you thought of was ..."]
intro= ["Is your number in the group of numbers below?",
        "Is your number in this group of numbers ?","Is your number in this third group of numbers ?",
        "Half way there. Is your number in this group of numbers ?",
        "One more after this one. Is your number in this group of numbers ?",
        "Last one. Is your number in this group of numbers ?"]
def format_list(xx):    
    for a,b,c,d,e,f,g,h in zip(xx[::8],xx[1::8],xx[2::8],xx[3::8],xx[4::8],xx[5::8],xx[6::8],xx[7::8]):
        print('{:<8}{:<8}{:<8}{:<8}{:<8}{:<8}{:<8}{:<}'.format(a,b,c,d,e,f,g,h))
    print('-'*62)
def main():    
    count=0
    your_guess= 0
    print(start_end[0])
    ready= input('are you ready?(enter to quit or any key)')
    if ready:
        while count < 6:
            print(intro[count])    
            format_list(num_lists[count])
            reply = input("y/n ?")
            if reply == "y" :
                your_guess += addition_num[count]
            count +=1
    print(start_end[1] + str(your_guess))
    replay= input('Play again? (enter to quit or any key)')
    if replay:        
        main()
if __name__ == '__main__':
    main()

回答

10 hjpotter92 Oct 17 2020 at 23:17

マジックナンバー

コメントですでに述べたように、数字\$ 1, 2, \cdots \$合計がどのように機能するか(または機能するはずか)がわからない人には、完全にランダムに見えます。リストの生成も非常に面倒です。同じトリックを最大\までの選択に拡張できます$ 127, 255, 511, \cdots, 2^{n} - 1 \$。

再帰的 main

mainプレーヤーがゲームをリプレイしたい場合に備えて、再帰的な呼び出しがあります。戻らない場合の再帰呼び出しは、スタックオーバーフローにつながる可能性があります。このシナリオでは、とにかく再帰は実際には必要ありません。

リストの乱用

ほとんどすべてがリスト内に配置されています。これには、\からのすべての番号が含まれます$ 1-63 \$、これらの数値から生成されたすべてのグラフ、上記のすべてのリストの集計、\の累乗のリスト$ 2 \$、 等々。

それらのいくつかにとって、タプル(不変)は良いです、他のものはとにかくリストに入れる必要はありません。

変数の命名

x、xx、xxx、xxxx、...本当に意味がありません。より適切な変数名を使用してください。


数値リストの生成:

for start in (2 ** i for i in range(6)):
    l = [_ for _ in range(start, 64) if _ % (start * 2) >= start]

リライト:

INTROS = (
    "Is your number in the group of numbers below?",
    "Is your number in this group of numbers?",
    "Is your number in this third group of numbers?",
    "Half way there. Is your number in this group of numbers?",
    "One more after this one. Is your number in this group of numbers?",
    "Last one. Is your number in this group of numbers?",
    # "Or maybe the following?",
    # "Add more intro strings here",
    # "to get larger guessing range",
)
COUNT = len(INTROS)
UPPER_LIMIT = 2 ** COUNT


def display_chart(index: int, columns: int = 8):
    print(INTROS[index])
    start = 1 << index
    chart = [str(x) for x in range(start, UPPER_LIMIT) if x % (start * 2) >= start]
    for i in range(len(chart) // columns):
        print("\t".join(chart[i * columns : (i + 1) * columns]))


def game():
    guess = 0
    print(f"Think of a number between 1 and {UPPER_LIMIT - 1}")
    for current in range(COUNT):
        display_chart(current)
        reply = input("y/n? ")
        if reply == "y":
            guess += 1 << current
    print(f"I think the number you thought of was ... {guess}")


def main():
    while True:
        game()
        character = input("Play again? (enter to quit or any key)")
        if not character:
            break


if __name__ == "__main__":
    main()

現在、書き換えは完全に動的です。範囲を拡大したい場合は、INTROSタプルに別のセクションを追加するだけです。

3 Reinderien Oct 17 2020 at 23:33

最初のパス:

  • リスト作成のもののほとんどを関数に移動します
  • PEP8の修正:スペースの標準化、継続エスケープの削除、関数間のスペース
  • リストの代わりにいくつかの不変のタプル
def make_num_lists():
    x = [xx for xx in range(1, 64)]
    num_i = [i for i in range(1, 64, 2)]
    num_ii = (x[ 1::16] + x[ 2::16] + x[ 5::16] + x[ 6::16] +
              x[ 9::16] + x[10::16] + x[13::16] + x[14::16])
    num_ii.sort()
    num_iii = (x[ 3::16] + x[ 4::16] + x[ 5::16] + x[ 6::16] +
               x[11::16] + x[12::16] + x[13::16] + x[14::16])
    num_iii.sort()
    num_iv = (x[ 7::16] + x[ 8::16] + x[ 9::16] + x[10::16] +
              x[11::16] + x[12::16] + x[13::16] + x[14::16])
    num_iv.sort()
    num_v = (x[15::32] + x[16::32] + x[17::32] + x[18::32] +
             x[19::32] + x[20::32] + x[21::32] + x[22::32] +
             x[23::32] + x[24::32] + x[25::32] + x[26::32] +
             x[27::32] + x[28::32] + x[29::32] + x[30::32])
    num_v.sort()
    num_vi = [x for x in range(32, 64)]
    return [num_i, num_ii, num_iii, num_iv, num_v, num_vi]


num_lists = make_num_lists()
addition_num = (1, 2, 4, 8, 16, 32)
start_end = (
    "Think of a number between 1 and 63",
    "I think the number you thought of was ...",
)
intro = (
    "Is your number in the group of numbers below?",
    "Is your number in this group of numbers ?",
    "Is your number in this third group of numbers ?",
    "Half way there. Is your number in this group of numbers ?",
    "One more after this one. Is your number in this group of numbers ?",
    "Last one. Is your number in this group of numbers ?",
)


def format_list(xx):
    for a,b,c,d,e,f,g,h in zip(xx[::8],xx[1::8],xx[2::8],xx[3::8],xx[4::8],xx[5::8],xx[6::8],xx[7::8]):
        print('{:<8}{:<8}{:<8}{:<8}{:<8}{:<8}{:<8}{:<}'.format(a,b,c,d,e,f,g,h))
    print('-'*62)


def main():
    count = 0
    your_guess = 0
    print(start_end[0])
    ready = input('are you ready?(enter to quit or any key)')
    if ready:
        while count < 6:
            print(intro[count])
            format_list(num_lists[count])
            reply = input("y/n ?")
            if reply == "y":
                your_guess += addition_num[count]
            count += 1
    print(start_end[1] + str(your_guess))
    replay = input('Play again? (enter to quit or any key)')
    if replay:
        main()


if __name__ == '__main__':
    main()

しかし、これは十分ではありません。@ hjpotter92が提案したことを実行します。