adivina tu número

Oct 17 2020

Un guión simple que le pide que piense en un número entre 1 y 63, luego ofrece una lista de números y le pregunta si su número está en esa lista. ¿Se puede refactorizar esto aún más? ¿Existen mejores formas de crear listas? ¿Alguna mejora?

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()

Respuestas

10 hjpotter92 Oct 17 2020 at 23:17

Números mágicos

Como ya se mencionó en los comentarios, los números \$ 1, 2, \cdots \$parece ser completamente aleatorio para cualquiera que no esté seguro de cómo va a funcionar (o se supone que va a funcionar) la suma. La generación de las listas también es muy engorrosa. El mismo truco podría ampliarse a una selección de hasta \$ 127, 255, 511, \cdots, 2^{n} - 1 \$.

Recursivo main

Tienes una llamada recursiva a mainen caso de que el jugador quiera volver a jugar el juego. Las llamadas recursivas cuando nunca regresa pueden provocar desbordamientos de pila. En este escenario, la recursividad no es realmente necesaria de todos modos.

Uso excesivo de listas

Tienes casi todo dentro de listas. Esto incluye todos los números de \$ 1-63 \$, todos los gráficos generados a partir de estos números, agregación de todas las listas anteriores, lista de poderes de \$ 2 \$, y así.

Para algunos de ellos, una tupla (inmutable) es buena, otros no necesitan ser colocados en una lista de todos modos.

Denominación variable

x, xx, xxx, xxxx, .. no son realmente significativo. Utilice mejores nombres de variables.


Para la generación de listas numéricas:

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

Volver a escribir:

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()

La reescritura es de naturaleza completamente dinámica ahora. Si desea aumentar el rango, simplemente agregue otra sección a la INTROStupla.

3 Reinderien Oct 17 2020 at 23:33

Primer pase:

  • Mover la mayor parte de la creación de listas a una función
  • Correcciones de PEP8: estandarizar espacios, deshacerse de los escapes de continuación, espacios entre funciones
  • Algunas tuplas inmutables en lugar de listas
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()

Pero esto no es suficiente. Haz lo que sugirió @ hjpotter92.