Arte ASCII en Python

Soy bastante nuevo en Python, lo elegí como un pasatiempo y, a través de algunas búsquedas, encontré un montón de ejercicios de ” The Practice of computing “, uno de ellos pregunta acerca de cómo escribir una figura ASCII, como la que se indica a continuación.

cruz ascii

Todo parece ser un ejercicio bastante fácil, pero no puedo parecer envolver mi cabeza en torno al uso de un número para dibujar esto, el ejercicio indica que el dibujo anterior se dibujó mediante el uso del número “1”.

También establece que ningún número menor de 0 o superior a 100 puede o debe usarse para crear un dibujo ASCII.

Aquí hay otro ejemplo:

La entrada aquí fue el número “2”.

mayor ascii cruz

He encontrado una manera de hacer que aparezca la primera imagen, pero no mediante el uso de los números dados de ninguna manera, solo un simple “else” dentro de un bucle while para que pueda filtrar los números que están por debajo o iguales a 0 y superior o igual a 100.

He llegado a un punto muerto.

Mi código como se indica anteriormente que no usa el número de variable para crear el primer dibujo:

while True: s = input("Give me a number to make a drawing with that is between 0 and 100: ") if not s.isdigit(): print ("Error, only numbers will make this program run.") continue #Try Again but with a number this time if int(s) >= 100: print ("The number is bigger than or equal to 100 and won't work. \nDo try again.") continue #try again if int(s) <= 0: print ("The number is smaller than or equal to 0 and won't work. \nDo try again.") continue #try again else: print ("%5s" %("*" *3),"\n"'%5s' %("* *"),"\n" '%7s' %("*** ***"),"\n" '%7s' %("* *"),"\n" '%7s' %("*** ***"),"\n" '%5s' %("* *"),"\n" '%5s' %("*" *3)) print ('Want to make another drawing ?') continue #make another drawing 

El ejercicio establece lo siguiente:

Una figura ASCII del tamaño $ n $ se compone de una o varias líneas. En cada línea solo se permiten espacios y las estrellas (*), después de cada estrella en una línea, no se permiten espacios como tales, debe terminar con una “\ n” o una nueva línea. Y luego seguidos por los ejemplos mencionados anteriormente.

Mi nuevo ejemplo de código, que depende de la entrada variable: Además, en este ejemplo de código, se configura para activarse cuando la entrada es 1, todavía tengo problemas con la “ampliación” del dibujo completo cuando aumente el número de entrada.

  while True: A = input("Give me a number to make a drawing with that is between 0 and 100: ") b = "***" c = "*" d = " " if not A.isdigit(): print ("Error, only numbers will make this program run.") continue #Try Again but with a number this time if int(A) >= 100: print ("The number is bigger than or equal to 100 and won't work. \nDo try again.") continue #try again if int(A) <= 0: print ("The number is smaller than or equal to 0 and won't work. \nDo try again.") continue #try again else : range(1,99) if int(A) == (1) : print ((d *((int(A))*2)) + b,) print ((d *((int(A))*2))+ c + d + c,) print ((d *((int(A))*0))+ b + d + b,) print ((d *((int(A))*0))+ c + d*5 + c,) print ((d *((int(A))*0))+ b + d + b,) print ((d *((int(A))*2))+ c + d + c,) print ((d *((int(A))*2)) + b,) continue #try again 

Pero todavía tengo un problam con “creciente” el número de espacios dentro de la cifra ASCII junto con el aumento de 1 a 2.

Como también tengo un problema con la línea 3, ya que debe indicarse a lo largo de los lados de la consola, debe tener un espaciado de 0 desde el lado, pero debe boost hasta un espaciado de 2 con el número 2 .

Piensa en la diferencia entre 1 y 2. Trata de dibujar a mano el aspecto de 3 y 4 para que la secuencia funcione. Piense en ello como uno de esos problemas en los que se le da el inicio de una secuencia y tiene que trabajar con el rest.

Me gusta:

0 1 1 2 3 5 8 13

Si no lo reconoces de inmediato, es la secuencia de Fibonacci. Una vez que descubras el patrón, puedes escribir una secuencia arbitrariamente larga de los valores.

Y piensa en esta simple secuencia de ascii:

1)

 # 

2)

 ## # 

3)

 ### ## # 

¿Qué aspecto tiene 4)?

U otra secuencia de ascii:

1)

 # 

2)

  # # # # 

3)

  # # # # # # # # 

¿Qué es (4)?

Si aún no tiene sentido, intente diseñar algunas de sus propias formas recursivas que sean un poco similares a la que está tratando de descubrir (tal vez algo parecido a mi segundo ejemplo). No se preocupe por cómo codificarlo por ahora, solo se preocupa por lo que debería ser la salida. Luego mire los patrones y salga con un algoritmo.

Primero, analice la figura línea por línea para identificar los diferentes tipos de patrones.

  • La tapa, que aparece solo en las líneas superior e inferior. Es cualquier número de espacios, seguido de tres estrellas.
  • El muro, que forma las secciones verticales de la figura. Es cualquier número de espacios, seguido de una estrella, seguido de cualquier número de espacios, seguido de una estrella.
  • El suelo, que forma secciones horizontales de la figura. Es cualquier número de espacios, seguido de tres estrellas, seguido de cualquier número de espacios, seguido de tres estrellas.

Podemos escribir una función que imprima cada uno de estos patrones.

 def cap(spacesBefore): print " " * spacesBefore + "***" def wall(spacesBefore, spacesBetween): print " " * spacesBefore + "*" + " " * spacesBetween + "*" def floor(spacesBefore, spacesBetween): print " " * spacesBefore + "***" + " " * spacesBetween + "***" 

Luego, escriba un código que muestre una figura de tamaño, 0, 1 y 2. Esto le dará una idea de cómo mostrar una figura de cualquier tamaño.

 #size 0 cap(0) wall(0,1) cap(0) print "\n" #size 1 cap(2) wall(2, 1) floor(0, 1) wall(0, 5) floor(0, 1) wall(2, 1) cap(2) print "\n" #size 2 cap(4) wall(4, 1) floor(2, 1) wall(2, 5) floor(0, 5) wall(0, 9) floor(0, 5) wall(2, 5) floor(2, 1) wall(4, 1) cap(4) 

Salida:

 *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** 

Al analizar el código utilizado para hacer estas figuras, algunos patrones se hacen evidentes. Para una figura de tamaño N:

  • Ambos extremos tienen N * 2 espacios precedentes.
  • Hay 2 * N + 1 líneas de pared.
  • Hay 2 * N líneas de piso.
  • La primera y segunda mitades de la figura son imágenes especulares.
  • El número de espacios anteriores para cada línea de muro comienza en N * 2, luego se reduce en dos hasta que llega a cero; luego vuelve a crecer en dos hasta que alcanza N * 2 una vez más.
  • El número de espacios entre las paredes comienza en 1 y aumenta en 4 hasta que alcanza 4 * N + 1; luego vuelve a encogerse en cuatro hasta que alcanza 1 una vez más.
  • El número de espacios anteriores para cada piso comienza en 2N-2, luego se reduce en dos hasta que llega a cero; luego vuelve a crecer en dos hasta que alcanza 2N-2 una vez más.
  • El número de espacios entre los pisos comienza en 1, y aumenta en 4 hasta que alcanza 4 * N-3; luego vuelve a encogerse en cuatro hasta que alcanza 1 una vez más.

Todos los patrones crecen y se encogen a una velocidad lineal, y luego se encogen y crecen a una velocidad lineal. Esto implica que deberíamos usar dos for bucles con condiciones opuestas, con un pequeño código adicional para las tapas y la pared central.

 def draw(N): cap(2*N) for i in range(N): #loop from 0 to N-1 wall(2*(Ni), 1+(4*i)) floor(2*(Ni-1), 1+(4*i)) wall(0, 4*N+1) for i in range(N-1, -1, -1): #loop from N-1 to 0 floor(2*(Ni-1), 1+(4*i)) wall(2*(Ni), 1+(4*i)) cap(2*N) 

Ahora prueba el código.

 for i in range(7,10): draw(i) print "\n" 

Salida:

  *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** 

Para encontrar el patrón, podrías imaginarte cómo lo dibujaría la tortuga . Por ejemplo, para dibujar:

 *** * * *** 

La tortuga puede seguir estas instrucciones:

  • girar a la derecha, avanzar
  • girar a la derecha, avanzar
  • girar a la derecha, avanzar
  • girar a la derecha, avanzar

Como un progtwig de Python:

 import turtle turtle.right(90); turtle.forward(50) turtle.right(90); turtle.forward(50) turtle.right(90); turtle.forward(50) turtle.right(90); turtle.forward(50) turtle.exitonclick() # leave GUI open until a click 

Si abreviamos “girar a la derecha” como 'r' y “avanzar” como "f" , las instrucciones son:

 'rfrfrfrf' 

Es fácil ver que es 'rf' * 4 . Siguiendo el mismo procedimiento para:

  *** * * *** *** * * *** *** * * *** 

las instrucciones son 'rflfrfrflfrfrflfrfrflfrf' o 'rflfrf' * 4 , donde 'l' significa “girar a la izquierda”.

La regla que describe ambos casos para n igual a 0 y 1 es:

 ("rf" + "lfrf" * n) * 4 

es decir, si n = 0 entonces es 'rf' * 4 , si n = 1 entonces es ('rf' + 'lfrf') * 4 . Para verificar la fórmula, puede dibujarla para n = 2 y compararla con la respuesta conocida:

  *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** 

Como un progtwig de Python:

 from turtle import Turtle def get_romb_program(n): assert n >= 0 side = "rf" + "lfrf" * n program = side * 4 # romb has 4 sides return program def draw(turtle, n): assert 0 <= n < 101 commands = {'r': lambda t: t.right(90), # turn right 'l': lambda t: t.left(90), # turn left 'f': lambda t: t.forward(2) } run(get_romb_program(n), turtle, commands) def run(program, t, commands): for c in program: commands[c](t) n = 2 t = Turtle() scr = t.getscreen() scr.xscale, scr.yscale = [101 // (n + 1)] * 2 draw(t, n) scr.exitonclick() 

Para imprimirlo como un arte ascii, puedes usar AsciiTurtle lugar de turtle.Turtle .

 class AsciiTurtle(object): def __init__(self): self.path = [(0, 0)] self.direction = (1, 0) def forward(self, distance): x, y = self.path[-1] for i in range(1, distance + 1): self.path.append((x + self.direction[0] * i, y + self.direction[1] * i)) def right(self, angle_ignored): # 90 degree turn right self.direction = self.direction[1], -self.direction[0] def left(self, angle_ignored): # 90 degree turn left self.direction = -self.direction[1], self.direction[0] def show(self): minx, maxx, maxy, miny = [f(xy[i] for xy in self.path) for i in [0, 1] for f in [min, max]] miny, maxy = -miny, -maxy # upside-down board = [[' '] * (maxx - minx + 1) for _ in range(maxy - miny + 1)] for x, y in self.path: board[-y - miny][x - minx] = '*' print('\n'.join(''.join(row) for row in board)) 

Ejemplo

 n = 5 t = AsciiTurtle() draw(t, n) # defined above t.show() 

Salida

  *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * *** *** * * ***