Haciendo arte ASCII de diamantes con Python

Estoy teniendo problemas para hacer este diamante. Cada vez que hago caracteres iguales a una longitud uniforme, resulta bien. Sin embargo, cuando es impar, solo se desordena la parte inferior del diamante. He estado trabajando horas en esto y casi he terminado. Gracias de antemano por la ayuda.

chars = 'ABCDEF' length = len(chars) string = '' dots = (length*2 - 1)*2 - 1 for i in range(length): string1 = '' string += chars[i] length1 = len(string) for j in range(0, length1): if j % 2 != 0: string1 += chars[length -1 - j].center(3, '.') else: string1 += chars[length - 1 - j] for k in range(i - 1, -1, -1): if k % 2 != 0: string1 += chars[length - 1 - k].center(3, '.') else: string1 += chars[length - 1 - k] string1 = string1.center(dots, '.') print(string1) string='' for i in range(length - 1): string1 = '' string += chars[i] length1 = len(string) for j in range(length - 1 - i): if j % 2 != 0: string1 += chars[length - 1 - j] else: string1 += chars[length -1 - j].center(3, '.') for k in range(i + 2, length): if k % 2 != 0: string1 += chars[k].center(3, '.') else: string1 += chars[k] string1 = string1.center(dots, '.') print(string1) 

Cuando la longitud del char es impar

Cuando la longitud de char es par

Esto es Python. Hay una multitud de funciones de cadena útiles que podría usar para crear arte ASCII inventivo en un puñado de líneas de código.

Algunos de los más importantes serían str.join , str.Xjust . También haremos uso de chr y ord para iterar sobre rangos de caracteres.

Primero, define una función que maneje el relleno.

 def pad(c1, c2, sep='.', field_width=10): out = sep.join(chr(x) for x in range(c2, c1, -1)).rjust(field_width, sep) # build the first part return sep.join([out, chr(c1), out[::-1]]) 

La primera línea de código construirá la primera mitad de la línea de diamante. La segunda línea une la primera mitad con la letra central y la versión invertida de la primera mitad.

A continuación, determine el rango: el tamaño de su diamante.

 start = 'A' end = ... field_width = (ord(end) - ord('A')) * 2 - 1 

Ahora, necesitará dos bucles separados, uno para el diamante superior y el otro para el inferior. Ambos bucles llaman pad en cada iteración.

 for e in range(ord(end), ord(start), -1): print(pad(e, ord(end), '.', field_width)) for e in range(ord(start), ord(end) + 1): print(pad(e, ord(end), '.', field_width)) 

end = 'E' :

 ........E........ ......EDE..... ....EDCDE... ..EDCBCDE. EDCBABCDE ..EDCBCDE. ....EDCDE... ......EDE..... ........E........ 

end = 'F' :

 ..........F.......... ........FEF....... ......FEDEF..... ....FEDCDEF... ..FEDCBCDEF. FEDCBABCDEF ..FEDCBCDEF. ....FEDCDEF... ......FEDEF..... ........FEF....... ..........F.......... 

La respuesta de Seth Difley explora un enfoque alternativo que consiste en construir la primera mitad del diamante y revertirla para obtener la segunda mitad. De hecho, este enfoque también se puede adoptar para esta solución, algo así como:

 lines = [] for e in range(ord(end), ord(start) - 1, -1): lines.append(pad(e, ord(end), '.', field_width)) for x in lines + lines[-2::-1]: print(x) 

Lo que también resulta en la misma salida, y es más rápido.

Estrategia: dado que la mitad superior del diamante se procesa correctamente en el progtwig existente, genere la mitad superior y luego genere la mitad inferior invirtiendo las líneas de la mitad superior. build_diamond devuelve una lista que contiene las cadenas para la mitad superior. print('\n'.join(string_list)) imprime la mitad superior. bottom_of_diamond_string_list = list(reversed(string_list))[1:] invierte las cadenas de la mitad superior y elimina la cadena central con [1:] para obtener las cadenas de la mitad inferior. print('\n'.join(bottom_of_diamond_string_list)) imprime la mitad inferior. Probado y funciona para 5 y 6 (pares e impares) de longitud. Se puede hacer mucho más código de limpieza, si se desea.

 chars = 'ABCDEF' length = len(chars) def build_diamond(length): dots = (length*2 - 1)*2 - 1 string = '' string_list = [] for i in range(length): string1 = '' string += chars[i] length1 = len(string) for j in range(0, length1): if j % 2 != 0: string1 += chars[length -1 - j].center(3, '.') else: string1 += chars[length - 1 - j] for k in range(i - 1, -1, -1): if k % 2 != 0: string1 += chars[length - 1 - k].center(3, '.') else: string1 += chars[length - 1 - k] string1 = string1.center(dots, '.') string_list.append(string1) return string_list if __name__ == '__main__': string_list = build_diamond(length) print('\n'.join(string_list)) bottom_of_diamond_string_list = list(reversed(string_list))[1:] print('\n'.join(bottom_of_diamond_string_list))