ASCII art in Python

前端 未结 3 1242
不知归路
不知归路 2020-12-15 07:06

I\'m pretty new to python, picked it up as an hobby interest, and through some searching found myself a bunch of exercises from \"The Practice of computing\", one o

相关标签:
3条回答
  • 2020-12-15 07:26

    Think about the difference between 1 and 2. Try to draw by hand what 3 and 4 should look like to make the sequence work. Think about it like one of those problems where you are given the start of a sequence and you have to work our the rest.

    Like:

    0 1 1 2 3 5 8 13

    If you don't recognize that right off, it is the Fibonacci sequence. Once you figure out the pattern you can write an arbitrarily long sequence of the values.

    And think about this simple ascii sequence:

    1)

    #
    

    2)

    ##
    #
    

    3)

    ###
    ##
    #
    

    What does 4) look like?

    Or another ascii sequence:

    1)

    #
    

    2)

     #
    # #
     #
    

    3)

      #
     # #
    #   #
     # #
      #
    

    What is (4)?

    If it still doesn't make sense, try designing a few recursive shapes of your own which are a little similar to the one you are trying to figure out (maybe something along the lines of my second example). Don't worry about how to code it for now, just worry about what the output should be. Then look at the patterns and come out with an algorithm.

    0 讨论(0)
  • 2020-12-15 07:27

    First, analyze the figure line-by-line to identify the different types of patterns.

    • The cap, which appears only on the top and bottom lines. It is any number of spaces, followed by three stars.
    • The wall, which forms vertical sections of the figure. It is any number of spaces, followed by one star, followed by any number of spaces, followed by a star.
    • The floor, which forms horizontal sections of the figure. It is any number of spaces, followed by three stars, followed by any number of spaces, followed by three stars.

    We can write a function that prints each of these patterns.

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

    Next, write code that will display a figure of size, 0, 1, and 2. This should give you insight on how to display a figure of any size.

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

    Output:

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

    Analyzing the code used to make these figures, some patterns become apparent. For a figure of size N:

    • Both end caps have N*2 preceding spaces.
    • There are 2*N+1 wall lines.
    • There are 2*N floor lines.
    • The first and second halves of the figure are mirror images.
    • The number of preceding spaces for each wall line begins at N*2, then shrinks by two until it reaches zero; then it grows by two again until it reaches N*2 once more.
    • The number of spaces between walls begins at 1, and increases by 4 until it reaches 4*N+1; then it shrinks by four again until it reaches 1 once more.
    • The number of preceding spaces for each floor begins at 2N-2, then shrinks by two until it reaches zero; then it grows by two again until it reaches 2N-2 once more.
    • The number of spaces between floors begins at 1, and increases by 4 until it reaches 4*N-3; then it shrinks by four again until it reaches 1 once more.

    The patterns all grow and shrink at a linear rate, and then shrink and grow at a linear rate. This implies that we should use two for loops with opposite conditions, with a little extra code for the caps and central wall.

    def draw(N):
        cap(2*N)
        for i in range(N):              #loop from 0 to N-1
            wall(2*(N-i), 1+(4*i))
            floor(2*(N-i-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*(N-i-1), 1+(4*i))
            wall(2*(N-i), 1+(4*i))
        cap(2*N)
    

    Now test the code.

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

    Output:

                  ***
                  * *
                *** ***
                *     *
              ***     ***
              *         *
            ***         ***
            *             *
          ***             ***
          *                 *
        ***                 ***
        *                     *
      ***                     ***
      *                         *
    ***                         ***
    *                             *
    ***                         ***
      *                         *
      ***                     ***
        *                     *
        ***                 ***
          *                 *
          ***             ***
            *             *
            ***         ***
              *         *
              ***     ***
                *     *
                *** ***
                  * *
                  ***
    
    
                    ***
                    * *
                  *** ***
                  *     *
                ***     ***
                *         *
              ***         ***
              *             *
            ***             ***
            *                 *
          ***                 ***
          *                     *
        ***                     ***
        *                         *
      ***                         ***
      *                             *
    ***                             ***
    *                                 *
    ***                             ***
      *                             *
      ***                         ***
        *                         *
        ***                     ***
          *                     *
          ***                 ***
            *                 *
            ***             ***
              *             *
              ***         ***
                *         *
                ***     ***
                  *     *
                  *** ***
                    * *
                    ***
    
    
                      ***
                      * *
                    *** ***
                    *     *
                  ***     ***
                  *         *
                ***         ***
                *             *
              ***             ***
              *                 *
            ***                 ***
            *                     *
          ***                     ***
          *                         *
        ***                         ***
        *                             *
      ***                             ***
      *                                 *
    ***                                 ***
    *                                     *
    ***                                 ***
      *                                 *
      ***                             ***
        *                             *
        ***                         ***
          *                         *
          ***                     ***
            *                     *
            ***                 ***
              *                 *
              ***             ***
                *             *
                ***         ***
                  *         *
                  ***     ***
                    *     *
                    *** ***
                      * *
                      ***
    
    0 讨论(0)
  • 2020-12-15 07:28

    To find the pattern you could imagine how would turtle draw it. For example, to draw:

    ***
    * *
    ***
    

    turtle can follow these instructions:

    • turn right, move forward
    • turn right, move forward
    • turn right, move forward
    • turn right, move forward

    As a Python program:

    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
    

    If we abbreviate "turn right" as 'r' and "move forward" as "f" then the instructions are:

    'rfrfrfrf'
    

    It is easy to see that it is 'rf' * 4. Following the same procedure for:

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

    the instructions are 'rflfrfrflfrfrflfrfrflfrf' or 'rflfrf' * 4, where 'l' stands for "turn left".

    The rule that describes both cases for n equal to 0 and 1 is:

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

    i.e., if n = 0 then it is 'rf' * 4, if n = 1 then it is ('rf' + 'lfrf') * 4. To check the formula, you could draw it for n = 2 and compare it with the known answer:

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

    As a Python program:

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

    To print it as an ascii art, you could use AsciiTurtle instead of 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))
    

    Example

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

    Output

              ***          
              * *          
            *** ***        
            *     *        
          ***     ***      
          *         *      
        ***         ***    
        *             *    
      ***             ***  
      *                 *  
    ***                 ***
    *                     *
    ***                 ***
      *                 *  
      ***             ***  
        *             *    
        ***         ***    
          *         *      
          ***     ***      
            *     *        
            *** ***        
              * *          
              ***          
    
    0 讨论(0)
提交回复
热议问题